NetworkManager/src/core/devices/nm-device-ethernet.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2128 lines
79 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2005 - 2014 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
#include "src/core/nm-default-daemon.h"
#include "nm-device-ethernet.h"
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <libudev.h>
#include <linux/if_ether.h>
#include "NetworkManagerUtils.h"
#include "NetworkManagerUtils.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-glib-aux/nm-uuid.h"
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-udev-aux/nm-udev-utils.h"
#include "nm-act-request.h"
#include "nm-config.h"
#include "nm-dcb.h"
#include "nm-device-ethernet-utils.h"
#include "nm-device-factory.h"
#include "nm-device-private.h"
#include "nm-device-veth.h"
#include "nm-manager.h"
#include "ppp/nm-ppp-mgr.h"
#include "settings/nm-settings-connection.h"
#include "settings/nm-settings.h"
#include "supplicant/nm-supplicant-config.h"
#include "supplicant/nm-supplicant-interface.h"
#include "supplicant/nm-supplicant-manager.h"
#define _NMLOG_DEVICE_TYPE NMDeviceEthernet
#include "nm-device-logging.h"
/*****************************************************************************/
#define PPPOE_RECONNECT_DELAY_MSEC 7000
#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
#define SUPPLICANT_LNK_TIMEOUT_SEC 15
/*****************************************************************************/
typedef enum {
DCB_WAIT_UNKNOWN = 0,
/* Ensure carrier is up before enabling DCB */
DCB_WAIT_CARRIER_PREENABLE_UP,
/* Wait for carrier down when device starts enabling */
DCB_WAIT_CARRIER_PRECONFIG_DOWN,
/* Wait for carrier up when device has finished enabling */
DCB_WAIT_CARRIER_PRECONFIG_UP,
/* Wait carrier down when device starts configuring */
DCB_WAIT_CARRIER_POSTCONFIG_DOWN,
/* Wait carrier up when device has finished configuring */
DCB_WAIT_CARRIER_POSTCONFIG_UP,
} DcbWait;
typedef struct _NMDeviceEthernetPrivate {
/* s390 */
char * subchan1;
char * subchan2;
char * subchan3;
char * subchannels; /* Composite used for checking unmanaged specs */
char ** subchannels_dbus; /* Array exported on D-Bus */
char * s390_nettype;
GHashTable *s390_options;
guint32 speed;
gulong carrier_id;
struct {
NMSupplicantManager * mgr;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
NMSupplMgrCreateIfaceHandle *create_handle;
NMSupplicantInterface * iface;
gulong iface_state_id;
gulong auth_state_id;
guint con_timeout_id;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
guint lnk_timeout_id;
bool is_associated : 1;
bool ready : 1;
} supplicant;
NMActRequestGetSecretsCallId *wired_secrets_id;
struct {
NMPppMgr *ppp_mgr;
GSource * wait_source;
gint64 last_pppoe_time_msec;
} ppp_data;
/* DCB */
DcbWait dcb_wait;
guint dcb_timeout_id;
guint32 ethtool_prev_speed;
NMPlatformLinkDuplexType ethtool_prev_duplex : 3;
bool dcb_handle_carrier_changes : 1;
bool ethtool_prev_set : 1;
bool ethtool_prev_autoneg : 1;
bool stage2_ready_dcb : 1;
} NMDeviceEthernetPrivate;
NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceEthernet, PROP_SPEED, PROP_S390_SUBCHANNELS, );
/*****************************************************************************/
G_DEFINE_TYPE(NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
#define NM_DEVICE_ETHERNET_GET_PRIVATE(self) \
_NM_GET_PRIVATE_PTR(self, NMDeviceEthernet, NM_IS_DEVICE_ETHERNET, NMDevice)
/*****************************************************************************/
2008-03-12 Dan Williams <dcbw@redhat.com> Move the 'carrier' property from NMDevice to NMDevice8023Ethernet; convert the libnm-glib NMDevice8023Ethernet to cached properties * introspection/nm-device-802-3-ethernet.xml - New 'Carrier' property - New 'PropertiesChanged' signal * introspection/nm-device.xml - Remove 'Carrier' property - Remove 'CarrierChanged' signal * src/nm-device-interface.c src/nm-device-interface.h - (nm_device_interface_init): remove 'carrier' property and 'carrier-changed' signal * src/nm-device.c src/nm-device.h - (nm_device_get_carrier, nm_device_set_carrier): remove - (nm_device_activate_stage5_ip_config_commit): don't bother updating the link here; wired device will handle that - (handle_dhcp_lease_change): don't bother updating link here - (get_property, nm_device_class_init): remove carrier property * src/nm-device-802-11-wireless.c - (real_update_link, nm_device_802_11_wireless_class_init): remove real_update_link(); wireless devices don't use carrier at all - (link_timeout_cb, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler, supplicant_mgr_state_cb_handler): remove anything to do with carrier * src/nm-device-802-3-ethernet.c src/nm-device-802-3-ethernet.h - (nm_device_802_3_ethernet_carrier_on, nm_device_802_3_ethernet_carrier_off, constructor): use set_carrier() instead of nm_device_set_carrier() - (device_state_changed): update link from sysfs on activation; replaces real_update_link() - (real_update_link): remove, replaced by device_state_changed() - (nm_device_802_3_ethernet_get_carrier, set_carrier): new functions - (nm_device_802_3_ethernet_get_speed): move up with other getters/setters - (real_get_generic_capabilities, real_can_interrupt_activation): use new get_carrier function - (get_property): add 'carrier' property - (nm_device_802_3_ethernet_class_init): add 'carrier' property and hook into property-changed signal helper * src/NetworkManagerPolicy.c - (device_carrier_changed): will only ever be called with a wired device - (device_added): only hook up to carrier-changed for wired devices * libnm-glib/nm-device.c libnm-glib/nm-device.h - (constructor, nm_device_class_init): remove carrier-changed signal - (device_carrier_changed_proxy): remove; unused - (nm_device_get_carrier): remove; carrier a property of wired devices * libnm-glib/nm-device-802-3-ethernet.c libnm-glib/nm-device-802-3-ethernet.h - Convert to cached properties like AP and Wireless objects - (nm_device_802_3_ethernet_get_hw_address): now returns a 'const char *' instead of a 'char *', return value should not be freed - (nm_device_802_3_ethernet_get_carrier): return current carrier status - (constructor): hook into properties-changed helper - (set_property, get_property): new functions - (nm_device_802_3_ethernet_class_init): export GObject properties * test/nm-tool.c - (detail_device): strdup the wired hardware address too since it's cached now * libnm-glib/libnm-glib-test.c - (dump_wired): strdup the wired hardware address too since it's cached now git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3428 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-03-12 16:12:39 +00:00
static void wired_secrets_cancel(NMDeviceEthernet *self);
/*****************************************************************************/
static char *
get_link_basename(const char *parent_path, const char *name, GError **error)
{
char *link_dest, *path;
char *result = NULL;
path = g_strdup_printf("%s/%s", parent_path, name);
link_dest = g_file_read_link(path, error);
if (link_dest) {
result = g_path_get_basename(link_dest);
g_free(link_dest);
}
g_free(path);
return result;
}
static void
_update_s390_subchannels(NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
struct udev_device * dev = NULL;
struct udev_device * parent = NULL;
const char * parent_path, *item;
int ifindex;
GDir * dir;
GError * error = NULL;
if (priv->subchannels) {
/* only read the subchannels once. For one, we don't expect them to change
* on multiple invocations. Second, we didn't implement proper reloading.
* Proper reloading might also be complicated, because the subchannels are
* used to match on devices based on a device-spec. Thus, it's not clear
* what it means to change afterwards. */
return;
}
ifindex = nm_device_get_ifindex((NMDevice *) self);
dev = nm_platform_link_get_udev_device(nm_device_get_platform(NM_DEVICE(self)), ifindex);
if (!dev)
return;
/* Try for the "ccwgroup" parent */
parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccwgroup", NULL);
if (!parent) {
/* FIXME: whatever 'lcs' devices' subsystem is here... */
/* Not an s390 device */
return;
}
parent_path = udev_device_get_syspath(parent);
dir = g_dir_open(parent_path, 0, &error);
if (!dir) {
_LOGW(LOGD_DEVICE | LOGD_PLATFORM,
"update-s390: failed to open directory '%s': %s",
parent_path,
error->message);
g_clear_error(&error);
return;
}
while ((item = g_dir_read_name(dir))) {
if (!strcmp(item, "cdev0")) {
priv->subchan1 = get_link_basename(parent_path, "cdev0", &error);
} else if (!strcmp(item, "cdev1")) {
priv->subchan2 = get_link_basename(parent_path, "cdev1", &error);
} else if (!strcmp(item, "cdev2")) {
priv->subchan3 = get_link_basename(parent_path, "cdev2", &error);
} else if (!strcmp(item, "driver")) {
priv->s390_nettype = get_link_basename(parent_path, "driver", &error);
} else if (!strcmp(item, "layer2") || !strcmp(item, "portname")
|| !strcmp(item, "portno")) {
gs_free char *path = NULL, *value = NULL;
path = g_strdup_printf("%s/%s", parent_path, item);
value = nm_platform_sysctl_get(nm_device_get_platform(NM_DEVICE(self)),
NMP_SYSCTL_PATHID_ABSOLUTE(path));
if (!strcmp(item, "portname") && !g_strcmp0(value, "no portname required")) {
/* Do nothing */
} else if (value && *value) {
g_hash_table_insert(priv->s390_options, g_strdup(item), value);
value = NULL;
} else
_LOGW(LOGD_DEVICE | LOGD_PLATFORM, "update-s390: error reading %s", path);
}
if (error) {
_LOGW(LOGD_DEVICE | LOGD_PLATFORM,
"update-s390: failed reading sysfs for %s (%s)",
item,
error->message);
g_clear_error(&error);
}
}
g_dir_close(dir);
if (priv->subchan3) {
priv->subchannels =
g_strdup_printf("%s,%s,%s", priv->subchan1, priv->subchan2, priv->subchan3);
} else if (priv->subchan2) {
priv->subchannels = g_strdup_printf("%s,%s", priv->subchan1, priv->subchan2);
} else
priv->subchannels = g_strdup(priv->subchan1);
priv->subchannels_dbus = g_new(char *, 3 + 1);
priv->subchannels_dbus[0] = g_strdup(priv->subchan1);
priv->subchannels_dbus[1] = g_strdup(priv->subchan2);
priv->subchannels_dbus[2] = g_strdup(priv->subchan3);
priv->subchannels_dbus[3] = NULL;
_LOGI(LOGD_DEVICE | LOGD_PLATFORM,
"update-s390: found s390 '%s' subchannels [%s]",
nm_device_get_driver((NMDevice *) self) ?: "(unknown driver)",
priv->subchannels);
_notify(self, PROP_S390_SUBCHANNELS);
}
static void
device_state_changed(NMDevice * device,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason)
{
if (new_state > NM_DEVICE_STATE_ACTIVATED)
wired_secrets_cancel(NM_DEVICE_ETHERNET(device));
}
2006-03-05 Dan Williams <dcbw@redhat.com> Process netlink messages in device subclasses rather than in NetworkManager.c. Also add support for recognizing Wireless Events. * configure.in - Find GLIB_GENMARSHAL * src/Makefile.am - Since we're marshalling custom types for wireless event signals, we get to create our own marshallers using GLIB_GENMARSHAL * src/NetworkManager.c - (nm_monitor_wired_link_state): renamed to nm_monitor_setup - (nm_monitor_setup): renamed from nm_monitor_wired_link_state, and cut down somewhat. We no longer process signals here. - (nm_data_new): create the netlink monitor here, and remove a useless call to nm_policy_schedule_device_change_check() - (nm_data_free): get rid of the netlink monitor here - (nm_device_link_activated, nm_device_link_deactivated): removed - (main): don't create the netlink monitor here, let nm_data_new do that. Call nm_policy_schedule_device_change_check() right before we jump to the mainloop to figure out which device to use first * src/NetworkManagerSystem.[ch] - (nm_system_get_rtnl_index_from_iface, nm_system_get_iface_from_rtnl_index): convert back and forth from interface names to interface indexes * src/nm-device-802-11-wireless.c - (real_init): connect to wireless-event signals from the netlink monitor object - (nm_device_802_11_wireless_event): new function, schedule handler for wireless event signals from the netlink monitor object. We want the handler to run in the device's context - (wireless_event_helper): handle wireless-event signals from netlink - (nm_device_802_11_wireless_dispose): disconnect wireless-event signal handler * src/nm-device-802-11-wireless.h - remove unused prototype for nm_device_802_11_wireless_new * src/nm-device-802-3-ethernet.c - (real_init): new function; set up signal handlers for link events - (nm_device_802_3_ethernet_link_activated): new function, schedule handler for netlink link activated events on device's main loop - (link_activated_helper): when we get a link activated event, set the device's link to be active - (nm_device_802_3_ethernet_link_deactivated): new function; schedule handler for netlink link deactivated events on device's main loop - (link_deactivated_helper): when we get a link deactivated event, set the device's link to be inactive - (nm_device_802_3_ethernet_dispose): disconnect signal handler on dispose * src/nm-device-802-3-ethernet.h - remove unused prototype for nm_device_802_3_ethernet_new * src/nm-device.[ch] - (nm_get_device_by_iface_locked): variant of nm_get_device_by_iface but locks the device list - (nm_device_set_active_link): a little bit of cleanup and de-indenting * src/nm-netlink-monitor.[ch] - (nm_netlink_monitor_class_install_signals): New signal "wireless-event" - (nm_netlink_monitor_new): keep reference to NMData so we can get at the device list - (nm_netlink_monitor_event_handler): expand for wireless events too * src/nm-marshal-main.c - Include generated nm-marshal.c and nm-marshal.h * src/nm-marshal.list - List of custom marshal functions git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@1555 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-03-06 01:10:58 +00:00
static void
nm_device_ethernet_init(NMDeviceEthernet *self)
2006-03-05 Dan Williams <dcbw@redhat.com> Process netlink messages in device subclasses rather than in NetworkManager.c. Also add support for recognizing Wireless Events. * configure.in - Find GLIB_GENMARSHAL * src/Makefile.am - Since we're marshalling custom types for wireless event signals, we get to create our own marshallers using GLIB_GENMARSHAL * src/NetworkManager.c - (nm_monitor_wired_link_state): renamed to nm_monitor_setup - (nm_monitor_setup): renamed from nm_monitor_wired_link_state, and cut down somewhat. We no longer process signals here. - (nm_data_new): create the netlink monitor here, and remove a useless call to nm_policy_schedule_device_change_check() - (nm_data_free): get rid of the netlink monitor here - (nm_device_link_activated, nm_device_link_deactivated): removed - (main): don't create the netlink monitor here, let nm_data_new do that. Call nm_policy_schedule_device_change_check() right before we jump to the mainloop to figure out which device to use first * src/NetworkManagerSystem.[ch] - (nm_system_get_rtnl_index_from_iface, nm_system_get_iface_from_rtnl_index): convert back and forth from interface names to interface indexes * src/nm-device-802-11-wireless.c - (real_init): connect to wireless-event signals from the netlink monitor object - (nm_device_802_11_wireless_event): new function, schedule handler for wireless event signals from the netlink monitor object. We want the handler to run in the device's context - (wireless_event_helper): handle wireless-event signals from netlink - (nm_device_802_11_wireless_dispose): disconnect wireless-event signal handler * src/nm-device-802-11-wireless.h - remove unused prototype for nm_device_802_11_wireless_new * src/nm-device-802-3-ethernet.c - (real_init): new function; set up signal handlers for link events - (nm_device_802_3_ethernet_link_activated): new function, schedule handler for netlink link activated events on device's main loop - (link_activated_helper): when we get a link activated event, set the device's link to be active - (nm_device_802_3_ethernet_link_deactivated): new function; schedule handler for netlink link deactivated events on device's main loop - (link_deactivated_helper): when we get a link deactivated event, set the device's link to be inactive - (nm_device_802_3_ethernet_dispose): disconnect signal handler on dispose * src/nm-device-802-3-ethernet.h - remove unused prototype for nm_device_802_3_ethernet_new * src/nm-device.[ch] - (nm_get_device_by_iface_locked): variant of nm_get_device_by_iface but locks the device list - (nm_device_set_active_link): a little bit of cleanup and de-indenting * src/nm-netlink-monitor.[ch] - (nm_netlink_monitor_class_install_signals): New signal "wireless-event" - (nm_netlink_monitor_new): keep reference to NMData so we can get at the device list - (nm_netlink_monitor_event_handler): expand for wireless events too * src/nm-marshal-main.c - Include generated nm-marshal.c and nm-marshal.h * src/nm-marshal.list - List of custom marshal functions git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@1555 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-03-06 01:10:58 +00:00
{
NMDeviceEthernetPrivate *priv;
priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate);
self->_priv = priv;
priv->s390_options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
2006-03-05 Dan Williams <dcbw@redhat.com> Process netlink messages in device subclasses rather than in NetworkManager.c. Also add support for recognizing Wireless Events. * configure.in - Find GLIB_GENMARSHAL * src/Makefile.am - Since we're marshalling custom types for wireless event signals, we get to create our own marshallers using GLIB_GENMARSHAL * src/NetworkManager.c - (nm_monitor_wired_link_state): renamed to nm_monitor_setup - (nm_monitor_setup): renamed from nm_monitor_wired_link_state, and cut down somewhat. We no longer process signals here. - (nm_data_new): create the netlink monitor here, and remove a useless call to nm_policy_schedule_device_change_check() - (nm_data_free): get rid of the netlink monitor here - (nm_device_link_activated, nm_device_link_deactivated): removed - (main): don't create the netlink monitor here, let nm_data_new do that. Call nm_policy_schedule_device_change_check() right before we jump to the mainloop to figure out which device to use first * src/NetworkManagerSystem.[ch] - (nm_system_get_rtnl_index_from_iface, nm_system_get_iface_from_rtnl_index): convert back and forth from interface names to interface indexes * src/nm-device-802-11-wireless.c - (real_init): connect to wireless-event signals from the netlink monitor object - (nm_device_802_11_wireless_event): new function, schedule handler for wireless event signals from the netlink monitor object. We want the handler to run in the device's context - (wireless_event_helper): handle wireless-event signals from netlink - (nm_device_802_11_wireless_dispose): disconnect wireless-event signal handler * src/nm-device-802-11-wireless.h - remove unused prototype for nm_device_802_11_wireless_new * src/nm-device-802-3-ethernet.c - (real_init): new function; set up signal handlers for link events - (nm_device_802_3_ethernet_link_activated): new function, schedule handler for netlink link activated events on device's main loop - (link_activated_helper): when we get a link activated event, set the device's link to be active - (nm_device_802_3_ethernet_link_deactivated): new function; schedule handler for netlink link deactivated events on device's main loop - (link_deactivated_helper): when we get a link deactivated event, set the device's link to be inactive - (nm_device_802_3_ethernet_dispose): disconnect signal handler on dispose * src/nm-device-802-3-ethernet.h - remove unused prototype for nm_device_802_3_ethernet_new * src/nm-device.[ch] - (nm_get_device_by_iface_locked): variant of nm_get_device_by_iface but locks the device list - (nm_device_set_active_link): a little bit of cleanup and de-indenting * src/nm-netlink-monitor.[ch] - (nm_netlink_monitor_class_install_signals): New signal "wireless-event" - (nm_netlink_monitor_new): keep reference to NMData so we can get at the device list - (nm_netlink_monitor_event_handler): expand for wireless events too * src/nm-marshal-main.c - Include generated nm-marshal.c and nm-marshal.h * src/nm-marshal.list - List of custom marshal functions git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@1555 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-03-06 01:10:58 +00:00
}
static NMDeviceCapabilities
get_generic_capabilities(NMDevice *device)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device);
int ifindex = nm_device_get_ifindex(device);
if (ifindex > 0) {
if (nm_platform_link_supports_carrier_detect(nm_device_get_platform(device), ifindex))
return NM_DEVICE_CAP_CARRIER_DETECT;
else {
_LOGI(LOGD_PLATFORM,
"driver '%s' does not support carrier detection.",
nm_device_get_driver(device));
}
}
return NM_DEVICE_CAP_NONE;
}
static guint32
_subchannels_count_num(const char *const *array)
{
int i;
if (!array)
return 0;
for (i = 0; array[i]; i++)
/* NOP */;
return i;
}
static gboolean
match_subchans(NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
const char *const * subchans;
guint32 num1, num2;
int i;
*try_mac = TRUE;
subchans = nm_setting_wired_get_s390_subchannels(s_wired);
num1 = _subchannels_count_num(subchans);
num2 = _subchannels_count_num((const char *const *) priv->subchannels_dbus);
/* connection has no subchannels */
if (num1 == 0)
return TRUE;
/* connection requires subchannels but the device has none */
if (num2 == 0)
return FALSE;
/* number of subchannels differ */
if (num1 != num2)
return FALSE;
/* Make sure each subchannel in the connection is a subchannel of this device */
for (i = 0; subchans[i]; i++) {
const char *candidate = subchans[i];
if ((priv->subchan1 && !strcmp(priv->subchan1, candidate))
|| (priv->subchan2 && !strcmp(priv->subchan2, candidate))
|| (priv->subchan3 && !strcmp(priv->subchan3, candidate)))
continue;
return FALSE; /* a subchannel was not found */
}
*try_mac = FALSE;
return TRUE;
}
static gboolean
check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device);
NMSettingWired * s_wired;
if (!NM_DEVICE_CLASS(nm_device_ethernet_parent_class)
->check_connection_compatible(device, connection, error))
return FALSE;
if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)
|| (nm_connection_is_type(connection, NM_SETTING_VETH_SETTING_NAME)
&& NM_IS_DEVICE_VETH(device))) {
s_wired = nm_connection_get_setting_wired(connection);
} else {
s_wired =
_nm_connection_check_main_setting(connection, NM_SETTING_WIRED_SETTING_NAME, error);
if (!s_wired)
return FALSE;
}
if (s_wired) {
const char * mac, *perm_hw_addr;
gboolean try_mac = TRUE;
const char *const *mac_blacklist;
int i;
if (!match_subchans(self, s_wired, &try_mac)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"s390 subchannels don't match");
return FALSE;
}
perm_hw_addr = nm_device_get_permanent_hw_address(device);
mac = nm_setting_wired_get_mac_address(s_wired);
if (perm_hw_addr) {
if (try_mac && mac && !nm_utils_hwaddr_matches(mac, -1, perm_hw_addr, -1)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"permanent MAC address doesn't match");
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)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"invalid MAC in blacklist");
return FALSE;
}
if (nm_utils_hwaddr_matches(mac_blacklist[i], -1, perm_hw_addr, -1)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"permanent MAC address of device blacklisted");
return FALSE;
}
}
} else if (mac) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"device has no permanent MAC address to match");
return FALSE;
}
}
return TRUE;
}
/*****************************************************************************/
/* 802.1X */
static void
supplicant_interface_release(NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
nm_clear_pointer(&priv->supplicant.create_handle,
nm_supplicant_manager_create_interface_cancel);
nm_clear_g_source(&priv->supplicant.lnk_timeout_id);
nm_clear_g_source(&priv->supplicant.con_timeout_id);
nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.iface_state_id);
nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.auth_state_id);
priv->supplicant.ready = FALSE;
if (priv->supplicant.iface) {
nm_supplicant_interface_disconnect(priv->supplicant.iface);
g_clear_object(&priv->supplicant.iface);
}
}
static void
supplicant_auth_state_changed(NMSupplicantInterface *iface,
GParamSpec * pspec,
NMDeviceEthernet * self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMSupplicantAuthState state;
state = nm_supplicant_interface_get_auth_state(priv->supplicant.iface);
_LOGD(LOGD_CORE, "supplicant auth state changed to %u", (unsigned) state);
if (state == NM_SUPPLICANT_AUTH_STATE_SUCCESS) {
nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.iface_state_id);
nm_device_update_dynamic_ip_setup(NM_DEVICE(self));
}
}
static gboolean
wired_auth_is_optional(NMDeviceEthernet *self)
{
NMSetting8021x *s_8021x;
s_8021x = nm_device_get_applied_setting(NM_DEVICE(self), NM_TYPE_SETTING_802_1X);
g_return_val_if_fail(s_8021x, FALSE);
return nm_setting_802_1x_get_optional(s_8021x);
}
static void
wired_auth_cond_fail(NMDeviceEthernet *self, NMDeviceStateReason reason)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMDevice * device = NM_DEVICE(self);
if (!wired_auth_is_optional(self)) {
supplicant_interface_release(self);
nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
return;
}
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) 802.1X authentication is optional, continuing after a failure");
priv->supplicant.ready = TRUE;
if (NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH))
nm_device_activate_schedule_stage2_device_config(device, FALSE);
if (!priv->supplicant.auth_state_id) {
priv->supplicant.auth_state_id =
g_signal_connect(priv->supplicant.iface,
"notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE,
G_CALLBACK(supplicant_auth_state_changed),
self);
}
}
static void
wired_secrets_cb(NMActRequest * req,
NMActRequestGetSecretsCallId *call_id,
NMSettingsConnection * connection,
GError * error,
gpointer user_data)
{
NMDeviceEthernet * self = user_data;
NMDevice * device = user_data;
NMDeviceEthernetPrivate *priv;
g_return_if_fail(NM_IS_DEVICE_ETHERNET(self));
g_return_if_fail(NM_IS_ACT_REQUEST(req));
priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
g_return_if_fail(priv->wired_secrets_id == call_id);
priv->wired_secrets_id = NULL;
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_return_if_fail(req == nm_device_get_act_request(device));
g_return_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_NEED_AUTH);
g_return_if_fail(nm_act_request_get_settings_connection(req) == connection);
if (error) {
_LOGW(LOGD_ETHER, "%s", error->message);
wired_auth_cond_fail(self, NM_DEVICE_STATE_REASON_NO_SECRETS);
return;
}
supplicant_interface_release(self);
nm_device_activate_schedule_stage1_device_prepare(device, FALSE);
}
static void
wired_secrets_cancel(NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
if (priv->wired_secrets_id)
nm_act_request_cancel_secrets(NULL, priv->wired_secrets_id);
nm_assert(!priv->wired_secrets_id);
}
static void
wired_secrets_get_secrets(NMDeviceEthernet * self,
const char * setting_name,
NMSecretAgentGetSecretsFlags flags)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMActRequest * req;
wired_secrets_cancel(self);
req = nm_device_get_act_request(NM_DEVICE(self));
g_return_if_fail(NM_IS_ACT_REQUEST(req));
priv->wired_secrets_id =
nm_act_request_get_secrets(req, TRUE, setting_name, flags, NULL, wired_secrets_cb, self);
g_return_if_fail(priv->wired_secrets_id);
}
static gboolean
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
supplicant_lnk_timeout_cb(gpointer user_data)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMDevice * device = NM_DEVICE(self);
NMActRequest * req;
NMConnection * applied_connection;
const char * setting_name;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
priv->supplicant.lnk_timeout_id = 0;
req = nm_device_get_act_request(device);
if (nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) {
wired_auth_cond_fail(self, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
return G_SOURCE_REMOVE;
}
/* Disconnect event during initial authentication and credentials
* ARE checked - we are likely to have wrong key. Ask the user for
* another one.
*/
if (nm_device_get_state(device) != NM_DEVICE_STATE_CONFIG)
goto time_out;
nm_active_connection_clear_secrets(NM_ACTIVE_CONNECTION(req));
applied_connection = nm_act_request_get_applied_connection(req);
setting_name = nm_connection_need_secrets(applied_connection, NULL);
if (!setting_name)
goto time_out;
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) disconnected during authentication, asking for new key.");
if (!wired_auth_is_optional(self))
supplicant_interface_release(self);
nm_device_state_changed(device,
NM_DEVICE_STATE_NEED_AUTH,
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
wired_secrets_get_secrets(self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
return G_SOURCE_REMOVE;
time_out:
_LOGW(LOGD_DEVICE | LOGD_ETHER, "link timed out.");
wired_auth_cond_fail(self, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
return G_SOURCE_REMOVE;
}
static NMSupplicantConfig *
build_supplicant_config(NMDeviceEthernet *self, GError **error)
{
const char * con_uuid;
NMSupplicantConfig *config = NULL;
NMSetting8021x * security;
NMConnection * connection;
guint32 mtu;
connection = nm_device_get_applied_connection(NM_DEVICE(self));
g_return_val_if_fail(connection, NULL);
con_uuid = nm_connection_get_uuid(connection);
mtu = nm_platform_link_get_mtu(nm_device_get_platform(NM_DEVICE(self)),
nm_device_get_ifindex(NM_DEVICE(self)));
config = nm_supplicant_config_new(NM_SUPPL_CAP_MASK_NONE);
security = nm_connection_get_setting_802_1x(connection);
if (!nm_supplicant_config_add_setting_8021x(config, security, con_uuid, mtu, TRUE, error)) {
g_prefix_error(error, "802-1x-setting: ");
g_clear_object(&config);
}
return config;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
static void
supplicant_iface_state_is_completed(NMDeviceEthernet *self, NMSupplicantInterfaceState state)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
if (state == NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) {
nm_clear_g_source(&priv->supplicant.lnk_timeout_id);
nm_clear_g_source(&priv->supplicant.con_timeout_id);
priv->supplicant.ready = TRUE;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
/* If this is the initial association during device activation,
* schedule the activation stage again to proceed.
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
*/
if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_CONFIG) {
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) Stage 2 of 5 (Device Configure) successful.");
nm_device_activate_schedule_stage2_device_config(NM_DEVICE(self), FALSE);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
}
return;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
if (!priv->supplicant.lnk_timeout_id && !priv->supplicant.con_timeout_id)
priv->supplicant.lnk_timeout_id =
g_timeout_add_seconds(SUPPLICANT_LNK_TIMEOUT_SEC, supplicant_lnk_timeout_cb, self);
}
static void
supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer user_data)
{
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
NMDeviceEthernet * self;
NMDeviceEthernetPrivate *priv;
if (nm_utils_error_is_cancelled_or_disposing(error))
return;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
self = NM_DEVICE_ETHERNET(user_data);
priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
if (error) {
supplicant_interface_release(self);
nm_device_queue_state(NM_DEVICE(self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
return;
}
nm_assert(!priv->supplicant.lnk_timeout_id);
nm_assert(!priv->supplicant.is_associated);
priv->supplicant.is_associated = TRUE;
supplicant_iface_state_is_completed(self,
nm_supplicant_interface_get_state(priv->supplicant.iface));
}
static gboolean
supplicant_iface_start(NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
gs_unref_object NMSupplicantConfig *config = NULL;
gs_free_error GError *error = NULL;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
config = build_supplicant_config(self, &error);
if (!config) {
_LOGE(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) couldn't build security configuration: %s",
error->message);
supplicant_interface_release(self);
nm_device_state_changed(NM_DEVICE(self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
return FALSE;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
nm_supplicant_interface_disconnect(priv->supplicant.iface);
nm_supplicant_interface_assoc(priv->supplicant.iface, config, supplicant_iface_assoc_cb, self);
return TRUE;
}
static void
supplicant_iface_state_cb(NMSupplicantInterface *iface,
int new_state_i,
int old_state_i,
int disconnect_reason,
gpointer user_data)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
NMDeviceEthernetPrivate * priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMSupplicantInterfaceState new_state = new_state_i;
NMSupplicantInterfaceState old_state = old_state_i;
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"supplicant interface state: %s -> %s",
nm_supplicant_interface_state_to_string(old_state),
nm_supplicant_interface_state_to_string(new_state));
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
supplicant_interface_release(self);
nm_device_state_changed(NM_DEVICE(self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
return;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
if (old_state == NM_SUPPLICANT_INTERFACE_STATE_STARTING) {
if (!supplicant_iface_start(self))
return;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
if (priv->supplicant.is_associated)
supplicant_iface_state_is_completed(self, new_state);
}
static gboolean
handle_auth_or_fail(NMDeviceEthernet *self, NMActRequest *req, gboolean new_secrets)
{
const char * setting_name;
NMConnection *applied_connection;
if (!nm_device_auth_retries_try_next(NM_DEVICE(self)))
return FALSE;
nm_device_state_changed(NM_DEVICE(self),
NM_DEVICE_STATE_NEED_AUTH,
NM_DEVICE_STATE_REASON_NONE);
nm_active_connection_clear_secrets(NM_ACTIVE_CONNECTION(req));
applied_connection = nm_act_request_get_applied_connection(req);
setting_name = nm_connection_need_secrets(applied_connection, NULL);
if (!setting_name) {
_LOGI(LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets.");
return FALSE;
}
_LOGI(LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) asking for new secrets");
/* Don't tear down supplicant if the authentication is optional
* because in case of a failure in getting new secrets we want to
* keep the supplicant alive.
*/
if (!wired_auth_is_optional(self))
supplicant_interface_release(self);
wired_secrets_get_secrets(
self,
setting_name,
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
| (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0));
return TRUE;
}
static gboolean
supplicant_connection_timeout_cb(gpointer user_data)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
2008-09-25 Dan Williams <dcbw@redhat.com> Fix bgo #549401 (inspired by patch from Alexander Sack) * src/nm-device-ethernet.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): rename from supplicant_interface_clean to match nm-device-wifi.c; clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler, supplicant_connection_timeout_cb): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_ethernet_dispose): clean up any pending supplicant state tasks * src/nm-device-wifi.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_wifi_dispose): clean up any pending supplicant state tasks git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4105 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-09-25 10:02:28 +00:00
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMDevice * device = NM_DEVICE(self);
NMActRequest * req;
NMSettingsConnection * connection;
guint64 timestamp = 0;
gboolean new_secrets = TRUE;
2008-09-25 Dan Williams <dcbw@redhat.com> Fix bgo #549401 (inspired by patch from Alexander Sack) * src/nm-device-ethernet.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): rename from supplicant_interface_clean to match nm-device-wifi.c; clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler, supplicant_connection_timeout_cb): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_ethernet_dispose): clean up any pending supplicant state tasks * src/nm-device-wifi.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_wifi_dispose): clean up any pending supplicant state tasks git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4105 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-09-25 10:02:28 +00:00
priv->supplicant.con_timeout_id = 0;
/* Authentication failed; either driver problems, the encryption key is
* wrong, the passwords or certificates were wrong or the Ethernet switch's
* port is not configured for 802.1x. */
_LOGW(LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) association took too long.");
req = nm_device_get_act_request(device);
connection = nm_act_request_get_settings_connection(req);
/* Ask for new secrets only if we've never activated this connection
* before. If we've connected before, don't bother the user with dialogs,
* just retry or fail, and if we never connect the user can fix the
* password somewhere else. */
if (nm_settings_connection_get_timestamp(connection, &timestamp))
new_secrets = !timestamp;
if (!handle_auth_or_fail(self, req, new_secrets)) {
wired_auth_cond_fail(self, NM_DEVICE_STATE_REASON_NO_SECRETS);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
return G_SOURCE_REMOVE;
}
if (!priv->supplicant.lnk_timeout_id && priv->supplicant.iface) {
NMSupplicantInterfaceState state;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
state = nm_supplicant_interface_get_state(priv->supplicant.iface);
if (state != NM_SUPPLICANT_INTERFACE_STATE_COMPLETED
&& nm_supplicant_interface_state_is_operational(state))
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
priv->supplicant.lnk_timeout_id =
g_timeout_add_seconds(SUPPLICANT_LNK_TIMEOUT_SEC, supplicant_lnk_timeout_cb, self);
}
return G_SOURCE_REMOVE;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
static void
supplicant_interface_create_cb(NMSupplicantManager * supplicant_manager,
NMSupplMgrCreateIfaceHandle *handle,
NMSupplicantInterface * iface,
GError * error,
gpointer user_data)
{
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
NMDeviceEthernet * self;
NMDeviceEthernetPrivate *priv;
guint timeout;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
if (nm_utils_error_is_cancelled(error))
return;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
self = user_data;
priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
nm_assert(priv->supplicant.create_handle == handle);
priv->supplicant.create_handle = NULL;
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
if (error) {
_LOGE(LOGD_DEVICE | LOGD_ETHER,
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
"Couldn't initialize supplicant interface: %s",
error->message);
supplicant_interface_release(self);
nm_device_state_changed(NM_DEVICE(self),
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
return;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
priv->supplicant.iface = g_object_ref(iface);
priv->supplicant.is_associated = FALSE;
priv->supplicant.iface_state_id = g_signal_connect(priv->supplicant.iface,
NM_SUPPLICANT_INTERFACE_STATE,
G_CALLBACK(supplicant_iface_state_cb),
self);
timeout = nm_device_get_supplicant_timeout(NM_DEVICE(self));
priv->supplicant.con_timeout_id =
g_timeout_add_seconds(timeout, supplicant_connection_timeout_cb, self);
if (nm_supplicant_interface_state_is_operational(nm_supplicant_interface_get_state(iface)))
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
supplicant_iface_start(self);
}
static NMPlatformLinkDuplexType
link_duplex_to_platform(const char *duplex)
{
if (!duplex)
return NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
if (nm_streq(duplex, "full"))
return NM_PLATFORM_LINK_DUPLEX_FULL;
if (nm_streq(duplex, "half"))
return NM_PLATFORM_LINK_DUPLEX_HALF;
g_return_val_if_reached(NM_PLATFORM_LINK_DUPLEX_UNKNOWN);
}
static void
link_negotiation_set(NMDevice *device)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMSettingWired * s_wired;
gboolean autoneg = TRUE;
gboolean link_autoneg;
NMPlatformLinkDuplexType duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
NMPlatformLinkDuplexType link_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
guint32 speed = 0;
guint32 link_speed;
s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED);
if (s_wired) {
autoneg = nm_setting_wired_get_auto_negotiate(s_wired);
speed = nm_setting_wired_get_speed(s_wired);
duplex = link_duplex_to_platform(nm_setting_wired_get_duplex(s_wired));
if (!autoneg && !speed && !duplex) {
_LOGD(LOGD_DEVICE, "set-link: ignore link negotiation");
return;
}
}
if (!nm_platform_ethtool_get_link_settings(nm_device_get_platform(device),
nm_device_get_ifindex(device),
&link_autoneg,
&link_speed,
&link_duplex)) {
_LOGW(LOGD_DEVICE, "set-link: unable to retrieve link negotiation");
return;
}
if (autoneg && !speed && !duplex)
_LOGD(LOGD_DEVICE, "set-link: configure auto-negotiation");
else {
_LOGD(LOGD_DEVICE,
"set-link: configure %snegotiation (%u Mbit, %s duplex)",
autoneg ? "auto-" : "static ",
speed,
nm_platform_link_duplex_type_to_string(duplex));
}
if (!priv->ethtool_prev_set) {
/* remember the values we had before setting it. */
priv->ethtool_prev_autoneg = link_autoneg;
if (link_autoneg) {
/* with autoneg, we only support advertising one speed/duplex. Likewise
* our nm_platform_ethtool_get_link_settings() can only return the current
* speed/duplex, but not all the modes that we were advertising.
*
* Do the best we can do: remember to re-enable autoneg, but don't restrict
* the mode. */
priv->ethtool_prev_speed = 0;
priv->ethtool_prev_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
} else {
priv->ethtool_prev_speed = link_speed;
priv->ethtool_prev_duplex = link_duplex;
}
priv->ethtool_prev_set = TRUE;
}
if (!nm_platform_ethtool_set_link_settings(nm_device_get_platform(device),
nm_device_get_ifindex(device),
autoneg,
speed,
duplex)) {
_LOGW(LOGD_DEVICE, "set-link: failure to set link negotiation");
return;
}
}
static gboolean
pppoe_reconnect_delay(gpointer user_data)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
nm_clear_g_source_inst(&priv->ppp_data.wait_source);
priv->ppp_data.last_pppoe_time_msec = 0;
_LOGI(LOGD_DEVICE, "PPPoE reconnect delay complete, resuming connection...");
nm_device_activate_schedule_stage1_device_prepare(NM_DEVICE(self), FALSE);
return G_SOURCE_CONTINUE;
}
static NMActStageReturn
act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
if (nm_device_sys_iface_state_is_external_or_assume(device)) {
if (!priv->ethtool_prev_set && !nm_device_sys_iface_state_is_external(device)) {
NMSettingWired *s_wired;
/* During restart of NetworkManager service we forget the original auto
* negotiation settings. When taking over a device, remember to reset
* the "default" during deactivate. */
s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED);
if (s_wired
&& (nm_setting_wired_get_auto_negotiate(s_wired)
|| nm_setting_wired_get_speed(s_wired)
|| nm_setting_wired_get_duplex(s_wired))) {
priv->ethtool_prev_set = TRUE;
priv->ethtool_prev_autoneg = TRUE;
priv->ethtool_prev_speed = 0;
priv->ethtool_prev_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
}
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
link_negotiation_set(device);
/* If we're re-activating a PPPoE connection a short while after
* a previous PPPoE connection was torn down, wait a bit to allow the
* remote side to handle the disconnection. Otherwise, the peer may
* get confused and fail to negotiate the new connection. (rh #1023503)
*
* FIXME(shutdown): when exiting, we also need to wait before quitting,
* at least for additional NM_SHUTDOWN_TIMEOUT_MS seconds because
* otherwise after restart the device won't work for the first seconds.
*/
if (priv->ppp_data.last_pppoe_time_msec != 0) {
gint64 delay =
nm_utils_get_monotonic_timestamp_msec() - priv->ppp_data.last_pppoe_time_msec;
if (delay < PPPOE_RECONNECT_DELAY_MSEC
&& nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE)) {
if (!priv->ppp_data.wait_source) {
_LOGI(LOGD_DEVICE,
"delaying PPPoE reconnect for %d.%03d seconds to ensure peer is ready...",
(int) (delay / 1000),
(int) (delay % 1000));
priv->ppp_data.wait_source =
nm_g_timeout_add_source(delay, pppoe_reconnect_delay, self);
}
return NM_ACT_STAGE_RETURN_POSTPONE;
}
nm_clear_g_source_inst(&priv->ppp_data.wait_source);
priv->ppp_data.last_pppoe_time_msec = 0;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static NMActStageReturn
supplicant_check_secrets_needed(NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMConnection * connection;
NMSetting8021x * security;
const char * setting_name;
connection = nm_device_get_applied_connection(NM_DEVICE(self));
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
security = nm_connection_get_setting_802_1x(connection);
if (!security) {
_LOGE(LOGD_DEVICE, "Invalid or missing 802.1X security");
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
return NM_ACT_STAGE_RETURN_FAILURE;
}
if (!priv->supplicant.mgr)
priv->supplicant.mgr = g_object_ref(nm_supplicant_manager_get());
/* If we need secrets, get them */
setting_name = nm_connection_need_secrets(connection, NULL);
if (setting_name) {
NMActRequest *req = nm_device_get_act_request(NM_DEVICE(self));
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) connection '%s' has security, but secrets are required.",
nm_connection_get_id(connection));
if (!handle_auth_or_fail(self, req, FALSE)) {
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS);
return NM_ACT_STAGE_RETURN_FAILURE;
}
return NM_ACT_STAGE_RETURN_POSTPONE;
}
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) connection '%s' requires no security. No secrets needed.",
nm_connection_get_id(connection));
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
supplicant_interface_release(self);
supplicant: large rework of wpa_supplicant handling Avoid GDBusProxy, instead use GDBusConnection directly. I very much prefer this because that way we have explicit control over what happens on D-Bus. With GDBusProxy this is hidden under another layer of complex code. The hardest part when using a D-Bus interface is to manage the state via an asynchronous medium. GDBusProxy contains state about the D-Bus interface and duplicate the state that we track. This makes it hard to reason about things. Rework creation of NMSupplicantInterface. Previously, a NMSupplicantInterface had multiple initialization states. In particular, the first state would not yet tie the interface to a certain D-Bus object path. Instead, NMSupplicantInterface would try and retry to create the D-Bus object. Now, NMSupplicantManager has an asynchronous method to create interface instances. The manager only creates an interface instance after the D-Bus path is known. That means, a NMSupplicantInterface instance is now strongly tied to a name-owner and D-Bus path. It follows that the state of NMSupplicantInterface can only go from STARTING, via the supplicant states, to DOWN. Never back. That was already previously the case that the state from DOWN was final and once the 3 initial states were passed, the interface's state would never go back to the initial state. Now this is more strict and more formalized. The 3 initialization states are combined. I think the tighter state handling simplifies users of NMSupplicantInterface. See for example "nm-device-ethernet.c". It's still complicated, because handling state is fundamentally difficult. NMSupplicantManager will take care to D-Bus activate wpa_supplicant only when necessary (poke). Previously, creating the manager instance would always start suppliant service. Now, it's started on demand.
2020-01-21 15:05:16 +01:00
priv->supplicant.create_handle =
nm_supplicant_manager_create_interface(priv->supplicant.mgr,
nm_device_get_ifindex(NM_DEVICE(self)),
NM_SUPPLICANT_DRIVER_WIRED,
supplicant_interface_create_cb,
self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static void
carrier_changed(NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMDeviceStateReason reason;
NMActStageReturn ret;
if (!nm_device_has_carrier(NM_DEVICE(self)))
return;
_LOGD(LOGD_DEVICE | LOGD_ETHER, "got carrier, initializing supplicant");
nm_clear_g_signal_handler(self, &priv->carrier_id);
ret = supplicant_check_secrets_needed(self, &reason);
if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
}
}
/*****************************************************************************/
static void
_ppp_mgr_cleanup(NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
nm_clear_pointer(&priv->ppp_data.ppp_mgr, nm_ppp_mgr_destroy);
}
static void
_ppp_mgr_stage3_maybe_ready(NMDeviceEthernet *self)
{
NMDevice * device = NM_DEVICE(self);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
int IS_IPv4;
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
const NMPppMgrIPData *ip_data;
ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_data.ppp_mgr, addr_family);
if (ip_data->ip_received)
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd);
}
if (nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG)
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL);
}
static void
_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data)
2008-03-07 Dan Williams <dcbw@redhat.com> First pass of multiple active device support. Expect bugs. * src/nm-ip4-config.c src/nm-ip4-config.h - (nm_ip4_config_get_secondary, nm_ip4_config_set_secondary): remove; there are better ways to do this in the named manager * src/nm-device.c src/nm-device.h - (nm_device_can_activate): return whether the device can activate a connection right now; taking into account things like carrier state and rfkill state - (nm_device_get_best_auto_connection): renamed from nm_device_get_best_connection - (real_act_stage4_get_ip4_config): MTU stuff is now handled in the device subclasses themselves, so that each device can override the MTU from it's NMSetting subclass if needed - (nm_device_set_ip4_config): set MTU when setting up routes and stuff in NetworkManagerSystem.c, not here * src/named-manager/nm-named-manager.c src/named-manager/nm-named-manager.h - (nm_named_manager_name_owner_changed, nm_named_manager_dbus_connection_changed): fix for changes to rewrite_resolv_conf() - (compute_nameservers): don't need the NMNamedManager at all, remove from parameter list - (merge_one_ip4_config): new function; merge ip4 configs together - (rewrite_resolv_conf): write out resolv.conf from all the stored ip4 configs; the VPN config takes precedence, then the best device config, then the rest of the configs - (get_domain_for_config): take the NMNamedManager as an argument to check whether the config is the VPN config - (add_ip4_config_to_named): fixups for removal of the 'secondary' attribute from ip4 configs - (add_all_ip4_configs_to_named): add all the configs in priority order - (remove_ip4_config_from_named): fix for changes to get_domain_for_config() - (nm_named_manager_add_ip4_config): assign the config to the right slot based on its type; callers must pass in the type now - (get_last_default_domain): remove, unused - (nm_named_manager_remove_ip4_config): handle config slots correctly * src/nm-device-802-11-wireless.c - (real_can_activate): new function - (real_get_best_auto_connection): renamed from real_get_best_connection - (real_act_stage4_get_ip4_config): handle MTU override * src/nm-device-802-3-ethernet.c - (real_can_activate): new function - (real_get_best_auto_connection): renamed from real_get_best_connection - (real_act_stage4_get_ip4_config): new function; handle MTU override * src/vpn-manager/nm-vpn-connection.c - (nm_vpn_connection_ip4_config_get): don't need to set the 'secondary' attribute on the ip4 config * src/NetworkManagerPolicy.c - (nm_policy_auto_get_best_device): remove - (nm_policy_device_change_check): remove - (update_default_route): new function; set the default route via the specified device - (get_device_priority): new function; return the priority number of a device type WRT which one should have the default route. Order is (highest to lowest) wired, wireless, GSM, CDMA. - (update_routing_and_dns): new function; determine which device should have the default route, then update the routing table and DNS - (maybe_auto_activate_device): new function; if a device is now available for activation, find out what connection it would like to activate and do it - (schedule_activate_check): new function; if a device can be activated now, schedule the activation. Each device may have only one pending activation at a given time. - (device_state_changed): if activation was canceled, try again, possibly with another connection; if the device was activated, update routing and DNS; if the device was deactivated, try again with another connection - (device_carrier_changed): if there is no carrier, deactivate the device; otherwise schedule an activation check for the device - (wireless_networks_changed): schedule an activation check for the device - (device_added): keep track of the signal handler IDs so they can be removed when the device goes away - (device_removed): remove any signal handlers that might be attached to the device; update routing and DNS - (schedule_activate_all): new function - (connections_added, connection_added, connection_updated): when connections change, schedule all devices for an activation check - (connection_removed): when a device is deactivated because its connection was removed, schedule another activation check for it - (nm_policy_destroy): destroy pending activations and disconnect all device signal handlers * src/nm-manager.c - (nm_manager_activate_device): if the device was already actived, deactivate it - (deactivate_old_device): remove - (connection_added_default_handler, impl_manager_activate_device): don't deactivate other devices when activating this one * src/backends/NetworkManagerGentoo.c src/backends/NetworkManagerFrugalware.c src/backends/NetworkManagerPaldo.c src/backends/NetworkManagerRedHat.c src/backends/NetworkManagerSlackware.c src/backends/NetworkManagerArch.c src/backends/NetworkManagerSuSE.c src/backends/NetworkManagerDebian.c - (nm_system_get_mtu): remove; MTU should be provided through the distro's system settings service plugin instead - (nm_system_device_add_default_route_via_device): remove - (nm_system_device_add_default_route_via_device_with_iface): remove - (nm_system_device_replace_default_route): new function; call generic implementation * src/backends/NetworkManagerGeneric.c src/backends/NetworkManagerGeneric.h - (nm_generic_device_add_default_route_via_device, nm_generic_device_add_default_route_via_device_with_iface): remove - (nm_generic_device_replace_default_route): replace the default route with the given route via some gateway * src/NetworkManagerSystem.c src/NetworkManagerSystem.h - (nm_system_device_set_from_ip4_config): let the policy handle updates to routing and DNS; but set the MTU here - (nm_system_vpn_device_set_from_ip4_config): set the route with the ip_iface of the active device; use the standard MTU setting function - (nm_system_set_mtu): remove - (nm_system_device_set_mtu): consolidate MTU setting code in one place git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3391 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-03-07 19:41:32 +00:00
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data);
NMDevice * device = NM_DEVICE(self);
NMDeviceState device_state;
if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED)
return;
device_state = nm_device_get_state(device);
if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) {
if (device_state <= NM_DEVICE_STATE_ACTIVATED)
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason);
return;
}
if (device_state < NM_DEVICE_STATE_IP_CONFIG) {
if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) {
gs_free char *old_name = NULL;
gs_free_error GError *error = NULL;
if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) {
_LOGW(LOGD_DEVICE | LOGD_PPP,
"could not take control of link %d: %s",
callback_data->data.ifindex,
error->message);
_ppp_mgr_cleanup(self);
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
return;
}
if (old_name)
nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
return;
}
_ppp_mgr_stage3_maybe_ready(self);
}
/*****************************************************************************/
static void dcb_state(NMDevice *device, gboolean timeout);
static gboolean
dcb_carrier_timeout(gpointer user_data)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMDevice * device = NM_DEVICE(user_data);
g_return_val_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG, G_SOURCE_REMOVE);
priv->dcb_timeout_id = 0;
if (priv->dcb_wait != DCB_WAIT_CARRIER_POSTCONFIG_DOWN) {
_LOGW(LOGD_DCB, "DCB: timed out waiting for carrier (step %d)", priv->dcb_wait);
}
dcb_state(device, TRUE);
return G_SOURCE_REMOVE;
}
static gboolean
dcb_configure(NMDevice *device)
{
NMDeviceEthernet * self = (NMDeviceEthernet *) device;
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMSettingDcb * s_dcb;
GError * error = NULL;
nm_clear_g_source(&priv->dcb_timeout_id);
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
g_return_val_if_fail(s_dcb, FALSE);
if (!nm_dcb_setup(nm_device_get_iface(device), s_dcb, &error)) {
_LOGW(LOGD_DCB, "Activation: (ethernet) failed to enable DCB/FCoE: %s", error->message);
g_clear_error(&error);
return FALSE;
}
/* Pause again just in case the device takes the carrier down when
* setting specific DCB attributes.
*/
_LOGD(LOGD_DCB, "waiting for carrier (postconfig down)");
priv->dcb_wait = DCB_WAIT_CARRIER_POSTCONFIG_DOWN;
priv->dcb_timeout_id = g_timeout_add_seconds(3, dcb_carrier_timeout, device);
return TRUE;
}
static gboolean
dcb_enable(NMDevice *device)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
GError * error = NULL;
nm_clear_g_source(&priv->dcb_timeout_id);
if (!nm_dcb_enable(nm_device_get_iface(device), TRUE, &error)) {
_LOGW(LOGD_DCB, "Activation: (ethernet) failed to enable DCB/FCoE: %s", error->message);
g_clear_error(&error);
return FALSE;
}
/* Pause for 3 seconds after enabling DCB to let the card reconfigure
* itself. Drivers will often re-initialize internal settings which
* takes the carrier down for 2 or more seconds. During this time,
* lldpad will refuse to do anything else with the card since the carrier
* is down. But NM might get the carrier-down signal long after calling
* "dcbtool dcb on", so we have to first wait for the carrier to go down.
*/
_LOGD(LOGD_DCB, "waiting for carrier (preconfig down)");
priv->dcb_wait = DCB_WAIT_CARRIER_PRECONFIG_DOWN;
priv->dcb_timeout_id = g_timeout_add_seconds(3, dcb_carrier_timeout, device);
return TRUE;
}
static void
dcb_state(NMDevice *device, gboolean timeout)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
gboolean carrier;
g_return_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG);
carrier = nm_platform_link_is_connected(nm_device_get_platform(device),
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) {
case DCB_WAIT_CARRIER_PREENABLE_UP:
if (timeout || carrier) {
_LOGD(LOGD_DCB, "dcb_state() enabling DCB");
nm_clear_g_source(&priv->dcb_timeout_id);
if (!dcb_enable(device)) {
priv->dcb_handle_carrier_changes = FALSE;
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED);
}
}
break;
case DCB_WAIT_CARRIER_PRECONFIG_DOWN:
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_wait = DCB_WAIT_CARRIER_PRECONFIG_UP;
if (!carrier) {
/* Wait for the carrier to come back up */
_LOGD(LOGD_DCB, "waiting for carrier (preconfig up)");
priv->dcb_timeout_id = g_timeout_add_seconds(5, dcb_carrier_timeout, device);
break;
}
_LOGD(LOGD_DCB, "dcb_state() preconfig down falling through");
/* fall-through */
case DCB_WAIT_CARRIER_PRECONFIG_UP:
if (timeout || carrier) {
_LOGD(LOGD_DCB, "dcb_state() preconfig up configuring DCB");
nm_clear_g_source(&priv->dcb_timeout_id);
if (!dcb_configure(device)) {
priv->dcb_handle_carrier_changes = FALSE;
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED);
}
}
break;
case DCB_WAIT_CARRIER_POSTCONFIG_DOWN:
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_wait = DCB_WAIT_CARRIER_POSTCONFIG_UP;
if (!carrier) {
/* Wait for the carrier to come back up */
_LOGD(LOGD_DCB, "waiting for carrier (postconfig up)");
priv->dcb_timeout_id = g_timeout_add_seconds(5, dcb_carrier_timeout, device);
break;
}
_LOGD(LOGD_DCB, "dcb_state() postconfig down falling through");
/* fall-through */
case DCB_WAIT_CARRIER_POSTCONFIG_UP:
if (timeout || carrier) {
_LOGD(LOGD_DCB, "dcb_state() postconfig up starting IP");
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_handle_carrier_changes = FALSE;
priv->dcb_wait = DCB_WAIT_UNKNOWN;
nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
break;
default:
g_assert_not_reached();
}
}
/*****************************************************************************/
static gboolean
wake_on_lan_enable(NMDevice *device)
{
NMSettingWiredWakeOnLan wol;
NMSettingWired * s_wired;
const char * password = NULL;
s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED);
if (NM_IS_DEVICE_VETH(device))
return FALSE;
if (s_wired) {
wol = nm_setting_wired_get_wake_on_lan(s_wired);
password = nm_setting_wired_get_wake_on_lan_password(s_wired);
if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)
goto found;
}
wol = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
NM_CON_DEFAULT("ethernet.wake-on-lan"),
device,
NM_SETTING_WIRED_WAKE_ON_LAN_NONE,
G_MAXINT32,
NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT);
if (NM_FLAGS_ANY(wol, NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS)
&& !nm_utils_is_power_of_two(wol)) {
nm_log_dbg(LOGD_ETHER, "invalid default value %u for wake-on-lan", (guint) wol);
wol = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT;
}
if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)
goto found;
wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
found:
return nm_platform_ethtool_set_wake_on_lan(nm_device_get_platform(device),
nm_device_get_ifindex(device),
_NM_SETTING_WIRED_WAKE_ON_LAN_CAST(wol),
password);
}
/*****************************************************************************/
static NMActStageReturn
act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMConnection * connection;
NMSettingConnection * s_con;
const char * connection_type;
NMSettingDcb * s_dcb;
NMActRequest * req;
connection = nm_device_get_applied_connection(device);
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
s_con = _nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION);
g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE);
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_handle_carrier_changes = FALSE;
connection_type = nm_setting_connection_get_connection_type(s_con);
if (nm_streq(connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
if (!priv->ppp_data.ppp_mgr) {
gs_free_error GError *error = NULL;
NMSettingPppoe * s_pppoe;
NMSettingPpp * s_ppp;
s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP);
if (s_ppp) {
guint32 mtu;
guint32 mru;
guint32 mxu;
mtu = nm_setting_ppp_get_mtu(s_ppp);
mru = nm_setting_ppp_get_mru(s_ppp);
mxu = MAX(mru, mtu);
if (mxu) {
_LOGD(LOGD_PPP,
"set MTU to %u (PPP interface MRU %u, MTU %u)",
mxu + PPPOE_ENCAP_OVERHEAD,
mru,
mtu);
nm_platform_link_set_mtu(nm_device_get_platform(device),
nm_device_get_ifindex(device),
mxu + PPPOE_ENCAP_OVERHEAD);
}
}
req = nm_device_get_act_request(device);
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
s_pppoe = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PPPOE);
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
priv->ppp_data.ppp_mgr =
nm_ppp_mgr_start(&((const NMPppMgrConfig){
.netns = nm_device_get_netns(device),
.parent_iface = nm_device_get_iface(device),
.callback = _ppp_mgr_callback,
.user_data = self,
.act_req = req,
.ppp_username = nm_setting_pppoe_get_username(s_pppoe),
.timeout_secs = 30,
.baud_override = 0,
}),
&error);
if (!priv->ppp_data.ppp_mgr) {
_LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
*out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
return NM_ACT_STAGE_RETURN_FAILURE;
}
return NM_ACT_STAGE_RETURN_POSTPONE;
}
if (nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX)
return NM_ACT_STAGE_RETURN_POSTPONE;
}
/* 802.1x has to run before any IP configuration since the 802.1x auth
* process opens the port up for normal traffic.
*/
if (nm_streq(connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
NMSetting8021x *security;
security = nm_device_get_applied_setting(device, NM_TYPE_SETTING_802_1X);
if (security) {
/* FIXME: we always return from this. stage2 must be re-entrant, and
* process all the necessary steps. Just returning for 8021x is wrong. */
if (priv->supplicant.ready)
return NM_ACT_STAGE_RETURN_SUCCESS;
if (!nm_device_has_carrier(NM_DEVICE(self))) {
_LOGD(LOGD_DEVICE | LOGD_ETHER,
"delay supplicant initialization until carrier goes up");
priv->carrier_id = g_signal_connect(self,
"notify::" NM_DEVICE_CARRIER,
G_CALLBACK(carrier_changed),
self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
return supplicant_check_secrets_needed(self, out_failure_reason);
}
}
wake_on_lan_enable(device);
/* DCB and FCoE setup */
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
if (!priv->stage2_ready_dcb && s_dcb) {
/* lldpad really really wants the carrier to be up */
if (nm_platform_link_is_connected(nm_device_get_platform(device),
nm_device_get_ifindex(device))) {
if (!dcb_enable(device)) {
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED);
return NM_ACT_STAGE_RETURN_FAILURE;
}
} else {
_LOGD(LOGD_DCB, "waiting for carrier (preenable up)");
priv->dcb_wait = DCB_WAIT_CARRIER_PREENABLE_UP;
priv->dcb_timeout_id = g_timeout_add_seconds(4, dcb_carrier_timeout, device);
}
priv->dcb_handle_carrier_changes = TRUE;
return NM_ACT_STAGE_RETURN_POSTPONE;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static guint32
get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device);
/* MTU only set for plain ethernet */
if (priv->ppp_data.ppp_mgr)
return 0;
return nm_device_get_configured_mtu_for_wired(device, out_source, out_force);
}
static void
act_stage3_ip_config(NMDevice *device, int addr_family)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMPppMgrState ppp_state;
if (!priv->ppp_data.ppp_mgr)
return;
ppp_state = nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr);
nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG));
if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) {
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL);
return;
}
2008-03-07 Dan Williams <dcbw@redhat.com> First pass of multiple active device support. Expect bugs. * src/nm-ip4-config.c src/nm-ip4-config.h - (nm_ip4_config_get_secondary, nm_ip4_config_set_secondary): remove; there are better ways to do this in the named manager * src/nm-device.c src/nm-device.h - (nm_device_can_activate): return whether the device can activate a connection right now; taking into account things like carrier state and rfkill state - (nm_device_get_best_auto_connection): renamed from nm_device_get_best_connection - (real_act_stage4_get_ip4_config): MTU stuff is now handled in the device subclasses themselves, so that each device can override the MTU from it's NMSetting subclass if needed - (nm_device_set_ip4_config): set MTU when setting up routes and stuff in NetworkManagerSystem.c, not here * src/named-manager/nm-named-manager.c src/named-manager/nm-named-manager.h - (nm_named_manager_name_owner_changed, nm_named_manager_dbus_connection_changed): fix for changes to rewrite_resolv_conf() - (compute_nameservers): don't need the NMNamedManager at all, remove from parameter list - (merge_one_ip4_config): new function; merge ip4 configs together - (rewrite_resolv_conf): write out resolv.conf from all the stored ip4 configs; the VPN config takes precedence, then the best device config, then the rest of the configs - (get_domain_for_config): take the NMNamedManager as an argument to check whether the config is the VPN config - (add_ip4_config_to_named): fixups for removal of the 'secondary' attribute from ip4 configs - (add_all_ip4_configs_to_named): add all the configs in priority order - (remove_ip4_config_from_named): fix for changes to get_domain_for_config() - (nm_named_manager_add_ip4_config): assign the config to the right slot based on its type; callers must pass in the type now - (get_last_default_domain): remove, unused - (nm_named_manager_remove_ip4_config): handle config slots correctly * src/nm-device-802-11-wireless.c - (real_can_activate): new function - (real_get_best_auto_connection): renamed from real_get_best_connection - (real_act_stage4_get_ip4_config): handle MTU override * src/nm-device-802-3-ethernet.c - (real_can_activate): new function - (real_get_best_auto_connection): renamed from real_get_best_connection - (real_act_stage4_get_ip4_config): new function; handle MTU override * src/vpn-manager/nm-vpn-connection.c - (nm_vpn_connection_ip4_config_get): don't need to set the 'secondary' attribute on the ip4 config * src/NetworkManagerPolicy.c - (nm_policy_auto_get_best_device): remove - (nm_policy_device_change_check): remove - (update_default_route): new function; set the default route via the specified device - (get_device_priority): new function; return the priority number of a device type WRT which one should have the default route. Order is (highest to lowest) wired, wireless, GSM, CDMA. - (update_routing_and_dns): new function; determine which device should have the default route, then update the routing table and DNS - (maybe_auto_activate_device): new function; if a device is now available for activation, find out what connection it would like to activate and do it - (schedule_activate_check): new function; if a device can be activated now, schedule the activation. Each device may have only one pending activation at a given time. - (device_state_changed): if activation was canceled, try again, possibly with another connection; if the device was activated, update routing and DNS; if the device was deactivated, try again with another connection - (device_carrier_changed): if there is no carrier, deactivate the device; otherwise schedule an activation check for the device - (wireless_networks_changed): schedule an activation check for the device - (device_added): keep track of the signal handler IDs so they can be removed when the device goes away - (device_removed): remove any signal handlers that might be attached to the device; update routing and DNS - (schedule_activate_all): new function - (connections_added, connection_added, connection_updated): when connections change, schedule all devices for an activation check - (connection_removed): when a device is deactivated because its connection was removed, schedule another activation check for it - (nm_policy_destroy): destroy pending activations and disconnect all device signal handlers * src/nm-manager.c - (nm_manager_activate_device): if the device was already actived, deactivate it - (deactivate_old_device): remove - (connection_added_default_handler, impl_manager_activate_device): don't deactivate other devices when activating this one * src/backends/NetworkManagerGentoo.c src/backends/NetworkManagerFrugalware.c src/backends/NetworkManagerPaldo.c src/backends/NetworkManagerRedHat.c src/backends/NetworkManagerSlackware.c src/backends/NetworkManagerArch.c src/backends/NetworkManagerSuSE.c src/backends/NetworkManagerDebian.c - (nm_system_get_mtu): remove; MTU should be provided through the distro's system settings service plugin instead - (nm_system_device_add_default_route_via_device): remove - (nm_system_device_add_default_route_via_device_with_iface): remove - (nm_system_device_replace_default_route): new function; call generic implementation * src/backends/NetworkManagerGeneric.c src/backends/NetworkManagerGeneric.h - (nm_generic_device_add_default_route_via_device, nm_generic_device_add_default_route_via_device_with_iface): remove - (nm_generic_device_replace_default_route): replace the default route with the given route via some gateway * src/NetworkManagerSystem.c src/NetworkManagerSystem.h - (nm_system_device_set_from_ip4_config): let the policy handle updates to routing and DNS; but set the MTU here - (nm_system_vpn_device_set_from_ip4_config): set the route with the ip_iface of the active device; use the standard MTU setting function - (nm_system_set_mtu): remove - (nm_system_device_set_mtu): consolidate MTU setting code in one place git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3391 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-03-07 19:41:32 +00:00
_ppp_mgr_stage3_maybe_ready(self);
2008-03-07 Dan Williams <dcbw@redhat.com> First pass of multiple active device support. Expect bugs. * src/nm-ip4-config.c src/nm-ip4-config.h - (nm_ip4_config_get_secondary, nm_ip4_config_set_secondary): remove; there are better ways to do this in the named manager * src/nm-device.c src/nm-device.h - (nm_device_can_activate): return whether the device can activate a connection right now; taking into account things like carrier state and rfkill state - (nm_device_get_best_auto_connection): renamed from nm_device_get_best_connection - (real_act_stage4_get_ip4_config): MTU stuff is now handled in the device subclasses themselves, so that each device can override the MTU from it's NMSetting subclass if needed - (nm_device_set_ip4_config): set MTU when setting up routes and stuff in NetworkManagerSystem.c, not here * src/named-manager/nm-named-manager.c src/named-manager/nm-named-manager.h - (nm_named_manager_name_owner_changed, nm_named_manager_dbus_connection_changed): fix for changes to rewrite_resolv_conf() - (compute_nameservers): don't need the NMNamedManager at all, remove from parameter list - (merge_one_ip4_config): new function; merge ip4 configs together - (rewrite_resolv_conf): write out resolv.conf from all the stored ip4 configs; the VPN config takes precedence, then the best device config, then the rest of the configs - (get_domain_for_config): take the NMNamedManager as an argument to check whether the config is the VPN config - (add_ip4_config_to_named): fixups for removal of the 'secondary' attribute from ip4 configs - (add_all_ip4_configs_to_named): add all the configs in priority order - (remove_ip4_config_from_named): fix for changes to get_domain_for_config() - (nm_named_manager_add_ip4_config): assign the config to the right slot based on its type; callers must pass in the type now - (get_last_default_domain): remove, unused - (nm_named_manager_remove_ip4_config): handle config slots correctly * src/nm-device-802-11-wireless.c - (real_can_activate): new function - (real_get_best_auto_connection): renamed from real_get_best_connection - (real_act_stage4_get_ip4_config): handle MTU override * src/nm-device-802-3-ethernet.c - (real_can_activate): new function - (real_get_best_auto_connection): renamed from real_get_best_connection - (real_act_stage4_get_ip4_config): new function; handle MTU override * src/vpn-manager/nm-vpn-connection.c - (nm_vpn_connection_ip4_config_get): don't need to set the 'secondary' attribute on the ip4 config * src/NetworkManagerPolicy.c - (nm_policy_auto_get_best_device): remove - (nm_policy_device_change_check): remove - (update_default_route): new function; set the default route via the specified device - (get_device_priority): new function; return the priority number of a device type WRT which one should have the default route. Order is (highest to lowest) wired, wireless, GSM, CDMA. - (update_routing_and_dns): new function; determine which device should have the default route, then update the routing table and DNS - (maybe_auto_activate_device): new function; if a device is now available for activation, find out what connection it would like to activate and do it - (schedule_activate_check): new function; if a device can be activated now, schedule the activation. Each device may have only one pending activation at a given time. - (device_state_changed): if activation was canceled, try again, possibly with another connection; if the device was activated, update routing and DNS; if the device was deactivated, try again with another connection - (device_carrier_changed): if there is no carrier, deactivate the device; otherwise schedule an activation check for the device - (wireless_networks_changed): schedule an activation check for the device - (device_added): keep track of the signal handler IDs so they can be removed when the device goes away - (device_removed): remove any signal handlers that might be attached to the device; update routing and DNS - (schedule_activate_all): new function - (connections_added, connection_added, connection_updated): when connections change, schedule all devices for an activation check - (connection_removed): when a device is deactivated because its connection was removed, schedule another activation check for it - (nm_policy_destroy): destroy pending activations and disconnect all device signal handlers * src/nm-manager.c - (nm_manager_activate_device): if the device was already actived, deactivate it - (deactivate_old_device): remove - (connection_added_default_handler, impl_manager_activate_device): don't deactivate other devices when activating this one * src/backends/NetworkManagerGentoo.c src/backends/NetworkManagerFrugalware.c src/backends/NetworkManagerPaldo.c src/backends/NetworkManagerRedHat.c src/backends/NetworkManagerSlackware.c src/backends/NetworkManagerArch.c src/backends/NetworkManagerSuSE.c src/backends/NetworkManagerDebian.c - (nm_system_get_mtu): remove; MTU should be provided through the distro's system settings service plugin instead - (nm_system_device_add_default_route_via_device): remove - (nm_system_device_add_default_route_via_device_with_iface): remove - (nm_system_device_replace_default_route): new function; call generic implementation * src/backends/NetworkManagerGeneric.c src/backends/NetworkManagerGeneric.h - (nm_generic_device_add_default_route_via_device, nm_generic_device_add_default_route_via_device_with_iface): remove - (nm_generic_device_replace_default_route): replace the default route with the given route via some gateway * src/NetworkManagerSystem.c src/NetworkManagerSystem.h - (nm_system_device_set_from_ip4_config): let the policy handle updates to routing and DNS; but set the MTU here - (nm_system_vpn_device_set_from_ip4_config): set the route with the ip_iface of the active device; use the standard MTU setting function - (nm_system_set_mtu): remove - (nm_system_device_set_mtu): consolidate MTU setting code in one place git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3391 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-03-07 19:41:32 +00:00
}
static void
deactivate(NMDevice *device)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMSettingDcb * s_dcb;
GError * error = NULL;
int ifindex;
nm_clear_g_source_inst(&priv->ppp_data.wait_source);
nm_clear_g_signal_handler(self, &priv->carrier_id);
_ppp_mgr_cleanup(self);
supplicant_interface_release(self);
priv->dcb_wait = DCB_WAIT_UNKNOWN;
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_handle_carrier_changes = FALSE;
priv->stage2_ready_dcb = FALSE;
/* Tear down DCB/FCoE if it was enabled */
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
if (s_dcb) {
if (!nm_dcb_cleanup(nm_device_get_iface(device), &error)) {
_LOGW(LOGD_DEVICE | LOGD_PLATFORM, "failed to disable DCB/FCoE: %s", error->message);
g_clear_error(&error);
}
}
/* Set last PPPoE connection time */
if (nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE))
priv->ppp_data.last_pppoe_time_msec = nm_utils_get_monotonic_timestamp_msec();
ifindex = nm_device_get_ifindex(device);
if (ifindex > 0 && priv->ethtool_prev_set) {
priv->ethtool_prev_set = FALSE;
_LOGD(LOGD_DEVICE,
"set-link: reset %snegotiation (%u Mbit, %s duplex)",
priv->ethtool_prev_autoneg ? "auto-" : "static ",
priv->ethtool_prev_speed,
nm_platform_link_duplex_type_to_string(priv->ethtool_prev_duplex));
if (!nm_platform_ethtool_set_link_settings(nm_device_get_platform(device),
ifindex,
priv->ethtool_prev_autoneg,
priv->ethtool_prev_speed,
priv->ethtool_prev_duplex)) {
_LOGW(LOGD_DEVICE, "set-link: failure to reset link negotiation");
return;
}
}
}
static gboolean
complete_connection(NMDevice * device,
NMConnection * connection,
const char * specific_object,
NMConnection *const *existing_connections,
GError ** error)
{
NMSettingWired *s_wired;
NMSettingPppoe *s_pppoe;
if (nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_VETH_SETTING_NAME)) {
NMSettingVeth *s_veth;
const char * peer_name = NULL;
const char * con_peer_name = NULL;
int ifindex;
nm_utils_complete_generic(nm_device_get_platform(device),
connection,
NM_SETTING_VETH_SETTING_NAME,
existing_connections,
NULL,
_("Veth connection"),
"veth",
NULL,
TRUE);
s_veth = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VETH);
ifindex = nm_device_get_ip_ifindex(device);
if (ifindex > 0) {
const NMPlatformLink *pllink;
pllink = nm_platform_link_get(nm_device_get_platform(device), ifindex);
if (pllink && pllink->type == NM_LINK_TYPE_VETH && pllink->parent > 0) {
pllink = nm_platform_link_get(nm_device_get_platform(device), pllink->parent);
if (pllink && pllink->type == NM_LINK_TYPE_VETH) {
peer_name = pllink->name;
}
}
}
if (!peer_name) {
nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "cannot find peer for veth device");
return FALSE;
}
con_peer_name = nm_setting_veth_get_peer(s_veth);
if (con_peer_name) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
"mismatching veth peer \"%s\"",
con_peer_name);
return FALSE;
} else
g_object_set(s_veth, NM_SETTING_VETH_PEER, peer_name, NULL);
return TRUE;
}
s_pppoe = nm_connection_get_setting_pppoe(connection);
/* We can't telepathically figure out the service name or username, so if
* those weren't given, we can't complete the connection.
*/
if (s_pppoe && !nm_setting_verify(NM_SETTING(s_pppoe), NULL, error))
return FALSE;
s_wired = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRED);
/* Default to an ethernet-only connection, but if a PPPoE setting was given
* then PPPoE should be our connection type.
*/
nm_utils_complete_generic(
nm_device_get_platform(device),
connection,
s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME,
existing_connections,
NULL,
s_pppoe ? _("PPPoE connection") : _("Wired connection"),
NULL,
nm_setting_wired_get_mac_address(s_wired) ? NULL : nm_device_get_iface(device),
s_pppoe ? FALSE : TRUE); /* No IPv6 by default yet for PPPoE */
return TRUE;
}
static NMConnection *
new_default_connection(NMDevice *self)
{
NMConnection * connection;
NMSettingsConnection *const *connections;
NMSetting * setting;
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
gs_unref_hashtable GHashTable *existing_ids = NULL;
struct udev_device * dev;
const char * perm_hw_addr;
const char * iface;
const char * uprop = "0";
gs_free char * defname = NULL;
gs_free char * uuid = NULL;
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
guint i, n_connections;
perm_hw_addr = nm_device_get_permanent_hw_address(self);
iface = nm_device_get_iface(self);
connection = nm_simple_connection_new();
setting = nm_setting_connection_new();
nm_connection_add_setting(connection, setting);
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
connections = nm_settings_get_connections(nm_device_get_settings(self), &n_connections);
if (n_connections > 0) {
existing_ids = g_hash_table_new(nm_str_hash, g_str_equal);
for (i = 0; i < n_connections; i++)
g_hash_table_add(existing_ids, (char *) nm_settings_connection_get_id(connections[i]));
}
defname = nm_device_ethernet_utils_get_default_wired_name(existing_ids);
if (!defname)
return NULL;
/* Create a stable UUID. The UUID is also the Network_ID for stable-privacy addr-gen-mode,
* thus when it changes we will also generate different IPv6 addresses. */
2021-05-02 21:32:31 +02:00
uuid = nm_uuid_generate_from_strings("default-wired",
nm_utils_machine_id_str(),
defname,
perm_hw_addr ?: iface,
NULL);
g_object_set(setting,
NM_SETTING_CONNECTION_ID,
defname,
NM_SETTING_CONNECTION_TYPE,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_CONNECTION_AUTOCONNECT,
TRUE,
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY,
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN,
NM_SETTING_CONNECTION_UUID,
uuid,
NM_SETTING_CONNECTION_TIMESTAMP,
(guint64) time(NULL),
NM_SETTING_CONNECTION_INTERFACE_NAME,
iface,
NULL);
/* Check if we should create a Link-Local only connection */
dev = nm_platform_link_get_udev_device(nm_device_get_platform(NM_DEVICE(self)),
nm_device_get_ip_ifindex(self));
if (dev)
uprop = udev_device_get_property_value(dev, "NM_AUTO_DEFAULT_LINK_LOCAL_ONLY");
if (_nm_utils_ascii_str_to_bool(uprop, FALSE)) {
setting = nm_setting_ip4_config_new();
g_object_set(setting,
NM_SETTING_IP_CONFIG_METHOD,
NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
NULL);
nm_connection_add_setting(connection, setting);
setting = nm_setting_ip6_config_new();
g_object_set(setting,
NM_SETTING_IP_CONFIG_METHOD,
NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL,
NM_SETTING_IP_CONFIG_MAY_FAIL,
TRUE,
NULL);
nm_connection_add_setting(connection, setting);
}
return connection;
}
static const char *
get_s390_subchannels(NMDevice *device)
{
nm_assert(NM_IS_DEVICE_ETHERNET(device));
return NM_DEVICE_ETHERNET_GET_PRIVATE(device)->subchannels;
}
static void
update_connection(NMDevice *device, NMConnection *connection)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device);
NMSettingWired *s_wired = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRED);
gboolean perm_hw_addr_is_fake;
const char * perm_hw_addr;
const char * mac = nm_device_get_hw_address(device);
const char * mac_prop = NM_SETTING_WIRED_MAC_ADDRESS;
GHashTableIter iter;
const char * key;
const char * value;
g_object_set(nm_connection_get_setting_connection(connection),
NM_SETTING_CONNECTION_TYPE,
nm_connection_get_setting_pppoe(connection) ? NM_SETTING_PPPOE_SETTING_NAME
: NM_SETTING_WIRED_SETTING_NAME,
NULL);
/* If the device reports a permanent address, use that for the MAC address
* and the current MAC, if different, is the cloned MAC.
*/
device: delay capturing permanent MAC address until UDEV is settled The permanent MAC address of an NMDevice shall not change as long as the device is realized. That is, we read it only once and don't change it afterwards. There are two issues that this commit tries to mitigate: (1) users are advised to use UDEV to rename interfaces. As we lookup the permenent MAC address using ethtool (which uses the interface name), there is a race where we could read the permanent MAC address using the wrong interface name. We should wait until UDEV finished initializing the device and until the interface name is stable (see rh#1388286). This commit still cannot avoid the race of ethtool entirely. It only tries to avoid ethtool until UDEV has done its work. That is, until we expect the interface name no longer to change. (2) some device types, don't have a permanent MAC address so we fall back to use the currently set address (fake). Again, users are advised to use UDEV to configure the MAC addresses on such software devices. Thus, we should not get the fake MAC address until UDEV initialized the device. This patch actually doesn't solve the problem at all yet. The reason is that a regular caller of nm_device_get_permanent_hw_address() can not afford to wait until UDEV settled. Thus, any user who requests the permanent MAC address before the link is initialized, runs into the problems above. In a next step, we shall revisit such calls to nm_device_get_permanent_hw_address() and delay them until the link is initialized.
2016-10-24 12:50:17 +02:00
perm_hw_addr = nm_device_get_permanent_hw_address_full(device, TRUE, &perm_hw_addr_is_fake);
if (perm_hw_addr && !perm_hw_addr_is_fake) {
g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL);
mac_prop = NULL;
if (mac && !nm_utils_hwaddr_matches(perm_hw_addr, -1, mac, -1))
mac_prop = NM_SETTING_WIRED_CLONED_MAC_ADDRESS;
}
if (mac_prop && mac && nm_utils_hwaddr_valid(mac, ETH_ALEN))
g_object_set(s_wired, mac_prop, mac, NULL);
/* We don't set the MTU as we don't know whether it was set explicitly */
/* s390 */
if (priv->subchannels_dbus)
g_object_set(s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, priv->subchannels_dbus, NULL);
if (priv->s390_nettype)
g_object_set(s_wired, NM_SETTING_WIRED_S390_NETTYPE, priv->s390_nettype, NULL);
_nm_setting_wired_clear_s390_options(s_wired);
g_hash_table_iter_init(&iter, priv->s390_options);
while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value))
nm_setting_wired_add_s390_option(s_wired, key, value);
}
static void
link_speed_update(NMDevice *device)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
guint32 speed;
if (!nm_platform_ethtool_get_link_settings(nm_device_get_platform(device),
nm_device_get_ifindex(device),
NULL,
&speed,
NULL))
return;
if (priv->speed == speed)
return;
priv->speed = speed;
_LOGD(LOGD_PLATFORM | LOGD_ETHER, "speed is now %d Mb/s", speed);
_notify(self, PROP_SPEED);
}
static void
carrier_changed_notify(NMDevice *device, gboolean carrier)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
if (priv->dcb_handle_carrier_changes) {
nm_assert(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG);
if (priv->dcb_timeout_id) {
_LOGD(LOGD_DCB, "carrier_changed() calling dcb_state()");
dcb_state(device, FALSE);
}
}
if (carrier)
link_speed_update(device);
NM_DEVICE_CLASS(nm_device_ethernet_parent_class)->carrier_changed_notify(device, carrier);
}
static void
link_changed(NMDevice *device, const NMPlatformLink *pllink)
{
NM_DEVICE_CLASS(nm_device_ethernet_parent_class)->link_changed(device, pllink);
if (!NM_IS_DEVICE_VETH(device) && pllink->initialized)
_update_s390_subchannels((NMDeviceEthernet *) device);
}
static gboolean
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
if (!NM_DEVICE_CLASS(nm_device_ethernet_parent_class)->is_available(device, flags))
return FALSE;
return !!nm_device_get_initial_hw_address(device);
}
static gboolean
can_reapply_change(NMDevice * device,
const char *setting_name,
NMSetting * s_old,
NMSetting * s_new,
GHashTable *diffs,
GError ** error)
{
NMDeviceClass *device_class;
/* Only handle wired setting here, delegate other settings to parent class */
if (nm_streq(setting_name, NM_SETTING_WIRED_SETTING_NAME)) {
return nm_device_hash_check_invalid_keys(
diffs,
NM_SETTING_WIRED_SETTING_NAME,
error,
NM_SETTING_WIRED_MTU, /* reapplied with IP config */
NM_SETTING_WIRED_SPEED,
NM_SETTING_WIRED_DUPLEX,
NM_SETTING_WIRED_AUTO_NEGOTIATE,
NM_SETTING_WIRED_WAKE_ON_LAN,
NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD);
}
device_class = NM_DEVICE_CLASS(nm_device_ethernet_parent_class);
return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
}
static void
reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device);
NMDeviceState state = nm_device_get_state(device);
NM_DEVICE_CLASS(nm_device_ethernet_parent_class)->reapply_connection(device, con_old, con_new);
_LOGD(LOGD_DEVICE, "reapplying wired settings");
if (state >= NM_DEVICE_STATE_PREPARE)
link_negotiation_set(device);
if (state >= NM_DEVICE_STATE_CONFIG)
wake_on_lan_enable(device);
}
static void
2009-07-07 14:39:08 -04:00
dispose(GObject *object)
{
2008-09-25 Dan Williams <dcbw@redhat.com> Fix bgo #549401 (inspired by patch from Alexander Sack) * src/nm-device-ethernet.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): rename from supplicant_interface_clean to match nm-device-wifi.c; clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler, supplicant_connection_timeout_cb): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_ethernet_dispose): clean up any pending supplicant state tasks * src/nm-device-wifi.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_wifi_dispose): clean up any pending supplicant state tasks git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4105 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-09-25 10:02:28 +00:00
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(object);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
wired_secrets_cancel(self);
supplicant_interface_release(self);
nm_clear_g_source_inst(&priv->ppp_data.wait_source);
nm_clear_g_source(&priv->dcb_timeout_id);
nm_clear_g_signal_handler(self, &priv->carrier_id);
G_OBJECT_CLASS(nm_device_ethernet_parent_class)->dispose(object);
}
2014-04-07 15:34:10 +02:00
static void
finalize(GObject *object)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(object);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
2014-04-07 15:34:10 +02:00
g_clear_object(&priv->supplicant.mgr);
g_free(priv->subchan1);
g_free(priv->subchan2);
g_free(priv->subchan3);
g_free(priv->subchannels);
g_strfreev(priv->subchannels_dbus);
2014-04-07 15:34:10 +02:00
g_free(priv->s390_nettype);
g_hash_table_destroy(priv->s390_options);
2014-04-07 15:34:10 +02:00
G_OBJECT_CLASS(nm_device_ethernet_parent_class)->finalize(object);
}
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(object);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
switch (prop_id) {
case PROP_SPEED:
g_value_set_uint(value, priv->speed);
break;
case PROP_S390_SUBCHANNELS:
g_value_set_boxed(value, priv->subchannels_dbus);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
static const NMDBusInterfaceInfoExtended interface_info_device_wired = {
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
NM_DBUS_INTERFACE_DEVICE_WIRED,
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("PermHwAddress",
"s",
NM_DEVICE_PERM_HW_ADDRESS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Speed", "u", NM_DEVICE_ETHERNET_SPEED),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("S390Subchannels",
"as",
NM_DEVICE_ETHERNET_S390_SUBCHANNELS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Carrier", "b", NM_DEVICE_CARRIER), ), ),
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
};
static void
nm_device_ethernet_class_init(NMDeviceEthernetClass *klass)
{
GObjectClass * object_class = G_OBJECT_CLASS(klass);
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
NMDeviceClass * device_class = NM_DEVICE_CLASS(klass);
g_type_class_add_private(object_class, sizeof(NMDeviceEthernetPrivate));
2009-07-07 14:39:08 -04:00
object_class->dispose = dispose;
2014-04-07 15:34:10 +02:00
object_class->finalize = finalize;
object_class->get_property = get_property;
object_class->set_property = set_property;
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_wired);
device_class->connection_type_supported = NM_SETTING_WIRED_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_ETHERNET);
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
device_class->new_default_connection = new_default_connection;
device_class->act_stage1_prepare_also_for_external_or_assume = TRUE;
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
device_class->act_stage2_config = act_stage2_config;
device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->get_configured_mtu = get_configured_mtu;
device_class->deactivate = deactivate;
device_class->get_s390_subchannels = get_s390_subchannels;
device_class->update_connection = update_connection;
device_class->carrier_changed_notify = carrier_changed_notify;
device_class->link_changed = link_changed;
device_class->is_available = is_available;
device_class->can_reapply_change = can_reapply_change;
device_class->reapply_connection = reapply_connection;
device_class->state_changed = device_state_changed;
obj_properties[PROP_SPEED] = g_param_spec_uint(NM_DEVICE_ETHERNET_SPEED,
"",
"",
0,
G_MAXUINT32,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_S390_SUBCHANNELS] =
g_param_spec_boxed(NM_DEVICE_ETHERNET_S390_SUBCHANNELS,
"",
"",
G_TYPE_STRV,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}
/*****************************************************************************/
#define NM_TYPE_ETHERNET_DEVICE_FACTORY (nm_ethernet_device_factory_get_type())
#define NM_ETHERNET_DEVICE_FACTORY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_ETHERNET_DEVICE_FACTORY, NMEthernetDeviceFactory))
static NMDevice *
create_device(NMDeviceFactory * factory,
const char * iface,
const NMPlatformLink *plink,
NMConnection * connection,
gboolean * out_ignore)
{
return g_object_new(NM_TYPE_DEVICE_ETHERNET,
NM_DEVICE_IFACE,
iface,
NM_DEVICE_TYPE_DESC,
"Ethernet",
NM_DEVICE_DEVICE_TYPE,
NM_DEVICE_TYPE_ETHERNET,
NM_DEVICE_LINK_TYPE,
NM_LINK_TYPE_ETHERNET,
NULL);
}
static gboolean
match_connection(NMDeviceFactory *factory, NMConnection *connection)
{
const char * type = nm_connection_get_connection_type(connection);
NMSettingPppoe *s_pppoe;
if (nm_streq(type, NM_SETTING_WIRED_SETTING_NAME))
return TRUE;
nm_assert(nm_streq(type, NM_SETTING_PPPOE_SETTING_NAME));
s_pppoe = nm_connection_get_setting_pppoe(connection);
return !nm_setting_pppoe_get_parent(s_pppoe);
}
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_class->create_device = create_device;
factory_class->match_connection = match_connection;);