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