1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program 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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Copyright (C) 2005 - 2012 Red Hat, Inc.
19 * Copyright (C) 2006 - 2008 Novell, Inc.
20 */
21
22 #include "config.h"
23 #include <glib.h>
24 #include <glib/gi18n.h>
25 #include <netinet/in.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <linux/sockios.h>
29 #include <linux/ethtool.h>
30 #include <linux/version.h>
31 #include <sys/ioctl.h>
32 #include <unistd.h>
33 #include <linux/if.h>
34 #include <errno.h>
35 #include <netinet/ether.h>
36
37 #include <gudev/gudev.h>
38
39 #include "nm-glib-compat.h"
40 #include "nm-device-ethernet.h"
41 #include "nm-device-private.h"
42 #include "nm-activation-request.h"
43 #include "NetworkManagerUtils.h"
44 #include "nm-supplicant-manager.h"
45 #include "nm-supplicant-interface.h"
46 #include "nm-supplicant-config.h"
47 #include "nm-setting-connection.h"
48 #include "nm-setting-wired.h"
49 #include "nm-setting-8021x.h"
50 #include "nm-setting-pppoe.h"
51 #include "nm-setting-bond.h"
52 #include "ppp-manager/nm-ppp-manager.h"
53 #include "nm-logging.h"
54 #include "nm-utils.h"
55 #include "nm-enum-types.h"
56 #include "nm-dbus-manager.h"
57 #include "nm-platform.h"
58
59 #include "nm-device-ethernet-glue.h"
60
61
62 G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
63
64 #define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate))
65
66 #define WIRED_SECRETS_TRIES "wired-secrets-tries"
67
68 #define NM_ETHERNET_ERROR (nm_ethernet_error_quark ())
69
70 typedef struct Supplicant {
71 NMSupplicantManager *mgr;
72 NMSupplicantInterface *iface;
73
74 /* signal handler ids */
75 guint iface_error_id;
76 guint iface_state_id;
77
78 /* Timeouts and idles */
79 guint iface_con_error_cb_id;
80 guint con_timeout_id;
81 } Supplicant;
82
83 typedef struct {
84 guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */
85 guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */
86
87 guint32 speed;
88
89 Supplicant supplicant;
90 guint supplicant_timeout_id;
91
92 /* s390 */
93 char * subchan1;
94 char * subchan2;
95 char * subchan3;
96 char * subchannels; /* Composite used for checking unmanaged specs */
97
98 /* PPPoE */
99 NMPPPManager *ppp_manager;
100 NMIP4Config *pending_ip4_config;
101 } NMDeviceEthernetPrivate;
102
103 enum {
104 PROP_0,
105 PROP_PERM_HW_ADDRESS,
106 PROP_SPEED,
107
108 LAST_PROP
109 };
110
111
112 static GQuark
113 nm_ethernet_error_quark (void)
114 {
115 static GQuark quark = 0;
116 if (!quark)
117 quark = g_quark_from_static_string ("nm-ethernet-error");
118 return quark;
119 }
120
121 static void
122 _update_s390_subchannels (NMDeviceEthernet *self)
123 {
124 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
125 const char *iface;
126 GUdevClient *client;
127 GUdevDevice *dev;
128 GUdevDevice *parent = NULL;
129 const char *parent_path, *item, *driver;
130 const char *subsystems[] = { "net", NULL };
131 GDir *dir;
132 GError *error = NULL;
133
134 iface = nm_device_get_iface (NM_DEVICE (self));
135
136 client = g_udev_client_new (subsystems);
137 if (!client) {
138 nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to initialize GUdev client", iface);
139 return;
140 }
141
142 dev = g_udev_client_query_by_subsystem_and_name (client, "net", iface);
143 if (!dev) {
144 nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to find device with udev", iface);
145 goto out;
146 }
147
148 /* Try for the "ccwgroup" parent */
149 parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL);
150 if (!parent) {
151 /* FIXME: whatever 'lcs' devices' subsystem is here... */
152 if (!parent) {
153 /* Not an s390 device */
154 goto out;
155 }
156 }
157
158 parent_path = g_udev_device_get_sysfs_path (parent);
159 dir = g_dir_open (parent_path, 0, &error);
160 if (!dir) {
161 nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to open directory '%s': %s",
162 iface, parent_path,
163 error && error->message ? error->message : "(unknown)");
164 g_clear_error (&error);
165 goto out;
166 }
167
168 /* FIXME: we probably care about ordering here to ensure that we map
169 * cdev0 -> subchan1, cdev1 -> subchan2, etc.
170 */
171 while ((item = g_dir_read_name (dir))) {
172 char buf[50];
173 char *cdev_path;
174
175 if (strncmp (item, "cdev", 4))
176 continue; /* Not a subchannel link */
177
178 cdev_path = g_strdup_printf ("%s/%s", parent_path, item);
179
180 memset (buf, 0, sizeof (buf));
181 errno = 0;
182 if (readlink (cdev_path, &buf[0], sizeof (buf) - 1) >= 0) {
183 if (!priv->subchan1)
184 priv->subchan1 = g_path_get_basename (buf);
185 else if (!priv->subchan2)
186 priv->subchan2 = g_path_get_basename (buf);
187 else if (!priv->subchan3)
188 priv->subchan3 = g_path_get_basename (buf);
189 } else {
190 nm_log_warn (LOGD_DEVICE | LOGD_HW,
191 "(%s): failed to read cdev link '%s': %d",
192 iface, cdev_path, errno);
193 }
194 g_free (cdev_path);
195 };
196
197 g_dir_close (dir);
198
199 if (priv->subchan3) {
200 priv->subchannels = g_strdup_printf ("%s,%s,%s",
201 priv->subchan1,
202 priv->subchan2,
203 priv->subchan3);
204 } else if (priv->subchan2) {
205 priv->subchannels = g_strdup_printf ("%s,%s",
206 priv->subchan1,
207 priv->subchan2);
208 } else
209 priv->subchannels = g_strdup (priv->subchan1);
210
211 driver = nm_device_get_driver (NM_DEVICE (self));
212 nm_log_info (LOGD_DEVICE | LOGD_HW,
213 "(%s): found s390 '%s' subchannels [%s]",
214 iface, driver ? driver : "(unknown driver)", priv->subchannels);
215
216 out:
217 if (parent)
218 g_object_unref (parent);
219 if (dev)
220 g_object_unref (dev);
221 g_object_unref (client);
222 }
223
224 static GObject*
225 constructor (GType type,
226 guint n_construct_params,
227 GObjectConstructParam *construct_params)
228 {
229 GObject *object;
230 NMDeviceEthernetPrivate *priv;
231 NMDevice *self;
232 int ifindex;
233
234 object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
235 n_construct_params,
236 construct_params);
237 if (object) {
238 self = NM_DEVICE (object);
(1) Event returned_pointer: |
Pointer "priv" returned by "g_type_instance_get_private((GTypeInstance *)self, nm_device_ethernet_get_type())" is never used. |
239 priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
240 ifindex = nm_device_get_ifindex (self);
241
242 g_assert ( nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_ETHERNET
243 || nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_VETH);
244
245 nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): kernel ifindex %d",
246 nm_device_get_iface (NM_DEVICE (self)),
247 nm_device_get_ifindex (NM_DEVICE (self)));
248
249 /* s390 stuff */
250 _update_s390_subchannels (NM_DEVICE_ETHERNET (self));
251 }
252
253 return object;
254 }
255
256 static void
257 clear_secrets_tries (NMDevice *device)
258 {
259 NMActRequest *req;
260 NMConnection *connection;
261
262 req = nm_device_get_act_request (device);
263 if (req) {
264 connection = nm_act_request_get_connection (req);
265 /* Clear wired secrets tries on success, failure, or when deactivating */
266 g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, NULL);
267 }
268 }
269
270 static void
271 device_state_changed (NMDevice *device,
272 NMDeviceState new_state,
273 NMDeviceState old_state,
274 NMDeviceStateReason reason)
275 {
276 switch (new_state) {
277 case NM_DEVICE_STATE_ACTIVATED:
278 case NM_DEVICE_STATE_FAILED:
279 case NM_DEVICE_STATE_DISCONNECTED:
280 clear_secrets_tries (device);
281 break;
282 default:
283 break;
284 }
285 }
286
287 static void
288 nm_device_ethernet_init (NMDeviceEthernet * self)
289 {
290 }
291
292 NMDevice *
293 nm_device_ethernet_new (NMPlatformLink *platform_device)
294 {
295 g_return_val_if_fail (platform_device != NULL, NULL);
296
297 return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET,
298 NM_DEVICE_PLATFORM_DEVICE, platform_device,
299 NM_DEVICE_TYPE_DESC, "Ethernet",
300 NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
301 NULL);
302 }
303
304 static void
305 update_permanent_hw_address (NMDevice *dev)
306 {
307 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
308 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
309 struct ifreq req;
310 struct ethtool_perm_addr *epaddr = NULL;
311 int fd, ret;
312
313 fd = socket (PF_INET, SOCK_DGRAM, 0);
314 if (fd < 0) {
315 nm_log_warn (LOGD_HW, "couldn't open control socket.");
316 return;
317 }
318
319 /* Get permanent MAC address */
320 memset (&req, 0, sizeof (struct ifreq));
321 strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ);
322
323 epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN);
324 epaddr->cmd = ETHTOOL_GPERMADDR;
325 epaddr->size = ETH_ALEN;
326 req.ifr_data = (void *) epaddr;
327
328 errno = 0;
329 ret = ioctl (fd, SIOCETHTOOL, &req);
330 if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) {
331 nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)",
332 nm_device_get_iface (dev), errno);
333 /* Fall back to current address */
334 memcpy (epaddr->data, nm_device_get_hw_address (dev, NULL), ETH_ALEN);
335 }
336
337 if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) {
338 memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN);
339 g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
340 }
341
342 g_free (epaddr);
343 close (fd);
344 }
345
346 static void
347 update_initial_hw_address (NMDevice *dev)
348 {
349 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
350 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
351 char *mac_str;
352
353 /* This sets initial MAC address from current MAC address. It should only
354 * be called from NMDevice constructor() to really get the initial address.
355 */
356 memcpy (priv->initial_hw_addr, nm_device_get_hw_address (dev, NULL), ETH_ALEN);
357
358 mac_str = nm_utils_hwaddr_ntoa (priv->initial_hw_addr, ARPHRD_ETHER);
359 nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s",
360 nm_device_get_iface (dev), mac_str);
361 g_free (mac_str);
362 }
363
364 static guint32
365 get_generic_capabilities (NMDevice *dev)
366 {
367 if (nm_platform_link_supports_carrier_detect (nm_device_get_ifindex (dev)))
368 return NM_DEVICE_CAP_CARRIER_DETECT;
369 else {
370 nm_log_info (LOGD_HW,
371 "(%s): driver '%s' does not support carrier detection.",
372 nm_device_get_iface (dev),
373 nm_device_get_driver (dev));
374 return NM_DEVICE_CAP_NONE;
375 }
376 }
377
378 static gboolean
379 match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac)
380 {
381 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
382 const GPtrArray *subchans;
383 int i;
384
385 *try_mac = TRUE;
386
387 subchans = nm_setting_wired_get_s390_subchannels (s_wired);
388 if (!subchans)
389 return TRUE;
390
391 /* connection requires subchannels but the device has none */
392 if (!priv->subchannels)
393 return FALSE;
394
395 /* Make sure each subchannel in the connection is a subchannel of this device */
396 for (i = 0; i < subchans->len; i++) {
397 const char *candidate = g_ptr_array_index (subchans, i);
398
399 if ( (priv->subchan1 && !strcmp (priv->subchan1, candidate))
400 || (priv->subchan2 && !strcmp (priv->subchan2, candidate))
401 || (priv->subchan3 && !strcmp (priv->subchan3, candidate)))
402 continue;
403
404 return FALSE; /* a subchannel was not found */
405 }
406
407 *try_mac = FALSE;
408 return TRUE;
409 }
410
411 static gboolean
412 check_connection_compatible (NMDevice *device,
413 NMConnection *connection,
414 GError **error)
415 {
416 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
417 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
418 NMSettingWired *s_wired;
419
420 if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->check_connection_compatible (device, connection, error))
421 return FALSE;
422
423 s_wired = nm_connection_get_setting_wired (connection);
424
425 if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) {
426 /* NOP */
427 } else if (nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) {
428 if (!s_wired) {
429 g_set_error (error,
430 NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INVALID,
431 "The connection was not a valid wired connection.");
432 return FALSE;
433 }
434 } else {
435 g_set_error (error,
436 NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED,
437 "The connection was not a wired, bond, or PPPoE connection.");
438 return FALSE;
439 }
440
441 if (s_wired) {
442 const GByteArray *mac;
443 gboolean try_mac = TRUE;
444 const GSList *mac_blacklist, *mac_blacklist_iter;
445
446 if (!match_subchans (self, s_wired, &try_mac)) {
447 g_set_error (error,
448 NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE,
449 "The connection's s390 subchannels did not match this device.");
450 return FALSE;
451 }
452
453 mac = nm_setting_wired_get_mac_address (s_wired);
454 if (try_mac && mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) {
455 g_set_error (error,
456 NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE,
457 "The connection's MAC address did not match this device.");
458 return FALSE;
459 }
460
461 /* Check for MAC address blacklist */
462 mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
463 for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter;
464 mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) {
465 struct ether_addr addr;
466
467 if (!ether_aton_r (mac_blacklist_iter->data, &addr)) {
468 g_warn_if_reached ();
469 return FALSE;
470 }
471 if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) {
472 g_set_error (error,
473 NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE,
474 "The connection's MAC address (%s) is blacklisted in %s.",
475 (char *) mac_blacklist_iter->data, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
476 return FALSE;
477 }
478 }
479 }
480
481 return TRUE;
482 }
483
484 /* FIXME: Move it to nm-device.c and then get rid of all foo_device_get_setting() all around.
485 It's here now to keep the patch short. */
486 static NMSetting *
487 device_get_setting (NMDevice *device, GType setting_type)
488 {
489 NMActRequest *req;
490 NMSetting *setting = NULL;
491
492 req = nm_device_get_act_request (device);
493 if (req) {
494 NMConnection *connection;
495
496 connection = nm_act_request_get_connection (req);
497 if (connection)
498 setting = nm_connection_get_setting (connection, setting_type);
499 }
500
501 return setting;
502 }
503
504 /*****************************************************************************/
505 /* 802.1X */
506
507 static void
508 remove_supplicant_timeouts (NMDeviceEthernet *self)
509 {
510 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
511
512 if (priv->supplicant.con_timeout_id) {
513 g_source_remove (priv->supplicant.con_timeout_id);
514 priv->supplicant.con_timeout_id = 0;
515 }
516
517 if (priv->supplicant_timeout_id) {
518 g_source_remove (priv->supplicant_timeout_id);
519 priv->supplicant_timeout_id = 0;
520 }
521 }
522
523 static void
524 remove_supplicant_interface_error_handler (NMDeviceEthernet *self)
525 {
526 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
527
528 if (priv->supplicant.iface_error_id != 0) {
529 g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
530 priv->supplicant.iface_error_id = 0;
531 }
532
533 if (priv->supplicant.iface_con_error_cb_id > 0) {
534 g_source_remove (priv->supplicant.iface_con_error_cb_id);
535 priv->supplicant.iface_con_error_cb_id = 0;
536 }
537 }
538
539 static void
540 supplicant_interface_release (NMDeviceEthernet *self)
541 {
542 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
543
544 remove_supplicant_timeouts (self);
545 remove_supplicant_interface_error_handler (self);
546
547 if (priv->supplicant.iface_state_id > 0) {
548 g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
549 priv->supplicant.iface_state_id = 0;
550 }
551
552 if (priv->supplicant.iface) {
553 nm_supplicant_interface_disconnect (priv->supplicant.iface);
554 nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface);
555 priv->supplicant.iface = NULL;
556 }
557 }
558
559 static void
560 wired_secrets_cb (NMActRequest *req,
561 guint32 call_id,
562 NMConnection *connection,
563 GError *error,
564 gpointer user_data)
565 {
566 NMDevice *dev = NM_DEVICE (user_data);
567
568 g_return_if_fail (req == nm_device_get_act_request (dev));
569 g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
570 g_return_if_fail (nm_act_request_get_connection (req) == connection);
571
572 if (error) {
573 nm_log_warn (LOGD_ETHER, "%s", error->message);
574 nm_device_state_changed (dev,
575 NM_DEVICE_STATE_FAILED,
576 NM_DEVICE_STATE_REASON_NO_SECRETS);
577 } else
578 nm_device_activate_schedule_stage1_device_prepare (dev);
579 }
580
581 static gboolean
582 link_timeout_cb (gpointer user_data)
583 {
584 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
585 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
586 NMDevice *dev = NM_DEVICE (self);
587 NMActRequest *req;
588 NMConnection *connection;
589 const char *setting_name;
590
591 priv->supplicant_timeout_id = 0;
592
593 req = nm_device_get_act_request (dev);
594
595 if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) {
596 nm_device_state_changed (dev,
597 NM_DEVICE_STATE_FAILED,
598 NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT);
599 return FALSE;
600 }
601
602 /* Disconnect event during initial authentication and credentials
603 * ARE checked - we are likely to have wrong key. Ask the user for
604 * another one.
605 */
606 if (nm_device_get_state (dev) != NM_DEVICE_STATE_CONFIG)
607 goto time_out;
608
609 connection = nm_act_request_get_connection (req);
610 nm_connection_clear_secrets (connection);
611 setting_name = nm_connection_need_secrets (connection, NULL);
612 if (!setting_name)
613 goto time_out;
614
615 nm_log_info (LOGD_DEVICE | LOGD_ETHER,
616 "Activation (%s/wired): disconnected during authentication,"
617 " asking for new key.",
618 nm_device_get_iface (dev));
619 supplicant_interface_release (self);
620
621 nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
622 nm_act_request_get_secrets (req,
623 setting_name,
624 NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW,
625 NULL,
626 wired_secrets_cb,
627 self);
628
629 return FALSE;
630
631 time_out:
632 nm_log_warn (LOGD_DEVICE | LOGD_ETHER,
633 "(%s): link timed out.", nm_device_get_iface (dev));
634 nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
635
636 return FALSE;
637 }
638
639 static NMSupplicantConfig *
640 build_supplicant_config (NMDeviceEthernet *self)
641 {
642 const char *con_uuid;
643 NMSupplicantConfig *config = NULL;
644 NMSetting8021x *security;
645 NMConnection *connection;
646
647 connection = nm_device_get_connection (NM_DEVICE (self));
648 g_assert (connection);
649 con_uuid = nm_connection_get_uuid (connection);
650
651 config = nm_supplicant_config_new ();
652
653 security = nm_connection_get_setting_802_1x (connection);
654 if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, TRUE)) {
655 nm_log_warn (LOGD_DEVICE, "Couldn't add 802.1X security setting to supplicant config.");
656 g_object_unref (config);
657 config = NULL;
658 }
659
660 return config;
661 }
662
663 static void
664 supplicant_iface_state_cb (NMSupplicantInterface *iface,
665 guint32 new_state,
666 guint32 old_state,
667 int disconnect_reason,
668 gpointer user_data)
669 {
670 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
671 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
672 NMDevice *device = NM_DEVICE (self);
673 NMSupplicantConfig *config;
674 gboolean success = FALSE;
675 NMDeviceState devstate;
676
677 if (new_state == old_state)
678 return;
679
680 nm_log_info (LOGD_DEVICE | LOGD_ETHER,
681 "(%s): supplicant interface state: %s -> %s",
682 nm_device_get_iface (device),
683 nm_supplicant_interface_state_to_string (old_state),
684 nm_supplicant_interface_state_to_string (new_state));
685
686 devstate = nm_device_get_state (device);
687
688 switch (new_state) {
689 case NM_SUPPLICANT_INTERFACE_STATE_READY:
690 config = build_supplicant_config (self);
691 if (config) {
692 success = nm_supplicant_interface_set_config (priv->supplicant.iface, config);
693 g_object_unref (config);
694
695 if (!success) {
696 nm_log_err (LOGD_DEVICE | LOGD_ETHER,
697 "Activation (%s/wired): couldn't send security "
698 "configuration to the supplicant.",
699 nm_device_get_iface (device));
700 }
701 } else {
702 nm_log_warn (LOGD_DEVICE | LOGD_ETHER,
703 "Activation (%s/wired): couldn't build security configuration.",
704 nm_device_get_iface (device));
705 }
706
707 if (!success) {
708 nm_device_state_changed (device,
709 NM_DEVICE_STATE_FAILED,
710 NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
711 }
712 break;
713 case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
714 remove_supplicant_interface_error_handler (self);
715 remove_supplicant_timeouts (self);
716
717 /* If this is the initial association during device activation,
718 * schedule the next activation stage.
719 */
720 if (devstate == NM_DEVICE_STATE_CONFIG) {
721 nm_log_info (LOGD_DEVICE | LOGD_ETHER,
722 "Activation (%s/wired) Stage 2 of 5 (Device Configure) successful.",
723 nm_device_get_iface (device));
724 nm_device_activate_schedule_stage3_ip_config_start (device);
725 }
726 break;
727 case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED:
728 if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
729 /* Start the link timeout so we allow some time for reauthentication */
730 if (!priv->supplicant_timeout_id)
731 priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, device);
732 }
733 break;
734 case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
735 supplicant_interface_release (self);
736 remove_supplicant_timeouts (self);
737
738 if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
739 nm_device_state_changed (device,
740 NM_DEVICE_STATE_FAILED,
741 NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
742 }
743 break;
744 default:
745 break;
746 }
747 }
748
749 static gboolean
750 supplicant_iface_connection_error_cb_handler (gpointer user_data)
751 {
752 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
753 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
754
755 supplicant_interface_release (self);
756 nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
757
758 priv->supplicant.iface_con_error_cb_id = 0;
759 return FALSE;
760 }
761
762 static void
763 supplicant_iface_connection_error_cb (NMSupplicantInterface *iface,
764 const char *name,
765 const char *message,
766 gpointer user_data)
767 {
768 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
769 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
770 guint id;
771
772 nm_log_warn (LOGD_DEVICE | LOGD_ETHER,
773 "Activation (%s/wired): association request to the supplicant failed: %s - %s",
774 nm_device_get_iface (NM_DEVICE (self)), name, message);
775
776 if (priv->supplicant.iface_con_error_cb_id)
777 g_source_remove (priv->supplicant.iface_con_error_cb_id);
778
779 id = g_idle_add (supplicant_iface_connection_error_cb_handler, self);
780 priv->supplicant.iface_con_error_cb_id = id;
781 }
782
783 static NMActStageReturn
784 handle_auth_or_fail (NMDeviceEthernet *self,
785 NMActRequest *req,
786 gboolean new_secrets)
787 {
788 const char *setting_name;
789 guint32 tries;
790 NMConnection *connection;
791
792 connection = nm_act_request_get_connection (req);
793 g_assert (connection);
794
795 tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRED_SECRETS_TRIES));
796 if (tries > 3)
797 return NM_ACT_STAGE_RETURN_FAILURE;
798
799 nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
800
801 nm_connection_clear_secrets (connection);
802 setting_name = nm_connection_need_secrets (connection, NULL);
803 if (setting_name) {
804 NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION;
805
806 /* If the caller doesn't necessarily want completely new secrets,
807 * only ask for new secrets after the first failure.
808 */
809 if (new_secrets || tries)
810 flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW;
811 nm_act_request_get_secrets (req, setting_name, flags, NULL, wired_secrets_cb, self);
812
813 g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries));
814 } else {
815 nm_log_info (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets.");
816 }
817
818 return NM_ACT_STAGE_RETURN_POSTPONE;
819 }
820
821 static gboolean
822 supplicant_connection_timeout_cb (gpointer user_data)
823 {
824 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
825 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
826 NMDevice *device = NM_DEVICE (self);
827 NMActRequest *req;
828 const char *iface;
829
830 priv->supplicant.con_timeout_id = 0;
831
832 iface = nm_device_get_iface (device);
833
834 /* Authentication failed, encryption key is probably bad */
835 nm_log_warn (LOGD_DEVICE | LOGD_ETHER,
836 "Activation (%s/wired): association took too long.", iface);
837
838 supplicant_interface_release (self);
839 req = nm_device_get_act_request (device);
840 g_assert (req);
841
842 if (handle_auth_or_fail (self, req, TRUE) == NM_ACT_STAGE_RETURN_POSTPONE) {
843 nm_log_info (LOGD_DEVICE | LOGD_ETHER,
844 "Activation (%s/wired): asking for new secrets", iface);
845 } else
846 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
847
848 return FALSE;
849 }
850
851 static gboolean
852 supplicant_interface_init (NMDeviceEthernet *self)
853 {
854 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
855 const char *iface;
856
857 iface = nm_device_get_iface (NM_DEVICE (self));
858
859 /* Create supplicant interface */
860 priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, iface, FALSE);
861 if (!priv->supplicant.iface) {
862 nm_log_err (LOGD_DEVICE | LOGD_ETHER,
863 "Couldn't initialize supplicant interface for %s.",
864 iface);
865 supplicant_interface_release (self);
866 return FALSE;
867 }
868
869 /* Listen for it's state signals */
870 priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface,
871 NM_SUPPLICANT_INTERFACE_STATE,
872 G_CALLBACK (supplicant_iface_state_cb),
873 self);
874
875 /* Hook up error signal handler to capture association errors */
876 priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface,
877 "connection-error",
878 G_CALLBACK (supplicant_iface_connection_error_cb),
879 self);
880
881 /* Set up a timeout on the connection attempt to fail it after 25 seconds */
882 priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
883
884 return TRUE;
885 }
886
887 static NMActStageReturn
888 act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
889 {
890 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
891 NMActRequest *req;
892 NMSettingWired *s_wired;
893 const GByteArray *cloned_mac;
894 NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
895
896 g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
897
898 ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason);
899 if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
900 req = nm_device_get_act_request (NM_DEVICE (self));
901 g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
902
903 s_wired = (NMSettingWired *) device_get_setting (dev, NM_TYPE_SETTING_WIRED);
904 if (s_wired) {
905 /* Set device MAC address if the connection wants to change it */
906 cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
907 if (cloned_mac && (cloned_mac->len == ETH_ALEN))
908 nm_device_set_hw_addr (dev, cloned_mac->data, "set", LOGD_ETHER);
909 }
910 }
911
912 return ret;
913 }
914
915 static NMActStageReturn
916 nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason)
917 {
918 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
919 NMConnection *connection;
920 NMSetting8021x *security;
921 const char *setting_name;
922 const char *iface;
923 NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
924
925 connection = nm_device_get_connection (NM_DEVICE (self));
926 g_assert (connection);
927 security = nm_connection_get_setting_802_1x (connection);
928 if (!security) {
929 nm_log_err (LOGD_DEVICE, "Invalid or missing 802.1X security");
930 *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
931 return ret;
932 }
933
934 if (!priv->supplicant.mgr)
935 priv->supplicant.mgr = nm_supplicant_manager_get ();
936
937 iface = nm_device_get_iface (NM_DEVICE (self));
938
939 /* If we need secrets, get them */
940 setting_name = nm_connection_need_secrets (connection, NULL);
941 if (setting_name) {
942 NMActRequest *req = nm_device_get_act_request (NM_DEVICE (self));
943
944 nm_log_info (LOGD_DEVICE | LOGD_ETHER,
945 "Activation (%s/wired): connection '%s' has security, but secrets are required.",
946 iface, nm_connection_get_id (connection));
947
948 ret = handle_auth_or_fail (self, req, FALSE);
949 if (ret != NM_ACT_STAGE_RETURN_POSTPONE)
950 *reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
951 } else {
952 nm_log_info (LOGD_DEVICE | LOGD_ETHER,
953 "Activation (%s/wired): connection '%s' requires no security. No secrets needed.",
954 iface, nm_connection_get_id (connection));
955
956 if (supplicant_interface_init (self))
957 ret = NM_ACT_STAGE_RETURN_POSTPONE;
958 else
959 *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
960 }
961
962 return ret;
963 }
964
965 /*****************************************************************************/
966 /* PPPoE */
967
968 static void
969 ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
970 {
971 NMDevice *device = NM_DEVICE (user_data);
972
973 switch (status) {
974 case NM_PPP_STATUS_DISCONNECT:
975 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
976 break;
977 case NM_PPP_STATUS_DEAD:
978 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
979 break;
980 default:
981 break;
982 }
983 }
984
985 static void
986 ppp_ip4_config (NMPPPManager *ppp_manager,
987 const char *iface,
988 NMIP4Config *config,
989 gpointer user_data)
990 {
991 NMDevice *device = NM_DEVICE (user_data);
992
993 /* Ignore PPP IP4 events that come in after initial configuration */
994 if (nm_device_activate_ip4_state_in_conf (device)) {
995 nm_device_set_ip_iface (device, iface);
996 nm_device_activate_schedule_ip4_config_result (device, config);
997 }
998 }
999
1000 static NMActStageReturn
1001 pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reason)
1002 {
1003 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
1004 NMConnection *connection;
1005 NMSettingPPPOE *s_pppoe;
1006 NMActRequest *req;
1007 GError *err = NULL;
1008 NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
1009
1010 req = nm_device_get_act_request (NM_DEVICE (self));
1011 g_assert (req);
1012
1013 connection = nm_act_request_get_connection (req);
1014 g_assert (req);
1015
1016 s_pppoe = nm_connection_get_setting_pppoe (connection);
1017 g_assert (s_pppoe);
1018
1019 priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self)));
1020 if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_pppoe_get_username (s_pppoe), 30, &err)) {
1021 g_signal_connect (priv->ppp_manager, "state-changed",
1022 G_CALLBACK (ppp_state_changed),
1023 self);
1024 g_signal_connect (priv->ppp_manager, "ip4-config",
1025 G_CALLBACK (ppp_ip4_config),
1026 self);
1027 ret = NM_ACT_STAGE_RETURN_POSTPONE;
1028 } else {
1029 nm_log_warn (LOGD_DEVICE, "(%s): PPPoE failed to start: %s",
1030 nm_device_get_iface (NM_DEVICE (self)), err->message);
1031 g_error_free (err);
1032
1033 g_object_unref (priv->ppp_manager);
1034 priv->ppp_manager = NULL;
1035
1036 *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
1037 }
1038
1039 return ret;
1040 }
1041
1042 static NMActStageReturn
1043 act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
1044 {
1045 NMSettingConnection *s_con;
1046 const char *connection_type;
1047 NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
1048
1049 g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
1050
1051 s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION));
1052 g_assert (s_con);
1053
1054 /* 802.1x has to run before any IP configuration since the 802.1x auth
1055 * process opens the port up for normal traffic.
1056 */
1057 connection_type = nm_setting_connection_get_connection_type (s_con);
1058 if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
1059 NMSetting8021x *security;
1060
1061 security = (NMSetting8021x *) device_get_setting (device, NM_TYPE_SETTING_802_1X);
1062 if (security)
1063 ret = nm_8021x_stage2_config (NM_DEVICE_ETHERNET (device), reason);
1064 }
1065
1066 return ret;
1067 }
1068
1069 static NMActStageReturn
1070 act_stage3_ip4_config_start (NMDevice *device,
1071 NMIP4Config **out_config,
1072 NMDeviceStateReason *reason)
1073 {
1074 NMSettingConnection *s_con;
1075 const char *connection_type;
1076
1077 g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
1078
1079 s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION));
1080 g_assert (s_con);
1081
1082 connection_type = nm_setting_connection_get_connection_type (s_con);
1083 if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME))
1084 return pppoe_stage3_ip4_config_start (NM_DEVICE_ETHERNET (device), reason);
1085
1086 return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage3_ip4_config_start (device, out_config, reason);
1087 }
1088
1089 static void
1090 ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
1091 {
1092 NMConnection *connection;
1093 NMSettingWired *s_wired;
1094 guint32 mtu;
1095
1096 /* MTU only set for plain ethernet */
1097 if (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->ppp_manager)
1098 return;
1099
1100 connection = nm_device_get_connection (device);
1101 g_assert (connection);
1102 s_wired = nm_connection_get_setting_wired (connection);
1103 g_assert (s_wired);
1104
1105 /* MTU override */
1106 mtu = nm_setting_wired_get_mtu (s_wired);
1107 if (mtu)
1108 nm_ip4_config_set_mtu (config, mtu);
1109 }
1110
1111 static void
1112 deactivate (NMDevice *device)
1113 {
1114 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
1115 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
1116
1117 /* Clear wired secrets tries when deactivating */
1118 clear_secrets_tries (device);
1119
1120 if (priv->pending_ip4_config) {
1121 g_object_unref (priv->pending_ip4_config);
1122 priv->pending_ip4_config = NULL;
1123 }
1124
1125 if (priv->ppp_manager) {
1126 g_object_unref (priv->ppp_manager);
1127 priv->ppp_manager = NULL;
1128 }
1129
1130 supplicant_interface_release (self);
1131
1132 /* Reset MAC address back to initial address */
1133 nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_ETHER);
1134 }
1135
1136 static gboolean
1137 complete_connection (NMDevice *device,
1138 NMConnection *connection,
1139 const char *specific_object,
1140 const GSList *existing_connections,
1141 GError **error)
1142 {
1143 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
1144 NMSettingWired *s_wired;
1145 NMSettingPPPOE *s_pppoe;
1146 const GByteArray *setting_mac;
1147
1148 s_pppoe = nm_connection_get_setting_pppoe (connection);
1149
1150 /* We can't telepathically figure out the service name or username, so if
1151 * those weren't given, we can't complete the connection.
1152 */
1153 if (s_pppoe && !nm_setting_verify (NM_SETTING (s_pppoe), NULL, error))
1154 return FALSE;
1155
1156 /* Default to an ethernet-only connection, but if a PPPoE setting was given
1157 * then PPPoE should be our connection type.
1158 */
1159 nm_utils_complete_generic (connection,
1160 s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME,
1161 existing_connections,
1162 s_pppoe ? _("PPPoE connection %d") : _("Wired connection %d"),
1163 NULL,
1164 s_pppoe ? FALSE : TRUE); /* No IPv6 by default yet for PPPoE */
1165
1166 s_wired = nm_connection_get_setting_wired (connection);
1167 if (!s_wired) {
1168 s_wired = (NMSettingWired *) nm_setting_wired_new ();
1169 nm_connection_add_setting (connection, NM_SETTING (s_wired));
1170 }
1171
1172 setting_mac = nm_setting_wired_get_mac_address (s_wired);
1173 if (setting_mac) {
1174 /* Make sure the setting MAC (if any) matches the device's permanent MAC */
1175 if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) {
1176 g_set_error_literal (error,
1177 NM_SETTING_WIRED_ERROR,
1178 NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
1179 NM_SETTING_WIRED_MAC_ADDRESS);
1180 return FALSE;
1181 }
1182 } else {
1183 GByteArray *mac;
1184 const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
1185
1186 /* Lock the connection to this device by default */
1187 if (memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) {
1188 mac = g_byte_array_sized_new (ETH_ALEN);
1189 g_byte_array_append (mac, priv->perm_hw_addr, ETH_ALEN);
1190 g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
1191 g_byte_array_free (mac, TRUE);
1192 }
1193 }
1194
1195 return TRUE;
1196 }
1197
1198 static gboolean
1199 spec_match_list (NMDevice *device, const GSList *specs)
1200 {
1201 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
1202
1203 if (priv->subchannels && nm_match_spec_s390_subchannels (specs, priv->subchannels))
1204 return TRUE;
1205
1206 return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
1207 }
1208
1209 static void
1210 update_connection (NMDevice *device, NMConnection *connection)
1211 {
1212 NMSettingWired *s_wired = nm_connection_get_setting_wired (connection);
1213 guint maclen;
1214 gconstpointer mac = nm_device_get_hw_address (device, &maclen);
1215
1216 if (!s_wired) {
1217 s_wired = (NMSettingWired *) nm_setting_wired_new ();
1218 nm_connection_add_setting (connection, (NMSetting *) s_wired);
1219 }
1220
1221 if (mac && maclen == 6) {
1222 GBytes *address = g_bytes_new (mac, maclen);
1223
1224 g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, address, NULL);
1225 }
1226
1227 /* We don't set the MTU as we don't know whether it was set explicitly */
1228 }
1229
1230 static void
1231 get_link_speed (NMDevice *device)
1232 {
1233 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
1234 struct ifreq ifr;
1235 struct ethtool_cmd edata = {
1236 .cmd = ETHTOOL_GSET,
1237 };
1238 guint32 speed;
1239 int fd;
1240
1241 fd = socket (PF_INET, SOCK_DGRAM, 0);
1242 if (fd < 0) {
1243 nm_log_warn (LOGD_HW | LOGD_ETHER, "couldn't open ethtool control socket.");
1244 return;
1245 }
1246
1247 memset (&ifr, 0, sizeof (struct ifreq));
1248 strncpy (ifr.ifr_name, nm_device_get_iface (device), IFNAMSIZ);
1249 ifr.ifr_data = (char *) &edata;
1250
1251 if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) {
1252 close (fd);
1253 return;
1254 }
1255 close (fd);
1256
1257 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
1258 speed = edata.speed;
1259 #else
1260 speed = ethtool_cmd_speed (&edata);
1261 #endif
1262 if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
1263 speed = 0;
1264
1265 if (priv->speed == speed)
1266 return;
1267
1268 priv->speed = speed;
1269 g_object_notify (G_OBJECT (device), "speed");
1270
1271 nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): speed is now %d Mb/s",
1272 nm_device_get_iface (device), speed);
1273 }
1274
1275 static void
1276 carrier_changed (NMDevice *device, gboolean carrier)
1277 {
1278 if (carrier)
1279 get_link_speed (device);
1280
1281 NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->carrier_changed (device, carrier);
1282 }
1283
1284 static void
1285 dispose (GObject *object)
1286 {
1287 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
1288 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
1289
1290 g_clear_object (&priv->supplicant.mgr);
1291 g_free (priv->subchan1);
1292 g_free (priv->subchan2);
1293 g_free (priv->subchan3);
1294 g_free (priv->subchannels);
1295
1296 G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
1297 }
1298
1299 static void
1300 get_property (GObject *object, guint prop_id,
1301 GValue *value, GParamSpec *pspec)
1302 {
1303 NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
1304 NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
1305
1306 switch (prop_id) {
1307 case PROP_PERM_HW_ADDRESS:
1308 g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
1309 break;
1310 case PROP_SPEED:
1311 g_value_set_uint (value, priv->speed);
1312 break;
1313 default:
1314 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1315 break;
1316 }
1317 }
1318
1319 static void
1320 set_property (GObject *object, guint prop_id,
1321 const GValue *value, GParamSpec *pspec)
1322 {
1323 switch (prop_id) {
1324 default:
1325 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1326 break;
1327 }
1328 }
1329
1330 static void
1331 nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
1332 {
1333 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1334 NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
1335
1336 g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate));
1337
1338 parent_class->connection_type = NM_SETTING_WIRED_SETTING_NAME;
1339
1340 /* virtual methods */
1341 object_class->constructor = constructor;
1342 object_class->dispose = dispose;
1343 object_class->get_property = get_property;
1344 object_class->set_property = set_property;
1345
1346 parent_class->get_generic_capabilities = get_generic_capabilities;
1347 parent_class->update_permanent_hw_address = update_permanent_hw_address;
1348 parent_class->update_initial_hw_address = update_initial_hw_address;
1349 parent_class->check_connection_compatible = check_connection_compatible;
1350 parent_class->complete_connection = complete_connection;
1351
1352 parent_class->act_stage1_prepare = act_stage1_prepare;
1353 parent_class->act_stage2_config = act_stage2_config;
1354 parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
1355 parent_class->ip4_config_pre_commit = ip4_config_pre_commit;
1356 parent_class->deactivate = deactivate;
1357 parent_class->spec_match_list = spec_match_list;
1358 parent_class->update_connection = update_connection;
1359 parent_class->carrier_changed = carrier_changed;
1360
1361 parent_class->state_changed = device_state_changed;
1362
1363 /* properties */
1364 g_object_class_install_property
1365 (object_class, PROP_PERM_HW_ADDRESS,
1366 g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS,
1367 "Permanent MAC Address",
1368 "Permanent hardware MAC address",
1369 NULL,
1370 G_PARAM_READABLE));
1371
1372 g_object_class_install_property
1373 (object_class, PROP_SPEED,
1374 g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED,
1375 "Speed",
1376 "Speed",
1377 0, G_MAXUINT32, 0,
1378 G_PARAM_READABLE));
1379
1380 nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
1381 G_TYPE_FROM_CLASS (klass),
1382 &dbus_glib_nm_device_ethernet_object_info);
1383
1384 dbus_g_error_domain_register (NM_ETHERNET_ERROR, NULL, NM_TYPE_ETHERNET_ERROR);
1385 }
1386