diff options
Diffstat (limited to 'src/devices/nm-device-ethernet.c')
| -rw-r--r-- | src/devices/nm-device-ethernet.c | 256 |
1 files changed, 87 insertions, 169 deletions
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index ac408d3d..af2cb8f2 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -26,10 +26,6 @@ #include <netinet/in.h> #include <string.h> #include <stdlib.h> -#include <linux/sockios.h> -#include <linux/ethtool.h> -#include <linux/version.h> -#include <sys/ioctl.h> #include <unistd.h> #include <errno.h> @@ -48,6 +44,7 @@ #include "nm-enum-types.h" #include "nm-dbus-manager.h" #include "nm-platform.h" +#include "nm-platform-utils.h" #include "nm-dcb.h" #include "nm-settings-connection.h" #include "nm-config.h" @@ -55,6 +52,7 @@ #include "nm-connection-provider.h" #include "nm-device-factory.h" #include "nm-core-internal.h" +#include "NetworkManagerUtils.h" #include "nm-device-ethernet-glue.h" @@ -99,9 +97,6 @@ typedef enum { } DcbWait; typedef struct { - char * perm_hw_addr; /* Permanent MAC address */ - char * initial_hw_addr; /* Initial MAC address (as seen when NM starts) */ - guint32 speed; Supplicant supplicant; @@ -156,26 +151,21 @@ static void _update_s390_subchannels (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - GUdevClient *client; GUdevDevice *dev; GUdevDevice *parent = NULL; const char *parent_path, *item, *driver; - const char *subsystems[] = { "net", NULL }; + int ifindex; GDir *dir; GError *error = NULL; - client = g_udev_client_new (subsystems); - if (!client) { - _LOGW (LOGD_DEVICE | LOGD_HW, "failed to initialize GUdev client"); - return; - } - - dev = g_udev_client_query_by_subsystem_and_name (client, "net", - nm_device_get_iface (NM_DEVICE (self))); + ifindex = nm_device_get_ifindex (NM_DEVICE (self)); + dev = (GUdevDevice *) nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex); if (!dev) { - _LOGW (LOGD_DEVICE | LOGD_HW, "failed to find device with udev"); + _LOGW (LOGD_DEVICE | LOGD_HW, "failed to find device %d '%s' with udev", + ifindex, str_if_set (nm_device_get_iface (NM_DEVICE (self)), "(null)")); goto out; } + g_object_ref (dev); /* Try for the "ccwgroup" parent */ parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL); @@ -210,7 +200,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) || !strcmp (item, "portno")) { char *path, *value; path = g_strdup_printf ("%s/%s", parent_path, item); - value = nm_platform_sysctl_get (path); + value = nm_platform_sysctl_get (NM_PLATFORM_GET, path); if (value && *value) g_hash_table_insert (priv->s390_options, g_strdup (item), g_strdup (value)); else @@ -247,7 +237,6 @@ out: g_object_unref (parent); if (dev) g_object_unref (dev); - g_object_unref (client); } static GObject* @@ -263,7 +252,7 @@ constructor (GType type, if (object) { #ifndef G_DISABLE_ASSERT int ifindex = nm_device_get_ifindex (NM_DEVICE (object)); - NMLinkType link_type = nm_platform_link_get_type (ifindex); + NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex); g_assert ( link_type == NM_LINK_TYPE_ETHERNET || link_type == NM_LINK_TYPE_VETH @@ -310,72 +299,12 @@ nm_device_ethernet_init (NMDeviceEthernet *self) priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } -static void -update_permanent_hw_address (NMDevice *dev) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - struct ifreq req; - struct ethtool_perm_addr *epaddr = NULL; - int fd, ret, errsv; - const char *mac; - - g_return_if_fail (priv->perm_hw_addr == NULL); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - _LOGW (LOGD_HW, "couldn't open control socket."); - return; - } - - /* Get permanent MAC address */ - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); - - epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); - epaddr->cmd = ETHTOOL_GPERMADDR; - epaddr->size = ETH_ALEN; - req.ifr_data = (void *) epaddr; - - errno = 0; - ret = ioctl (fd, SIOCETHTOOL, &req); - errsv = errno; - if ((ret < 0) || !nm_ethernet_address_is_valid (epaddr->data, ETH_ALEN)) { - _LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address (error %d)", errsv); - /* Fall back to current address */ - mac = nm_device_get_hw_address (dev); - if (mac) - nm_utils_hwaddr_aton (mac, epaddr->data, ETH_ALEN); - else - memset (epaddr->data, 0, ETH_ALEN); - } - - priv->perm_hw_addr = nm_utils_hwaddr_ntoa (epaddr->data, ETH_ALEN); - - g_free (epaddr); - close (fd); -} - -static void -update_initial_hw_address (NMDevice *dev) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - /* This sets initial MAC address from current MAC address. It should only - * be called from NMDevice constructor() to really get the initial address. - */ - priv->initial_hw_addr = g_strdup (nm_device_get_hw_address (dev)); - - _LOGD (LOGD_DEVICE | LOGD_ETHER, "read initial MAC address %s", priv->initial_hw_addr); -} - -static guint32 +static NMDeviceCapabilities get_generic_capabilities (NMDevice *device) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - if (nm_platform_link_supports_carrier_detect (nm_device_get_ifindex (device))) + if (nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, nm_device_get_ifindex (device))) return NM_DEVICE_CAP_CARRIER_DETECT; else { _LOGI (LOGD_HW, "driver '%s' does not support carrier detection.", @@ -421,7 +350,6 @@ static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMSettingWired *s_wired; if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->check_connection_compatible (device, connection)) @@ -438,7 +366,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return FALSE; if (s_wired) { - const char *mac; + const char *mac, *perm_hw_addr; gboolean try_mac = TRUE; const char * const *mac_blacklist; int i; @@ -446,21 +374,25 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!match_subchans (self, s_wired, &try_mac)) return FALSE; + perm_hw_addr = nm_device_get_permanent_hw_address (device); mac = nm_setting_wired_get_mac_address (s_wired); - if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, priv->perm_hw_addr, -1)) - return FALSE; - - /* Check for MAC address blacklist */ - mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); - for (i = 0; mac_blacklist[i]; i++) { - if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) { - g_warn_if_reached (); + if (perm_hw_addr) { + if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) return FALSE; - } - if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, priv->perm_hw_addr, -1)) - return FALSE; - } + /* Check for MAC address blacklist */ + mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); + for (i = 0; mac_blacklist[i]; i++) { + if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) { + g_warn_if_reached (); + return FALSE; + } + + if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_hw_addr, -1)) + return FALSE; + } + } else if (mac) + return FALSE; } return TRUE; @@ -1160,7 +1092,7 @@ dcb_state (NMDevice *device, gboolean timeout) g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG); - carrier = nm_platform_link_is_connected (nm_device_get_ifindex (device)); + carrier = nm_platform_link_is_connected (NM_PLATFORM_GET, nm_device_get_ifindex (device)); _LOGD (LOGD_DCB, "dcb_state() wait %d carrier %d timeout %d", priv->dcb_wait, carrier, timeout); switch (priv->dcb_wait) { @@ -1278,7 +1210,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); if (s_dcb) { /* lldpad really really wants the carrier to be up */ - if (nm_platform_link_is_connected (nm_device_get_ifindex (device))) { + if (nm_platform_link_is_connected (NM_PLATFORM_GET, nm_device_get_ifindex (device))) { if (!dcb_enable (device)) { *reason = NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; @@ -1391,8 +1323,8 @@ deactivate (NMDevice *device) NM_DEVICE_ETHERNET_GET_PRIVATE (device)->last_pppoe_time = nm_utils_get_monotonic_timestamp_s (); /* Reset MAC address back to initial address */ - if (priv->initial_hw_addr) - nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_ETHER); + if (nm_device_get_initial_hw_address (device)) + nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_ETHER); } static gboolean @@ -1402,10 +1334,10 @@ complete_connection (NMDevice *device, const GSList *existing_connections, GError **error) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); NMSettingWired *s_wired; NMSettingPppoe *s_pppoe; const char *setting_mac; + const char *perm_hw_addr; s_pppoe = nm_connection_get_setting_pppoe (connection); @@ -1432,21 +1364,22 @@ complete_connection (NMDevice *device, nm_connection_add_setting (connection, NM_SETTING (s_wired)); } - setting_mac = nm_setting_wired_get_mac_address (s_wired); - if (setting_mac) { - /* Make sure the setting MAC (if any) matches the device's permanent MAC */ - if (!nm_utils_hwaddr_matches (setting_mac, -1, priv->perm_hw_addr, -1)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("connection does not match device")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS); - return FALSE; - } - } else { - if (!nm_utils_hwaddr_matches (priv->perm_hw_addr, -1, NULL, ETH_ALEN)) { + perm_hw_addr = nm_device_get_permanent_hw_address (device); + if (perm_hw_addr) { + setting_mac = nm_setting_wired_get_mac_address (s_wired); + if (setting_mac) { + /* Make sure the setting MAC (if any) matches the device's permanent MAC */ + if (!nm_utils_hwaddr_matches (setting_mac, -1, perm_hw_addr, -1)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("connection does not match device")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS); + return FALSE; + } + } else { g_object_set (G_OBJECT (s_wired), - NM_SETTING_WIRED_MAC_ADDRESS, priv->perm_hw_addr, + NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL); } } @@ -1463,7 +1396,7 @@ new_default_connection (NMDevice *self) const char *hw_address; char *defname, *uuid; - if (!nm_config_get_ethernet_can_auto_default (nm_config_get (), self)) + if (nm_config_get_no_auto_default_for_device (nm_config_get (), self)) return NULL; hw_address = nm_device_get_hw_address (self); @@ -1495,15 +1428,19 @@ new_default_connection (NMDevice *self) return connection; } -static gboolean +static NMMatchSpecMatchType spec_match_list (NMDevice *device, const GSList *specs) { + NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m; NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - if (priv->subchannels && nm_match_spec_s390_subchannels (specs, priv->subchannels)) - return TRUE; - - return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs); + if (priv->subchannels) + matched = nm_match_spec_s390_subchannels (specs, priv->subchannels); + if (matched != NM_MATCH_SPEC_NEG_MATCH) { + m = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs); + matched = MAX (matched, m); + } + return matched; } static void @@ -1511,6 +1448,7 @@ update_connection (NMDevice *device, NMConnection *connection) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); NMSettingWired *s_wired = nm_connection_get_setting_wired (connection); + const char *perm_hw_addr = nm_device_get_permanent_hw_address (device); const char *mac = nm_device_get_hw_address (device); const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; GHashTableIter iter; @@ -1524,11 +1462,11 @@ update_connection (NMDevice *device, NMConnection *connection) /* If the device reports a permanent address, use that for the MAC address * and the current MAC, if different, is the cloned MAC. */ - if (!nm_utils_hwaddr_matches (priv->perm_hw_addr, -1, NULL, ETH_ALEN)) { - g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, priv->perm_hw_addr, NULL); + if (perm_hw_addr) { + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL); mac_prop = NULL; - if (mac && !nm_utils_hwaddr_matches (priv->perm_hw_addr, -1, mac, -1)) + if (mac && !nm_utils_hwaddr_matches (perm_hw_addr, -1, mac, -1)) mac_prop = NM_SETTING_WIRED_CLONED_MAC_ADDRESS; } @@ -1562,37 +1500,10 @@ get_link_speed (NMDevice *device) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - struct ifreq ifr; - struct ethtool_cmd edata = { - .cmd = ETHTOOL_GSET, - }; guint32 speed; - int fd; - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - _LOGW (LOGD_HW | LOGD_ETHER, "couldn't open ethtool control socket."); + if (!nmp_utils_ethtool_get_link_speed (nm_device_get_iface (device), &speed)) return; - } - - memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, nm_device_get_iface (device), IFNAMSIZ); - ifr.ifr_data = (char *) &edata; - - if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { - close (fd); - return; - } - close (fd); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - speed = edata.speed; -#else - speed = ethtool_cmd_speed (&edata); -#endif - if (speed == G_MAXUINT16 || speed == G_MAXUINT32) - speed = 0; - if (priv->speed == speed) return; @@ -1612,6 +1523,17 @@ carrier_changed (NMDevice *device, gboolean carrier) } static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->link_changed (device, info); + if (!priv->subchan1 && info->initialized) + _update_s390_subchannels (self); +} + +static void dispose (GObject *object) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); @@ -1634,8 +1556,6 @@ finalize (GObject *object) NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - g_free (priv->perm_hw_addr); - g_free (priv->initial_hw_addr); g_clear_object (&priv->supplicant.mgr); g_free (priv->subchan1); g_free (priv->subchan2); @@ -1656,7 +1576,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PERM_HW_ADDRESS: - g_value_set_string (value, priv->perm_hw_addr); + g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (object))); break; case PROP_SPEED: g_value_set_uint (value, priv->speed); @@ -1696,8 +1616,6 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) object_class->set_property = set_property; parent_class->get_generic_capabilities = get_generic_capabilities; - parent_class->update_permanent_hw_address = update_permanent_hw_address; - parent_class->update_initial_hw_address = update_initial_hw_address; parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; parent_class->new_default_connection = new_default_connection; @@ -1710,6 +1628,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->spec_match_list = spec_match_list; parent_class->update_connection = update_connection; parent_class->carrier_changed = carrier_changed; + parent_class->link_changed = link_changed; parent_class->state_changed = device_state_changed; @@ -1739,19 +1658,18 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) #define NM_ETHERNET_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ETHERNET_FACTORY, NMEthernetFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error) +new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) { - if (plink->type == NM_LINK_TYPE_ETHERNET) { - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_TYPE_DESC, "Ethernet", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, - NULL); - } - return NULL; + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET, + NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_TYPE_DESC, "Ethernet", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, + NULL); } -DEFINE_DEVICE_FACTORY_INTERNAL(ETHERNET, Ethernet, ethernet, \ - factory_iface->new_link = new_link; \ +NM_DEVICE_FACTORY_DEFINE_INTERNAL (ETHERNET, Ethernet, ethernet, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_ETHERNET) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME), + factory_iface->new_link = new_link; ) |