2008-07-09 14:05:49 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
2005-12-31 08:21:24 +00:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
2008-06-26 18:31:52 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
2017-03-20 13:36:00 +00:00
|
|
|
* Copyright (C) 2005 - 2017 Red Hat, Inc.
|
2008-11-03 04:13:42 +00:00
|
|
|
* Copyright (C) 2006 - 2008 Novell, Inc.
|
2005-12-31 08:21:24 +00:00
|
|
|
*/
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2014-11-13 10:07:02 -05:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
#include "nm-device.h"
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <string.h>
|
2008-03-14 20:37:48 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
2008-07-09 14:05:49 +00:00
|
|
|
#include <signal.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
#include <arpa/inet.h>
|
2008-08-15 15:34:28 +00:00
|
|
|
#include <fcntl.h>
|
2015-10-03 19:44:27 +02:00
|
|
|
#include <linux/if_addr.h>
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
#include <linux/rtnetlink.h>
|
2005-12-31 08:21:24 +00:00
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
#include "nm-utils/nm-dedup-multi.h"
|
|
|
|
|
|
2016-06-01 12:31:36 +02:00
|
|
|
#include "nm-common-macros.h"
|
2005-12-31 08:21:24 +00:00
|
|
|
#include "nm-device-private.h"
|
|
|
|
|
#include "NetworkManagerUtils.h"
|
2013-10-18 12:32:01 +02:00
|
|
|
#include "nm-manager.h"
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "platform/nm-platform.h"
|
2017-06-29 15:19:35 +02:00
|
|
|
#include "platform/nmp-object.h"
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "ndisc/nm-ndisc.h"
|
|
|
|
|
#include "ndisc/nm-lndp-ndisc.h"
|
|
|
|
|
#include "dhcp/nm-dhcp-manager.h"
|
2016-09-28 19:37:10 +02:00
|
|
|
#include "nm-act-request.h"
|
2016-08-16 05:55:58 +05:30
|
|
|
#include "nm-proxy-config.h"
|
2014-07-17 17:06:44 -04:00
|
|
|
#include "nm-ip4-config.h"
|
|
|
|
|
#include "nm-ip6-config.h"
|
2016-08-16 05:55:58 +05:30
|
|
|
#include "nm-pacrunner-manager.h"
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "dnsmasq/nm-dnsmasq-manager.h"
|
2008-07-17 17:04:13 +00:00
|
|
|
#include "nm-dhcp4-config.h"
|
2014-07-17 17:06:44 -04:00
|
|
|
#include "nm-dhcp6-config.h"
|
2013-05-09 10:24:08 -04:00
|
|
|
#include "nm-rfkill-manager.h"
|
2011-10-07 15:58:08 +02:00
|
|
|
#include "nm-firewall-manager.h"
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "settings/nm-settings-connection.h"
|
|
|
|
|
#include "settings/nm-settings.h"
|
2014-08-16 01:33:46 +02:00
|
|
|
#include "nm-auth-utils.h"
|
2017-04-17 20:17:45 +02:00
|
|
|
#include "nm-netns.h"
|
2012-06-03 19:32:16 -05:00
|
|
|
#include "nm-dispatcher.h"
|
2013-03-19 10:24:35 -04:00
|
|
|
#include "nm-config.h"
|
2017-05-13 21:57:51 +02:00
|
|
|
#include "nm-utils/c-list.h"
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "dns/nm-dns-manager.h"
|
2014-10-27 21:12:07 +01:00
|
|
|
#include "nm-core-internal.h"
|
2016-09-27 13:35:29 +02:00
|
|
|
#include "systemd/nm-sd.h"
|
2015-10-07 11:48:38 +02:00
|
|
|
#include "nm-lldp-listener.h"
|
2015-07-14 10:19:19 +02:00
|
|
|
#include "nm-audit-manager.h"
|
2015-12-23 14:15:05 +01:00
|
|
|
#include "nm-arping-manager.h"
|
2017-03-20 13:36:00 +00:00
|
|
|
#include "nm-connectivity.h"
|
|
|
|
|
#include "nm-dbus-interface.h"
|
2017-10-23 15:41:07 +02:00
|
|
|
#include "nm-device-vlan.h"
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-08-02 14:52:49 +02:00
|
|
|
#include "nm-device-logging.h"
|
|
|
|
|
_LOG_DECLARE_SELF (NMDevice);
|
|
|
|
|
|
2016-11-23 13:14:08 +01:00
|
|
|
#include "introspection/org.freedesktop.NetworkManager.Device.h"
|
|
|
|
|
#include "introspection/org.freedesktop.NetworkManager.Device.Statistics.h"
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2017-02-02 12:38:35 +01:00
|
|
|
/*****************************************************************************/
|
2011-11-18 00:05:37 -06:00
|
|
|
|
2017-02-02 12:38:35 +01:00
|
|
|
#define DHCP_RESTART_TIMEOUT 120
|
|
|
|
|
#define DHCP_NUM_TRIES_MAX 3
|
|
|
|
|
#define DEFAULT_AUTOCONNECT TRUE
|
|
|
|
|
|
2017-09-02 17:26:53 +02:00
|
|
|
#define CARRIER_WAIT_TIME_MS 5000
|
|
|
|
|
#define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000
|
|
|
|
|
|
2017-11-02 10:56:30 +01:00
|
|
|
#define NM_DEVICE_AUTH_RETRIES_UNSET -1
|
|
|
|
|
#define NM_DEVICE_AUTH_RETRIES_INFINITY -2
|
|
|
|
|
#define NM_DEVICE_AUTH_RETRIES_DEFAULT 3
|
|
|
|
|
|
2017-02-02 12:38:35 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
typedef void (*ActivationHandleFunc) (NMDevice *self);
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
ActivationHandleFunc func;
|
|
|
|
|
guint id;
|
|
|
|
|
} ActivationHandleData;
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
CLEANUP_TYPE_KEEP,
|
|
|
|
|
CLEANUP_TYPE_REMOVED,
|
|
|
|
|
CLEANUP_TYPE_DECONFIGURE,
|
|
|
|
|
} CleanupType;
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
IP_NONE = 0,
|
|
|
|
|
IP_WAIT,
|
|
|
|
|
IP_CONF,
|
|
|
|
|
IP_DONE,
|
|
|
|
|
IP_FAIL
|
|
|
|
|
} IpState;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2017-05-13 21:57:51 +02:00
|
|
|
CList lst_slave;
|
2017-02-02 12:38:35 +01:00
|
|
|
NMDevice *slave;
|
|
|
|
|
gulong watch_id;
|
|
|
|
|
bool slave_is_enslaved;
|
|
|
|
|
bool configure;
|
|
|
|
|
} SlaveInfo;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
NMDevice *device;
|
|
|
|
|
guint idle_add_id;
|
|
|
|
|
int ifindex;
|
|
|
|
|
} DeleteOnDeactivateData;
|
|
|
|
|
|
|
|
|
|
typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean);
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
ArpingCallback callback;
|
|
|
|
|
NMDevice *device;
|
|
|
|
|
NMIP4Config **configs;
|
|
|
|
|
} ArpingData;
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
HW_ADDR_TYPE_UNSET = 0,
|
|
|
|
|
HW_ADDR_TYPE_PERMANENT,
|
|
|
|
|
HW_ADDR_TYPE_EXPLICIT,
|
|
|
|
|
HW_ADDR_TYPE_GENERATED,
|
|
|
|
|
} HwAddrType;
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
typedef enum {
|
|
|
|
|
FIREWALL_STATE_UNMANAGED = 0,
|
|
|
|
|
FIREWALL_STATE_INITIALIZED,
|
|
|
|
|
FIREWALL_STATE_WAIT_STAGE_3,
|
|
|
|
|
FIREWALL_STATE_WAIT_IP_CONFIG,
|
|
|
|
|
} FirewallState;
|
|
|
|
|
|
2017-02-02 12:38:35 +01:00
|
|
|
/*****************************************************************************/
|
2011-11-18 00:05:37 -06:00
|
|
|
|
2009-07-15 17:22:10 -04:00
|
|
|
enum {
|
2011-11-18 00:09:37 -06:00
|
|
|
STATE_CHANGED,
|
2009-07-15 17:22:10 -04:00
|
|
|
AUTOCONNECT_ALLOWED,
|
2012-06-01 15:27:39 -05:00
|
|
|
AUTH_REQUEST,
|
2012-05-29 09:56:50 -05:00
|
|
|
IP4_CONFIG_CHANGED,
|
|
|
|
|
IP6_CONFIG_CHANGED,
|
2016-11-03 12:05:12 +01:00
|
|
|
IP6_PREFIX_DELEGATED,
|
|
|
|
|
IP6_SUBNET_NEEDED,
|
2014-02-10 08:49:47 -06:00
|
|
|
REMOVED,
|
2014-02-24 18:10:18 -06:00
|
|
|
RECHECK_AUTO_ACTIVATE,
|
2014-05-28 10:18:34 -04:00
|
|
|
RECHECK_ASSUME,
|
2009-07-15 17:22:10 -04:00
|
|
|
LAST_SIGNAL,
|
|
|
|
|
};
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_UDI,
|
|
|
|
|
PROP_IFACE,
|
|
|
|
|
PROP_IP_IFACE,
|
|
|
|
|
PROP_DRIVER,
|
2012-06-01 16:48:57 +02:00
|
|
|
PROP_DRIVER_VERSION,
|
|
|
|
|
PROP_FIRMWARE_VERSION,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_CAPABILITIES,
|
2013-05-07 10:23:44 -04:00
|
|
|
PROP_CARRIER,
|
2013-12-16 15:16:43 +01:00
|
|
|
PROP_MTU,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_IP4_ADDRESS,
|
|
|
|
|
PROP_IP4_CONFIG,
|
|
|
|
|
PROP_DHCP4_CONFIG,
|
|
|
|
|
PROP_IP6_CONFIG,
|
|
|
|
|
PROP_DHCP6_CONFIG,
|
|
|
|
|
PROP_STATE,
|
2012-01-29 22:40:37 +01:00
|
|
|
PROP_STATE_REASON,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_ACTIVE_CONNECTION,
|
|
|
|
|
PROP_DEVICE_TYPE,
|
2015-12-08 14:49:50 +01:00
|
|
|
PROP_LINK_TYPE,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_MANAGED,
|
2012-05-14 15:32:54 +02:00
|
|
|
PROP_AUTOCONNECT,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_FIRMWARE_MISSING,
|
2015-04-14 14:16:04 +02:00
|
|
|
PROP_NM_PLUGIN_MISSING,
|
2011-11-18 00:34:08 -06:00
|
|
|
PROP_TYPE_DESC,
|
|
|
|
|
PROP_RFKILL_TYPE,
|
|
|
|
|
PROP_IFINDEX,
|
2012-08-01 11:16:48 -06:00
|
|
|
PROP_AVAILABLE_CONNECTIONS,
|
2013-10-11 14:59:26 -04:00
|
|
|
PROP_PHYSICAL_PORT_ID,
|
2014-01-02 14:46:02 -05:00
|
|
|
PROP_MASTER,
|
2016-12-26 11:12:39 +01:00
|
|
|
PROP_PARENT,
|
2013-05-01 09:28:16 -04:00
|
|
|
PROP_HW_ADDRESS,
|
2016-06-17 18:53:45 +02:00
|
|
|
PROP_PERM_HW_ADDRESS,
|
2013-08-13 17:45:34 -04:00
|
|
|
PROP_HAS_PENDING_ACTION,
|
2015-04-29 16:34:38 +02:00
|
|
|
PROP_METERED,
|
2015-10-07 11:48:38 +02:00
|
|
|
PROP_LLDP_NEIGHBORS,
|
2014-09-05 08:50:02 -05:00
|
|
|
PROP_REAL,
|
2015-12-02 10:33:19 +01:00
|
|
|
PROP_SLAVES,
|
2016-08-10 11:54:31 +02:00
|
|
|
PROP_REFRESH_RATE_MS,
|
|
|
|
|
PROP_TX_BYTES,
|
|
|
|
|
PROP_RX_BYTES,
|
2017-03-20 13:36:00 +00:00
|
|
|
PROP_CONNECTIVITY,
|
2016-02-29 16:27:27 +05:30
|
|
|
);
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2015-12-07 17:05:12 +01:00
|
|
|
typedef struct _NMDevicePrivate {
|
device: use "bool" type for fields in NMDevice
Contrary to gboolean, bool is only one byte in size.
Due to alignment and ordering of the fields, this saves
merely 16 bytes per NMDevicePrivate struct (on x86_64),
still.
Also, bool is coerced by the compiler to be strictly FALSE or
TRUE -- contrary to gboolean, which can be any integer.
Thus, for bool type, "g_assert (NM_IN_SET (value, FALSE, TRUE));"
never fails. That is desirable as well.
While not a large win, it seems favorable to use bool type for
fields of a struct.
2016-05-11 17:02:10 +02:00
|
|
|
bool in_state_changed;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
guint device_link_changed_id;
|
|
|
|
|
guint device_ip_link_changed_id;
|
|
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
NMDeviceState state;
|
2012-01-29 22:40:37 +01:00
|
|
|
NMDeviceStateReason state_reason;
|
2017-02-02 12:28:32 +01:00
|
|
|
struct {
|
2017-02-02 12:39:07 +01:00
|
|
|
guint id;
|
|
|
|
|
|
|
|
|
|
/* The @state/@reason is only valid, when @id is set. */
|
2017-02-02 12:28:32 +01:00
|
|
|
NMDeviceState state;
|
|
|
|
|
NMDeviceStateReason reason;
|
|
|
|
|
} queued_state;
|
2017-03-01 17:26:45 +01:00
|
|
|
|
2015-06-24 08:59:36 +00:00
|
|
|
guint queued_ip4_config_id;
|
|
|
|
|
guint queued_ip6_config_id;
|
2013-12-16 16:52:36 +01:00
|
|
|
GSList *pending_actions;
|
2015-10-03 19:50:30 +02:00
|
|
|
GSList *dad6_failed_addrs;
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2016-12-26 11:12:39 +01:00
|
|
|
NMDevice *parent_device;
|
|
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
char * udi;
|
|
|
|
|
char * iface; /* may change, could be renamed by user */
|
2010-04-21 14:58:25 -07:00
|
|
|
int ifindex;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
2016-12-26 11:12:39 +01:00
|
|
|
int parent_ifindex;
|
|
|
|
|
|
2017-11-02 10:56:30 +01:00
|
|
|
int auth_retries;
|
|
|
|
|
|
2016-10-26 12:20:12 +02:00
|
|
|
union {
|
|
|
|
|
const guint8 hw_addr_len; /* read-only */
|
|
|
|
|
guint8 hw_addr_len_;
|
|
|
|
|
};
|
2017-02-02 12:34:30 +01:00
|
|
|
|
|
|
|
|
HwAddrType hw_addr_type:5;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
bool real:1;
|
|
|
|
|
|
|
|
|
|
/* there was a IP config change, but no idle action was scheduled because device
|
|
|
|
|
* is still not platform-init */
|
|
|
|
|
bool queued_ip4_config_pending:1;
|
|
|
|
|
bool queued_ip6_config_pending:1;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
char * ip_iface;
|
2010-04-21 14:58:25 -07:00
|
|
|
int ip_ifindex;
|
2009-07-07 14:34:01 -04:00
|
|
|
NMDeviceType type;
|
|
|
|
|
char * type_desc;
|
2015-05-15 15:00:07 +02:00
|
|
|
char * type_description;
|
2015-12-08 14:49:50 +01:00
|
|
|
NMLinkType link_type;
|
2015-04-17 15:15:38 +02:00
|
|
|
NMDeviceCapabilities capabilities;
|
2009-07-07 14:34:01 -04:00
|
|
|
char * driver;
|
2012-06-01 16:48:57 +02:00
|
|
|
char * driver_version;
|
|
|
|
|
char * firmware_version;
|
2010-03-25 11:36:19 -07:00
|
|
|
RfKillType rfkill_type;
|
2016-05-20 13:47:23 +02:00
|
|
|
bool firmware_missing:1;
|
|
|
|
|
bool nm_plugin_missing:1;
|
|
|
|
|
bool hw_addr_perm_fake:1; /* whether the permanent HW address could not be read and is a fake */
|
2016-12-18 13:54:26 +01:00
|
|
|
|
|
|
|
|
NMUtilsStableType current_stable_id_type:3;
|
|
|
|
|
|
2017-05-31 16:42:05 +02:00
|
|
|
bool nm_owned:1; /* whether the device is a device owned and created by NM */
|
2017-03-01 17:26:45 +01:00
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
bool assume_state_guess_assume:1;
|
|
|
|
|
char * assume_state_connection_uuid;
|
|
|
|
|
|
2012-08-01 11:16:48 -06:00
|
|
|
GHashTable * available_connections;
|
2014-06-21 12:44:56 -04:00
|
|
|
char * hw_addr;
|
2016-06-03 13:37:08 +02:00
|
|
|
char * hw_addr_perm;
|
|
|
|
|
char * hw_addr_initial;
|
2013-10-11 14:59:26 -04:00
|
|
|
char * physical_port_id;
|
2015-03-24 12:46:18 -05:00
|
|
|
guint dev_id;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
NMUnmanagedFlags unmanaged_mask;
|
2014-03-31 21:45:54 -05:00
|
|
|
NMUnmanagedFlags unmanaged_flags;
|
2014-03-05 22:20:14 +01:00
|
|
|
DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */
|
2013-04-24 10:40:58 -04:00
|
|
|
|
2014-08-05 20:08:34 +02:00
|
|
|
GCancellable *deactivating_cancellable;
|
|
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
guint32 ip4_address;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
NMActRequest * queued_act_request;
|
2017-01-24 19:43:52 +01:00
|
|
|
bool queued_act_request_is_waiting_for_carrier:1;
|
|
|
|
|
bool act_request_public:1;
|
|
|
|
|
NMActRequest *act_request;
|
|
|
|
|
gulong act_request_id;
|
2015-10-06 11:05:14 +02:00
|
|
|
ActivationHandleData act_handle4; /* for layer2 and IPv4. */
|
|
|
|
|
ActivationHandleData act_handle6;
|
2014-05-28 10:18:34 -04:00
|
|
|
guint recheck_assume_id;
|
2015-04-13 17:16:55 -05:00
|
|
|
struct {
|
2015-10-06 11:05:14 +02:00
|
|
|
guint call_id;
|
2015-04-13 17:16:55 -05:00
|
|
|
NMDeviceStateReason available_reason;
|
|
|
|
|
NMDeviceStateReason unavailable_reason;
|
|
|
|
|
} recheck_available;
|
2014-06-12 14:20:14 +02:00
|
|
|
struct {
|
|
|
|
|
guint call_id;
|
|
|
|
|
NMDeviceState post_state;
|
|
|
|
|
NMDeviceStateReason post_state_reason;
|
|
|
|
|
} dispatcher;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2013-05-07 10:23:44 -04:00
|
|
|
/* Link stuff */
|
|
|
|
|
guint link_connected_id;
|
|
|
|
|
guint link_disconnected_id;
|
|
|
|
|
guint carrier_defer_id;
|
2013-12-09 16:32:36 -06:00
|
|
|
guint carrier_wait_id;
|
2017-04-14 17:46:20 +02:00
|
|
|
gulong config_changed_id;
|
2013-12-16 15:16:43 +01:00
|
|
|
guint32 mtu;
|
2017-01-13 15:55:48 +01:00
|
|
|
guint32 ip6_mtu;
|
2017-01-16 10:20:26 +01:00
|
|
|
guint32 mtu_initial;
|
|
|
|
|
guint32 ip6_mtu_initial;
|
|
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
guint32 v4_route_table;
|
|
|
|
|
guint32 v6_route_table;
|
|
|
|
|
|
2017-09-02 17:26:53 +02:00
|
|
|
/* when carrier goes away, we give a grace period of CARRIER_WAIT_TIME_MS
|
|
|
|
|
* until taking action.
|
|
|
|
|
*
|
|
|
|
|
* When changing MTU, the device might take longer then that. So, whenever
|
|
|
|
|
* NM changes the MTU it sets @carrier_wait_until_ms to CARRIER_WAIT_TIME_AFTER_MTU_MS
|
|
|
|
|
* in the future. This is used to extend the grace period in this particular case. */
|
|
|
|
|
gint64 carrier_wait_until_ms;
|
|
|
|
|
|
2017-03-01 17:26:45 +01:00
|
|
|
bool carrier:1;
|
|
|
|
|
bool ignore_carrier:1;
|
|
|
|
|
|
2017-01-16 12:18:51 +01:00
|
|
|
bool mtu_initialized:1;
|
|
|
|
|
|
|
|
|
|
bool up:1; /* IFF_UP */
|
2013-05-07 10:23:44 -04:00
|
|
|
|
2017-03-16 14:37:54 +01:00
|
|
|
bool v4_commit_first_time:1;
|
|
|
|
|
bool v6_commit_first_time:1;
|
|
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
bool default_route_metric_penalty_ip4_has:1;
|
|
|
|
|
bool default_route_metric_penalty_ip6_has:1;
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
NMDeviceSysIfaceState sys_iface_state:2;
|
|
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
bool v4_route_table_initalized:1;
|
|
|
|
|
bool v6_route_table_initalized:1;
|
|
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:4;
|
|
|
|
|
|
2010-01-13 18:06:05 -08:00
|
|
|
/* Generic DHCP stuff */
|
2014-07-30 10:57:45 -04:00
|
|
|
char * dhcp_anycast_address;
|
2010-01-13 17:59:54 -08:00
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
char * current_stable_id;
|
|
|
|
|
|
2016-08-16 05:55:58 +05:30
|
|
|
/* Proxy Configuration */
|
2016-10-04 11:58:32 +02:00
|
|
|
NMProxyConfig *proxy_config;
|
2016-10-04 12:13:16 +02:00
|
|
|
NMPacrunnerManager *pacrunner_manager;
|
2017-04-21 15:46:56 +02:00
|
|
|
NMPacrunnerCallId *pacrunner_call_id;
|
2016-08-16 05:55:58 +05:30
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
/* IP4 configuration info */
|
2013-08-01 10:34:46 -05:00
|
|
|
NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */
|
2016-08-29 14:27:46 +02:00
|
|
|
union {
|
|
|
|
|
const IpState ip4_state;
|
|
|
|
|
IpState ip4_state_;
|
|
|
|
|
};
|
2014-11-21 13:13:48 +01:00
|
|
|
NMIP4Config * con_ip4_config; /* config from the setting */
|
2013-08-01 10:34:46 -05:00
|
|
|
NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */
|
2013-08-01 15:44:53 -05:00
|
|
|
NMIP4Config * ext_ip4_config; /* Stuff added outside NM */
|
2014-07-15 17:16:56 -05:00
|
|
|
NMIP4Config * wwan_ip4_config; /* WWAN configuration */
|
2015-08-19 23:07:13 +02:00
|
|
|
GSList * vpn4_configs; /* VPNs which use this device */
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
|
2017-03-16 14:27:03 +00:00
|
|
|
bool v4_has_shadowed_routes;
|
|
|
|
|
const char *ip4_rp_filter;
|
2013-08-01 10:34:46 -05:00
|
|
|
|
|
|
|
|
/* DHCPv4 tracking */
|
2016-04-07 14:34:31 +02:00
|
|
|
struct {
|
|
|
|
|
NMDhcpClient * client;
|
|
|
|
|
gulong state_sigid;
|
|
|
|
|
NMDhcp4Config * config;
|
|
|
|
|
guint restart_id;
|
2016-04-07 15:00:47 +02:00
|
|
|
guint num_tries_left;
|
2017-03-07 14:34:17 +01:00
|
|
|
char * pac_url;
|
2017-05-04 10:05:25 +02:00
|
|
|
bool was_active;
|
2016-04-07 14:34:31 +02:00
|
|
|
} dhcp4;
|
2008-05-29 20:58:52 +00:00
|
|
|
|
2017-02-02 12:28:32 +01:00
|
|
|
struct {
|
|
|
|
|
NMLogDomain log_domain;
|
|
|
|
|
guint timeout;
|
|
|
|
|
guint watch;
|
|
|
|
|
GPid pid;
|
|
|
|
|
const char *binary;
|
|
|
|
|
const char *address;
|
|
|
|
|
guint deadline;
|
|
|
|
|
} gw_ping;
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2008-07-09 14:05:49 +00:00
|
|
|
/* dnsmasq stuff for shared connections */
|
2009-07-07 14:34:01 -04:00
|
|
|
NMDnsMasqManager *dnsmasq_manager;
|
|
|
|
|
gulong dnsmasq_state_id;
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2014-07-02 15:19:58 +02:00
|
|
|
/* Firewall */
|
2017-05-03 18:34:17 +02:00
|
|
|
FirewallState fw_state:4;
|
|
|
|
|
NMFirewallManager *fw_mgr;
|
2015-09-23 16:41:14 +02:00
|
|
|
NMFirewallManagerCallId fw_call;
|
2011-10-07 15:58:08 +02:00
|
|
|
|
2015-04-08 14:00:11 +02:00
|
|
|
/* IPv4LL stuff */
|
2015-04-20 18:13:41 +02:00
|
|
|
sd_ipv4ll * ipv4ll;
|
|
|
|
|
guint ipv4ll_timeout;
|
2017-09-13 16:45:22 +02:00
|
|
|
guint rt6_temporary_not_available_id;
|
2009-07-29 12:12:41 -04:00
|
|
|
|
2015-12-23 14:15:05 +01:00
|
|
|
/* IPv4 DAD stuff */
|
|
|
|
|
struct {
|
|
|
|
|
GSList * dad_list;
|
|
|
|
|
NMArpingManager * announcing;
|
|
|
|
|
} arping;
|
|
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
/* IP6 configuration info */
|
2009-07-30 13:50:42 -04:00
|
|
|
NMIP6Config * ip6_config;
|
2016-08-29 14:27:46 +02:00
|
|
|
union {
|
|
|
|
|
const IpState ip6_state;
|
|
|
|
|
IpState ip6_state_;
|
|
|
|
|
};
|
2014-11-21 13:13:48 +01:00
|
|
|
NMIP6Config * con_ip6_config; /* config from the setting */
|
2013-10-15 21:03:42 -05:00
|
|
|
NMIP6Config * wwan_ip6_config;
|
2013-08-15 12:55:56 -05:00
|
|
|
NMIP6Config * ext_ip6_config; /* Stuff added outside NM */
|
2016-01-30 21:37:22 +01:00
|
|
|
NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */
|
2015-08-19 23:07:13 +02:00
|
|
|
GSList * vpn6_configs; /* VPNs which use this device */
|
device: use "bool" type for fields in NMDevice
Contrary to gboolean, bool is only one byte in size.
Due to alignment and ordering of the fields, this saves
merely 16 bytes per NMDevicePrivate struct (on x86_64),
still.
Also, bool is coerced by the compiler to be strictly FALSE or
TRUE -- contrary to gboolean, which can be any integer.
Thus, for bool type, "g_assert (NM_IN_SET (value, FALSE, TRUE));"
never fails. That is desirable as well.
While not a large win, it seems favorable to use bool type for
fields of a struct.
2016-05-11 17:02:10 +02:00
|
|
|
bool nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */
|
2016-03-14 18:37:57 +01:00
|
|
|
NMIP6Config * dad6_ip6_config;
|
2011-10-21 14:25:35 -05:00
|
|
|
|
2017-09-13 16:45:22 +02:00
|
|
|
GHashTable * rt6_temporary_not_available;
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
NMNDisc * ndisc;
|
|
|
|
|
gulong ndisc_changed_id;
|
|
|
|
|
gulong ndisc_timeout_id;
|
|
|
|
|
NMSettingIP6ConfigPrivacy ndisc_use_tempaddr;
|
2011-10-21 14:25:35 -05:00
|
|
|
/* IP6 config from autoconf */
|
|
|
|
|
NMIP6Config * ac_ip6_config;
|
2009-09-16 13:18:24 +02:00
|
|
|
|
2013-11-07 22:59:43 +01:00
|
|
|
guint linklocal6_timeout_id;
|
2015-10-03 19:44:27 +02:00
|
|
|
guint8 linklocal6_dad_counter;
|
2013-11-07 22:59:43 +01:00
|
|
|
|
2014-02-21 17:04:59 -05:00
|
|
|
GHashTable * ip6_saved_properties;
|
2012-02-21 15:44:19 +01:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
struct {
|
|
|
|
|
NMDhcpClient * client;
|
2016-10-13 11:06:25 +00:00
|
|
|
NMNDiscDHCPLevel mode;
|
2016-04-07 14:45:57 +02:00
|
|
|
gulong state_sigid;
|
2016-11-03 12:05:12 +01:00
|
|
|
gulong prefix_sigid;
|
2016-04-07 14:45:57 +02:00
|
|
|
NMDhcp6Config * config;
|
|
|
|
|
/* IP6 config from DHCP */
|
|
|
|
|
NMIP6Config * ip6_config;
|
|
|
|
|
/* Event ID of the current IP6 config from DHCP */
|
|
|
|
|
char * event_id;
|
|
|
|
|
guint restart_id;
|
2016-04-07 15:09:54 +02:00
|
|
|
guint num_tries_left;
|
2016-11-03 12:05:12 +01:00
|
|
|
guint needed_prefixes;
|
2017-05-04 10:05:25 +02:00
|
|
|
bool was_active;
|
2016-04-07 14:45:57 +02:00
|
|
|
} dhcp6;
|
2010-01-14 00:45:10 -08:00
|
|
|
|
2016-11-03 12:05:12 +01:00
|
|
|
gboolean needs_ip6_subnet;
|
|
|
|
|
|
2013-07-25 15:36:45 +02:00
|
|
|
/* master interface for bridge/bond/team slave */
|
2012-11-14 14:05:30 -06:00
|
|
|
NMDevice * master;
|
device: use "bool" type for fields in NMDevice
Contrary to gboolean, bool is only one byte in size.
Due to alignment and ordering of the fields, this saves
merely 16 bytes per NMDevicePrivate struct (on x86_64),
still.
Also, bool is coerced by the compiler to be strictly FALSE or
TRUE -- contrary to gboolean, which can be any integer.
Thus, for bool type, "g_assert (NM_IN_SET (value, FALSE, TRUE));"
never fails. That is desirable as well.
While not a large win, it seems favorable to use bool type for
fields of a struct.
2016-05-11 17:02:10 +02:00
|
|
|
bool is_enslaved;
|
|
|
|
|
bool master_ready_handled;
|
2016-01-04 10:29:06 +01:00
|
|
|
gulong master_ready_id;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2013-01-24 17:47:59 -06:00
|
|
|
/* slave management */
|
2017-05-13 21:57:51 +02:00
|
|
|
CList slaves; /* list of SlaveInfo */
|
2012-05-02 10:28:16 -05:00
|
|
|
|
2015-04-29 16:34:38 +02:00
|
|
|
NMMetered metered;
|
|
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
NMSettings *settings;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
NMNetns *netns;
|
|
|
|
|
|
2015-10-07 11:48:38 +02:00
|
|
|
NMLldpListener *lldp_listener;
|
2017-03-20 13:36:00 +00:00
|
|
|
NMConnectivityState connectivity_state;
|
|
|
|
|
guint concheck_periodic_id;
|
|
|
|
|
guint64 concheck_seq;
|
2016-01-19 11:33:33 +01:00
|
|
|
|
|
|
|
|
guint check_delete_unrealized_id;
|
2016-08-10 11:54:31 +02:00
|
|
|
|
2016-08-16 11:35:23 +02:00
|
|
|
struct {
|
2016-08-16 12:10:23 +02:00
|
|
|
guint timeout_id;
|
2016-08-16 11:35:23 +02:00
|
|
|
guint refresh_rate_ms;
|
|
|
|
|
guint64 tx_bytes;
|
|
|
|
|
guint64 rx_bytes;
|
|
|
|
|
} stats;
|
2016-08-10 11:54:31 +02:00
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
} NMDevicePrivate;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2017-02-02 12:38:35 +01:00
|
|
|
G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT)
|
|
|
|
|
|
|
|
|
|
#define NM_DEVICE_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDevice, NM_IS_DEVICE)
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-03-07 14:34:17 +01:00
|
|
|
static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url);
|
2016-08-16 05:55:58 +05:30
|
|
|
|
2017-09-22 12:11:32 +02:00
|
|
|
static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs);
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
static gboolean nm_device_set_ip4_config (NMDevice *self,
|
2009-08-05 18:03:09 -04:00
|
|
|
NMIP4Config *config,
|
2017-09-12 13:45:53 +02:00
|
|
|
gboolean commit,
|
|
|
|
|
GPtrArray *ip4_dev_route_blacklist);
|
2013-08-01 10:34:46 -05:00
|
|
|
static gboolean ip4_config_merge_and_apply (NMDevice *self,
|
2017-02-22 20:20:22 +01:00
|
|
|
gboolean commit);
|
2013-08-01 10:34:46 -05:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
static gboolean nm_device_set_ip6_config (NMDevice *self,
|
2009-08-05 18:03:09 -04:00
|
|
|
NMIP6Config *config,
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
gboolean commit);
|
2016-04-15 20:01:36 +02:00
|
|
|
static gboolean ip6_config_merge_and_apply (NMDevice *self,
|
2017-02-22 20:20:22 +01:00
|
|
|
gboolean commit);
|
2008-11-07 13:57:39 +00:00
|
|
|
|
2017-03-01 17:28:46 +01:00
|
|
|
static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure);
|
2014-07-15 13:36:24 +02:00
|
|
|
static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success);
|
|
|
|
|
static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason);
|
2011-09-19 14:19:53 +02:00
|
|
|
|
2014-07-22 16:24:07 -05:00
|
|
|
static gboolean addrconf6_start_with_link_ready (NMDevice *self);
|
2014-11-14 16:04:44 -06:00
|
|
|
static NMActStageReturn linklocal6_start (NMDevice *self);
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2014-12-08 12:50:10 +01:00
|
|
|
static void _carrier_wait_check_queued_act_request (NMDevice *self);
|
|
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
static const char *_activation_func_to_string (ActivationHandleFunc func);
|
2017-10-02 13:55:27 +02:00
|
|
|
static void activation_source_handle_cb (NMDevice *self, int addr_family);
|
2015-10-06 11:05:14 +02:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
static void _set_state_full (NMDevice *self,
|
2014-05-23 18:25:05 -05:00
|
|
|
NMDeviceState state,
|
|
|
|
|
NMDeviceStateReason reason,
|
|
|
|
|
gboolean quitting);
|
2017-02-02 12:39:07 +01:00
|
|
|
static void queued_state_clear (NMDevice *device);
|
2014-09-05 08:50:02 -05:00
|
|
|
static gboolean queued_ip4_config_change (gpointer user_data);
|
|
|
|
|
static gboolean queued_ip6_config_change (gpointer user_data);
|
2016-03-09 15:04:11 +01:00
|
|
|
static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data);
|
|
|
|
|
static gboolean ip_config_valid (NMDeviceState state);
|
2017-09-11 10:43:48 +02:00
|
|
|
static NMActStageReturn dhcp4_start (NMDevice *self);
|
2017-02-22 17:04:00 +01:00
|
|
|
static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll);
|
2016-03-09 15:04:11 +01:00
|
|
|
static void nm_device_start_ip_check (NMDevice *self);
|
2016-09-26 14:45:35 +02:00
|
|
|
static void realize_start_setup (NMDevice *self,
|
|
|
|
|
const NMPlatformLink *plink,
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
gboolean assume_state_guess_assume,
|
|
|
|
|
const char *assume_state_connection_uuid,
|
2017-06-07 22:11:50 +02:00
|
|
|
gboolean set_nm_owned,
|
2016-09-26 14:45:35 +02:00
|
|
|
NMUnmanFlagOp unmanaged_user_explicit);
|
2017-10-13 13:11:11 +02:00
|
|
|
static void _set_mtu (NMDevice *self, guint32 mtu);
|
2017-01-15 13:38:33 +01:00
|
|
|
static void _commit_mtu (NMDevice *self, const NMIP4Config *config);
|
2017-10-02 13:55:27 +02:00
|
|
|
static void dhcp_schedule_restart (NMDevice *self, int addr_family, const char *reason);
|
2016-06-28 14:12:57 +02:00
|
|
|
static void _cancel_activation (NMDevice *self);
|
2015-12-14 15:15:23 +01:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2017-01-27 14:13:09 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState,
|
|
|
|
|
NM_UTILS_LOOKUP_DEFAULT ( NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNKNOWN, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unknown"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNMANAGED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unmanaged"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNAVAILABLE, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unavailable"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_DISCONNECTED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "disconnected"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_PREPARE, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "prepare"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_CONFIG, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "config"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_NEED_AUTH, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "need-auth"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_IP_CONFIG, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-config"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_IP_CHECK, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-check"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_SECONDARIES, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "secondaries"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_ACTIVATED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "activated"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_DEACTIVATING, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "deactivating"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_FAILED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"),
|
|
|
|
|
);
|
2013-10-21 12:50:58 -04:00
|
|
|
|
2017-06-07 17:22:16 +02:00
|
|
|
const char *
|
|
|
|
|
nm_device_state_to_str (NMDeviceState state)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2017-01-27 13:57:15 +01:00
|
|
|
return queued_state_to_string (state) + NM_STRLEN (NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2009-07-07 14:34:01 -04:00
|
|
|
|
2016-02-01 14:09:56 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason,
|
|
|
|
|
NM_UTILS_LOOKUP_DEFAULT (NULL),
|
2016-01-24 14:28:31 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_UNKNOWN, "unknown"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NONE, "none"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_MANAGED, "managed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_UNMANAGED, "unmanaged"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONFIG_FAILED, "config-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, "ip-config-unavailable"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, "ip-config-expired"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NO_SECRETS, "no-secrets"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, "supplicant-disconnect"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED, "supplicant-config-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, "supplicant-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, "supplicant-timeout"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_START_FAILED, "ppp-start-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_DISCONNECT, "ppp-disconnect"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_FAILED, "ppp-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_START_FAILED, "dhcp-start-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_ERROR, "dhcp-error"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_FAILED, "dhcp-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_START_FAILED, "sharing-start-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_FAILED, "sharing-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, "autoip-start-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_ERROR, "autoip-error"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_FAILED, "autoip-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_BUSY, "modem-busy"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, "modem-no-dialtone"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, "modem-no-carrier"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, "modem-dial-timeout"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, "modem-dial-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, "modem-init-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_APN_FAILED, "gsm-apn-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, "gsm-registration-idle"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED, "gsm-registration-denied"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT, "gsm-registration-timeout"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, "gsm-registration-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, "gsm-pin-check-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, "firmware-missing"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_REMOVED, "removed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SLEEPING, "sleeping"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, "connection-removed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_USER_REQUESTED, "user-requested"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CARRIER, "carrier-changed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, "connection-assumed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, "supplicant-available"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, "modem-not-found"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BT_FAILED, "bluetooth-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, "gsm-sim-not-inserted"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, "gsm-sim-pin-required"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, "gsm-sim-puk-required"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, "gsm-sim-wrong"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_INFINIBAND_MODE, "infiniband-mode"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, "dependency-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BR2684_FAILED, "br2684-bridge-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE, "modem-manager-unavailable"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, "ssid-not-found"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED, "secondary-connection-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, "dcb-fcoe-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, "teamd-control-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_FAILED, "modem-failed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, "modem-available"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, "sim-pin-incorrect"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NEW_ACTIVATION, "new-activation"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED, "parent-changed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, "parent-managed-changed"),
|
2017-10-16 21:32:12 +02:00
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_OVSDB_FAILED, "ovsdb-failed"),
|
2017-11-02 14:22:10 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"),
|
2015-12-07 14:28:09 +01:00
|
|
|
);
|
2014-05-20 15:13:59 -05:00
|
|
|
|
2015-12-07 14:28:09 +01:00
|
|
|
#define reason_to_string(reason) \
|
2016-01-24 14:28:31 +01:00
|
|
|
NM_UTILS_LOOKUP_STR (_reason_to_string, reason)
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-05-16 19:01:37 +02:00
|
|
|
NMSettings *
|
|
|
|
|
nm_device_get_settings (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->settings;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
NMNetns *
|
|
|
|
|
nm_device_get_netns (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->netns;
|
|
|
|
|
}
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
NMDedupMultiIndex *
|
|
|
|
|
nm_device_get_multi_index (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return nm_netns_get_multi_idx (nm_device_get_netns (self));
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
NMPlatform *
|
|
|
|
|
nm_device_get_platform (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return nm_netns_get_platform (nm_device_get_netns (self));
|
|
|
|
|
}
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
static NMIP4Config *
|
|
|
|
|
_ip4_config_new (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return nm_ip4_config_new (nm_device_get_multi_index (self),
|
|
|
|
|
nm_device_get_ip_ifindex (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMIP6Config *
|
|
|
|
|
_ip6_config_new (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return nm_ip6_config_new (nm_device_get_multi_index (self),
|
|
|
|
|
nm_device_get_ip_ifindex (self));
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_sys_iface_state_to_str, NMDeviceSysIfaceState,
|
|
|
|
|
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_ASSUME, "assume"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_MANAGED, "managed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_REMOVED, "removed"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
NMDeviceSysIfaceState
|
|
|
|
|
nm_device_sys_iface_state_get (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->sys_iface_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_sys_iface_state_is_external (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_IN_SET (nm_device_sys_iface_state_get (self),
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_sys_iface_state_is_external_or_assume (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_IN_SET (nm_device_sys_iface_state_get (self),
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_ASSUME);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_sys_iface_state_set (NMDevice *self,
|
|
|
|
|
NMDeviceSysIfaceState sys_iface_state)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
g_return_if_fail (NM_IN_SET (sys_iface_state,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_ASSUME,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_MANAGED,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_REMOVED));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
if (priv->sys_iface_state != sys_iface_state) {
|
|
|
|
|
_LOGT (LOGD_DEVICE, "sys-iface-state: %s -> %s",
|
|
|
|
|
_sys_iface_state_to_str (priv->sys_iface_state),
|
|
|
|
|
_sys_iface_state_to_str (sys_iface_state));
|
|
|
|
|
priv->sys_iface_state = sys_iface_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this function only sets a flag, no immediate actions are initiated.
|
|
|
|
|
*
|
|
|
|
|
* If you change this, make sure that all callers are fine with such actions. */
|
|
|
|
|
|
|
|
|
|
nm_assert (priv->sys_iface_state == sys_iface_state);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-26 14:08:27 +02:00
|
|
|
static void
|
|
|
|
|
_active_connection_set_state_flags_full (NMDevice *self,
|
|
|
|
|
NMActivationStateFlags flags,
|
|
|
|
|
NMActivationStateFlags mask)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *ac;
|
|
|
|
|
|
|
|
|
|
ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (self));
|
|
|
|
|
if (ac)
|
|
|
|
|
nm_active_connection_set_state_flags_full (ac, flags, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_active_connection_set_state_flags (NMDevice *self,
|
|
|
|
|
NMActivationStateFlags flags)
|
|
|
|
|
{
|
|
|
|
|
_active_connection_set_state_flags_full (self, flags, flags);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
void
|
|
|
|
|
nm_device_assume_state_get (NMDevice *self,
|
|
|
|
|
gboolean *out_assume_state_guess_assume,
|
|
|
|
|
const char **out_assume_state_connection_uuid)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NM_SET_OUT (out_assume_state_guess_assume, priv->assume_state_guess_assume);
|
|
|
|
|
NM_SET_OUT (out_assume_state_connection_uuid, priv->assume_state_connection_uuid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_assume_state_set (NMDevice *self,
|
|
|
|
|
gboolean assume_state_guess_assume,
|
|
|
|
|
const char *assume_state_connection_uuid)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
if ( priv->assume_state_guess_assume == !!assume_state_guess_assume
|
|
|
|
|
&& nm_streq0 (priv->assume_state_connection_uuid, assume_state_connection_uuid))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_DEVICE, "assume-state: set guess-assume=%c, connection=%s%s%s",
|
|
|
|
|
assume_state_guess_assume ? '1' : '0',
|
|
|
|
|
NM_PRINT_FMT_QUOTE_STRING (assume_state_connection_uuid));
|
|
|
|
|
priv->assume_state_guess_assume = assume_state_guess_assume;
|
|
|
|
|
g_free (priv->assume_state_connection_uuid);
|
|
|
|
|
priv->assume_state_connection_uuid = g_strdup (assume_state_connection_uuid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_assume_state_reset (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
_assume_state_set (self, FALSE, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-05-09 16:30:41 +02:00
|
|
|
static void
|
|
|
|
|
init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config)
|
|
|
|
|
{
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
gint priority;
|
|
|
|
|
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"ipv4.dns-priority",
|
|
|
|
|
self);
|
|
|
|
|
priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0);
|
|
|
|
|
nm_ip4_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config)
|
|
|
|
|
{
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
gint priority;
|
|
|
|
|
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"ipv6.dns-priority",
|
|
|
|
|
self);
|
|
|
|
|
priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0);
|
|
|
|
|
nm_ip6_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-05-09 16:30:41 +02:00
|
|
|
|
2017-03-16 14:51:59 +00:00
|
|
|
static gboolean
|
|
|
|
|
nm_device_ipv4_sysctl_set (NMDevice *self, const char *property, const char *value)
|
|
|
|
|
{
|
2017-04-17 20:17:45 +02:00
|
|
|
NMPlatform *platform = nm_device_get_platform (self);
|
2017-03-16 14:51:59 +00:00
|
|
|
gs_free char *value_to_free = NULL;
|
|
|
|
|
const char *value_to_set;
|
2017-10-23 13:55:54 +02:00
|
|
|
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
|
2017-03-16 14:51:59 +00:00
|
|
|
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!nm_device_get_ip_ifindex (self))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2017-03-16 14:51:59 +00:00
|
|
|
if (value) {
|
|
|
|
|
value_to_set = value;
|
|
|
|
|
} else {
|
|
|
|
|
/* Set to a default value when we've got a NULL @value. */
|
|
|
|
|
value_to_free = nm_platform_sysctl_get (platform,
|
2017-10-23 13:55:54 +02:00
|
|
|
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, "default", property)));
|
2017-03-16 14:51:59 +00:00
|
|
|
value_to_set = value_to_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nm_platform_sysctl_set (platform,
|
2017-10-23 13:55:54 +02:00
|
|
|
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, nm_device_get_ip_iface (self), property)),
|
2017-03-16 14:51:59 +00:00
|
|
|
value_to_set);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
nm_device_ipv4_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback)
|
|
|
|
|
{
|
2017-10-23 13:55:54 +02:00
|
|
|
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
|
2017-10-23 13:55:54 +02:00
|
|
|
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!nm_device_get_ip_ifindex (self))
|
|
|
|
|
return fallback;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
return nm_platform_sysctl_get_int_checked (nm_device_get_platform (self),
|
2017-10-23 13:55:54 +02:00
|
|
|
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, nm_device_get_ip_iface (self), property)),
|
2017-03-16 14:51:59 +00:00
|
|
|
10,
|
|
|
|
|
0,
|
|
|
|
|
G_MAXUINT32,
|
|
|
|
|
fallback);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-15 21:03:42 -05:00
|
|
|
gboolean
|
2014-02-21 17:04:59 -05:00
|
|
|
nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value)
|
|
|
|
|
{
|
2017-10-23 13:55:54 +02:00
|
|
|
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
|
2017-10-23 13:55:54 +02:00
|
|
|
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!nm_device_get_ip_ifindex (self))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2017-10-23 13:55:54 +02:00
|
|
|
return nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET6, buf, nm_device_get_ip_iface (self), property)), value);
|
2010-05-03 03:42:43 -07:00
|
|
|
}
|
|
|
|
|
|
2015-02-25 15:35:26 +01:00
|
|
|
static guint32
|
2017-01-14 12:51:01 +01:00
|
|
|
nm_device_ipv6_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback)
|
2015-02-25 15:35:26 +01:00
|
|
|
{
|
2017-10-23 13:55:54 +02:00
|
|
|
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
|
2017-10-23 13:55:54 +02:00
|
|
|
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!nm_device_get_ip_ifindex (self))
|
|
|
|
|
return fallback;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
return nm_platform_sysctl_get_int_checked (nm_device_get_platform (self),
|
2017-10-23 13:55:54 +02:00
|
|
|
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET6, buf, nm_device_get_ip_iface (self), property)),
|
2017-01-14 12:51:01 +01:00
|
|
|
10,
|
|
|
|
|
0,
|
|
|
|
|
G_MAXUINT32,
|
|
|
|
|
fallback);
|
2015-02-25 15:35:26 +01:00
|
|
|
}
|
|
|
|
|
|
2015-04-17 15:19:48 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps)
|
2012-06-01 16:48:57 +02:00
|
|
|
{
|
2015-04-17 15:15:38 +02:00
|
|
|
return NM_FLAGS_ANY (NM_DEVICE_GET_PRIVATE (self)->capabilities, caps);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2012-06-01 16:48:57 +02:00
|
|
|
|
2016-05-09 18:16:45 +02:00
|
|
|
static void
|
|
|
|
|
_add_capabilities (NMDevice *self, NMDeviceCapabilities capabilities)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!NM_FLAGS_ALL (priv->capabilities, capabilities)) {
|
|
|
|
|
priv->capabilities |= capabilities;
|
|
|
|
|
_notify (self, PROP_CAPABILITIES);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2013-01-22 16:43:15 +01:00
|
|
|
|
2016-06-21 18:07:56 +02:00
|
|
|
static const char *
|
2016-12-18 13:54:26 +01:00
|
|
|
_get_stable_id (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
NMUtilsStableType *out_stable_type)
|
2016-06-21 18:07:56 +02:00
|
|
|
{
|
2016-12-18 13:54:26 +01:00
|
|
|
NMDevicePrivate *priv;
|
2016-06-21 18:07:56 +02:00
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
2016-06-21 18:07:56 +02:00
|
|
|
nm_assert (NM_IS_CONNECTION (connection));
|
|
|
|
|
nm_assert (out_stable_type);
|
|
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* we cache the generated stable ID for the time of an activation.
|
|
|
|
|
*
|
|
|
|
|
* The reason is, that we don't want the stable-id to change as long
|
|
|
|
|
* as the device is active.
|
|
|
|
|
*
|
|
|
|
|
* Especially with ${RANDOM} stable-id we want to generate *one* configuration
|
|
|
|
|
* for each activation. */
|
|
|
|
|
if (G_UNLIKELY (!priv->current_stable_id)) {
|
|
|
|
|
gs_free char *default_id = NULL;
|
|
|
|
|
gs_free char *generated = NULL;
|
|
|
|
|
NMUtilsStableType stable_type;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
const char *stable_id;
|
|
|
|
|
const char *uuid;
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
|
|
|
|
|
stable_id = nm_setting_connection_get_stable_id (s_con);
|
|
|
|
|
|
|
|
|
|
if (!stable_id) {
|
|
|
|
|
default_id = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"connection.stable-id",
|
|
|
|
|
self);
|
|
|
|
|
stable_id = default_id;
|
|
|
|
|
}
|
2016-06-21 18:07:56 +02:00
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
uuid = nm_connection_get_uuid (connection);
|
|
|
|
|
|
|
|
|
|
stable_type = nm_utils_stable_id_parse (stable_id,
|
|
|
|
|
uuid,
|
|
|
|
|
NULL,
|
|
|
|
|
&generated);
|
|
|
|
|
|
|
|
|
|
/* current_stable_id_type is a bitfield! */
|
|
|
|
|
priv->current_stable_id_type = stable_type;
|
2017-01-09 20:22:06 +01:00
|
|
|
nm_assert (stable_type <= (NMUtilsStableType) 0x3);
|
|
|
|
|
nm_assert (stable_type + (NMUtilsStableType) 1 > (NMUtilsStableType) 0);
|
|
|
|
|
nm_assert (priv->current_stable_id_type == stable_type);
|
2016-12-18 13:54:26 +01:00
|
|
|
|
|
|
|
|
if (stable_type == NM_UTILS_STABLE_TYPE_UUID)
|
|
|
|
|
priv->current_stable_id = g_strdup (uuid);
|
|
|
|
|
else if (stable_type == NM_UTILS_STABLE_TYPE_STABLE_ID)
|
|
|
|
|
priv->current_stable_id = g_strdup (stable_id);
|
|
|
|
|
else if (stable_type == NM_UTILS_STABLE_TYPE_GENERATED)
|
|
|
|
|
priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_generated_complete (generated));
|
|
|
|
|
else {
|
|
|
|
|
nm_assert (stable_type == NM_UTILS_STABLE_TYPE_RANDOM);
|
|
|
|
|
priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_random ());
|
|
|
|
|
}
|
|
|
|
|
_LOGT (LOGD_DEVICE,
|
|
|
|
|
"stable-id: type=%d, \"%s\""
|
|
|
|
|
"%s%s%s",
|
|
|
|
|
(int) priv->current_stable_id_type,
|
|
|
|
|
priv->current_stable_id,
|
|
|
|
|
NM_PRINT_FMT_QUOTED (stable_type == NM_UTILS_STABLE_TYPE_GENERATED, " from \"", generated, "\"", ""));
|
2016-06-21 18:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
*out_stable_type = priv->current_stable_id_type;
|
|
|
|
|
return priv->current_stable_id;
|
2016-06-21 18:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-06-21 18:07:56 +02:00
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_ip_state_to_string, IpState,
|
|
|
|
|
NM_UTILS_LOOKUP_DEFAULT_WARN ("unknown"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (IP_NONE, "none"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (IP_WAIT, "wait"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (IP_CONF, "conf"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (IP_DONE, "done"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (IP_FAIL, "fail"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_set_ip_state (NMDevice *self, int addr_family, IpState new_state)
|
|
|
|
|
{
|
|
|
|
|
IpState *p;
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_assert_addr_family (addr_family);
|
2016-08-29 14:27:46 +02:00
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
p = (addr_family == AF_INET)
|
|
|
|
|
? &priv->ip4_state_
|
|
|
|
|
: &priv->ip6_state_;
|
2016-08-29 14:27:46 +02:00
|
|
|
|
|
|
|
|
if (*p != new_state) {
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGT (LOGD_DEVICE, "ip%c-state: set to %d (%s)",
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
(int) new_state,
|
|
|
|
|
_ip_state_to_string (new_state));
|
2016-08-29 14:27:46 +02:00
|
|
|
*p = new_state;
|
2017-09-26 14:08:27 +02:00
|
|
|
|
|
|
|
|
if (new_state == IP_DONE) {
|
|
|
|
|
/* we only set the IPx_READY flag once we reach IP_DONE state. We don't
|
|
|
|
|
* ever clear it, even if we later enter IP_FAIL state.
|
|
|
|
|
*
|
|
|
|
|
* This is not documented/guaranteed behavior, but seems to make sense for now. */
|
|
|
|
|
_active_connection_set_state_flags (self,
|
|
|
|
|
addr_family == AF_INET
|
|
|
|
|
? NM_ACTIVATION_STATE_FLAG_IP4_READY
|
|
|
|
|
: NM_ACTIVATION_STATE_FLAG_IP6_READY);
|
|
|
|
|
}
|
2016-08-29 14:27:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
const char *
|
|
|
|
|
nm_device_get_udi (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->udi;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
nm_device_get_iface (NMDevice *self)
|
|
|
|
|
{
|
2015-07-08 16:49:19 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->iface;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2017-07-03 16:24:59 +02:00
|
|
|
gboolean
|
2017-09-08 14:09:51 +02:00
|
|
|
nm_device_take_over_link (NMDevice *self, const char *ifname, gboolean *renamed)
|
2017-07-03 16:24:59 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
const NMPlatformLink *plink;
|
|
|
|
|
NMPlatform *platform;
|
2017-09-08 14:09:51 +02:00
|
|
|
gboolean up, success = TRUE;
|
2017-07-03 16:24:59 +02:00
|
|
|
int ifindex;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (priv->ifindex <= 0, FALSE);
|
2017-09-08 14:09:51 +02:00
|
|
|
g_return_val_if_fail (ifname, FALSE);
|
|
|
|
|
|
|
|
|
|
NM_SET_OUT (renamed, FALSE);
|
2017-07-03 16:24:59 +02:00
|
|
|
|
|
|
|
|
platform = nm_device_get_platform (self);
|
|
|
|
|
plink = nm_platform_link_get_by_ifname (platform, ifname);
|
|
|
|
|
if (!plink)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
ifindex = plink->ifindex;
|
2017-09-08 14:09:51 +02:00
|
|
|
|
|
|
|
|
if (!nm_streq (ifname, nm_device_get_iface (self))) {
|
|
|
|
|
up = NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP);
|
|
|
|
|
|
|
|
|
|
/* Rename the link to the device ifname */
|
|
|
|
|
if (up)
|
|
|
|
|
nm_platform_link_set_down (platform, ifindex);
|
|
|
|
|
success = nm_platform_link_set_name (platform, ifindex, nm_device_get_iface (self));
|
|
|
|
|
if (up)
|
|
|
|
|
nm_platform_link_set_up (platform, ifindex, NULL);
|
|
|
|
|
|
|
|
|
|
NM_SET_OUT (renamed, success);
|
|
|
|
|
}
|
2017-07-03 16:24:59 +02:00
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
priv->ifindex = ifindex;
|
|
|
|
|
_notify (self, PROP_IFINDEX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-21 14:58:25 -07:00
|
|
|
int
|
|
|
|
|
nm_device_get_ifindex (NMDevice *self)
|
|
|
|
|
{
|
2014-09-24 16:58:07 -05:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), 0);
|
2010-04-21 14:58:25 -07:00
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ifindex;
|
|
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_is_software:
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
*
|
|
|
|
|
* Indicates if the device is a software-based virtual device without
|
|
|
|
|
* backing hardware, which can be added and removed programmatically.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the device is a software-based device
|
|
|
|
|
*/
|
2013-08-22 19:15:05 +02:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_is_software (NMDevice *self)
|
2013-08-22 19:15:05 +02:00
|
|
|
{
|
2014-09-24 17:46:15 -05:00
|
|
|
return NM_FLAGS_HAS (NM_DEVICE_GET_PRIVATE (self)->capabilities, NM_DEVICE_CAP_IS_SOFTWARE);
|
2013-08-22 19:15:05 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_is_real:
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the device exists, %FALSE if the device is a placeholder
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_is_real (NMDevice *self)
|
|
|
|
|
{
|
2016-01-12 10:38:16 +01:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->real;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
const char *
|
2007-12-06 14:51:43 +00:00
|
|
|
nm_device_get_ip_iface (NMDevice *self)
|
|
|
|
|
{
|
2009-07-07 14:34:01 -04:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
2007-12-06 14:51:43 +00:00
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2007-12-06 14:51:43 +00:00
|
|
|
/* If it's not set, default to iface */
|
2009-07-07 14:34:01 -04:00
|
|
|
return priv->ip_iface ? priv->ip_iface : priv->iface;
|
2007-12-06 14:51:43 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-21 14:58:25 -07:00
|
|
|
int
|
|
|
|
|
nm_device_get_ip_ifindex (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, 0);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-05-27 11:20:31 +02:00
|
|
|
/* If it's not set, default to ifindex */
|
2010-04-21 14:58:25 -07:00
|
|
|
return priv->ip_iface ? priv->ip_ifindex : priv->ifindex;
|
|
|
|
|
}
|
2007-12-06 14:51:43 +00:00
|
|
|
|
2017-01-11 19:35:09 -06:00
|
|
|
/**
|
|
|
|
|
* nm_device_set_ip_iface:
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @iface: the new IP interface name
|
|
|
|
|
*
|
|
|
|
|
* Updates the IP interface name and possibly the ifindex.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the anything (name or ifindex) changed, %FALSE if nothing
|
|
|
|
|
* changed.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2007-12-06 14:51:43 +00:00
|
|
|
nm_device_set_ip_iface (NMDevice *self, const char *iface)
|
|
|
|
|
{
|
2010-04-21 14:58:25 -07:00
|
|
|
NMDevicePrivate *priv;
|
2016-12-26 18:11:03 +01:00
|
|
|
int ifindex;
|
2010-04-21 14:58:25 -07:00
|
|
|
|
2017-01-11 19:35:09 -06:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2007-12-06 14:51:43 +00:00
|
|
|
|
2010-04-21 14:58:25 -07:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-12-26 18:11:03 +01:00
|
|
|
if (nm_streq0 (iface, priv->ip_iface)) {
|
|
|
|
|
if (!iface)
|
2017-01-11 19:35:09 -06:00
|
|
|
return FALSE;
|
2017-04-17 20:17:45 +02:00
|
|
|
ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), iface);
|
2016-12-26 18:11:03 +01:00
|
|
|
if ( ifindex <= 0
|
|
|
|
|
|| priv->ip_ifindex == ifindex)
|
2017-01-11 19:35:09 -06:00
|
|
|
return FALSE;
|
2014-07-24 17:14:30 -05:00
|
|
|
|
2016-12-26 18:11:03 +01:00
|
|
|
priv->ip_ifindex = ifindex;
|
|
|
|
|
_LOGD (LOGD_DEVICE, "ip-ifname: update ifindex for ifname '%s': %d", iface, priv->ip_ifindex);
|
|
|
|
|
} else {
|
|
|
|
|
g_free (priv->ip_iface);
|
|
|
|
|
priv->ip_iface = g_strdup (iface);
|
|
|
|
|
|
|
|
|
|
if (iface) {
|
|
|
|
|
/* The @iface name is not in sync with the platform cache.
|
|
|
|
|
* So, there is no point asking the platform cache to resolve
|
|
|
|
|
* the ifindex. Instead, we can only hope that the interface
|
|
|
|
|
* with this name still exists and we resolve the ifindex
|
|
|
|
|
* anew.
|
|
|
|
|
*/
|
2017-04-17 20:17:45 +02:00
|
|
|
priv->ip_ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), iface);
|
2016-12-26 18:11:03 +01:00
|
|
|
if (priv->ip_ifindex > 0)
|
|
|
|
|
_LOGD (LOGD_DEVICE, "ip-ifname: set ifname '%s', ifindex %d", iface, priv->ip_ifindex);
|
|
|
|
|
else
|
|
|
|
|
_LOGW (LOGD_DEVICE, "ip-ifname: set ifname '%s', unknown ifindex", iface);
|
core: don't up devices during IP configuration stages
Assumed connections shouldn't require touching the device, and the
device should was already set IFF_UP during stage2 (which is
skipped for assumed connections). Instead, what the code was really
trying to do, was to ensure tha the IP interface the device was
going to use was up.
The only cases where the IP interface might *not* be up after stage2
is where the IP interface is different than the device's interface,
like for Bluetooth, ADSL, WWAN, and PPPoE. Move the call to
nm_platform_link_set_up() into nm_device_set_ip_iface() which all
those device types will call.
Thus, only the device types that really need to up their IP interface
will do so, but other devices (including when activating assumed
connections) that don't need to do this, won't do it.
2013-11-08 10:58:35 -06:00
|
|
|
} else {
|
2016-12-26 18:11:03 +01:00
|
|
|
priv->ip_ifindex = 0;
|
|
|
|
|
_LOGD (LOGD_DEVICE, "ip-ifname: clear ifname");
|
2010-04-21 14:58:25 -07:00
|
|
|
}
|
|
|
|
|
}
|
2010-06-10 10:16:39 -07:00
|
|
|
|
2016-12-26 18:11:03 +01:00
|
|
|
if (priv->ip_ifindex > 0) {
|
2017-10-10 18:20:05 +02:00
|
|
|
if (nm_platform_check_kernel_support (nm_device_get_platform (self),
|
|
|
|
|
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_set_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ip_ifindex, TRUE);
|
2016-12-26 18:11:03 +01:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_is_up (nm_device_get_platform (self), priv->ip_ifindex))
|
|
|
|
|
nm_platform_link_set_up (nm_device_get_platform (self), priv->ip_ifindex, NULL);
|
2016-12-26 18:11:03 +01:00
|
|
|
}
|
2016-10-19 15:55:01 +02:00
|
|
|
|
2014-02-21 17:04:59 -05:00
|
|
|
/* We don't care about any saved values from the old iface */
|
|
|
|
|
g_hash_table_remove_all (priv->ip6_saved_properties);
|
2013-10-24 13:55:06 -04:00
|
|
|
|
2016-12-26 18:11:03 +01:00
|
|
|
_notify (self, PROP_IP_IFACE);
|
2017-01-11 19:35:09 -06:00
|
|
|
return TRUE;
|
2016-12-26 18:11:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_ip_iface_update (NMDevice *self, const char *ip_iface)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (priv->ip_iface, FALSE);
|
|
|
|
|
g_return_val_if_fail (priv->ip_ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (ip_iface, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!ip_iface[0])
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (nm_streq (priv->ip_iface, ip_iface))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
_LOGI (LOGD_DEVICE, "ip-ifname: interface index %d renamed ip_iface (%d) from '%s' to '%s'",
|
|
|
|
|
priv->ifindex, priv->ip_ifindex,
|
|
|
|
|
priv->ip_iface, ip_iface);
|
|
|
|
|
g_free (priv->ip_iface);
|
|
|
|
|
priv->ip_iface = g_strdup (ip_iface);
|
|
|
|
|
_notify (self, PROP_IP_IFACE);
|
|
|
|
|
return TRUE;
|
2007-12-06 14:51:43 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-12-26 11:12:39 +01:00
|
|
|
int
|
|
|
|
|
nm_device_parent_get_ifindex (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), 0);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
return priv->parent_ifindex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMDevice *
|
|
|
|
|
nm_device_parent_get_device (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
return priv->parent_device;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parent_changed_notify (NMDevice *self,
|
|
|
|
|
int old_ifindex,
|
|
|
|
|
NMDevice *old_parent,
|
|
|
|
|
int new_ifindex,
|
|
|
|
|
NMDevice *new_parent)
|
|
|
|
|
{
|
|
|
|
|
/* empty handler to allow subclasses to always chain up the virtual function. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_parent_set_ifindex (NMDevice *self,
|
|
|
|
|
int parent_ifindex,
|
|
|
|
|
gboolean force_check)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMDevice *parent_device;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
int old_ifindex;
|
|
|
|
|
NMDevice *old_device;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (parent_ifindex <= 0)
|
|
|
|
|
parent_ifindex = 0;
|
|
|
|
|
|
|
|
|
|
old_ifindex = priv->parent_ifindex;
|
|
|
|
|
old_device = priv->parent_device;
|
|
|
|
|
|
|
|
|
|
if (priv->parent_ifindex == parent_ifindex) {
|
|
|
|
|
if (parent_ifindex > 0) {
|
|
|
|
|
if ( !force_check
|
|
|
|
|
&& priv->parent_device
|
|
|
|
|
&& nm_device_get_ifindex (priv->parent_device) == parent_ifindex)
|
|
|
|
|
return FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
if (!priv->parent_device)
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
priv->parent_ifindex = parent_ifindex;
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parent_ifindex > 0) {
|
|
|
|
|
parent_device = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
|
|
|
|
|
if (parent_device == self)
|
|
|
|
|
parent_device = NULL;
|
|
|
|
|
} else
|
|
|
|
|
parent_device = NULL;
|
|
|
|
|
|
|
|
|
|
if (parent_device != priv->parent_device) {
|
|
|
|
|
priv->parent_device = parent_device;
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
|
if (priv->parent_ifindex <= 0)
|
|
|
|
|
_LOGD (LOGD_DEVICE, "parent: clear");
|
|
|
|
|
else if (!priv->parent_device)
|
|
|
|
|
_LOGD (LOGD_DEVICE, "parent: ifindex %d, no device", priv->parent_ifindex);
|
|
|
|
|
else {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "parent: ifindex %d, device %p, %s", priv->parent_ifindex,
|
|
|
|
|
priv->parent_device, nm_device_get_iface (priv->parent_device));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->parent_changed_notify (self, old_ifindex, old_device, priv->parent_ifindex, priv->parent_device);
|
|
|
|
|
|
|
|
|
|
_notify (self, PROP_PARENT);
|
|
|
|
|
}
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_parent_set_ifindex (NMDevice *self,
|
|
|
|
|
int parent_ifindex)
|
|
|
|
|
{
|
|
|
|
|
_parent_set_ifindex (self, parent_ifindex, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_parent_notify_changed (NMDevice *self,
|
|
|
|
|
NMDevice *change_candidate,
|
|
|
|
|
gboolean device_removed)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
|
|
|
|
nm_assert (NM_IS_DEVICE (change_candidate));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->parent_ifindex > 0) {
|
|
|
|
|
if ( priv->parent_device == change_candidate
|
|
|
|
|
|| priv->parent_ifindex == nm_device_get_ifindex (change_candidate))
|
|
|
|
|
return _parent_set_ifindex (self, priv->parent_ifindex, device_removed);
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
static void
|
|
|
|
|
_stats_update_counters (NMDevice *self,
|
|
|
|
|
guint64 tx_bytes,
|
|
|
|
|
guint64 rx_bytes)
|
2016-08-10 11:54:31 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
if (priv->stats.tx_bytes != tx_bytes) {
|
|
|
|
|
priv->stats.tx_bytes = tx_bytes;
|
|
|
|
|
_notify (self, PROP_TX_BYTES);
|
|
|
|
|
}
|
|
|
|
|
if (priv->stats.rx_bytes != rx_bytes) {
|
|
|
|
|
priv->stats.rx_bytes = rx_bytes;
|
|
|
|
|
_notify (self, PROP_RX_BYTES);
|
|
|
|
|
}
|
2016-08-10 11:54:31 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
static void
|
2016-08-16 15:55:04 +02:00
|
|
|
_stats_update_counters_from_pllink (NMDevice *self, const NMPlatformLink *pllink)
|
2016-08-10 11:54:31 +02:00
|
|
|
{
|
2016-08-16 15:55:04 +02:00
|
|
|
_stats_update_counters (self, pllink->tx_bytes, pllink->rx_bytes);
|
2016-08-16 12:10:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_stats_timeout_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = user_data;
|
2016-08-16 15:55:04 +02:00
|
|
|
int ifindex;
|
|
|
|
|
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
|
|
|
|
|
_LOGT (LOGD_DEVICE, "stats: refresh %d", ifindex);
|
|
|
|
|
|
|
|
|
|
if (ifindex > 0)
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_refresh (nm_device_get_platform (self), ifindex);
|
2016-08-16 12:10:23 +02:00
|
|
|
|
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
_stats_refresh_rate_real (guint refresh_rate_ms)
|
|
|
|
|
{
|
|
|
|
|
const guint STATS_REFRESH_RATE_MS_MIN = 200;
|
|
|
|
|
|
|
|
|
|
if (refresh_rate_ms == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (refresh_rate_ms < STATS_REFRESH_RATE_MS_MIN) {
|
|
|
|
|
/* you cannot set the refresh-rate arbitrarly small. E.g.
|
|
|
|
|
* setting to 1ms is just killing. Have a lowest number. */
|
|
|
|
|
return STATS_REFRESH_RATE_MS_MIN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return refresh_rate_ms;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_stats_set_refresh_rate (NMDevice *self, guint refresh_rate_ms)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2016-08-16 15:55:04 +02:00
|
|
|
int ifindex;
|
2016-08-16 12:10:23 +02:00
|
|
|
guint old_rate;
|
2016-08-10 11:54:31 +02:00
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-08-16 12:10:23 +02:00
|
|
|
|
|
|
|
|
if (priv->stats.refresh_rate_ms == refresh_rate_ms)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
old_rate = priv->stats.refresh_rate_ms;
|
|
|
|
|
priv->stats.refresh_rate_ms = refresh_rate_ms;
|
|
|
|
|
_notify (self, PROP_REFRESH_RATE_MS);
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_DEVICE, "stats: set refresh to %u ms", priv->stats.refresh_rate_ms);
|
|
|
|
|
|
|
|
|
|
if (!nm_device_is_real (self))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
refresh_rate_ms = _stats_refresh_rate_real (refresh_rate_ms);
|
|
|
|
|
if (_stats_refresh_rate_real (old_rate) == refresh_rate_ms)
|
2016-08-10 11:54:31 +02:00
|
|
|
return;
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
nm_clear_g_source (&priv->stats.timeout_id);
|
|
|
|
|
|
2016-08-16 15:55:04 +02:00
|
|
|
if (!refresh_rate_ms)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* trigger an inital refresh of the data whenever the refresh-rate changes.
|
|
|
|
|
* As we process the result in an idle handler with device_link_changed(),
|
|
|
|
|
* we don't get the result right away. */
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
if (ifindex > 0)
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_refresh (nm_device_get_platform (self), ifindex);
|
2016-08-16 12:10:23 +02:00
|
|
|
|
|
|
|
|
priv->stats.timeout_id = g_timeout_add (refresh_rate_ms, _stats_timeout_cb, self);
|
2016-08-10 11:54:31 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-04-10 15:29:45 -05:00
|
|
|
static gboolean
|
|
|
|
|
get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid)
|
|
|
|
|
{
|
2015-03-24 12:46:18 -05:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-05-09 17:19:30 +02:00
|
|
|
const NMPlatformLink *pllink;
|
2014-04-10 15:29:45 -05:00
|
|
|
int ifindex;
|
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
/* If we get here, we *must* have a kernel netdev, which implies an ifindex */
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
2016-05-09 17:21:41 +02:00
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
2014-04-10 15:29:45 -05:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex);
|
2016-05-09 17:21:41 +02:00
|
|
|
if ( !pllink
|
|
|
|
|
|| NM_IN_SET (pllink->type, NM_LINK_TYPE_NONE, NM_LINK_TYPE_UNKNOWN))
|
|
|
|
|
return FALSE;
|
2014-04-10 15:29:45 -05:00
|
|
|
|
2016-05-09 17:19:30 +02:00
|
|
|
if (pllink->addr.len <= 0)
|
2014-04-10 15:29:45 -05:00
|
|
|
return FALSE;
|
2016-05-09 17:19:30 +02:00
|
|
|
if (pllink->addr.len > NM_UTILS_HWADDR_LEN_MAX)
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
2014-04-10 15:29:45 -05:00
|
|
|
|
2016-05-09 17:19:30 +02:00
|
|
|
success = nm_utils_get_ipv6_interface_identifier (pllink->type,
|
|
|
|
|
pllink->addr.data,
|
|
|
|
|
pllink->addr.len,
|
2015-03-24 12:46:18 -05:00
|
|
|
priv->dev_id,
|
2014-04-10 15:29:45 -05:00
|
|
|
out_iid);
|
|
|
|
|
if (!success) {
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGW (LOGD_PLATFORM, "failed to generate interface identifier "
|
2016-05-09 17:19:30 +02:00
|
|
|
"for link type %u hwaddr_len %u", pllink->type, (unsigned) pllink->addr.len);
|
2014-04-10 15:29:45 -05:00
|
|
|
}
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-11 12:19:28 +02:00
|
|
|
/**
|
|
|
|
|
* nm_device_get_ip_iface_identifier:
|
|
|
|
|
* @self: an #NMDevice
|
|
|
|
|
* @iid: where to place the interface identifier
|
|
|
|
|
* @ignore_token: force creation of a non-tokenized address
|
|
|
|
|
*
|
|
|
|
|
* Return the interface's identifier for the EUI64 address generation mode.
|
|
|
|
|
* It's either a manually set token or and identifier generated in a
|
|
|
|
|
* hardware-specific way.
|
|
|
|
|
*
|
|
|
|
|
* Unless @ignore_token is set the token is preferred. That is the case
|
|
|
|
|
* for link-local addresses (to mimic kernel behavior).
|
|
|
|
|
*
|
|
|
|
|
* Returns: #TRUE if the @iid could be set
|
|
|
|
|
*/
|
2014-07-24 17:14:30 -05:00
|
|
|
static gboolean
|
2016-05-11 12:19:28 +02:00
|
|
|
nm_device_get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *iid, gboolean ignore_token)
|
2014-07-24 17:14:30 -05:00
|
|
|
{
|
2016-05-11 12:19:28 +02:00
|
|
|
NMSettingIP6Config *s_ip6;
|
|
|
|
|
const char *token = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
2016-07-07 16:29:25 +02:00
|
|
|
if (!ignore_token) {
|
|
|
|
|
s_ip6 = (NMSettingIP6Config *)
|
2017-04-27 13:58:38 +02:00
|
|
|
nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP6_CONFIG);
|
2016-07-07 16:29:25 +02:00
|
|
|
g_return_val_if_fail (s_ip6, FALSE);
|
2016-05-11 12:19:28 +02:00
|
|
|
token = nm_setting_ip6_config_get_token (s_ip6);
|
2016-07-07 16:29:25 +02:00
|
|
|
}
|
2016-05-11 12:19:28 +02:00
|
|
|
if (token)
|
|
|
|
|
return nm_utils_ipv6_interface_identifier_get_from_token (iid, token);
|
|
|
|
|
else
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->get_ip_iface_identifier (self, iid);
|
2014-07-24 17:14:30 -05:00
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
const char *
|
|
|
|
|
nm_device_get_driver (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->driver;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2012-06-01 16:48:57 +02:00
|
|
|
const char *
|
|
|
|
|
nm_device_get_driver_version (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->driver_version;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
NMDeviceType
|
|
|
|
|
nm_device_get_device_type (NMDevice *self)
|
|
|
|
|
{
|
2008-06-10 15:54:23 +00:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->type;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-08 14:49:50 +01:00
|
|
|
NMLinkType
|
|
|
|
|
nm_device_get_link_type (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_LINK_TYPE_UNKNOWN);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->link_type;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-29 16:34:38 +02:00
|
|
|
/**
|
|
|
|
|
* nm_device_get_metered:
|
|
|
|
|
* @setting: the #NMDevice
|
|
|
|
|
*
|
|
|
|
|
* Returns: the #NMDevice:metered property of the device.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
|
|
|
|
NMMetered
|
|
|
|
|
nm_device_get_metered (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_METERED_UNKNOWN);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->metered;
|
|
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2017-09-28 15:06:28 +02:00
|
|
|
static guint32
|
|
|
|
|
_get_route_metric_default (NMDevice *self)
|
2008-09-30 15:04:10 +00:00
|
|
|
{
|
2014-11-26 19:35:12 +01:00
|
|
|
/* Device 'priority' is used for the default route-metric and is based on
|
|
|
|
|
* the device type. The settings ipv4.route-metric and ipv6.route-metric
|
|
|
|
|
* can overwrite this default.
|
2012-05-17 17:01:50 -05:00
|
|
|
*
|
2017-09-28 15:06:28 +02:00
|
|
|
* For both IPv4 and IPv6 we use the same default values.
|
2014-11-26 19:35:12 +01:00
|
|
|
*
|
|
|
|
|
* The route-metric is used for the metric of the routes of device.
|
|
|
|
|
* This also applies to the default route. Therefore it affects also
|
|
|
|
|
* which device is the "best".
|
|
|
|
|
*
|
|
|
|
|
* For comparison, note that iproute2 by default adds IPv4 routes with
|
|
|
|
|
* metric 0, and IPv6 routes with metric 1024. The latter is the IPv6
|
2014-11-26 20:47:44 +01:00
|
|
|
* "user default" in the kernel (NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6).
|
2014-11-26 19:35:12 +01:00
|
|
|
* In kernel, the full uint32_t range is available for route
|
|
|
|
|
* metrics (except for IPv6, where 0 means 1024).
|
2012-05-17 17:01:50 -05:00
|
|
|
*/
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
switch (nm_device_get_device_type (self)) {
|
2014-11-26 19:35:12 +01:00
|
|
|
/* 50 is reserved for VPN (NM_VPN_ROUTE_METRIC_DEFAULT) */
|
2012-05-17 17:01:50 -05:00
|
|
|
case NM_DEVICE_TYPE_ETHERNET:
|
2016-02-24 17:37:50 +01:00
|
|
|
case NM_DEVICE_TYPE_VETH:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 100;
|
2016-06-30 18:20:22 +02:00
|
|
|
case NM_DEVICE_TYPE_MACSEC:
|
|
|
|
|
return 125;
|
2012-05-17 17:01:50 -05:00
|
|
|
case NM_DEVICE_TYPE_INFINIBAND:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 150;
|
2012-05-17 17:01:50 -05:00
|
|
|
case NM_DEVICE_TYPE_ADSL:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 200;
|
2012-05-17 17:01:50 -05:00
|
|
|
case NM_DEVICE_TYPE_WIMAX:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 250;
|
2012-05-17 17:01:50 -05:00
|
|
|
case NM_DEVICE_TYPE_BOND:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 300;
|
2013-07-25 15:36:45 +02:00
|
|
|
case NM_DEVICE_TYPE_TEAM:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 350;
|
2013-07-25 15:36:45 +02:00
|
|
|
case NM_DEVICE_TYPE_VLAN:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 400;
|
2015-10-01 11:06:42 +02:00
|
|
|
case NM_DEVICE_TYPE_MACVLAN:
|
|
|
|
|
return 410;
|
2015-01-22 18:47:32 +01:00
|
|
|
case NM_DEVICE_TYPE_BRIDGE:
|
|
|
|
|
return 425;
|
2015-09-15 15:08:06 +02:00
|
|
|
case NM_DEVICE_TYPE_TUN:
|
|
|
|
|
return 450;
|
2017-06-06 15:55:08 +02:00
|
|
|
case NM_DEVICE_TYPE_PPP:
|
|
|
|
|
return 460;
|
2015-10-14 10:52:09 +02:00
|
|
|
case NM_DEVICE_TYPE_VXLAN:
|
|
|
|
|
return 500;
|
2017-01-31 14:14:33 +01:00
|
|
|
case NM_DEVICE_TYPE_DUMMY:
|
|
|
|
|
return 550;
|
2013-07-25 15:36:45 +02:00
|
|
|
case NM_DEVICE_TYPE_WIFI:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 600;
|
2013-07-25 15:36:45 +02:00
|
|
|
case NM_DEVICE_TYPE_OLPC_MESH:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 650;
|
2015-10-30 15:14:23 +01:00
|
|
|
case NM_DEVICE_TYPE_IP_TUNNEL:
|
|
|
|
|
return 675;
|
2015-07-21 11:37:10 +02:00
|
|
|
case NM_DEVICE_TYPE_MODEM:
|
|
|
|
|
return 700;
|
|
|
|
|
case NM_DEVICE_TYPE_BT:
|
|
|
|
|
return 750;
|
2017-10-02 08:39:09 +02:00
|
|
|
case NM_DEVICE_TYPE_OVS_BRIDGE:
|
2017-10-02 08:39:09 +02:00
|
|
|
case NM_DEVICE_TYPE_OVS_INTERFACE:
|
2017-10-02 08:39:09 +02:00
|
|
|
case NM_DEVICE_TYPE_OVS_PORT:
|
2017-10-02 08:39:09 +02:00
|
|
|
return 800;
|
2015-01-22 18:47:32 +01:00
|
|
|
case NM_DEVICE_TYPE_GENERIC:
|
2014-11-26 19:35:12 +01:00
|
|
|
return 950;
|
2015-01-22 18:47:32 +01:00
|
|
|
case NM_DEVICE_TYPE_UNKNOWN:
|
|
|
|
|
return 10000;
|
|
|
|
|
case NM_DEVICE_TYPE_UNUSED1:
|
|
|
|
|
case NM_DEVICE_TYPE_UNUSED2:
|
|
|
|
|
/* omit default: to get compiler warning about missing switch cases */
|
|
|
|
|
break;
|
2012-05-17 17:01:50 -05:00
|
|
|
}
|
2015-01-22 18:47:32 +01:00
|
|
|
return 11000;
|
2008-09-30 15:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
static gboolean
|
|
|
|
|
default_route_metric_penalty_detect (NMDevice *self)
|
2017-03-27 15:22:22 +00:00
|
|
|
{
|
2017-05-03 18:05:44 +02:00
|
|
|
#if WITH_CONCHECK
|
2017-03-27 15:22:22 +00:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-05-02 18:19:08 +02:00
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
/* currently we don't differentiate between IPv4 and IPv6 when detecting
|
|
|
|
|
* connectivity. */
|
2017-05-03 18:05:44 +02:00
|
|
|
if ( priv->connectivity_state != NM_CONNECTIVITY_FULL
|
2017-10-04 15:21:21 +02:00
|
|
|
&& nm_connectivity_check_enabled (nm_connectivity_get ())) {
|
|
|
|
|
return TRUE;
|
2017-05-02 18:19:08 +02:00
|
|
|
}
|
2017-05-03 18:05:44 +02:00
|
|
|
#endif
|
2017-10-04 15:21:21 +02:00
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
default_route_metric_penalty_get (NMDevice *self, int addr_family)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
nm_assert_addr_family (addr_family);
|
|
|
|
|
|
|
|
|
|
if ( addr_family == AF_INET
|
|
|
|
|
? priv->default_route_metric_penalty_ip4_has
|
|
|
|
|
: priv->default_route_metric_penalty_ip6_has)
|
|
|
|
|
return 20000;
|
|
|
|
|
return 0;
|
2017-03-27 15:22:22 +00:00
|
|
|
}
|
|
|
|
|
|
2017-08-30 19:10:15 +02:00
|
|
|
guint32
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (NMDevice *self,
|
|
|
|
|
int addr_family)
|
2014-08-28 18:11:35 +02:00
|
|
|
{
|
2015-05-15 12:21:59 +02:00
|
|
|
char *value;
|
|
|
|
|
gint64 route_metric;
|
|
|
|
|
NMSettingIPConfig *s_ip;
|
2014-08-28 18:32:05 +02:00
|
|
|
NMConnection *connection;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), G_MAXUINT32);
|
2017-08-30 19:10:15 +02:00
|
|
|
g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), G_MAXUINT32);
|
2014-08-28 18:32:05 +02:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2015-05-15 12:21:59 +02:00
|
|
|
if (connection) {
|
2017-08-30 19:10:15 +02:00
|
|
|
s_ip = addr_family == AF_INET
|
2015-05-15 12:21:59 +02:00
|
|
|
? nm_connection_get_setting_ip4_config (connection)
|
|
|
|
|
: nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
|
|
|
|
|
/* Slave interfaces don't have IP settings, but we may get here when
|
|
|
|
|
* external changes are made or when noticing IP changes when starting
|
|
|
|
|
* the slave connection.
|
|
|
|
|
*/
|
|
|
|
|
if (s_ip) {
|
|
|
|
|
route_metric = nm_setting_ip_config_get_route_metric (s_ip);
|
|
|
|
|
if (route_metric >= 0)
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-12 15:04:16 -05:00
|
|
|
|
2015-05-15 12:21:59 +02:00
|
|
|
/* use the current NMConfigData, which makes this configuration reloadable.
|
|
|
|
|
* Note that that means that the route-metric might change between SIGHUP.
|
|
|
|
|
* You must cache the returned value if that is a problem. */
|
2015-06-09 08:47:41 +02:00
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
2017-08-30 19:10:15 +02:00
|
|
|
addr_family == AF_INET ? "ipv4.route-metric" : "ipv6.route-metric", self);
|
2015-05-15 12:21:59 +02:00
|
|
|
if (value) {
|
|
|
|
|
route_metric = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1);
|
|
|
|
|
g_free (value);
|
|
|
|
|
|
|
|
|
|
if (route_metric >= 0)
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2017-09-28 15:06:28 +02:00
|
|
|
route_metric = _get_route_metric_default (self);
|
2015-05-15 12:21:59 +02:00
|
|
|
out:
|
2017-08-30 19:10:15 +02:00
|
|
|
return nm_utils_ip_route_metric_normalize (addr_family, route_metric);
|
2014-08-28 18:11:35 +02:00
|
|
|
}
|
|
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
guint32
|
|
|
|
|
nm_device_get_route_table (NMDevice *self,
|
|
|
|
|
int addr_family,
|
|
|
|
|
gboolean fallback_main)
|
2017-09-13 17:42:41 +02:00
|
|
|
{
|
2017-10-04 15:21:21 +02:00
|
|
|
NMDevicePrivate *priv;
|
2017-09-13 17:42:41 +02:00
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingIPConfig *s_ip;
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
guint32 route_table = 0;
|
2017-09-13 17:42:41 +02:00
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_assert_addr_family (addr_family);
|
2017-09-13 17:42:41 +02:00
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), RT_TABLE_MAIN);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
/* the route table setting affects how we sync routes. We shall
|
|
|
|
|
* not change it while the device is active, hence, cache it. */
|
|
|
|
|
if (addr_family == AF_INET) {
|
|
|
|
|
if (priv->v4_route_table_initalized)
|
|
|
|
|
return priv->v4_route_table ?: (fallback_main ? RT_TABLE_MAIN : 0);
|
|
|
|
|
} else {
|
|
|
|
|
if (priv->v6_route_table_initalized)
|
|
|
|
|
return priv->v6_route_table ?: (fallback_main ? RT_TABLE_MAIN : 0);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-13 17:42:41 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (connection) {
|
|
|
|
|
if (addr_family == AF_INET)
|
|
|
|
|
s_ip = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
else
|
|
|
|
|
s_ip = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
|
|
|
|
|
if (s_ip)
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
route_table = nm_setting_ip_config_get_route_table (s_ip);
|
2017-09-13 17:42:41 +02:00
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
/* we only lookup the global default if we also have an applied
|
|
|
|
|
* connection. Otherwise, the connection is not active, and the
|
|
|
|
|
* connection default doesn't matter. */
|
|
|
|
|
if (route_table == 0) {
|
|
|
|
|
gs_free char *value = NULL;
|
2017-09-13 17:42:41 +02:00
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
addr_family == AF_INET
|
|
|
|
|
? "ipv4.route-table"
|
|
|
|
|
: "ipv6.route-table",
|
|
|
|
|
self);
|
|
|
|
|
route_table = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-13 17:42:41 +02:00
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
if (addr_family == AF_INET) {
|
|
|
|
|
priv->v4_route_table_initalized = TRUE;
|
|
|
|
|
priv->v4_route_table = route_table;
|
|
|
|
|
} else {
|
|
|
|
|
priv->v6_route_table_initalized = TRUE;
|
|
|
|
|
priv->v6_route_table = route_table;
|
2017-09-13 17:42:41 +02:00
|
|
|
}
|
|
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
_LOGT (LOGD_DEVICE,
|
|
|
|
|
"ipv%c.route-table = %u%s",
|
|
|
|
|
addr_family == AF_INET ? '4' : '6',
|
|
|
|
|
(guint) (route_table ?: RT_TABLE_MAIN),
|
|
|
|
|
route_table ? "" : " (policy routing not enabled)");
|
|
|
|
|
|
|
|
|
|
return route_table ?: (fallback_main ? RT_TABLE_MAIN : 0);
|
2017-09-13 17:42:41 +02:00
|
|
|
}
|
|
|
|
|
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
const NMPObject *
|
|
|
|
|
nm_device_get_best_default_route (NMDevice *self,
|
|
|
|
|
int addr_family)
|
2016-04-15 17:43:17 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
switch (addr_family) {
|
|
|
|
|
case AF_INET:
|
2017-10-04 15:21:21 +02:00
|
|
|
return priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL;
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
case AF_INET6:
|
2017-10-04 15:21:21 +02:00
|
|
|
return priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL;
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
case AF_UNSPEC:
|
|
|
|
|
return (priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL)
|
2017-10-04 15:21:21 +02:00
|
|
|
?: (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL);
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
default:
|
|
|
|
|
g_return_val_if_reached (NULL);
|
2016-04-15 17:43:17 +02:00
|
|
|
}
|
2014-08-29 00:03:47 +02:00
|
|
|
}
|
|
|
|
|
|
2009-07-07 14:24:12 -04:00
|
|
|
const char *
|
|
|
|
|
nm_device_get_type_desc (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
2009-07-07 14:34:01 -04:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->type_desc;
|
2009-07-07 14:24:12 -04:00
|
|
|
}
|
|
|
|
|
|
2015-05-15 15:00:07 +02:00
|
|
|
const char *
|
|
|
|
|
nm_device_get_type_description (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
/* Beware: this function should return the same
|
|
|
|
|
* value as nm_device_get_type_description() in libnm. */
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->get_type_description (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
get_type_description (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!priv->type_description) {
|
|
|
|
|
const char *typename;
|
|
|
|
|
|
|
|
|
|
typename = G_OBJECT_TYPE_NAME (self);
|
|
|
|
|
if (g_str_has_prefix (typename, "NMDevice"))
|
|
|
|
|
typename += 8;
|
|
|
|
|
priv->type_description = g_ascii_strdown (typename, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return priv->type_description;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 16:09:22 -05:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_has_carrier (NMDevice *self)
|
2014-05-20 16:09:22 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->carrier;
|
2014-05-20 16:09:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMActRequest *
|
|
|
|
|
nm_device_get_act_request (NMDevice *self)
|
|
|
|
|
{
|
2017-03-08 14:11:22 +01:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
2014-05-20 16:09:22 -05:00
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->act_request;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
NMSettingsConnection *
|
|
|
|
|
nm_device_get_settings_connection (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
return priv->act_request ? nm_act_request_get_settings_connection (priv->act_request) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 16:09:22 -05:00
|
|
|
NMConnection *
|
2015-07-14 16:53:24 +02:00
|
|
|
nm_device_get_applied_connection (NMDevice *self)
|
2014-05-20 16:09:22 -05:00
|
|
|
{
|
2016-06-02 22:16:54 +02:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 16:09:22 -05:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFlags compare_flags)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!priv->act_request)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags);
|
2014-05-20 16:09:22 -05:00
|
|
|
}
|
|
|
|
|
|
2016-02-11 21:33:15 +01:00
|
|
|
NMSetting *
|
2016-06-02 22:16:54 +02:00
|
|
|
nm_device_get_applied_setting (NMDevice *self, GType setting_type)
|
2016-02-11 21:33:15 +01:00
|
|
|
{
|
2016-06-02 22:16:54 +02:00
|
|
|
NMConnection *connection;
|
2016-02-11 21:33:15 +01:00
|
|
|
|
2016-06-02 22:16:54 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
return connection ? nm_connection_get_setting (connection, setting_type) : NULL;
|
2016-02-11 21:33:15 +01:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 16:09:22 -05:00
|
|
|
RfKillType
|
|
|
|
|
nm_device_get_rfkill_type (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->rfkill_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_get_physical_port_id (NMDevice *self)
|
2014-05-20 16:09:22 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->physical_port_id;
|
2014-05-20 16:09:22 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-05-20 16:09:22 -05:00
|
|
|
|
2017-03-20 13:36:00 +00:00
|
|
|
static void
|
|
|
|
|
update_connectivity_state (NMDevice *self, NMConnectivityState state)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* If the connectivity check is disabled, make an optimistic guess. */
|
|
|
|
|
if (state == NM_CONNECTIVITY_UNKNOWN) {
|
|
|
|
|
if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
if (nm_device_get_best_default_route (self, AF_UNSPEC))
|
2017-03-20 13:36:00 +00:00
|
|
|
state = NM_CONNECTIVITY_FULL;
|
|
|
|
|
else
|
|
|
|
|
state = NM_CONNECTIVITY_LIMITED;
|
|
|
|
|
} else {
|
|
|
|
|
state = NM_CONNECTIVITY_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (priv->connectivity_state != state) {
|
|
|
|
|
#if WITH_CONCHECK
|
|
|
|
|
_LOGD (LOGD_CONCHECK, "state changed from %s to %s",
|
|
|
|
|
nm_connectivity_state_to_string (priv->connectivity_state),
|
|
|
|
|
nm_connectivity_state_to_string (state));
|
|
|
|
|
#endif
|
|
|
|
|
priv->connectivity_state = state;
|
|
|
|
|
_notify (self, PROP_CONNECTIVITY);
|
2017-03-27 15:22:22 +00:00
|
|
|
|
2017-06-08 00:26:00 +02:00
|
|
|
if ( priv->state == NM_DEVICE_STATE_ACTIVATED
|
|
|
|
|
&& !nm_device_sys_iface_state_is_external (self)) {
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
if ( nm_device_get_best_default_route (self, AF_INET)
|
2017-09-28 14:22:07 +02:00
|
|
|
&& !ip4_config_merge_and_apply (self, TRUE))
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
_LOGW (LOGD_IP4, "Failed to update IPv4 route metric");
|
|
|
|
|
if ( nm_device_get_best_default_route (self, AF_INET6)
|
2017-06-08 00:26:00 +02:00
|
|
|
&& !ip6_config_merge_and_apply (self, TRUE))
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
_LOGW (LOGD_IP6, "Failed to update IPv6 route metric");
|
device: don't update disconnected devices routes after connectivity check
When the device is not activated it does not make sense to try to
update its default route metric based on connectivity status.
Fixes the following:
nm_ip4_config_commit: assertion 'ifindex > 0' failed
#0 raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/pt-raise.c:37
#1 g_logv (breakpoint=1) at gmessages.c:324
#2 g_logv (log_domain=<> "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=<optimized out>) at gmessages.c:1081
#3 g_log (log_domain=<optimized out>, log_level=<optimized out>, format=<optimized out>) at gmessages.c:1119
#4 g_return_if_fail_warning (log_domain=<optimized out>, pretty_function=<optimized out>, expression=<optimized out>) at gmessages.c:1128
#5 nm_ip4_config_commit (config=<> [NMIP4Config], ifindex=<optimized out>, routes_full_sync=<optimized out>, default_route_metric=-1) at src/nm-ip4-config.c:339
#6 nm_device_set_ip4_config (self=<> [NMDeviceTun], new_config=<> [NMIP4Config], default_route_metric=450, commit=1, routes_full_sync=<optimized out>) at src/devices/nm-device.c:9635
#7 ip4_config_merge_and_apply (self=<> [NMDeviceTun], config=0x0, commit=1) at src/devices/nm-device.c:5541
#8 update_connectivity_state (self=<> [NMDeviceTun], state=NM_CONNECTIVITY_NONE) at src/devices/nm-device.c:1743
#9 concheck_periodic_update (self=<> [NMDeviceTun]) at src/devices/nm-device.c:1872
#10 nm_device_set_ip4_config (self=<> [NMDeviceTun], new_config=0x0, default_route_metric=0, commit=1, routes_full_sync=1) at src/devices/nm-device.c:9669
#11 _cleanup_generic_post (self=<> [NMDeviceTun], cleanup_type=CLEANUP_TYPE_KEEP) at src/devices/nm-device.c:11863
#12 nm_device_cleanup (self=<> [NMDeviceTun], reason=NM_DEVICE_STATE_REASON_NOW_UNMANAGED, cleanup_type=<optimized out>) at src/devices/nm-device.c:12006
#13 _set_state_full (self=<> [NMDeviceTun], state=<optimized out>, reason=<optimized out>, quitting=<optimized out>) at src/devices/nm-device.c:12376
#14 nm_device_unrealize (self=<> [NMDeviceTun], remove_resources=<optimized out>, error=<>) at src/devices/nm-device.c:3183
#15 _platform_link_cb_idle (data=<>) at src/nm-manager.c:2359
#16 g_idle_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at gmain.c:5439
#17 g_main_context_dispatch (context=<>) at gmain.c:3152
#18 g_main_context_dispatch (context=<>) at gmain.c:3767
#19 g_main_context_iterate (context=<>, block=1, dispatch=1, self=<optimized out>) a
Fixes: 6b7e9f9b225e81d365fd95901a88a7bc59c1eb39
https://bugzilla.redhat.com/show_bug.cgi?id=1436978
2017-03-29 14:05:53 +02:00
|
|
|
}
|
2017-03-20 13:36:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
NMDevice *self;
|
|
|
|
|
NMDeviceConnectivityCallback callback;
|
|
|
|
|
gpointer user_data;
|
|
|
|
|
guint64 seq;
|
|
|
|
|
} ConnectivityCheckData;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
concheck_done (ConnectivityCheckData *data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = data->self;
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* The unsolicited connectivity checks don't hook a callback. */
|
|
|
|
|
if (data->callback)
|
|
|
|
|
data->callback (data->self, priv->connectivity_state, data->user_data);
|
|
|
|
|
g_object_unref (data->self);
|
|
|
|
|
g_slice_free (ConnectivityCheckData, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_CONCHECK
|
|
|
|
|
static void
|
|
|
|
|
concheck_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
ConnectivityCheckData *data = user_data;
|
|
|
|
|
NMDevice *self = data->self;
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnectivity *connectivity = NM_CONNECTIVITY (source_object);
|
|
|
|
|
NMConnectivityState state;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
state = nm_connectivity_check_finish (connectivity, result, &error);
|
|
|
|
|
if (error) {
|
|
|
|
|
_LOGW (LOGD_DEVICE, "connectivity checking on '%s' failed: %s",
|
|
|
|
|
nm_device_get_iface (self), error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data->seq == priv->concheck_seq)
|
|
|
|
|
update_connectivity_state (data->self, state);
|
|
|
|
|
concheck_done (data);
|
|
|
|
|
}
|
|
|
|
|
#endif /* WITH_CONCHECK */
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
no_concheck (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
ConnectivityCheckData *data = user_data;
|
|
|
|
|
|
|
|
|
|
concheck_done (data);
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_check_connectivity (NMDevice *self,
|
|
|
|
|
NMDeviceConnectivityCallback callback,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
ConnectivityCheckData *data;
|
|
|
|
|
#if WITH_CONCHECK
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
data = g_slice_new0 (ConnectivityCheckData);
|
|
|
|
|
data->self = g_object_ref (self);
|
|
|
|
|
data->callback = callback;
|
|
|
|
|
data->user_data = user_data;
|
|
|
|
|
|
|
|
|
|
#if WITH_CONCHECK
|
|
|
|
|
if (priv->concheck_periodic_id) {
|
|
|
|
|
data->seq = ++priv->concheck_seq;
|
|
|
|
|
|
|
|
|
|
/* Kick off a real connectivity check. */
|
|
|
|
|
nm_connectivity_check_async (nm_connectivity_get (),
|
2017-06-08 00:23:05 +02:00
|
|
|
nm_device_get_ip_iface (self),
|
2017-03-20 13:36:00 +00:00
|
|
|
concheck_cb,
|
|
|
|
|
data);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Fake one. */
|
|
|
|
|
g_idle_add (no_concheck, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMConnectivityState
|
|
|
|
|
nm_device_get_connectivity_state (NMDevice *self)
|
|
|
|
|
{
|
2017-05-02 18:19:08 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_CONNECTIVITY_UNKNOWN);
|
2017-03-20 13:36:00 +00:00
|
|
|
|
2017-05-02 18:19:08 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->connectivity_state;
|
2017-03-20 13:36:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_CONCHECK
|
|
|
|
|
static void
|
|
|
|
|
concheck_periodic (NMConnectivity *connectivity, NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
nm_device_check_connectivity (self, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
concheck_periodic_update (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
#if WITH_CONCHECK
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
gboolean check_enable;
|
|
|
|
|
|
|
|
|
|
check_enable = (priv->state == NM_DEVICE_STATE_ACTIVATED)
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
&& nm_device_get_best_default_route (self, AF_UNSPEC);
|
2017-03-20 13:36:00 +00:00
|
|
|
|
|
|
|
|
if (check_enable && !priv->concheck_periodic_id) {
|
|
|
|
|
/* We just gained a default route. Enable periodic checking. */
|
|
|
|
|
priv->concheck_periodic_id = g_signal_connect (nm_connectivity_get (),
|
|
|
|
|
NM_CONNECTIVITY_PERIODIC_CHECK,
|
|
|
|
|
G_CALLBACK (concheck_periodic), self);
|
|
|
|
|
/* Also kick off a check right away. */
|
|
|
|
|
nm_device_check_connectivity (self, NULL, NULL);
|
|
|
|
|
} else if (!check_enable && priv->concheck_periodic_id) {
|
|
|
|
|
/* The default route has gone off, and so has connectivity. */
|
|
|
|
|
g_signal_handler_disconnect (nm_connectivity_get (), priv->concheck_periodic_id);
|
|
|
|
|
priv->concheck_periodic_id = 0;
|
2017-03-27 15:22:22 +00:00
|
|
|
update_connectivity_state (self, NM_CONNECTIVITY_NONE);
|
2017-03-20 13:36:00 +00:00
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
/* update_connectivity_state() figures out how to lie about
|
|
|
|
|
* connectivity state if the actual state is not really known. */
|
|
|
|
|
update_connectivity_state (self, NM_CONNECTIVITY_UNKNOWN);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
static SlaveInfo *
|
|
|
|
|
find_slave_info (NMDevice *self, NMDevice *slave)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-05-13 21:57:51 +02:00
|
|
|
CList *iter;
|
2012-11-14 14:05:30 -06:00
|
|
|
SlaveInfo *info;
|
|
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_for_each (iter, &priv->slaves) {
|
|
|
|
|
info = c_list_entry (iter, SlaveInfo, lst_slave);
|
2012-11-14 14:05:30 -06:00
|
|
|
if (info->slave == slave)
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-28 18:35:30 -06:00
|
|
|
/**
|
2015-08-06 14:37:12 +02:00
|
|
|
* nm_device_master_enslave_slave:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the master device
|
2012-02-28 18:35:30 -06:00
|
|
|
* @slave: the slave device to enslave
|
2014-02-25 16:44:01 -05:00
|
|
|
* @connection: (allow-none): the slave device's connection
|
2012-02-28 18:35:30 -06:00
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* If @self is capable of enslaving other devices (ie it's a bridge, bond, team,
|
2013-07-25 15:36:45 +02:00
|
|
|
* etc) then this function enslaves @slave.
|
2012-02-28 18:35:30 -06:00
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
|
|
|
|
|
* other devices.
|
|
|
|
|
*/
|
2012-11-14 14:05:30 -06:00
|
|
|
static gboolean
|
2015-08-06 14:37:12 +02:00
|
|
|
nm_device_master_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connection)
|
2012-02-28 18:35:30 -06:00
|
|
|
{
|
2012-11-14 14:05:30 -06:00
|
|
|
SlaveInfo *info;
|
|
|
|
|
gboolean success = FALSE;
|
2014-02-25 16:44:01 -05:00
|
|
|
gboolean configure;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
2012-02-28 18:35:30 -06:00
|
|
|
g_return_val_if_fail (slave != NULL, FALSE);
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL, FALSE);
|
2012-02-28 18:35:30 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
info = find_slave_info (self, slave);
|
2012-11-14 14:05:30 -06:00
|
|
|
if (!info)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2015-08-06 14:17:29 +02:00
|
|
|
if (info->slave_is_enslaved)
|
2014-02-25 16:44:01 -05:00
|
|
|
success = TRUE;
|
|
|
|
|
else {
|
|
|
|
|
configure = (info->configure && connection != NULL);
|
|
|
|
|
if (configure)
|
|
|
|
|
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
success = NM_DEVICE_GET_CLASS (self)->enslave_slave (self, slave, connection, configure);
|
2015-08-06 14:17:29 +02:00
|
|
|
info->slave_is_enslaved = success;
|
2014-02-25 16:44:01 -05:00
|
|
|
}
|
2013-10-21 12:50:58 -04:00
|
|
|
|
|
|
|
|
nm_device_slave_notify_enslave (info->slave, success);
|
2013-01-18 14:34:40 -06:00
|
|
|
|
|
|
|
|
/* Ensure the device's hardware address is up-to-date; it often changes
|
|
|
|
|
* when slaves change.
|
|
|
|
|
*/
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_update_hw_address (self);
|
2013-01-18 14:34:40 -06:00
|
|
|
|
2013-01-25 11:59:05 -06:00
|
|
|
/* Restart IP configuration if we're waiting for slaves. Do this
|
|
|
|
|
* after updating the hardware address as IP config may need the
|
|
|
|
|
* new address.
|
|
|
|
|
*/
|
|
|
|
|
if (success) {
|
2014-07-15 13:36:24 +02:00
|
|
|
if (NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT)
|
|
|
|
|
nm_device_activate_stage3_ip4_start (self);
|
2013-01-25 11:59:05 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
if (NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT)
|
|
|
|
|
nm_device_activate_stage3_ip6_start (self);
|
2013-01-25 11:59:05 -06:00
|
|
|
}
|
|
|
|
|
|
2016-03-17 14:17:32 +01:00
|
|
|
/* Since slave devices don't have their own IP configuration,
|
|
|
|
|
* set the MTU here.
|
|
|
|
|
*/
|
2017-01-15 13:38:33 +01:00
|
|
|
_commit_mtu (slave, NM_DEVICE_GET_PRIVATE (slave)->ip4_config);
|
2016-03-17 14:17:32 +01:00
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
return success;
|
2012-02-28 18:35:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2015-08-06 14:37:12 +02:00
|
|
|
* nm_device_master_release_one_slave:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the master device
|
2012-02-28 18:35:30 -06:00
|
|
|
* @slave: the slave device to release
|
2014-07-15 13:36:24 +02:00
|
|
|
* @configure: whether @self needs to actually release @slave
|
device: fix warning releasing of slave when slave device gets removed
When the slave device gets removed, the master is not in a state-change when
calling nm_device_release_one_slave(). This triggers a warning [1].
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c144c "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fff8b1d35b0) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x3370cc1fdc "%s") at gmessages.c:1025
#2 0x0000003370c50956 in g_warn_message (domain=domain@entry=0x4c144c "NetworkManager", file=file@entry=0x4b14d5 "devices/nm-device.c", line=line@entry=841, func=func@entry=0x4b48f0 <__FUNCTION__.35456> "nm_device_release_one_slave",
warnexpr=warnexpr@entry=0x0) at gmessages.c:1058
#3 0x0000000000436c30 in nm_device_release_one_slave (dev=dev@entry=0xd92540, slave=slave@entry=0xdb0e50, configure=configure@entry=1) at devices/nm-device.c:841
#4 0x000000000043a779 in slave_state_changed (slave=0xdb0e50, slave_new_state=NM_DEVICE_STATE_UNMANAGED, slave_old_state=NM_DEVICE_STATE_ACTIVATED, reason=<optimized out>, self=0xd92540) at devices/nm-device.c:1214
#5 0x0000003371805d8c in ffi_call_unix64 () at ../src/x86/unix64.S:76
#6 0x00000033718056bc in ffi_call (cif=cif@entry=0x7fff8b1d3a00, fn=0x43a677 <slave_state_changed>, rvalue=0x7fff8b1d3970, avalue=avalue@entry=0x7fff8b1d38f0) at ../src/x86/ffi64.c:522
#7 0x0000003371c10ad8 in g_cclosure_marshal_generic (closure=0xd76120, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1454
#8 0x0000003371c10298 in g_closure_invoke (closure=0xd76120, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fff8b1d3c00, invocation_hint=invocation_hint@entry=0x7fff8b1d3ba0) at gclosure.c:777
#9 0x0000003371c2235d in signal_emit_unlocked_R (node=node@entry=0xd9d850, detail=detail@entry=0, instance=instance@entry=0xdb0e50, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff8b1d3c00) at gsignal.c:3586
#10 0x0000003371c2a0f2 in g_signal_emit_valist (instance=instance@entry=0xdb0e50, signal_id=signal_id@entry=68, detail=detail@entry=0, var_args=var_args@entry=0x7fff8b1d3e38) at gsignal.c:3330
#11 0x0000003371c2a8f8 in g_signal_emit_by_name (instance=instance@entry=0xdb0e50, detailed_signal=detailed_signal@entry=0x4c3ce2 "state-changed") at gsignal.c:3426
#12 0x000000000043754f in _set_state_full (device=device@entry=0xdb0e50, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6689
#13 0x000000000043797c in nm_device_state_changed (device=device@entry=0xdb0e50, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#14 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0xdb0e50, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#15 0x00000000004799c2 in remove_device (manager=manager@entry=0xd86150, device=0xdb0e50, quitting=quitting@entry=0) at nm-manager.c:769
#16 0x000000000047e3bf in platform_link_cb (platform=<optimized out>, ifindex=35, plink=<optimized out>, change_type=<optimized out>, reason=<optimized out>, user_data=<optimized out>) at nm-manager.c:2123
#17 0x0000003371805d8c in ffi_call_unix64 () at ../src/x86/unix64.S:76
#18 0x00000033718056bc in ffi_call (cif=cif@entry=0x7fff8b1d4320, fn=0x47e34b <platform_link_cb>, rvalue=0x7fff8b1d4290, avalue=avalue@entry=0x7fff8b1d4210) at ../src/x86/ffi64.c:522
#19 0x0000003371c10ad8 in g_cclosure_marshal_generic (closure=0xd32e40, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1454
#20 0x0000003371c10298 in g_closure_invoke (closure=0xd32e40, return_value=return_value@entry=0x0, n_param_values=5, param_values=param_values@entry=0x7fff8b1d4520, invocation_hint=invocation_hint@entry=0x7fff8b1d44c0) at gclosure.c:777
#21 0x0000003371c2235d in signal_emit_unlocked_R (node=node@entry=0xcf5780, detail=detail@entry=0, instance=instance@entry=0xcf78a0, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff8b1d4520) at gsignal.c:3586
#22 0x0000003371c2a0f2 in g_signal_emit_valist (instance=instance@entry=0xcf78a0, signal_id=signal_id@entry=2, detail=detail@entry=0, var_args=var_args@entry=0x7fff8b1d4778) at gsignal.c:3330
#23 0x0000003371c2a8f8 in g_signal_emit_by_name (instance=instance@entry=0xcf78a0, detailed_signal=detailed_signal@entry=0x4b183d "link-changed") at gsignal.c:3426
#24 0x000000000044c6f3 in announce_object (platform=platform@entry=0xcf78a0, object=0xde1720, change_type=change_type@entry=NM_PLATFORM_SIGNAL_REMOVED, reason=reason@entry=NM_PLATFORM_REASON_EXTERNAL)
at platform/nm-linux-platform.c:1572
#25 0x000000000044ec07 in event_notification (msg=<optimized out>, user_data=<optimized out>) at platform/nm-linux-platform.c:1886
#26 0x0000003844c1117f in nl_cb_call (msg=<optimized out>, type=<optimized out>, cb=<optimized out>) at ../include/netlink-private/netlink.h:141
#27 recvmsgs (cb=0xcf7240, sk=0xcf7330) at nl.c:952
#28 nl_recvmsgs_report (sk=0xcf7330, cb=0xcf7240) at nl.c:1003
#29 0x0000003844c11549 in nl_recvmsgs (sk=<optimized out>, cb=<optimized out>) at nl.c:1027
#30 0x0000003844c11569 in nl_recvmsgs_default (sk=<optimized out>) at nl.c:1041
#31 0x000000000044e955 in event_handler (channel=<optimized out>, io_condition=<optimized out>, user_data=0xcf78a0) at platform/nm-linux-platform.c:3804
#32 0x0000003370c492a6 in g_main_dispatch (context=0xcf5190) at gmain.c:3066
#33 g_main_context_dispatch (context=context@entry=0xcf5190) at gmain.c:3642
#34 0x0000003370c49628 in g_main_context_iterate (context=0xcf5190, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3713
#35 0x0000003370c49a3a in g_main_loop_run (loop=0xcf4e30) at gmain.c:3907
#36 0x0000000000429f15 in main (argc=1, argv=0x7fff8b1d4f38) at main.c:678
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 11:18:45 +02:00
|
|
|
* @reason: the state change reason for the @slave
|
2012-02-28 18:35:30 -06:00
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* If @self is capable of enslaving other devices (ie it's a bridge, bond, team,
|
2014-02-25 16:44:01 -05:00
|
|
|
* etc) then this function releases the previously enslaved @slave and/or
|
2014-07-15 13:36:24 +02:00
|
|
|
* updates the state of @self and @slave to reflect its release.
|
2012-02-28 18:35:30 -06:00
|
|
|
*/
|
2015-12-02 10:53:16 +01:00
|
|
|
static void
|
2015-08-06 14:37:12 +02:00
|
|
|
nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure, NMDeviceStateReason reason)
|
2012-11-14 14:05:30 -06:00
|
|
|
{
|
2015-12-02 10:53:16 +01:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMDevicePrivate *slave_priv;
|
2012-11-14 14:05:30 -06:00
|
|
|
SlaveInfo *info;
|
2015-12-02 10:53:16 +01:00
|
|
|
gs_unref_object NMDevice *self_free = NULL;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_fail (NM_DEVICE (self));
|
|
|
|
|
g_return_if_fail (NM_DEVICE (slave));
|
|
|
|
|
g_return_if_fail (NM_DEVICE_GET_CLASS (self)->release_slave != NULL);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
info = find_slave_info (self, slave);
|
2015-12-02 10:53:16 +01:00
|
|
|
|
2017-03-01 17:26:45 +01:00
|
|
|
_LOGT (LOGD_CORE, "master: release one slave %p/%s%s", slave, nm_device_get_iface (slave),
|
2015-12-02 10:53:16 +01:00
|
|
|
!info ? " (not registered)" : "");
|
|
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
if (!info)
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_reached ();
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
slave_priv = NM_DEVICE_GET_PRIVATE (slave);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_fail (self == slave_priv->master);
|
|
|
|
|
nm_assert (slave == info->slave);
|
|
|
|
|
|
|
|
|
|
/* first, let subclasses handle the release ... */
|
2015-12-02 09:56:17 +01:00
|
|
|
if (info->slave_is_enslaved)
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->release_slave (self, slave, configure);
|
2013-12-05 09:13:26 -05:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
/* raise notifications about the release, including clearing is_enslaved. */
|
|
|
|
|
nm_device_slave_notify_release (slave, reason);
|
|
|
|
|
|
|
|
|
|
/* keep both alive until the end of the function.
|
|
|
|
|
* Transfers ownership from slave_priv->master. */
|
|
|
|
|
self_free = self;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_unlink_init (&info->lst_slave);
|
2015-12-02 10:53:16 +01:00
|
|
|
slave_priv->master = NULL;
|
|
|
|
|
|
|
|
|
|
g_signal_handler_disconnect (slave, info->watch_id);
|
|
|
|
|
g_object_unref (slave);
|
|
|
|
|
g_slice_free (SlaveInfo, info);
|
2013-01-18 14:34:40 -06:00
|
|
|
|
2017-09-27 10:16:15 +02:00
|
|
|
if (c_list_is_empty (&priv->slaves)) {
|
|
|
|
|
_active_connection_set_state_flags_full (self,
|
|
|
|
|
0,
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-18 14:34:40 -06:00
|
|
|
/* Ensure the device's hardware address is up-to-date; it often changes
|
|
|
|
|
* when slaves change.
|
|
|
|
|
*/
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_update_hw_address (self);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, NM_UNMAN_FLAG_OP_FORGET, NM_DEVICE_STATE_REASON_REMOVED);
|
2012-11-14 14:05:30 -06:00
|
|
|
}
|
|
|
|
|
|
2015-04-07 14:24:12 +02:00
|
|
|
/**
|
|
|
|
|
* can_unmanaged_external_down:
|
|
|
|
|
* @self: the device
|
|
|
|
|
*
|
|
|
|
|
* Check whether the device should stay NM_UNMANAGED_EXTERNAL_DOWN unless
|
|
|
|
|
* IFF_UP-ed externally.
|
|
|
|
|
*/
|
2014-12-03 12:47:30 -06:00
|
|
|
static gboolean
|
2015-04-07 14:24:12 +02:00
|
|
|
can_unmanaged_external_down (NMDevice *self)
|
2014-12-03 12:47:30 -06:00
|
|
|
{
|
2017-05-31 16:42:05 +02:00
|
|
|
return !NM_DEVICE_GET_PRIVATE (self)->nm_owned
|
2016-03-23 09:49:39 +01:00
|
|
|
&& nm_device_is_software (self);
|
2014-12-03 12:47:30 -06:00
|
|
|
}
|
|
|
|
|
|
2016-03-21 14:56:15 +01:00
|
|
|
static NMUnmanFlagOp
|
|
|
|
|
is_unmanaged_external_down (NMDevice *self, gboolean consider_can)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if ( consider_can
|
|
|
|
|
&& !NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self))
|
|
|
|
|
return NM_UNMAN_FLAG_OP_FORGET;
|
|
|
|
|
|
|
|
|
|
/* Manage externally-created software interfaces only when they are IFF_UP */
|
|
|
|
|
if ( priv->ifindex <= 0
|
2016-03-21 15:30:07 +01:00
|
|
|
|| !priv->up
|
2017-05-13 21:57:51 +02:00
|
|
|
|| !( !c_list_is_empty (&priv->slaves)
|
|
|
|
|
|| nm_platform_link_can_assume (nm_device_get_platform (self), priv->ifindex)))
|
2016-03-21 14:56:15 +01:00
|
|
|
return NM_UNMAN_FLAG_OP_SET_UNMANAGED;
|
|
|
|
|
|
|
|
|
|
return NM_UNMAN_FLAG_OP_SET_MANAGED;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 14:15:49 +01:00
|
|
|
static void
|
2016-03-21 15:30:07 +01:00
|
|
|
set_unmanaged_external_down (NMDevice *self, gboolean only_if_unmanaged)
|
2016-03-24 14:15:49 +01:00
|
|
|
{
|
|
|
|
|
NMUnmanFlagOp ext_flags;
|
|
|
|
|
|
|
|
|
|
if (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_EXTERNAL_DOWN))
|
|
|
|
|
return;
|
|
|
|
|
|
2016-03-21 15:30:07 +01:00
|
|
|
if (only_if_unmanaged) {
|
|
|
|
|
if (!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-24 14:15:49 +01:00
|
|
|
ext_flags = is_unmanaged_external_down (self, FALSE);
|
|
|
|
|
if (ext_flags != NM_UNMAN_FLAG_OP_SET_UNMANAGED) {
|
|
|
|
|
/* Ensure the assume check is queued before any queued state changes
|
|
|
|
|
* from the transition to UNAVAILABLE.
|
|
|
|
|
*/
|
|
|
|
|
nm_device_queue_recheck_assume (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_device_set_unmanaged_by_flags (self,
|
|
|
|
|
NM_UNMANAGED_EXTERNAL_DOWN,
|
|
|
|
|
ext_flags,
|
|
|
|
|
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-26 01:26:36 -04:00
|
|
|
void
|
|
|
|
|
nm_device_update_dynamic_ip_setup (NMDevice *self)
|
2015-06-25 14:50:23 +00:00
|
|
|
{
|
2016-03-26 01:26:36 -04:00
|
|
|
NMDevicePrivate *priv;
|
2016-04-25 12:06:40 +02:00
|
|
|
GError *error = NULL;
|
2015-11-10 14:17:42 +01:00
|
|
|
gconstpointer addr;
|
|
|
|
|
size_t addr_length;
|
2015-06-25 14:50:23 +00:00
|
|
|
|
2016-03-26 01:26:36 -04:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-06-25 14:50:23 +00:00
|
|
|
g_hash_table_remove_all (priv->ip6_saved_properties);
|
|
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
if (priv->dhcp4.client) {
|
2015-06-25 14:50:23 +00:00
|
|
|
if (!nm_device_dhcp4_renew (self, FALSE)) {
|
|
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
NM_DEVICE_STATE_FAILED,
|
|
|
|
|
NM_DEVICE_STATE_REASON_DHCP_FAILED);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.client) {
|
2015-06-25 14:50:23 +00:00
|
|
|
if (!nm_device_dhcp6_renew (self, FALSE)) {
|
|
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
NM_DEVICE_STATE_FAILED,
|
|
|
|
|
NM_DEVICE_STATE_REASON_DHCP_FAILED);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-10-13 11:06:25 +00:00
|
|
|
if (priv->ndisc) {
|
2015-06-25 14:50:23 +00:00
|
|
|
/* FIXME: todo */
|
|
|
|
|
}
|
|
|
|
|
if (priv->dnsmasq_manager) {
|
|
|
|
|
/* FIXME: todo */
|
|
|
|
|
}
|
2015-10-07 11:48:38 +02:00
|
|
|
|
|
|
|
|
if (priv->lldp_listener && nm_lldp_listener_is_running (priv->lldp_listener)) {
|
|
|
|
|
nm_lldp_listener_stop (priv->lldp_listener);
|
2017-04-17 20:17:45 +02:00
|
|
|
addr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &addr_length);
|
2015-11-10 14:17:42 +01:00
|
|
|
|
2016-02-29 14:30:15 +01:00
|
|
|
if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) {
|
2015-10-07 11:48:38 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s",
|
|
|
|
|
priv->lldp_listener, error->message);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-06-25 14:50:23 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 16:21:55 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-05-12 16:17:18 +02:00
|
|
|
static void
|
|
|
|
|
carrier_changed_notify (NMDevice *self, gboolean carrier)
|
|
|
|
|
{
|
|
|
|
|
/* stub */
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-07 10:23:44 -04:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
carrier_changed (NMDevice *self, gboolean carrier)
|
2013-05-07 10:23:44 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-05-07 10:23:44 -04:00
|
|
|
|
2016-01-19 21:20:46 +01:00
|
|
|
if (priv->state <= NM_DEVICE_STATE_UNMANAGED)
|
2013-05-07 10:23:44 -04:00
|
|
|
return;
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_recheck_available_connections (self);
|
2013-11-04 19:51:28 -06:00
|
|
|
|
2014-04-02 09:15:54 -05:00
|
|
|
/* ignore-carrier devices ignore all carrier-down events */
|
|
|
|
|
if (priv->ignore_carrier && !carrier)
|
|
|
|
|
return;
|
2013-07-12 10:43:45 -04:00
|
|
|
|
2017-06-01 23:08:30 +02:00
|
|
|
if (nm_device_is_master (self)) {
|
2017-06-01 23:57:03 +02:00
|
|
|
if (carrier) {
|
|
|
|
|
/* Force master to retry getting ip addresses when carrier
|
|
|
|
|
* is restored. */
|
|
|
|
|
if (priv->state == NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
nm_device_update_dynamic_ip_setup (self);
|
|
|
|
|
else {
|
|
|
|
|
if (nm_device_activate_ip4_state_in_wait (self))
|
|
|
|
|
nm_device_activate_stage3_ip4_start (self);
|
|
|
|
|
if (nm_device_activate_ip6_state_in_wait (self))
|
|
|
|
|
nm_device_activate_stage3_ip6_start (self);
|
|
|
|
|
}
|
2013-05-07 10:23:44 -04:00
|
|
|
return;
|
2017-06-02 11:11:50 +02:00
|
|
|
}
|
2017-06-01 23:57:03 +02:00
|
|
|
/* fall-through and change state of device */
|
2017-05-14 09:45:53 +02:00
|
|
|
} else if (priv->is_enslaved && !carrier) {
|
2013-07-25 15:36:45 +02:00
|
|
|
/* Slaves don't deactivate when they lose carrier; for
|
|
|
|
|
* bonds/teams in particular that would be actively
|
|
|
|
|
* counterproductive.
|
2013-05-07 10:23:44 -04:00
|
|
|
*/
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (carrier) {
|
|
|
|
|
if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) {
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED,
|
2013-05-07 10:23:44 -04:00
|
|
|
NM_DEVICE_STATE_REASON_CARRIER);
|
2014-03-14 15:21:14 -05:00
|
|
|
} else if (priv->state == NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
/* If the device is already in DISCONNECTED state without a carrier
|
|
|
|
|
* (probably because it is tagged for carrier ignore) ensure that
|
|
|
|
|
* when the carrier appears, auto connections are rechecked for
|
|
|
|
|
* the device.
|
|
|
|
|
*/
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_emit_recheck_auto_activate (self);
|
2015-06-25 14:50:23 +00:00
|
|
|
} else if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
|
|
|
|
|
/* If the device is active without a carrier (probably because it is
|
|
|
|
|
* tagged for carrier ignore) ensure that when the carrier appears we
|
|
|
|
|
* renew DHCP leases and such.
|
|
|
|
|
*/
|
2016-03-26 01:26:36 -04:00
|
|
|
nm_device_update_dynamic_ip_setup (self);
|
2013-05-07 10:23:44 -04:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) {
|
2017-02-02 12:39:07 +01:00
|
|
|
if ( priv->queued_state.id
|
|
|
|
|
&& priv->queued_state.state >= NM_DEVICE_STATE_DISCONNECTED)
|
|
|
|
|
queued_state_clear (self);
|
2013-05-07 10:23:44 -04:00
|
|
|
} else {
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_queue_state (self, NM_DEVICE_STATE_UNAVAILABLE,
|
2013-05-07 10:23:44 -04:00
|
|
|
NM_DEVICE_STATE_REASON_CARRIER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define LINK_DISCONNECT_DELAY 4
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2017-05-12 16:21:55 +02:00
|
|
|
carrier_disconnected_action_cb (gpointer user_data)
|
2013-05-07 10:23:44 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-05-07 10:23:44 -04:00
|
|
|
|
2017-06-02 16:47:10 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "carrier: link disconnected (calling deferred action) (id=%u)", priv->carrier_defer_id);
|
2014-03-06 15:09:57 +01:00
|
|
|
|
2013-05-07 10:23:44 -04:00
|
|
|
priv->carrier_defer_id = 0;
|
2017-05-12 16:17:18 +02:00
|
|
|
carrier_changed (self, FALSE);
|
2013-05-07 10:23:44 -04:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-06 15:09:57 +01:00
|
|
|
static void
|
2017-05-12 16:21:55 +02:00
|
|
|
carrier_disconnected_action_cancel (NMDevice *self)
|
2014-03-06 15:09:57 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-05-12 16:22:47 +02:00
|
|
|
guint id = priv->carrier_defer_id;
|
2014-03-06 15:09:57 +01:00
|
|
|
|
2017-05-12 16:22:47 +02:00
|
|
|
if (nm_clear_g_source (&priv->carrier_defer_id)) {
|
2017-06-02 16:47:10 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "carrier: link disconnected (canceling deferred action) (id=%u)",
|
2017-05-12 16:22:47 +02:00
|
|
|
id);
|
2014-03-06 15:09:57 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-07 10:23:44 -04:00
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_set_carrier (NMDevice *self, gboolean carrier)
|
2013-05-07 10:23:44 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMDeviceState state = nm_device_get_state (self);
|
2013-05-07 10:23:44 -04:00
|
|
|
|
|
|
|
|
if (priv->carrier == carrier)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
priv->carrier = carrier;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_CARRIER);
|
2013-05-07 10:23:44 -04:00
|
|
|
|
|
|
|
|
if (priv->carrier) {
|
2017-06-02 16:47:10 +02:00
|
|
|
_LOGI (LOGD_DEVICE, "carrier: link connected");
|
2017-05-12 16:21:55 +02:00
|
|
|
carrier_disconnected_action_cancel (self);
|
2017-06-02 16:09:55 +02:00
|
|
|
NM_DEVICE_GET_CLASS (self)->carrier_changed_notify (self, carrier);
|
2017-05-12 16:17:18 +02:00
|
|
|
carrier_changed (self, TRUE);
|
2013-12-09 16:32:36 -06:00
|
|
|
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
if (priv->carrier_wait_id) {
|
|
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
|
2014-12-08 12:50:10 +01:00
|
|
|
_carrier_wait_check_queued_act_request (self);
|
2013-12-09 16:32:36 -06:00
|
|
|
}
|
2013-05-07 10:23:44 -04:00
|
|
|
} else {
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
if (priv->carrier_wait_id)
|
|
|
|
|
nm_device_add_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
|
2017-06-02 16:09:55 +02:00
|
|
|
NM_DEVICE_GET_CLASS (self)->carrier_changed_notify (self, carrier);
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
if ( state <= NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
&& !priv->queued_act_request) {
|
2017-06-02 16:47:10 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "carrier: link disconnected");
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
carrier_changed (self, FALSE);
|
|
|
|
|
} else {
|
|
|
|
|
priv->carrier_defer_id = g_timeout_add_seconds (LINK_DISCONNECT_DELAY,
|
|
|
|
|
carrier_disconnected_action_cb, self);
|
2017-06-02 16:47:10 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "carrier: link disconnected (deferring action for %d seconds) (id=%u)",
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
LINK_DISCONNECT_DELAY, priv->carrier_defer_id);
|
|
|
|
|
}
|
2013-05-07 10:23:44 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-14 22:08:26 +02:00
|
|
|
static void
|
|
|
|
|
nm_device_set_carrier_from_platform (NMDevice *self)
|
|
|
|
|
{
|
2017-05-15 11:35:41 +02:00
|
|
|
if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
|
|
|
|
|
if (!nm_device_has_capability (self, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) {
|
|
|
|
|
nm_device_set_carrier (self,
|
|
|
|
|
nm_platform_link_is_connected (nm_device_get_platform (self),
|
|
|
|
|
nm_device_get_ip_ifindex (self)));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* Fake online link when carrier detection is not available. */
|
|
|
|
|
if (!priv->carrier) {
|
|
|
|
|
priv->carrier = TRUE;
|
|
|
|
|
_notify (self, PROP_CARRIER);
|
|
|
|
|
}
|
2017-05-14 22:08:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 16:21:55 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-12-05 13:12:55 +01:00
|
|
|
static void
|
2015-12-02 10:53:16 +01:00
|
|
|
device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink)
|
2014-12-05 13:12:55 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-08-24 09:09:18 +02:00
|
|
|
NMDevice *master;
|
|
|
|
|
nm_auto_nmpobj const NMPObject *plink_master_keep_alive = NULL;
|
|
|
|
|
const NMPlatformLink *plink_master;
|
2014-12-05 13:12:55 +01:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_fail (plink);
|
2014-09-24 16:58:07 -05:00
|
|
|
|
2015-12-16 18:51:58 +01:00
|
|
|
if (plink->master <= 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-08-24 09:09:18 +02:00
|
|
|
master = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->master);
|
|
|
|
|
plink_master = nm_platform_link_get (nm_device_get_platform (self), plink->master);
|
|
|
|
|
plink_master_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink_master));
|
|
|
|
|
|
|
|
|
|
if ( master == NULL
|
|
|
|
|
&& plink_master
|
|
|
|
|
&& g_strcmp0 (plink_master->name, "ovs-system") == 0
|
|
|
|
|
&& plink_master->type == NM_LINK_TYPE_OPENVSWITCH) {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "the device claimed by openvswitch");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
if (priv->master) {
|
|
|
|
|
if ( plink->master > 0
|
|
|
|
|
&& plink->master == nm_device_get_ifindex (priv->master)) {
|
|
|
|
|
/* call add-slave again. We expect @self already to be added to
|
|
|
|
|
* the master, but this also triggers a recheck-assume. */
|
|
|
|
|
nm_device_master_add_slave (priv->master, self, FALSE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-09-24 16:58:07 -05:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
|
|
|
|
}
|
2017-08-24 09:09:18 +02:00
|
|
|
|
|
|
|
|
if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave)
|
|
|
|
|
nm_device_master_add_slave (master, self, FALSE);
|
|
|
|
|
else if (master) {
|
|
|
|
|
_LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring",
|
|
|
|
|
nm_device_get_iface (master));
|
|
|
|
|
} else {
|
|
|
|
|
_LOGW (LOGD_DEVICE, "enslaved to unknown device %d (%s%s%s)",
|
|
|
|
|
plink->master,
|
|
|
|
|
NM_PRINT_FMT_QUOTED (plink_master, "\"", plink_master->name, "\"", "??"));
|
2014-12-05 13:12:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-03 12:15:32 +01:00
|
|
|
static void
|
|
|
|
|
ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-11-10 08:53:17 +01:00
|
|
|
gint32 now;
|
2016-11-03 12:15:32 +01:00
|
|
|
GArray *addresses, *dns_servers, *dns_domains;
|
|
|
|
|
guint len, i;
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMDedupMultiHeadEntry *head_entry;
|
|
|
|
|
NMDedupMultiIter ipconf_iter;
|
2016-11-03 12:15:32 +01:00
|
|
|
|
|
|
|
|
if (nm_ndisc_get_node_type (ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-11-10 08:53:17 +01:00
|
|
|
now = nm_utils_get_monotonic_timestamp_s ();
|
|
|
|
|
|
2017-07-07 23:34:41 +02:00
|
|
|
head_entry = nm_ip6_config_lookup_addresses (priv->ip6_config);
|
|
|
|
|
addresses = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscAddress),
|
|
|
|
|
head_entry ? head_entry->len : 0);
|
|
|
|
|
nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) {
|
|
|
|
|
const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS (ipconf_iter.current->obj);
|
2016-11-03 12:15:32 +01:00
|
|
|
NMNDiscAddress *ndisc_addr;
|
|
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if ( addr->n_ifa_flags & IFA_F_TENTATIVE
|
|
|
|
|
|| addr->n_ifa_flags & IFA_F_DADFAILED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (addr->plen != 64)
|
|
|
|
|
continue;
|
|
|
|
|
|
2016-11-10 08:10:28 +01:00
|
|
|
g_array_set_size (addresses, addresses->len+1);
|
2016-11-03 12:15:32 +01:00
|
|
|
ndisc_addr = &g_array_index (addresses, NMNDiscAddress, addresses->len-1);
|
|
|
|
|
ndisc_addr->address = addr->address;
|
|
|
|
|
ndisc_addr->timestamp = addr->timestamp;
|
|
|
|
|
ndisc_addr->lifetime = addr->lifetime;
|
|
|
|
|
ndisc_addr->preferred = addr->preferred;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len = nm_ip6_config_get_num_nameservers (priv->ip6_config);
|
2016-11-10 08:53:17 +01:00
|
|
|
dns_servers = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscDNSServer), len);
|
|
|
|
|
g_array_set_size (dns_servers, len);
|
2016-11-03 12:15:32 +01:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip6_config, i);
|
|
|
|
|
NMNDiscDNSServer *ndisc_nameserver;
|
|
|
|
|
|
2016-11-10 10:03:59 +01:00
|
|
|
ndisc_nameserver = &g_array_index (dns_servers, NMNDiscDNSServer, i);
|
2016-11-03 12:15:32 +01:00
|
|
|
ndisc_nameserver->address = *nameserver;
|
|
|
|
|
ndisc_nameserver->timestamp = now;
|
|
|
|
|
ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len = nm_ip6_config_get_num_searches (priv->ip6_config);
|
2016-11-10 08:53:17 +01:00
|
|
|
dns_domains = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscDNSDomain), len);
|
|
|
|
|
g_array_set_size (dns_domains, len);
|
2016-11-03 12:15:32 +01:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
const char *search = nm_ip6_config_get_search (priv->ip6_config, i);
|
|
|
|
|
NMNDiscDNSDomain *ndisc_search;
|
|
|
|
|
|
2016-11-10 10:03:59 +01:00
|
|
|
ndisc_search = &g_array_index (dns_domains, NMNDiscDNSDomain, i);
|
2016-11-10 10:03:59 +01:00
|
|
|
ndisc_search->domain = (char *) search;
|
2016-11-03 12:15:32 +01:00
|
|
|
ndisc_search->timestamp = now;
|
|
|
|
|
ndisc_search->lifetime = NM_NDISC_ROUTER_LIFETIME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_ndisc_set_config (ndisc, addresses, dns_servers, dns_domains);
|
2016-11-10 08:53:17 +01:00
|
|
|
g_array_unref (addresses);
|
|
|
|
|
g_array_unref (dns_servers);
|
|
|
|
|
g_array_unref (dns_domains);
|
2016-11-03 12:15:32 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
static gboolean
|
|
|
|
|
device_link_changed (NMDevice *self)
|
2014-03-18 10:18:56 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-03-18 10:18:56 -04:00
|
|
|
gboolean ip_ifname_changed = FALSE;
|
2017-10-27 11:56:20 +02:00
|
|
|
nm_auto_nmpobj const NMPObject *pllink_keep_alive = NULL;
|
2015-06-20 12:05:01 +02:00
|
|
|
const NMPlatformLink *pllink;
|
2015-06-17 19:13:08 +02:00
|
|
|
int ifindex;
|
2016-04-15 20:01:36 +02:00
|
|
|
gboolean was_up;
|
2016-05-16 17:36:56 +02:00
|
|
|
gboolean update_unmanaged_specs = FALSE;
|
2016-05-24 13:45:58 +02:00
|
|
|
gboolean got_hw_addr = FALSE, had_hw_addr;
|
2014-01-28 21:25:34 +01:00
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
priv->device_link_changed_id = 0;
|
|
|
|
|
|
|
|
|
|
ifindex = nm_device_get_ifindex (self);
|
2017-04-17 20:17:45 +02:00
|
|
|
pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex);
|
2015-06-20 12:05:01 +02:00
|
|
|
if (!pllink)
|
2015-06-17 19:13:08 +02:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
pllink_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (pllink));
|
2015-04-13 16:29:37 -05:00
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
nm_device_update_from_platform_link (self, pllink);
|
2016-08-16 15:55:04 +02:00
|
|
|
|
2016-05-24 13:45:58 +02:00
|
|
|
had_hw_addr = (priv->hw_addr != NULL);
|
|
|
|
|
nm_device_update_hw_address (self);
|
|
|
|
|
got_hw_addr = (!had_hw_addr && priv->hw_addr);
|
2016-10-24 12:50:17 +02:00
|
|
|
nm_device_update_permanent_hw_address (self, FALSE);
|
2016-05-24 13:45:58 +02:00
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
if (pllink->name[0] && strcmp (priv->iface, pllink->name) != 0) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'",
|
2017-10-27 11:56:20 +02:00
|
|
|
priv->ifindex, priv->iface, pllink->name);
|
2014-03-18 10:18:56 -04:00
|
|
|
g_free (priv->iface);
|
2017-10-27 11:56:20 +02:00
|
|
|
priv->iface = g_strdup (pllink->name);
|
2014-01-28 21:25:34 +01:00
|
|
|
|
2014-03-18 10:18:56 -04:00
|
|
|
/* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */
|
|
|
|
|
ip_ifname_changed = !priv->ip_iface;
|
2014-01-28 21:25:34 +01:00
|
|
|
|
2016-05-16 17:36:56 +02:00
|
|
|
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT))
|
2016-10-25 15:27:57 +02:00
|
|
|
nm_device_set_unmanaged_by_user_settings (self);
|
2016-05-16 17:36:56 +02:00
|
|
|
else
|
|
|
|
|
update_unmanaged_specs = TRUE;
|
|
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IFACE);
|
2014-03-18 10:18:56 -04:00
|
|
|
if (ip_ifname_changed)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP_IFACE);
|
2014-01-28 21:25:34 +01:00
|
|
|
|
2014-03-18 10:18:56 -04:00
|
|
|
/* Re-match available connections against the new interface name */
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_recheck_available_connections (self);
|
2014-01-28 21:25:34 +01:00
|
|
|
|
2014-03-18 10:18:56 -04:00
|
|
|
/* Let any connections that use the new interface name have a chance
|
|
|
|
|
* to auto-activate on the device.
|
|
|
|
|
*/
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_emit_recheck_auto_activate (self);
|
2013-12-16 15:16:43 +01:00
|
|
|
}
|
|
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
if (priv->ndisc && pllink->inet6_token.id) {
|
|
|
|
|
if (nm_ndisc_set_iid (priv->ndisc, pllink->inet6_token))
|
2016-04-29 21:34:06 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
|
2014-09-27 09:04:46 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-02 15:47:16 +01:00
|
|
|
/* Update carrier from link event if applicable. */
|
|
|
|
|
if ( nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)
|
|
|
|
|
&& !nm_device_has_capability (self, NM_DEVICE_CAP_NONSTANDARD_CARRIER))
|
|
|
|
|
nm_device_set_carrier (self, pllink->connected);
|
|
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
klass->link_changed (self, pllink);
|
2014-05-19 09:56:29 -04:00
|
|
|
|
|
|
|
|
/* Update DHCP, etc, if needed */
|
|
|
|
|
if (ip_ifname_changed)
|
2016-03-26 01:26:36 -04:00
|
|
|
nm_device_update_dynamic_ip_setup (self);
|
2014-12-03 12:47:30 -06:00
|
|
|
|
2016-04-15 20:01:36 +02:00
|
|
|
was_up = priv->up;
|
2017-10-27 11:56:20 +02:00
|
|
|
priv->up = NM_FLAGS_HAS (pllink->n_ifi_flags, IFF_UP);
|
device: fix race wrongly managing external-down device due to late udev signal
Executing:
# brctl addbr lbr0
# ip addr add 10.1.1.1/24 dev lbr0
# ip link set lbr0 up
can result in a race so that NetworkManager would manage the device
(and clear the IP addresses).
It happens, when NetworkManager first receives platform signals that
the device is already up:
signal: link changed: 11: lbr0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu 1500 arp 1 bridge* not-init addrgenmode eui64 addr D2:A1:B4:17:18:F2 driver bridge
Note that the device is still unknown via udev (not-init). The
unmanaged-state NM_UNMANAGED_EXTERNAL_DOWN gets cleared, but the
device still stays unmanaged.
Only afterwards the device is known in udev:
signal: link changed: 11: lbr0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu 1500 arp 1 bridge* init addrgenmode eui64 addr D2:A1:B4:17:18:F2 driver bridge
At this point, we also clear NM_UNMANAGED_PLATFORM_INIT, making
the device managed with reason NM_DEVICE_STATE_REASON_NOW_MANAGED.
That results in managing the external device.
Fix that by only clearing NM_UNMANAGED_EXTERNAL_DOWN after the device
is no longer NM_UNMANAGED_PLATFORM_INIT.
https://bugzilla.redhat.com/show_bug.cgi?id=1269199
2015-10-08 11:11:42 +02:00
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
if ( pllink->initialized
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
&& nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
|
2016-02-18 16:13:23 +01:00
|
|
|
NMDeviceStateReason reason;
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
nm_device_set_unmanaged_by_user_udev (self);
|
2017-09-26 16:28:49 +02:00
|
|
|
nm_device_set_unmanaged_by_user_conf (self);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
2016-04-08 11:36:13 +02:00
|
|
|
reason = NM_DEVICE_STATE_REASON_NOW_MANAGED;
|
|
|
|
|
|
2016-03-21 14:56:15 +01:00
|
|
|
/* If the device is a external-down candidated but no longer has external
|
|
|
|
|
* down set, we must clear the platform-unmanaged flag with reason
|
|
|
|
|
* "assumed". */
|
|
|
|
|
if ( nm_device_get_unmanaged_mask (self, NM_UNMANAGED_EXTERNAL_DOWN)
|
|
|
|
|
&& !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) {
|
2016-04-08 11:36:13 +02:00
|
|
|
/* actually, user-udev overwrites external-down. So we only assume the device,
|
|
|
|
|
* when it is a external-down candidate, which is not managed via udev. */
|
|
|
|
|
if (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_USER_UDEV)) {
|
|
|
|
|
/* Ensure the assume check is queued before any queued state changes
|
|
|
|
|
* from the transition to UNAVAILABLE.
|
|
|
|
|
*/
|
|
|
|
|
nm_device_queue_recheck_assume (self);
|
|
|
|
|
reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-18 16:13:23 +01:00
|
|
|
|
|
|
|
|
nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
}
|
core: fix re-activation of connections on EXTERNAL_DOWN interfaces (bgo #741742)
When userspace IPv6LL capability is compiled into NetworkManager,
during deactivation NM will toggle userspace IPv6LL in some cases.
This causes link change events in the platform, which show up
in nm-device.c::device_link_changed().
When an EXTERNAL_DOWN interface was activated, the EXTERNAL_DOWN
flag was never cleared even if the device was set IFF_UP or if
a connection was activated via D-Bus (which explicitly sets the
device up).
Second, the device_link_changed() code changed device state
whether or not IFF_UP had actually changed, it simply looked at
the current value.
Together, this caused the first activation of an EXTERNAL_DOWN
device to succeed, but the EXTERNAL_DOWN flag was never cleared
even though the activation set the device IFF_UP. When a second
activation request came in, the device was moved to DISCONNECTED
state and IPv6LL genmode was reset, causing device_link_changed()
to run. Since the device had EXTERNAL_DOWN and IFF_UP were still
set, nm_device_set_unmanaged_flag() code was triggered to clear
EXTERNAL_DOWN, which resulted in a state transition to UNAVAILABLE
with a reason of CONNECTION_ASSUMED. This caused the second
activation request to fail because UNAVAILABLE devices cannot
activate connections by definition.
The fix has three parts:
1) Only change EXTERNAL_DOWN if IFF_UP actually changes, to prevent
spurious changes when something other than IFF_UP changes
2) Only clear EXTERNAL_DOWN when IFF_UP changes while the device
is UNMANAGED, since any state higher than UNMANAGED implies that
either an activation request was received (and thus the device
should be managed) or IFF_UP was set
3) Clear EXTERNAL_DOWN (without triggering state changes) when
any state higher than UNAVAILABLE is entered, since this implies
that a connection is activating or the device is no longer
IFF_UP
fixes:NetworkManager_Test108_testcase_303655
https://bugzilla.gnome.org/show_bug.cgi?id=741742
2014-12-18 23:38:37 -06:00
|
|
|
|
2016-03-21 15:30:07 +01:00
|
|
|
set_unmanaged_external_down (self, FALSE);
|
2015-04-13 16:29:37 -05:00
|
|
|
|
2017-10-27 11:56:20 +02:00
|
|
|
device_recheck_slave_status (self, pllink);
|
2016-04-15 20:01:36 +02:00
|
|
|
|
|
|
|
|
if (priv->up && !was_up) {
|
|
|
|
|
/* the link was down and just came up. That happens for example, while changing MTU.
|
|
|
|
|
* We must restore IP configuration. */
|
|
|
|
|
if (priv->ip4_state == IP_DONE) {
|
2017-09-28 14:22:07 +02:00
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE))
|
2016-04-15 20:01:36 +02:00
|
|
|
_LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again");
|
|
|
|
|
}
|
|
|
|
|
if (priv->ip6_state == IP_DONE) {
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2016-04-15 20:01:36 +02:00
|
|
|
_LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-16 17:36:56 +02:00
|
|
|
if (update_unmanaged_specs)
|
2016-10-25 15:27:57 +02:00
|
|
|
nm_device_set_unmanaged_by_user_settings (self);
|
2016-05-16 17:36:56 +02:00
|
|
|
|
2016-05-24 13:45:58 +02:00
|
|
|
if ( got_hw_addr
|
|
|
|
|
&& !priv->up
|
|
|
|
|
&& nm_device_get_state (self) == NM_DEVICE_STATE_UNAVAILABLE) {
|
|
|
|
|
/*
|
|
|
|
|
* If the device is UNAVAILABLE, any previous try to
|
|
|
|
|
* bring it up probably has failed because of the
|
|
|
|
|
* invalid hardware address; try again.
|
|
|
|
|
*/
|
|
|
|
|
nm_device_bring_up (self, TRUE, NULL);
|
|
|
|
|
nm_device_queue_recheck_available (self,
|
|
|
|
|
NM_DEVICE_STATE_REASON_NONE,
|
|
|
|
|
NM_DEVICE_STATE_REASON_NONE);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
return G_SOURCE_REMOVE;
|
2014-03-18 10:18:56 -04:00
|
|
|
}
|
|
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
static gboolean
|
|
|
|
|
device_ip_link_changed (NMDevice *self)
|
2014-03-18 10:18:56 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-06-20 12:05:01 +02:00
|
|
|
const NMPlatformLink *pllink;
|
2015-06-17 19:13:08 +02:00
|
|
|
|
|
|
|
|
priv->device_ip_link_changed_id = 0;
|
2014-03-18 10:18:56 -04:00
|
|
|
|
2016-01-04 14:22:01 +01:00
|
|
|
if (!priv->ip_ifindex)
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
pllink = nm_platform_link_get (nm_device_get_platform (self), priv->ip_ifindex);
|
2015-06-20 12:05:01 +02:00
|
|
|
if (!pllink)
|
2015-06-17 19:13:08 +02:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
|
2016-08-16 15:55:04 +02:00
|
|
|
_stats_update_counters_from_pllink (self, pllink);
|
|
|
|
|
|
2016-12-26 18:11:03 +01:00
|
|
|
if (_ip_iface_update (self, pllink->name))
|
2016-03-26 01:26:36 -04:00
|
|
|
nm_device_update_dynamic_ip_setup (self);
|
2016-08-16 12:10:23 +02:00
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
return G_SOURCE_REMOVE;
|
2013-07-27 10:41:44 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-18 10:18:56 -04:00
|
|
|
static void
|
2014-07-24 17:14:30 -05:00
|
|
|
link_changed_cb (NMPlatform *platform,
|
2016-10-22 13:08:36 +02:00
|
|
|
int obj_type_i,
|
2014-07-24 17:14:30 -05:00
|
|
|
int ifindex,
|
|
|
|
|
NMPlatformLink *info,
|
2016-10-22 13:08:36 +02:00
|
|
|
int change_type_i,
|
2014-07-24 17:14:30 -05:00
|
|
|
NMDevice *self)
|
2014-03-18 10:18:56 -04:00
|
|
|
{
|
2016-10-22 13:08:36 +02:00
|
|
|
const NMPlatformSignalChangeType change_type = change_type_i;
|
2015-06-17 19:13:08 +02:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
2014-03-18 10:18:56 -04:00
|
|
|
if (change_type != NM_PLATFORM_SIGNAL_CHANGED)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (ifindex == nm_device_get_ifindex (self)) {
|
|
|
|
|
if (!priv->device_link_changed_id) {
|
|
|
|
|
priv->device_link_changed_id = g_idle_add ((GSourceFunc) device_link_changed, self);
|
|
|
|
|
_LOGD (LOGD_DEVICE, "queued link change for ifindex %d", ifindex);
|
|
|
|
|
}
|
|
|
|
|
} else if (ifindex == nm_device_get_ip_ifindex (self)) {
|
|
|
|
|
if (!priv->device_ip_link_changed_id) {
|
|
|
|
|
priv->device_ip_link_changed_id = g_idle_add ((GSourceFunc) device_ip_link_changed, self);
|
|
|
|
|
_LOGD (LOGD_DEVICE, "queued link change for ip-ifindex %d", ifindex);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-18 10:18:56 -04:00
|
|
|
}
|
|
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
in_addr_t network;
|
|
|
|
|
guint8 plen;
|
|
|
|
|
} IP4RPFilterData;
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
_v4_has_shadowed_routes_detect_hash (const IP4RPFilterData *d)
|
|
|
|
|
{
|
2017-10-13 14:00:22 +02:00
|
|
|
NMHashState h;
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
|
2017-10-13 14:00:22 +02:00
|
|
|
nm_hash_init (&h, 1105201169u);
|
2017-10-17 13:28:25 +02:00
|
|
|
nm_hash_update_vals (&h,
|
|
|
|
|
d->network,
|
|
|
|
|
d->plen);
|
2017-10-13 14:00:22 +02:00
|
|
|
return nm_hash_complete (&h);
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_v4_has_shadowed_routes_detect_equal (const IP4RPFilterData *d1, const IP4RPFilterData *d2)
|
|
|
|
|
{
|
|
|
|
|
return d1->network == d2->network && d1->plen == d2->plen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_v4_has_shadowed_routes_detect (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMPlatform *platform;
|
|
|
|
|
int ifindex;
|
|
|
|
|
NMPLookup lookup;
|
|
|
|
|
const NMDedupMultiHeadEntry *head_entry;
|
|
|
|
|
NMDedupMultiIter iter;
|
|
|
|
|
const NMPObject *o;
|
|
|
|
|
guint data_len;
|
|
|
|
|
gs_unref_hashtable GHashTable *data_hash = NULL;
|
|
|
|
|
gs_free IP4RPFilterData *data_arr = NULL;
|
|
|
|
|
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
if (ifindex <= 0)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
platform = nm_device_get_platform (self);
|
|
|
|
|
|
|
|
|
|
head_entry = nm_platform_lookup (platform,
|
|
|
|
|
nmp_lookup_init_addrroute (&lookup,
|
|
|
|
|
NMP_OBJECT_TYPE_IP4_ROUTE,
|
|
|
|
|
ifindex));
|
|
|
|
|
if (!head_entry)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* first, create a lookup index @data_hash for all network/plen pairs. */
|
|
|
|
|
data_len = 0;
|
|
|
|
|
data_arr = g_new (IP4RPFilterData, head_entry->len);
|
|
|
|
|
data_hash = g_hash_table_new ((GHashFunc) _v4_has_shadowed_routes_detect_hash,
|
|
|
|
|
(GEqualFunc) _v4_has_shadowed_routes_detect_equal);
|
|
|
|
|
|
|
|
|
|
nmp_cache_iter_for_each (&iter, head_entry, &o) {
|
|
|
|
|
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
|
|
|
|
|
IP4RPFilterData *d;
|
|
|
|
|
|
|
|
|
|
nm_assert (r->ifindex == ifindex);
|
|
|
|
|
|
2017-08-21 23:17:12 +02:00
|
|
|
if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
|
|
|
|
|
|| r->table_coerced)
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
d = &data_arr[data_len++];
|
|
|
|
|
d->network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
|
|
|
|
|
d->plen = r->plen;
|
|
|
|
|
g_hash_table_add (data_hash, d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* then, search if there is any route on another interface with the same
|
|
|
|
|
* network/plen destination. If yes, we consider this a multihoming
|
|
|
|
|
* setup. */
|
|
|
|
|
head_entry = nm_platform_lookup (platform,
|
|
|
|
|
nmp_lookup_init_obj_type (&lookup,
|
|
|
|
|
NMP_OBJECT_TYPE_IP4_ROUTE));
|
|
|
|
|
nmp_cache_iter_for_each (&iter, head_entry, &o) {
|
|
|
|
|
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
|
|
|
|
|
IP4RPFilterData d;
|
|
|
|
|
|
|
|
|
|
if ( r->ifindex == ifindex
|
2017-08-21 23:17:12 +02:00
|
|
|
|| NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
|
|
|
|
|
|| r->table_coerced)
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
d.network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
|
|
|
|
|
d.plen = r->plen;
|
|
|
|
|
if (g_hash_table_contains (data_hash, &d))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-16 14:27:03 +00:00
|
|
|
static void
|
|
|
|
|
ip4_rp_filter_update (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
const char *ip4_rp_filter;
|
|
|
|
|
|
|
|
|
|
if ( priv->v4_has_shadowed_routes
|
core: rework handling of default-routes and drop NMDefaultRouteManager
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a5205ffcf761abd3e0897a22b254c7797.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb750260045239ab85574366bae8102eff8058cc, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
2017-08-30 11:46:42 +02:00
|
|
|
|| nm_device_get_best_default_route (self, AF_INET)) {
|
2017-03-16 14:27:03 +00:00
|
|
|
if (nm_device_ipv4_sysctl_get_uint32 (self, "rp_filter", 0) != 1) {
|
|
|
|
|
/* Don't touch the rp_filter if it's not strict. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* Loose rp_filter */
|
|
|
|
|
ip4_rp_filter = "2";
|
|
|
|
|
} else {
|
|
|
|
|
/* Default rp_filter */
|
|
|
|
|
ip4_rp_filter = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ip4_rp_filter != priv->ip4_rp_filter) {
|
|
|
|
|
nm_device_ipv4_sysctl_set (self, "rp_filter", ip4_rp_filter);
|
|
|
|
|
priv->ip4_rp_filter = ip4_rp_filter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-27 10:41:44 +02:00
|
|
|
static void
|
2017-01-02 15:38:24 +01:00
|
|
|
link_changed (NMDevice *self, const NMPlatformLink *pllink)
|
2013-07-27 10:41:44 +02:00
|
|
|
{
|
2017-01-02 15:47:16 +01:00
|
|
|
/* stub implementation of virtual function to allow subclasses to chain up. */
|
2013-05-07 10:23:44 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-09 12:42:29 -05:00
|
|
|
static gboolean
|
|
|
|
|
link_type_compatible (NMDevice *self,
|
|
|
|
|
NMLinkType link_type,
|
|
|
|
|
gboolean *out_compatible,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
2015-12-08 14:51:04 +01:00
|
|
|
NMDeviceClass *klass;
|
|
|
|
|
NMLinkType device_type;
|
2014-10-09 12:42:29 -05:00
|
|
|
guint i = 0;
|
|
|
|
|
|
2015-12-08 14:51:04 +01:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
klass = NM_DEVICE_GET_CLASS (self);
|
|
|
|
|
|
2014-10-09 12:42:29 -05:00
|
|
|
if (!klass->link_types) {
|
|
|
|
|
NM_SET_OUT (out_compatible, FALSE);
|
|
|
|
|
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"Device does not support platform links");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 16:55:07 +02:00
|
|
|
device_type = self->_priv->link_type;
|
2015-12-08 14:51:04 +01:00
|
|
|
if (device_type > NM_LINK_TYPE_UNKNOWN && device_type != link_type) {
|
|
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"Needed link type 0x%x does not match the platform link type 0x%X",
|
|
|
|
|
device_type, link_type);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-09 12:42:29 -05:00
|
|
|
for (i = 0; klass->link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
|
|
|
|
|
if (klass->link_types[i] == link_type)
|
|
|
|
|
return TRUE;
|
|
|
|
|
if (klass->link_types[i] == NM_LINK_TYPE_ANY)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NM_SET_OUT (out_compatible, FALSE);
|
|
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"Device does not support platform link type 0x%X",
|
|
|
|
|
link_type);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
/**
|
2016-01-10 14:56:05 +01:00
|
|
|
* nm_device_realize_start():
|
2014-09-05 08:50:02 -05:00
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @plink: an existing platform link or %NULL
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
* @assume_state_guess_assume: set the guess_assume state.
|
|
|
|
|
* @assume_state_connection_uuid: set the connection uuid to assume.
|
2017-06-07 22:11:50 +02:00
|
|
|
* @set_nm_owned: for software device, if TRUE set nm-owned.
|
2016-09-26 14:45:35 +02:00
|
|
|
* @unmanaged_user_explicit: the user-explicit unmanaged flag to apply
|
|
|
|
|
* on the device initially.
|
2014-10-09 12:42:29 -05:00
|
|
|
* @out_compatible: %TRUE on return if @self is compatible with @plink
|
2014-09-05 08:50:02 -05:00
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
2014-09-24 16:58:07 -05:00
|
|
|
* Initializes and sets up the device using existing backing resources. Before
|
2016-01-10 14:56:05 +01:00
|
|
|
* the device is ready for use nm_device_realize_finish() must be called.
|
2014-10-09 12:42:29 -05:00
|
|
|
* @out_compatible will only be set if @plink is not %NULL, and
|
2014-09-05 08:50:02 -05:00
|
|
|
*
|
2016-01-12 10:38:16 +01:00
|
|
|
* Important: if nm_device_realize_start() returns %TRUE, the caller MUST
|
|
|
|
|
* also call nm_device_realize_finish() to balance g_object_freeze_notify().
|
|
|
|
|
*
|
2014-09-05 08:50:02 -05:00
|
|
|
* Returns: %TRUE on success, %FALSE on error
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2016-01-10 14:56:05 +01:00
|
|
|
nm_device_realize_start (NMDevice *self,
|
2016-01-10 15:13:20 +01:00
|
|
|
const NMPlatformLink *plink,
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
gboolean assume_state_guess_assume,
|
|
|
|
|
const char *assume_state_connection_uuid,
|
2017-06-07 22:11:50 +02:00
|
|
|
gboolean set_nm_owned,
|
2016-09-26 14:45:35 +02:00
|
|
|
NMUnmanFlagOp unmanaged_user_explicit,
|
2016-01-10 14:56:05 +01:00
|
|
|
gboolean *out_compatible,
|
|
|
|
|
GError **error)
|
2014-09-05 08:50:02 -05:00
|
|
|
{
|
2017-09-29 16:58:24 +02:00
|
|
|
nm_auto_nmpobj const NMPObject *plink_keep_alive = NULL;
|
|
|
|
|
|
|
|
|
|
nm_assert (!plink || NMP_OBJECT_GET_TYPE (NMP_OBJECT_UP_CAST (plink)) == NMP_OBJECT_TYPE_LINK);
|
2016-08-16 15:40:08 +02:00
|
|
|
|
2014-10-09 12:42:29 -05:00
|
|
|
NM_SET_OUT (out_compatible, TRUE);
|
|
|
|
|
|
|
|
|
|
if (plink) {
|
|
|
|
|
if (g_strcmp0 (nm_device_get_iface (self), plink->name) != 0) {
|
|
|
|
|
NM_SET_OUT (out_compatible, FALSE);
|
|
|
|
|
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"Device interface name does not match platform link");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!link_type_compatible (self, plink->type, out_compatible, error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2017-09-29 16:58:24 +02:00
|
|
|
plink_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink));
|
2016-08-16 15:40:08 +02:00
|
|
|
}
|
2017-09-29 16:58:24 +02:00
|
|
|
|
|
|
|
|
realize_start_setup (self,
|
|
|
|
|
plink,
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
assume_state_guess_assume,
|
|
|
|
|
assume_state_connection_uuid,
|
|
|
|
|
set_nm_owned,
|
|
|
|
|
unmanaged_user_explicit);
|
2014-09-05 08:50:02 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_device_create_and_realize():
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @connection: the #NMConnection being activated
|
|
|
|
|
* @parent: the parent #NMDevice if any
|
|
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Creates any backing resources needed to realize the device to proceed
|
|
|
|
|
* with activating @connection.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success, %FALSE on error
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_create_and_realize (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
NMDevice *parent,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
2017-09-29 16:58:24 +02:00
|
|
|
nm_auto_nmpobj const NMPObject *plink_keep_alive = NULL;
|
2014-09-24 16:58:07 -05:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-12-09 15:13:57 +01:00
|
|
|
const NMPlatformLink *plink = NULL;
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2014-09-24 16:58:07 -05:00
|
|
|
/* Must be set before device is realized */
|
2017-05-31 16:42:05 +02:00
|
|
|
priv->nm_owned = !nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface);
|
2014-09-24 16:58:07 -05:00
|
|
|
|
2017-05-31 16:42:05 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "create (is %snm-owned)", priv->nm_owned ? "" : "not ");
|
2016-01-12 17:07:04 +01:00
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
/* Create any resources the device needs */
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->create_and_realize) {
|
|
|
|
|
if (!NM_DEVICE_GET_CLASS (self)->create_and_realize (self, connection, parent, &plink, error))
|
|
|
|
|
return FALSE;
|
2017-06-30 17:49:44 +02:00
|
|
|
if (plink) {
|
2017-09-29 16:58:24 +02:00
|
|
|
nm_assert (NMP_OBJECT_GET_TYPE (NMP_OBJECT_UP_CAST (plink)) == NMP_OBJECT_TYPE_LINK);
|
|
|
|
|
plink_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink));
|
2017-06-30 17:49:44 +02:00
|
|
|
}
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
|
|
|
|
|
2017-09-29 16:58:24 +02:00
|
|
|
realize_start_setup (self,
|
|
|
|
|
plink,
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
FALSE, /* assume_state_guess_assume */
|
|
|
|
|
NULL, /* assume_state_connection_uuid */
|
|
|
|
|
FALSE, NM_UNMAN_FLAG_OP_FORGET);
|
2016-01-10 14:56:05 +01:00
|
|
|
nm_device_realize_finish (self, plink);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if (nm_device_get_managed (self, FALSE)) {
|
|
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
NM_DEVICE_STATE_UNAVAILABLE,
|
|
|
|
|
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
|
|
|
|
}
|
2014-09-05 08:50:02 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-16 15:44:24 +02:00
|
|
|
void
|
|
|
|
|
nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink)
|
2014-09-05 08:50:02 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-08-16 15:44:24 +02:00
|
|
|
const char *str;
|
|
|
|
|
int ifindex;
|
|
|
|
|
guint32 mtu;
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-08-16 15:44:24 +02:00
|
|
|
g_return_if_fail (plink == NULL || link_type_compatible (self, plink->type, NULL, NULL));
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-08-16 15:44:24 +02:00
|
|
|
str = plink ? nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex) : NULL;
|
|
|
|
|
if (g_strcmp0 (str, priv->udi)) {
|
2014-09-05 08:50:02 -05:00
|
|
|
g_free (priv->udi);
|
2017-08-16 15:44:24 +02:00
|
|
|
priv->udi = g_strdup (str);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_UDI);
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
|
|
|
|
|
2017-08-16 15:44:24 +02:00
|
|
|
str = plink ? plink->name : NULL;
|
|
|
|
|
if (str && g_strcmp0 (str, priv->iface)) {
|
2014-09-05 08:50:02 -05:00
|
|
|
g_free (priv->iface);
|
2017-08-16 15:44:24 +02:00
|
|
|
priv->iface = g_strdup (str);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IFACE);
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
|
|
|
|
|
2017-08-16 15:44:24 +02:00
|
|
|
str = plink ? plink->driver : NULL;
|
|
|
|
|
if (g_strcmp0 (str, priv->driver) != 0) {
|
2014-09-05 08:50:02 -05:00
|
|
|
g_free (priv->driver);
|
2017-08-16 15:44:24 +02:00
|
|
|
priv->driver = g_strdup (str);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DRIVER);
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
2017-08-16 15:44:24 +02:00
|
|
|
|
|
|
|
|
if (plink) {
|
|
|
|
|
priv->up = NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP);
|
|
|
|
|
if (plink->ifindex == nm_device_get_ip_ifindex (self))
|
|
|
|
|
_stats_update_counters_from_pllink (self, plink);
|
|
|
|
|
} else {
|
|
|
|
|
priv->up = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mtu = plink ? plink->mtu : 0;
|
|
|
|
|
_set_mtu (self, mtu);
|
|
|
|
|
|
|
|
|
|
ifindex = plink ? plink->ifindex : 0;
|
|
|
|
|
if (priv->ifindex != ifindex) {
|
|
|
|
|
priv->ifindex = ifindex;
|
|
|
|
|
_notify (self, PROP_IFINDEX);
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->link_changed (self, plink);
|
|
|
|
|
}
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
|
|
|
|
|
2017-04-14 23:33:14 +02:00
|
|
|
static void
|
|
|
|
|
device_init_sriov_num_vfs (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
int num_vfs;
|
|
|
|
|
|
|
|
|
|
if ( priv->ifindex > 0
|
|
|
|
|
&& nm_device_has_capability (self, NM_DEVICE_CAP_SRIOV)) {
|
|
|
|
|
value = nm_config_data_get_device_config (NM_CONFIG_GET_DATA,
|
2017-04-19 10:29:04 +02:00
|
|
|
NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS,
|
2017-04-14 23:33:14 +02:00
|
|
|
self,
|
|
|
|
|
NULL);
|
|
|
|
|
num_vfs = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT32, -1);
|
|
|
|
|
if (num_vfs >= 0) {
|
|
|
|
|
nm_platform_link_set_sriov_num_vfs (nm_device_get_platform (self),
|
|
|
|
|
priv->ifindex, num_vfs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 14:06:35 -05:00
|
|
|
static void
|
2017-04-14 17:46:20 +02:00
|
|
|
config_changed (NMConfig *config,
|
|
|
|
|
NMConfigData *config_data,
|
|
|
|
|
NMConfigChangeFlags changes,
|
|
|
|
|
NMConfigData *old_data,
|
|
|
|
|
NMDevice *self)
|
2015-05-26 14:06:35 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if ( priv->state <= NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
|| priv->state > NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
priv->ignore_carrier = nm_config_data_get_ignore_carrier (config_data, self);
|
2017-04-14 17:46:20 +02:00
|
|
|
|
|
|
|
|
if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_VALUES))
|
|
|
|
|
device_init_sriov_num_vfs (self);
|
2015-05-26 14:06:35 -05:00
|
|
|
}
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
static void
|
2017-01-02 15:53:18 +01:00
|
|
|
realize_start_notify (NMDevice *self,
|
|
|
|
|
const NMPlatformLink *pllink)
|
2014-09-05 08:50:02 -05:00
|
|
|
{
|
2017-01-02 15:53:18 +01:00
|
|
|
/* the default implementation of realize_start_notify() just calls
|
|
|
|
|
* link_changed() -- which by default does nothing. */
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->link_changed (self, pllink);
|
2016-01-08 17:24:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* realize_start_setup():
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @plink: the #NMPlatformLink if backed by a kernel netdevice
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
* @assume_state_guess_assume: set the guess_assume state.
|
|
|
|
|
* @assume_state_connection_uuid: set the connection uuid to assume.
|
2017-06-07 22:11:50 +02:00
|
|
|
* @set_nm_owned: if TRUE and device is a software-device, set nm-owned.
|
|
|
|
|
* TRUE.
|
2016-09-26 14:45:35 +02:00
|
|
|
* @unmanaged_user_explicit: the user-explict unmanaged flag to set.
|
2016-01-08 17:24:24 +01:00
|
|
|
*
|
|
|
|
|
* Update the device from backing resource properties (like hardware
|
|
|
|
|
* addresses, carrier states, driver/firmware info, etc). This function
|
|
|
|
|
* should only change properties for this device, and should not perform
|
|
|
|
|
* any tasks that affect other interfaces (like master/slave or parent/child
|
|
|
|
|
* stuff).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2016-09-26 14:45:35 +02:00
|
|
|
realize_start_setup (NMDevice *self,
|
|
|
|
|
const NMPlatformLink *plink,
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
gboolean assume_state_guess_assume,
|
|
|
|
|
const char *assume_state_connection_uuid,
|
2017-06-07 22:11:50 +02:00
|
|
|
gboolean set_nm_owned,
|
2016-09-26 14:45:35 +02:00
|
|
|
NMUnmanFlagOp unmanaged_user_explicit)
|
2016-01-08 17:24:24 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMDeviceClass *klass;
|
2014-09-05 08:50:02 -05:00
|
|
|
static guint32 id = 0;
|
2016-05-09 18:16:45 +02:00
|
|
|
NMDeviceCapabilities capabilities = 0;
|
2016-05-11 16:53:16 +02:00
|
|
|
NMConfig *config;
|
2016-08-16 12:10:23 +02:00
|
|
|
guint real_rate;
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-09-29 16:58:24 +02:00
|
|
|
/* plink is a NMPlatformLink type, however, we require it to come from the platform
|
|
|
|
|
* cache (where else would it come from?). */
|
|
|
|
|
nm_assert (!plink || NMP_OBJECT_GET_TYPE (NMP_OBJECT_UP_CAST (plink)) == NMP_OBJECT_TYPE_LINK);
|
|
|
|
|
|
2016-01-08 17:24:24 +01:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
/* The device should not be realized */
|
2016-01-12 10:38:16 +01:00
|
|
|
g_return_if_fail (!priv->real);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
g_return_if_fail (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT));
|
2014-09-05 08:50:02 -05:00
|
|
|
g_return_if_fail (priv->ip_ifindex <= 0);
|
|
|
|
|
g_return_if_fail (priv->ip_iface == NULL);
|
2016-05-05 11:05:07 +02:00
|
|
|
g_return_if_fail (!priv->queued_ip4_config_id);
|
|
|
|
|
g_return_if_fail (!priv->queued_ip6_config_id);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2016-01-12 17:07:04 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "start setup of %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), plink ? plink->ifindex : 0);
|
|
|
|
|
|
2016-01-08 17:24:24 +01:00
|
|
|
klass = NM_DEVICE_GET_CLASS (self);
|
|
|
|
|
|
2016-01-10 14:56:05 +01:00
|
|
|
/* Balanced by a thaw in nm_device_realize_finish() */
|
2014-09-05 08:50:02 -05:00
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
|
|
2017-01-16 12:18:51 +01:00
|
|
|
priv->mtu_initialized = FALSE;
|
2017-01-16 10:20:26 +01:00
|
|
|
priv->mtu_initial = 0;
|
|
|
|
|
priv->ip6_mtu_initial = 0;
|
2017-01-13 15:55:48 +01:00
|
|
|
priv->ip6_mtu = 0;
|
2017-10-13 13:11:11 +02:00
|
|
|
_set_mtu (self, 0);
|
2017-01-13 15:55:48 +01:00
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
_assume_state_set (self, assume_state_guess_assume, assume_state_connection_uuid);
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);
|
|
|
|
|
|
2017-08-16 15:44:24 +02:00
|
|
|
if (plink)
|
|
|
|
|
nm_device_update_from_platform_link (self, plink);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
|
|
|
|
if (priv->ifindex > 0) {
|
2017-04-17 20:17:45 +02:00
|
|
|
priv->physical_port_id = nm_platform_link_get_physical_port_id (nm_device_get_platform (self), priv->ifindex);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_PHYSICAL_PORT_ID);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
priv->dev_id = nm_platform_link_get_dev_id (nm_device_get_platform (self), priv->ifindex);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (nm_platform_link_is_software (nm_device_get_platform (self), priv->ifindex))
|
2016-05-09 18:16:45 +02:00
|
|
|
capabilities |= NM_DEVICE_CAP_IS_SOFTWARE;
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-10-13 13:11:11 +02:00
|
|
|
_set_mtu (self,
|
|
|
|
|
nm_platform_link_get_mtu (nm_device_get_platform (self),
|
|
|
|
|
priv->ifindex));
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_get_driver_info (nm_device_get_platform (self),
|
2014-09-05 08:50:02 -05:00
|
|
|
priv->ifindex,
|
|
|
|
|
NULL,
|
|
|
|
|
&priv->driver_version,
|
|
|
|
|
&priv->firmware_version);
|
|
|
|
|
if (priv->driver_version)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DRIVER_VERSION);
|
2014-09-05 08:50:02 -05:00
|
|
|
if (priv->firmware_version)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_FIRMWARE_VERSION);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-10-10 18:20:05 +02:00
|
|
|
if (nm_platform_check_kernel_support (nm_device_get_platform (self),
|
|
|
|
|
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
|
2017-04-17 20:17:45 +02:00
|
|
|
priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex);
|
2017-04-14 23:16:11 +02:00
|
|
|
|
|
|
|
|
if (nm_platform_link_supports_sriov (nm_device_get_platform (self), priv->ifindex))
|
|
|
|
|
capabilities |= NM_DEVICE_CAP_SRIOV;
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
|
|
|
|
|
2016-01-08 17:24:24 +01:00
|
|
|
if (klass->get_generic_capabilities)
|
2016-05-09 18:16:45 +02:00
|
|
|
capabilities |= klass->get_generic_capabilities (self);
|
|
|
|
|
|
|
|
|
|
_add_capabilities (self, capabilities);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-05-31 16:58:21 +02:00
|
|
|
if ( !priv->nm_owned
|
2017-06-07 22:11:50 +02:00
|
|
|
&& set_nm_owned
|
2017-05-31 16:58:21 +02:00
|
|
|
&& nm_device_is_software (self)) {
|
2017-06-07 22:11:50 +02:00
|
|
|
priv->nm_owned = TRUE;
|
|
|
|
|
_LOGD (LOGD_DEVICE, "set nm-owned from state file");
|
2017-05-31 16:58:21 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
if (!priv->udi) {
|
|
|
|
|
/* Use a placeholder UDI until we get a real one */
|
|
|
|
|
priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_UDI);
|
2014-09-05 08:50:02 -05:00
|
|
|
}
|
|
|
|
|
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
priv->queued_ip4_config_pending = TRUE;
|
|
|
|
|
priv->queued_ip6_config_pending = TRUE;
|
2014-09-05 08:50:02 -05:00
|
|
|
|
|
|
|
|
nm_device_update_hw_address (self);
|
2015-12-14 08:46:29 +01:00
|
|
|
nm_device_update_initial_hw_address (self);
|
2016-10-24 12:50:17 +02:00
|
|
|
nm_device_update_permanent_hw_address (self, FALSE);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
|
|
|
|
/* Note: initial hardware address must be read before calling get_ignore_carrier() */
|
2016-05-11 16:53:16 +02:00
|
|
|
config = nm_config_get ();
|
|
|
|
|
priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self);
|
2017-04-14 17:46:20 +02:00
|
|
|
if (!priv->config_changed_id) {
|
|
|
|
|
priv->config_changed_id = g_signal_connect (config,
|
2016-05-11 16:53:16 +02:00
|
|
|
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
|
2017-04-14 17:46:20 +02:00
|
|
|
G_CALLBACK (config_changed),
|
2016-05-11 16:53:16 +02:00
|
|
|
self);
|
|
|
|
|
}
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-05-15 11:35:41 +02:00
|
|
|
nm_device_set_carrier_from_platform (self);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2017-04-14 23:33:14 +02:00
|
|
|
device_init_sriov_num_vfs (self);
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
nm_assert (!priv->stats.timeout_id);
|
|
|
|
|
real_rate = _stats_refresh_rate_real (priv->stats.refresh_rate_ms);
|
2016-08-16 15:55:04 +02:00
|
|
|
if (real_rate)
|
2016-08-16 12:10:23 +02:00
|
|
|
priv->stats.timeout_id = g_timeout_add (real_rate, _stats_timeout_cb, self);
|
2016-08-10 11:54:31 +02:00
|
|
|
|
2016-01-08 17:24:24 +01:00
|
|
|
klass->realize_start_notify (self, plink);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
2016-09-26 14:45:35 +02:00
|
|
|
nm_assert (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_USER_EXPLICIT));
|
|
|
|
|
nm_device_set_unmanaged_flags (self,
|
|
|
|
|
NM_UNMANAGED_USER_EXPLICIT,
|
|
|
|
|
unmanaged_user_explicit);
|
|
|
|
|
|
2016-03-21 14:56:15 +01:00
|
|
|
/* Do not manage externally created software devices until they are IFF_UP
|
|
|
|
|
* or have IP addressing */
|
|
|
|
|
nm_device_set_unmanaged_flags (self,
|
|
|
|
|
NM_UNMANAGED_EXTERNAL_DOWN,
|
|
|
|
|
is_unmanaged_external_down (self, TRUE));
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
|
|
|
|
/* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag.
|
|
|
|
|
* Later we might want to manage 'lo' too. Currently that doesn't work because
|
|
|
|
|
* NetworkManager might down the interface or remove the 127.0.0.1 address. */
|
|
|
|
|
nm_device_set_unmanaged_flags (self, NM_UNMANAGED_LOOPBACK, priv->ifindex == 1);
|
|
|
|
|
|
|
|
|
|
nm_device_set_unmanaged_by_user_udev (self);
|
2017-09-26 16:28:49 +02:00
|
|
|
nm_device_set_unmanaged_by_user_conf (self);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
|
|
|
|
nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT,
|
|
|
|
|
plink && !plink->initialized);
|
2016-01-08 16:53:47 +01:00
|
|
|
}
|
|
|
|
|
|
2016-01-08 17:08:54 +01:00
|
|
|
/**
|
2016-01-10 14:56:05 +01:00
|
|
|
* nm_device_realize_finish():
|
2016-01-08 17:08:54 +01:00
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @plink: the #NMPlatformLink if backed by a kernel netdevice
|
|
|
|
|
*
|
|
|
|
|
* Update the device's master/slave or parent/child relationships from
|
|
|
|
|
* backing resource properties. After this function finishes, the device
|
|
|
|
|
* is ready for network connectivity.
|
|
|
|
|
*/
|
2014-09-24 16:58:07 -05:00
|
|
|
void
|
2016-01-10 14:56:05 +01:00
|
|
|
nm_device_realize_finish (NMDevice *self, const NMPlatformLink *plink)
|
2014-09-24 16:58:07 -05:00
|
|
|
{
|
2016-01-12 10:38:16 +01:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2014-10-09 12:42:29 -05:00
|
|
|
g_return_if_fail (!plink || link_type_compatible (self, plink->type, NULL, NULL));
|
|
|
|
|
|
2016-01-12 10:38:16 +01:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (!priv->real);
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if (plink)
|
2016-01-08 17:08:54 +01:00
|
|
|
device_recheck_slave_status (self, plink);
|
2014-09-24 16:58:07 -05:00
|
|
|
|
2016-01-12 10:38:16 +01:00
|
|
|
priv->real = TRUE;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_REAL);
|
2014-09-05 08:50:02 -05:00
|
|
|
|
2014-09-24 16:58:07 -05:00
|
|
|
nm_device_recheck_available_connections (self);
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
/* Balanced by a freeze in realize_start_setup(). */
|
2014-09-05 08:50:02 -05:00
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
static void
|
2016-01-10 15:19:58 +01:00
|
|
|
unrealize_notify (NMDevice *self)
|
2014-09-24 15:13:19 -05:00
|
|
|
{
|
2016-01-10 15:19:58 +01:00
|
|
|
/* Stub implementation for unrealize_notify(). It does nothing,
|
|
|
|
|
* but allows derived classes to uniformly invoke the parent
|
|
|
|
|
* implementation. */
|
2014-09-24 15:13:19 -05:00
|
|
|
}
|
|
|
|
|
|
2016-01-19 11:33:33 +01:00
|
|
|
static gboolean
|
2016-01-20 18:02:34 +01:00
|
|
|
available_connections_check_delete_unrealized_on_idle (gpointer user_data)
|
2016-01-19 11:33:33 +01:00
|
|
|
{
|
|
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->check_delete_unrealized_id = 0;
|
|
|
|
|
|
|
|
|
|
if ( g_hash_table_size (priv->available_connections) == 0
|
|
|
|
|
&& !nm_device_is_real (self))
|
|
|
|
|
g_signal_emit (self, signals[REMOVED], 0);
|
|
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 20:52:55 +01:00
|
|
|
static void
|
2016-01-20 18:02:34 +01:00
|
|
|
available_connections_check_delete_unrealized (NMDevice *self)
|
2016-01-18 20:52:55 +01:00
|
|
|
{
|
2016-01-19 11:33:33 +01:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* always rescheadule the remove signal. */
|
|
|
|
|
nm_clear_g_source (&priv->check_delete_unrealized_id);
|
2016-01-18 20:52:55 +01:00
|
|
|
|
|
|
|
|
if ( g_hash_table_size (priv->available_connections) == 0
|
|
|
|
|
&& !nm_device_is_real (self))
|
2016-01-20 18:02:34 +01:00
|
|
|
priv->check_delete_unrealized_id = g_idle_add (available_connections_check_delete_unrealized_on_idle, self);
|
2016-01-18 20:52:55 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_unrealize():
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @remove_resources: if %TRUE, remove backing resources
|
|
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Clears any properties that depend on backing resources (kernel devices,
|
|
|
|
|
* etc) and removes those resources if @remove_resources is %TRUE.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success, %FALSE on error
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2016-01-10 15:19:58 +01:00
|
|
|
int ifindex;
|
2014-09-24 15:13:19 -05:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
if (!nm_device_is_software (self) || !nm_device_is_real (self)) {
|
|
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_SOFTWARE,
|
|
|
|
|
"This device is not a software device or is not realized");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (priv->iface != NULL, FALSE);
|
2016-01-12 10:38:16 +01:00
|
|
|
g_return_val_if_fail (priv->real, FALSE);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
|
|
|
|
|
2016-01-12 17:07:04 +01:00
|
|
|
ifindex = nm_device_get_ifindex (self);
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_DEVICE, "unrealize (ifindex %d)", ifindex > 0 ? ifindex : 0);
|
|
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
nm_device_assume_state_reset (self);
|
|
|
|
|
|
2016-01-10 15:19:58 +01:00
|
|
|
if (remove_resources) {
|
2016-04-20 09:16:41 +02:00
|
|
|
if (NM_DEVICE_GET_CLASS (self)->unrealize) {
|
|
|
|
|
if (!NM_DEVICE_GET_CLASS (self)->unrealize (self, error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
} else if (ifindex > 0) {
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_delete (nm_device_get_platform (self), ifindex);
|
2016-04-20 09:16:41 +02:00
|
|
|
}
|
2016-01-10 15:19:58 +01:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 14:30:57 +02:00
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
2016-01-10 15:19:58 +01:00
|
|
|
NM_DEVICE_GET_CLASS (self)->unrealize_notify (self);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
2016-12-26 11:12:39 +01:00
|
|
|
_parent_set_ifindex (self, 0, FALSE);
|
|
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
if (priv->ifindex > 0) {
|
|
|
|
|
priv->ifindex = 0;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IFINDEX);
|
2014-09-24 15:13:19 -05:00
|
|
|
}
|
|
|
|
|
priv->ip_ifindex = 0;
|
2016-12-26 18:11:03 +01:00
|
|
|
if (nm_clear_g_free (&priv->ip_iface))
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP_IFACE);
|
2016-12-26 18:11:03 +01:00
|
|
|
|
2017-10-13 13:11:11 +02:00
|
|
|
_set_mtu (self, 0);
|
2017-01-13 15:55:48 +01:00
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
if (priv->driver_version) {
|
|
|
|
|
g_clear_pointer (&priv->driver_version, g_free);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DRIVER_VERSION);
|
2014-09-24 15:13:19 -05:00
|
|
|
}
|
|
|
|
|
if (priv->firmware_version) {
|
|
|
|
|
g_clear_pointer (&priv->firmware_version, g_free);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_FIRMWARE_VERSION);
|
2014-09-24 15:13:19 -05:00
|
|
|
}
|
|
|
|
|
if (priv->udi) {
|
|
|
|
|
g_clear_pointer (&priv->udi, g_free);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_UDI);
|
2014-09-24 15:13:19 -05:00
|
|
|
}
|
|
|
|
|
if (priv->physical_port_id) {
|
|
|
|
|
g_clear_pointer (&priv->physical_port_id, g_free);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_PHYSICAL_PORT_ID);
|
2014-09-24 15:13:19 -05:00
|
|
|
}
|
2016-08-16 12:10:23 +02:00
|
|
|
|
|
|
|
|
nm_clear_g_source (&priv->stats.timeout_id);
|
|
|
|
|
_stats_update_counters (self, 0, 0);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
2016-10-26 12:20:12 +02:00
|
|
|
priv->hw_addr_len_ = 0;
|
|
|
|
|
if (nm_clear_g_free (&priv->hw_addr))
|
|
|
|
|
_notify (self, PROP_HW_ADDRESS);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
priv->hw_addr_type = HW_ADDR_TYPE_UNSET;
|
2016-10-26 12:20:12 +02:00
|
|
|
if (nm_clear_g_free (&priv->hw_addr_perm))
|
|
|
|
|
_notify (self, PROP_PERM_HW_ADDRESS);
|
2016-06-03 13:37:08 +02:00
|
|
|
g_clear_pointer (&priv->hw_addr_initial, g_free);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
|
|
|
|
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
|
2016-01-04 12:07:33 +01:00
|
|
|
if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
|
|
|
|
|
priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_CAPABILITIES);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
2017-04-14 17:46:20 +02:00
|
|
|
nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id);
|
2016-05-11 16:53:16 +02:00
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
priv->real = FALSE;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_REAL);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
|
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
nm_device_set_unmanaged_flags (self,
|
|
|
|
|
NM_UNMANAGED_PLATFORM_INIT,
|
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
|
|
nm_device_set_unmanaged_flags (self,
|
|
|
|
|
NM_UNMANAGED_PARENT |
|
|
|
|
|
NM_UNMANAGED_LOOPBACK |
|
|
|
|
|
NM_UNMANAGED_USER_UDEV |
|
2016-08-30 14:58:52 +02:00
|
|
|
NM_UNMANAGED_USER_EXPLICIT |
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
NM_UNMANAGED_EXTERNAL_DOWN |
|
|
|
|
|
NM_UNMANAGED_IS_SLAVE,
|
|
|
|
|
NM_UNMAN_FLAG_OP_FORGET);
|
|
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
NM_DEVICE_STATE_UNMANAGED,
|
|
|
|
|
remove_resources ?
|
|
|
|
|
NM_DEVICE_STATE_REASON_USER_REQUESTED : NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
|
|
|
|
|
|
2015-12-14 12:51:49 +01:00
|
|
|
/* Garbage-collect unneeded unrealized devices. */
|
|
|
|
|
nm_device_recheck_available_connections (self);
|
|
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-09 10:22:19 -06:00
|
|
|
/**
|
|
|
|
|
* nm_device_notify_component_added():
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice
|
2014-02-09 10:22:19 -06:00
|
|
|
* @component: the component being added by a plugin
|
|
|
|
|
*
|
|
|
|
|
* Called by the manager to notify the device that a new component has
|
|
|
|
|
* been found. The device implementation should return %TRUE if it
|
|
|
|
|
* wishes to claim the component, or %FALSE if it cannot.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE to claim the component, %FALSE if the component cannot be
|
|
|
|
|
* claimed.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_notify_component_added (NMDevice *self, GObject *component)
|
2014-02-09 10:22:19 -06:00
|
|
|
{
|
2015-11-24 16:43:18 +01:00
|
|
|
NMDeviceClass *klass;
|
2017-05-25 18:22:44 +02:00
|
|
|
NMDevicePrivate *priv;
|
2015-11-24 16:43:18 +01:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
2017-05-25 18:22:44 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-11-24 16:43:18 +01:00
|
|
|
klass = NM_DEVICE_GET_CLASS (self);
|
2017-05-25 18:22:44 +02:00
|
|
|
|
|
|
|
|
if (priv->state == NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
/* A device could have stayed disconnected because it would
|
|
|
|
|
* want to register with a network server that now become
|
|
|
|
|
* available. */
|
|
|
|
|
nm_device_recheck_available_connections (self);
|
|
|
|
|
if (g_hash_table_size (priv->available_connections) > 0)
|
|
|
|
|
nm_device_emit_recheck_auto_activate (self);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-24 16:43:18 +01:00
|
|
|
if (klass->component_added)
|
|
|
|
|
return klass->component_added (self, component);
|
2017-05-25 18:22:44 +02:00
|
|
|
|
2014-02-09 10:22:19 -06:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_device_owns_iface():
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice
|
2014-02-09 10:22:19 -06:00
|
|
|
* @iface: an interface name
|
|
|
|
|
*
|
|
|
|
|
* Called by the manager to ask if the device or any of its components owns
|
|
|
|
|
* @iface. For example, a WWAN implementation would return %TRUE for an
|
|
|
|
|
* ethernet interface name that was owned by the WWAN device's modem component,
|
|
|
|
|
* because that ethernet interface is controlled by the WWAN device and cannot
|
|
|
|
|
* be used independently of the WWAN device.
|
|
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Returns: %TRUE if @self or it's components owns the interface name,
|
2014-02-09 10:22:19 -06:00
|
|
|
* %FALSE if not
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_owns_iface (NMDevice *self, const char *iface)
|
2014-02-09 10:22:19 -06:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
if (NM_DEVICE_GET_CLASS (self)->owns_iface)
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->owns_iface (self, iface);
|
2014-02-09 10:22:19 -06:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-08 16:11:51 -05:00
|
|
|
NMConnection *
|
|
|
|
|
nm_device_new_default_connection (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->new_default_connection)
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->new_default_connection (self);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
static void
|
|
|
|
|
slave_state_changed (NMDevice *slave,
|
|
|
|
|
NMDeviceState slave_new_state,
|
|
|
|
|
NMDeviceState slave_old_state,
|
|
|
|
|
NMDeviceStateReason reason,
|
|
|
|
|
NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
gboolean release = FALSE;
|
2017-08-31 18:29:42 +02:00
|
|
|
gboolean configure;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "slave %s state change %d (%s) -> %d (%s)",
|
|
|
|
|
nm_device_get_iface (slave),
|
|
|
|
|
slave_old_state,
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (slave_old_state),
|
2014-02-12 23:54:26 +01:00
|
|
|
slave_new_state,
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (slave_new_state));
|
2012-11-14 14:05:30 -06:00
|
|
|
|
|
|
|
|
/* Don't try to enslave slaves until the master is ready */
|
|
|
|
|
if (priv->state < NM_DEVICE_STATE_CONFIG)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (slave_new_state == NM_DEVICE_STATE_IP_CONFIG)
|
2015-08-06 14:37:12 +02:00
|
|
|
nm_device_master_enslave_slave (self, slave, nm_device_get_applied_connection (slave));
|
2012-11-14 14:05:30 -06:00
|
|
|
else if (slave_new_state > NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
release = TRUE;
|
|
|
|
|
else if ( slave_new_state <= NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
&& slave_old_state > NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
/* Catch failures due to unavailable or unmanaged */
|
|
|
|
|
release = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (release) {
|
2017-08-31 18:29:42 +02:00
|
|
|
configure = priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED
|
|
|
|
|
&& nm_device_sys_iface_state_get (slave) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL;
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
nm_device_master_release_one_slave (self, slave,
|
2017-08-31 18:29:42 +02:00
|
|
|
configure,
|
2017-03-13 15:34:14 +01:00
|
|
|
reason);
|
2013-07-25 15:36:45 +02:00
|
|
|
/* Bridge/bond/team interfaces are left up until manually deactivated */
|
2017-05-13 21:57:51 +02:00
|
|
|
if ( c_list_is_empty (&priv->slaves)
|
|
|
|
|
&& priv->state == NM_DEVICE_STATE_ACTIVATED)
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "last slave removed; remaining activated");
|
2012-11-14 14:05:30 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_device_master_add_slave:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the master device
|
2012-11-14 14:05:30 -06:00
|
|
|
* @slave: the slave device to enslave
|
2013-11-07 01:08:02 -06:00
|
|
|
* @configure: pass %TRUE if the slave should be configured by the master, or
|
|
|
|
|
* %FALSE if it is already configured outside NetworkManager
|
2012-11-14 14:05:30 -06:00
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* If @self is capable of enslaving other devices (ie it's a bridge, bond, team,
|
2013-07-25 15:36:45 +02:00
|
|
|
* etc) then this function adds @slave to the slave list for later enslavement.
|
2017-03-01 17:28:46 +01:00
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the slave was enslaved. %FALSE means, the slave was already
|
|
|
|
|
* enslaved and nothing was done.
|
2012-11-14 14:05:30 -06:00
|
|
|
*/
|
2017-03-01 17:28:46 +01:00
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure)
|
2012-02-28 18:35:30 -06:00
|
|
|
{
|
2015-12-02 10:53:16 +01:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMDevicePrivate *slave_priv;
|
2012-11-14 14:05:30 -06:00
|
|
|
SlaveInfo *info;
|
2017-03-01 17:28:46 +01:00
|
|
|
gboolean changed = FALSE;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2017-03-01 17:28:46 +01:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL, FALSE);
|
2015-12-02 10:53:16 +01:00
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
slave_priv = NM_DEVICE_GET_PRIVATE (slave);
|
|
|
|
|
|
|
|
|
|
info = find_slave_info (self, slave);
|
|
|
|
|
|
2017-03-01 17:26:45 +01:00
|
|
|
_LOGT (LOGD_CORE, "master: add one slave %p/%s%s", slave, nm_device_get_iface (slave),
|
2015-12-02 10:53:16 +01:00
|
|
|
info ? " (already registered)" : "");
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2014-02-25 16:44:01 -05:00
|
|
|
if (configure)
|
2017-03-01 17:28:46 +01:00
|
|
|
g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
2015-12-02 10:53:16 +01:00
|
|
|
|
|
|
|
|
if (!info) {
|
2017-03-01 17:28:46 +01:00
|
|
|
g_return_val_if_fail (!slave_priv->master, FALSE);
|
|
|
|
|
g_return_val_if_fail (!slave_priv->is_enslaved, FALSE);
|
2014-02-25 16:44:01 -05:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
info = g_slice_new0 (SlaveInfo);
|
2012-11-14 14:05:30 -06:00
|
|
|
info->slave = g_object_ref (slave);
|
2013-11-07 01:08:02 -06:00
|
|
|
info->configure = configure;
|
2015-12-07 19:42:59 +01:00
|
|
|
info->watch_id = g_signal_connect (slave,
|
|
|
|
|
NM_DEVICE_STATE_CHANGED,
|
2014-07-15 13:36:24 +02:00
|
|
|
G_CALLBACK (slave_state_changed), self);
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_link_tail (&priv->slaves, &info->lst_slave);
|
2015-12-02 10:53:16 +01:00
|
|
|
slave_priv->master = g_object_ref (self);
|
2012-02-28 18:35:30 -06:00
|
|
|
|
2017-09-27 10:16:15 +02:00
|
|
|
_active_connection_set_state_flags (self,
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES);
|
|
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
/* no need to emit
|
|
|
|
|
*
|
2016-02-29 16:27:27 +05:30
|
|
|
* _notify (slave, PROP_MASTER);
|
2015-12-02 10:53:16 +01:00
|
|
|
*
|
|
|
|
|
* because slave_priv->is_enslaved is not true, thus the value
|
|
|
|
|
* didn't change yet. */
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
|
|
|
|
g_warn_if_fail (!NM_FLAGS_HAS (slave_priv->unmanaged_mask, NM_UNMANAGED_IS_SLAVE));
|
|
|
|
|
nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
2017-03-01 17:28:46 +01:00
|
|
|
changed = TRUE;
|
2015-12-02 10:53:16 +01:00
|
|
|
} else
|
2017-03-01 17:28:46 +01:00
|
|
|
g_return_val_if_fail (slave_priv->master == self, FALSE);
|
2015-12-02 10:53:16 +01:00
|
|
|
|
|
|
|
|
nm_device_queue_recheck_assume (self);
|
2015-12-17 15:31:02 +01:00
|
|
|
nm_device_queue_recheck_assume (slave);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2017-03-01 17:28:46 +01:00
|
|
|
return changed;
|
|
|
|
|
}
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2013-10-11 14:59:26 -04:00
|
|
|
/**
|
|
|
|
|
* nm_device_master_check_slave_physical_port:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the master device
|
2013-10-11 14:59:26 -04:00
|
|
|
* @slave: a slave device
|
|
|
|
|
* @log_domain: domain to log a warning in
|
|
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Checks if @self already has a slave with the same #NMDevice:physical-port-id
|
2013-10-11 14:59:26 -04:00
|
|
|
* as @slave, and logs a warning if so.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_master_check_slave_physical_port (NMDevice *self, NMDevice *slave,
|
2015-05-12 16:44:24 +02:00
|
|
|
NMLogDomain log_domain)
|
2013-10-11 14:59:26 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-10-11 14:59:26 -04:00
|
|
|
const char *slave_physical_port_id, *existing_physical_port_id;
|
|
|
|
|
SlaveInfo *info;
|
2017-05-13 21:57:51 +02:00
|
|
|
CList *iter;
|
2013-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
slave_physical_port_id = nm_device_get_physical_port_id (slave);
|
|
|
|
|
if (!slave_physical_port_id)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_for_each (iter, &priv->slaves) {
|
|
|
|
|
info = c_list_entry (iter, SlaveInfo, lst_slave);
|
2013-10-11 14:59:26 -04:00
|
|
|
if (info->slave == slave)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
existing_physical_port_id = nm_device_get_physical_port_id (info->slave);
|
|
|
|
|
if (!g_strcmp0 (slave_physical_port_id, existing_physical_port_id)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (log_domain, "slave %s shares a physical port with existing slave %s",
|
|
|
|
|
nm_device_get_ip_iface (slave),
|
|
|
|
|
nm_device_get_ip_iface (info->slave));
|
2013-10-11 14:59:26 -04:00
|
|
|
/* Since this function will get called for every slave, we only have
|
|
|
|
|
* to warn about the first match we find; if there are other matches
|
|
|
|
|
* later in the list, we will have already warned about them matching
|
|
|
|
|
* @existing earlier.
|
|
|
|
|
*/
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
/* release all slaves */
|
|
|
|
|
static void
|
2013-12-05 09:13:26 -05:00
|
|
|
nm_device_master_release_slaves (NMDevice *self)
|
2012-11-14 14:05:30 -06:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
device: fix warning releasing of slave when slave device gets removed
When the slave device gets removed, the master is not in a state-change when
calling nm_device_release_one_slave(). This triggers a warning [1].
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c144c "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fff8b1d35b0) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x3370cc1fdc "%s") at gmessages.c:1025
#2 0x0000003370c50956 in g_warn_message (domain=domain@entry=0x4c144c "NetworkManager", file=file@entry=0x4b14d5 "devices/nm-device.c", line=line@entry=841, func=func@entry=0x4b48f0 <__FUNCTION__.35456> "nm_device_release_one_slave",
warnexpr=warnexpr@entry=0x0) at gmessages.c:1058
#3 0x0000000000436c30 in nm_device_release_one_slave (dev=dev@entry=0xd92540, slave=slave@entry=0xdb0e50, configure=configure@entry=1) at devices/nm-device.c:841
#4 0x000000000043a779 in slave_state_changed (slave=0xdb0e50, slave_new_state=NM_DEVICE_STATE_UNMANAGED, slave_old_state=NM_DEVICE_STATE_ACTIVATED, reason=<optimized out>, self=0xd92540) at devices/nm-device.c:1214
#5 0x0000003371805d8c in ffi_call_unix64 () at ../src/x86/unix64.S:76
#6 0x00000033718056bc in ffi_call (cif=cif@entry=0x7fff8b1d3a00, fn=0x43a677 <slave_state_changed>, rvalue=0x7fff8b1d3970, avalue=avalue@entry=0x7fff8b1d38f0) at ../src/x86/ffi64.c:522
#7 0x0000003371c10ad8 in g_cclosure_marshal_generic (closure=0xd76120, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1454
#8 0x0000003371c10298 in g_closure_invoke (closure=0xd76120, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fff8b1d3c00, invocation_hint=invocation_hint@entry=0x7fff8b1d3ba0) at gclosure.c:777
#9 0x0000003371c2235d in signal_emit_unlocked_R (node=node@entry=0xd9d850, detail=detail@entry=0, instance=instance@entry=0xdb0e50, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff8b1d3c00) at gsignal.c:3586
#10 0x0000003371c2a0f2 in g_signal_emit_valist (instance=instance@entry=0xdb0e50, signal_id=signal_id@entry=68, detail=detail@entry=0, var_args=var_args@entry=0x7fff8b1d3e38) at gsignal.c:3330
#11 0x0000003371c2a8f8 in g_signal_emit_by_name (instance=instance@entry=0xdb0e50, detailed_signal=detailed_signal@entry=0x4c3ce2 "state-changed") at gsignal.c:3426
#12 0x000000000043754f in _set_state_full (device=device@entry=0xdb0e50, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6689
#13 0x000000000043797c in nm_device_state_changed (device=device@entry=0xdb0e50, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#14 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0xdb0e50, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#15 0x00000000004799c2 in remove_device (manager=manager@entry=0xd86150, device=0xdb0e50, quitting=quitting@entry=0) at nm-manager.c:769
#16 0x000000000047e3bf in platform_link_cb (platform=<optimized out>, ifindex=35, plink=<optimized out>, change_type=<optimized out>, reason=<optimized out>, user_data=<optimized out>) at nm-manager.c:2123
#17 0x0000003371805d8c in ffi_call_unix64 () at ../src/x86/unix64.S:76
#18 0x00000033718056bc in ffi_call (cif=cif@entry=0x7fff8b1d4320, fn=0x47e34b <platform_link_cb>, rvalue=0x7fff8b1d4290, avalue=avalue@entry=0x7fff8b1d4210) at ../src/x86/ffi64.c:522
#19 0x0000003371c10ad8 in g_cclosure_marshal_generic (closure=0xd32e40, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1454
#20 0x0000003371c10298 in g_closure_invoke (closure=0xd32e40, return_value=return_value@entry=0x0, n_param_values=5, param_values=param_values@entry=0x7fff8b1d4520, invocation_hint=invocation_hint@entry=0x7fff8b1d44c0) at gclosure.c:777
#21 0x0000003371c2235d in signal_emit_unlocked_R (node=node@entry=0xcf5780, detail=detail@entry=0, instance=instance@entry=0xcf78a0, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff8b1d4520) at gsignal.c:3586
#22 0x0000003371c2a0f2 in g_signal_emit_valist (instance=instance@entry=0xcf78a0, signal_id=signal_id@entry=2, detail=detail@entry=0, var_args=var_args@entry=0x7fff8b1d4778) at gsignal.c:3330
#23 0x0000003371c2a8f8 in g_signal_emit_by_name (instance=instance@entry=0xcf78a0, detailed_signal=detailed_signal@entry=0x4b183d "link-changed") at gsignal.c:3426
#24 0x000000000044c6f3 in announce_object (platform=platform@entry=0xcf78a0, object=0xde1720, change_type=change_type@entry=NM_PLATFORM_SIGNAL_REMOVED, reason=reason@entry=NM_PLATFORM_REASON_EXTERNAL)
at platform/nm-linux-platform.c:1572
#25 0x000000000044ec07 in event_notification (msg=<optimized out>, user_data=<optimized out>) at platform/nm-linux-platform.c:1886
#26 0x0000003844c1117f in nl_cb_call (msg=<optimized out>, type=<optimized out>, cb=<optimized out>) at ../include/netlink-private/netlink.h:141
#27 recvmsgs (cb=0xcf7240, sk=0xcf7330) at nl.c:952
#28 nl_recvmsgs_report (sk=0xcf7330, cb=0xcf7240) at nl.c:1003
#29 0x0000003844c11549 in nl_recvmsgs (sk=<optimized out>, cb=<optimized out>) at nl.c:1027
#30 0x0000003844c11569 in nl_recvmsgs_default (sk=<optimized out>) at nl.c:1041
#31 0x000000000044e955 in event_handler (channel=<optimized out>, io_condition=<optimized out>, user_data=0xcf78a0) at platform/nm-linux-platform.c:3804
#32 0x0000003370c492a6 in g_main_dispatch (context=0xcf5190) at gmain.c:3066
#33 g_main_context_dispatch (context=context@entry=0xcf5190) at gmain.c:3642
#34 0x0000003370c49628 in g_main_context_iterate (context=0xcf5190, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3713
#35 0x0000003370c49a3a in g_main_loop_run (loop=0xcf4e30) at gmain.c:3907
#36 0x0000000000429f15 in main (argc=1, argv=0x7fff8b1d4f38) at main.c:678
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 11:18:45 +02:00
|
|
|
NMDeviceStateReason reason;
|
device: don't tell the device to unconfigure if it's gone already
After the device is unrealized a lot of its properites are reset. Notably, it
doesn't have an ifindex anymore so there's nothing to unconfigure really. This
makes at least NMDeviceBond unhappy:
(bond device with a slave is removed externally)
NetworkManager[21022]: <info> (bond0): device state change: activated -> unmanaged (reason 'unmanaged') [100 10 3]
NetworkManager[21022]: nm_platform_link_release: assertion 'master > 0' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff4ec88c3 in g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
#1 0x00007ffff4ec8a3f in g_log (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff4f3673d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff4ec8a79 in g_return_if_fail_warning (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", pretty_function=pretty_function@entry=0x55555575ea50 <__FUNCTION__.33801> "nm_platform_link_relea8
#3 0x000055555560559a in nm_platform_link_release (self=0x555555a27bb0 [NMLinuxPlatform], master=master@entry=0, slave=slave@entry=3) at platform/nm-platform.c:1326
#4 0x00005555555b506e in release_slave (device=<optimized out>, slave=0x555555b6d770 [NMDeviceEthernet], configure=<optimized out>) at devices/nm-device-bond.c:423
#5 0x00005555555dab7b in nm_device_master_release_one_slave (self=self@entry=0x555555bf0cc0 [NMDeviceBond], slave=0x555555b6d770 [NMDeviceEthernet], configure=configure@entry=1, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED) at devices/nm-device.c:1137
#6 0x00005555555dadb6 in nm_device_master_release_slaves (self=self@entry=0x555555bf0cc0 [NMDeviceBond]) at devices/nm-device.c:2344
#7 0x00005555555dd12f in nm_device_cleanup (self=self@entry=0x555555bf0cc0 [NMDeviceBond], reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED, cleanup_type=cleanup_type@entry=CLEANUP_TYPE_DECONFIGURE)
at devices/nm-device.c:9133
#8 0x00005555555de3ea in _set_state_full (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED, quitting=quitting@entry=0) at devices/nm-device.c:9510
#9 0x00005555555dedb7 in nm_device_state_changed (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED)
at devices/nm-device.c:9769
#10 0x00005555555e11b4 in nm_device_unrealize (self=self@entry=0x555555bf0cc0 [NMDeviceBond], remove_resources=remove_resources@entry=0, error=error@entry=0x7fffffffd788) at devices/nm-device.c:2062
#11 0x000055555565c9c5 in _platform_link_cb_idle (data=0x555555c6e2b0) at nm-manager.c:2055
#12 0x00007ffff4ec179a in g_main_context_dispatch (context=0x555555a226c0) at gmain.c:3109
#13 0x00007ffff4ec179a in g_main_context_dispatch (context=context@entry=0x555555a226c0) at gmain.c:3708
#14 0x00007ffff4ec1ae8 in g_main_context_iterate (context=0x555555a226c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3779
#15 0x00007ffff4ec1dba in g_main_loop_run (loop=0x555555a22780) at gmain.c:3973
#16 0x00005555555b3e5f in main (argc=1, argv=0x7fffffffdb18) at main.c:488
2015-12-11 17:23:51 +01:00
|
|
|
gboolean configure = TRUE;
|
2017-05-13 21:57:51 +02:00
|
|
|
CList *iter, *safe;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2014-02-25 16:44:01 -05:00
|
|
|
/* Don't release the slaves if this connection doesn't belong to NM. */
|
2017-03-13 15:34:14 +01:00
|
|
|
if (nm_device_sys_iface_state_is_external (self))
|
2014-02-25 16:44:01 -05:00
|
|
|
return;
|
|
|
|
|
|
device: fix warning releasing of slave when slave device gets removed
When the slave device gets removed, the master is not in a state-change when
calling nm_device_release_one_slave(). This triggers a warning [1].
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c144c "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fff8b1d35b0) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x3370cc1fdc "%s") at gmessages.c:1025
#2 0x0000003370c50956 in g_warn_message (domain=domain@entry=0x4c144c "NetworkManager", file=file@entry=0x4b14d5 "devices/nm-device.c", line=line@entry=841, func=func@entry=0x4b48f0 <__FUNCTION__.35456> "nm_device_release_one_slave",
warnexpr=warnexpr@entry=0x0) at gmessages.c:1058
#3 0x0000000000436c30 in nm_device_release_one_slave (dev=dev@entry=0xd92540, slave=slave@entry=0xdb0e50, configure=configure@entry=1) at devices/nm-device.c:841
#4 0x000000000043a779 in slave_state_changed (slave=0xdb0e50, slave_new_state=NM_DEVICE_STATE_UNMANAGED, slave_old_state=NM_DEVICE_STATE_ACTIVATED, reason=<optimized out>, self=0xd92540) at devices/nm-device.c:1214
#5 0x0000003371805d8c in ffi_call_unix64 () at ../src/x86/unix64.S:76
#6 0x00000033718056bc in ffi_call (cif=cif@entry=0x7fff8b1d3a00, fn=0x43a677 <slave_state_changed>, rvalue=0x7fff8b1d3970, avalue=avalue@entry=0x7fff8b1d38f0) at ../src/x86/ffi64.c:522
#7 0x0000003371c10ad8 in g_cclosure_marshal_generic (closure=0xd76120, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1454
#8 0x0000003371c10298 in g_closure_invoke (closure=0xd76120, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fff8b1d3c00, invocation_hint=invocation_hint@entry=0x7fff8b1d3ba0) at gclosure.c:777
#9 0x0000003371c2235d in signal_emit_unlocked_R (node=node@entry=0xd9d850, detail=detail@entry=0, instance=instance@entry=0xdb0e50, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff8b1d3c00) at gsignal.c:3586
#10 0x0000003371c2a0f2 in g_signal_emit_valist (instance=instance@entry=0xdb0e50, signal_id=signal_id@entry=68, detail=detail@entry=0, var_args=var_args@entry=0x7fff8b1d3e38) at gsignal.c:3330
#11 0x0000003371c2a8f8 in g_signal_emit_by_name (instance=instance@entry=0xdb0e50, detailed_signal=detailed_signal@entry=0x4c3ce2 "state-changed") at gsignal.c:3426
#12 0x000000000043754f in _set_state_full (device=device@entry=0xdb0e50, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6689
#13 0x000000000043797c in nm_device_state_changed (device=device@entry=0xdb0e50, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#14 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0xdb0e50, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#15 0x00000000004799c2 in remove_device (manager=manager@entry=0xd86150, device=0xdb0e50, quitting=quitting@entry=0) at nm-manager.c:769
#16 0x000000000047e3bf in platform_link_cb (platform=<optimized out>, ifindex=35, plink=<optimized out>, change_type=<optimized out>, reason=<optimized out>, user_data=<optimized out>) at nm-manager.c:2123
#17 0x0000003371805d8c in ffi_call_unix64 () at ../src/x86/unix64.S:76
#18 0x00000033718056bc in ffi_call (cif=cif@entry=0x7fff8b1d4320, fn=0x47e34b <platform_link_cb>, rvalue=0x7fff8b1d4290, avalue=avalue@entry=0x7fff8b1d4210) at ../src/x86/ffi64.c:522
#19 0x0000003371c10ad8 in g_cclosure_marshal_generic (closure=0xd32e40, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1454
#20 0x0000003371c10298 in g_closure_invoke (closure=0xd32e40, return_value=return_value@entry=0x0, n_param_values=5, param_values=param_values@entry=0x7fff8b1d4520, invocation_hint=invocation_hint@entry=0x7fff8b1d44c0) at gclosure.c:777
#21 0x0000003371c2235d in signal_emit_unlocked_R (node=node@entry=0xcf5780, detail=detail@entry=0, instance=instance@entry=0xcf78a0, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff8b1d4520) at gsignal.c:3586
#22 0x0000003371c2a0f2 in g_signal_emit_valist (instance=instance@entry=0xcf78a0, signal_id=signal_id@entry=2, detail=detail@entry=0, var_args=var_args@entry=0x7fff8b1d4778) at gsignal.c:3330
#23 0x0000003371c2a8f8 in g_signal_emit_by_name (instance=instance@entry=0xcf78a0, detailed_signal=detailed_signal@entry=0x4b183d "link-changed") at gsignal.c:3426
#24 0x000000000044c6f3 in announce_object (platform=platform@entry=0xcf78a0, object=0xde1720, change_type=change_type@entry=NM_PLATFORM_SIGNAL_REMOVED, reason=reason@entry=NM_PLATFORM_REASON_EXTERNAL)
at platform/nm-linux-platform.c:1572
#25 0x000000000044ec07 in event_notification (msg=<optimized out>, user_data=<optimized out>) at platform/nm-linux-platform.c:1886
#26 0x0000003844c1117f in nl_cb_call (msg=<optimized out>, type=<optimized out>, cb=<optimized out>) at ../include/netlink-private/netlink.h:141
#27 recvmsgs (cb=0xcf7240, sk=0xcf7330) at nl.c:952
#28 nl_recvmsgs_report (sk=0xcf7330, cb=0xcf7240) at nl.c:1003
#29 0x0000003844c11549 in nl_recvmsgs (sk=<optimized out>, cb=<optimized out>) at nl.c:1027
#30 0x0000003844c11569 in nl_recvmsgs_default (sk=<optimized out>) at nl.c:1041
#31 0x000000000044e955 in event_handler (channel=<optimized out>, io_condition=<optimized out>, user_data=0xcf78a0) at platform/nm-linux-platform.c:3804
#32 0x0000003370c492a6 in g_main_dispatch (context=0xcf5190) at gmain.c:3066
#33 g_main_context_dispatch (context=context@entry=0xcf5190) at gmain.c:3642
#34 0x0000003370c49628 in g_main_context_iterate (context=0xcf5190, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3713
#35 0x0000003370c49a3a in g_main_loop_run (loop=0xcf4e30) at gmain.c:3907
#36 0x0000000000429f15 in main (argc=1, argv=0x7fff8b1d4f38) at main.c:678
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 11:18:45 +02:00
|
|
|
reason = priv->state_reason;
|
|
|
|
|
if (priv->state == NM_DEVICE_STATE_FAILED)
|
|
|
|
|
reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_get (nm_device_get_platform (self), priv->ifindex))
|
device: don't tell the device to unconfigure if it's gone already
After the device is unrealized a lot of its properites are reset. Notably, it
doesn't have an ifindex anymore so there's nothing to unconfigure really. This
makes at least NMDeviceBond unhappy:
(bond device with a slave is removed externally)
NetworkManager[21022]: <info> (bond0): device state change: activated -> unmanaged (reason 'unmanaged') [100 10 3]
NetworkManager[21022]: nm_platform_link_release: assertion 'master > 0' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff4ec88c3 in g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
#1 0x00007ffff4ec8a3f in g_log (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff4f3673d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff4ec8a79 in g_return_if_fail_warning (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", pretty_function=pretty_function@entry=0x55555575ea50 <__FUNCTION__.33801> "nm_platform_link_relea8
#3 0x000055555560559a in nm_platform_link_release (self=0x555555a27bb0 [NMLinuxPlatform], master=master@entry=0, slave=slave@entry=3) at platform/nm-platform.c:1326
#4 0x00005555555b506e in release_slave (device=<optimized out>, slave=0x555555b6d770 [NMDeviceEthernet], configure=<optimized out>) at devices/nm-device-bond.c:423
#5 0x00005555555dab7b in nm_device_master_release_one_slave (self=self@entry=0x555555bf0cc0 [NMDeviceBond], slave=0x555555b6d770 [NMDeviceEthernet], configure=configure@entry=1, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED) at devices/nm-device.c:1137
#6 0x00005555555dadb6 in nm_device_master_release_slaves (self=self@entry=0x555555bf0cc0 [NMDeviceBond]) at devices/nm-device.c:2344
#7 0x00005555555dd12f in nm_device_cleanup (self=self@entry=0x555555bf0cc0 [NMDeviceBond], reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED, cleanup_type=cleanup_type@entry=CLEANUP_TYPE_DECONFIGURE)
at devices/nm-device.c:9133
#8 0x00005555555de3ea in _set_state_full (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED, quitting=quitting@entry=0) at devices/nm-device.c:9510
#9 0x00005555555dedb7 in nm_device_state_changed (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED)
at devices/nm-device.c:9769
#10 0x00005555555e11b4 in nm_device_unrealize (self=self@entry=0x555555bf0cc0 [NMDeviceBond], remove_resources=remove_resources@entry=0, error=error@entry=0x7fffffffd788) at devices/nm-device.c:2062
#11 0x000055555565c9c5 in _platform_link_cb_idle (data=0x555555c6e2b0) at nm-manager.c:2055
#12 0x00007ffff4ec179a in g_main_context_dispatch (context=0x555555a226c0) at gmain.c:3109
#13 0x00007ffff4ec179a in g_main_context_dispatch (context=context@entry=0x555555a226c0) at gmain.c:3708
#14 0x00007ffff4ec1ae8 in g_main_context_iterate (context=0x555555a226c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3779
#15 0x00007ffff4ec1dba in g_main_loop_run (loop=0x555555a22780) at gmain.c:3973
#16 0x00005555555b3e5f in main (argc=1, argv=0x7fffffffdb18) at main.c:488
2015-12-11 17:23:51 +01:00
|
|
|
configure = FALSE;
|
|
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_for_each_safe (iter, safe, &priv->slaves) {
|
|
|
|
|
SlaveInfo *info = c_list_entry (iter, SlaveInfo, lst_slave);
|
2013-05-15 14:39:16 -05:00
|
|
|
|
device: don't tell the device to unconfigure if it's gone already
After the device is unrealized a lot of its properites are reset. Notably, it
doesn't have an ifindex anymore so there's nothing to unconfigure really. This
makes at least NMDeviceBond unhappy:
(bond device with a slave is removed externally)
NetworkManager[21022]: <info> (bond0): device state change: activated -> unmanaged (reason 'unmanaged') [100 10 3]
NetworkManager[21022]: nm_platform_link_release: assertion 'master > 0' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff4ec88c3 in g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
#1 0x00007ffff4ec8a3f in g_log (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff4f3673d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff4ec8a79 in g_return_if_fail_warning (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", pretty_function=pretty_function@entry=0x55555575ea50 <__FUNCTION__.33801> "nm_platform_link_relea8
#3 0x000055555560559a in nm_platform_link_release (self=0x555555a27bb0 [NMLinuxPlatform], master=master@entry=0, slave=slave@entry=3) at platform/nm-platform.c:1326
#4 0x00005555555b506e in release_slave (device=<optimized out>, slave=0x555555b6d770 [NMDeviceEthernet], configure=<optimized out>) at devices/nm-device-bond.c:423
#5 0x00005555555dab7b in nm_device_master_release_one_slave (self=self@entry=0x555555bf0cc0 [NMDeviceBond], slave=0x555555b6d770 [NMDeviceEthernet], configure=configure@entry=1, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED) at devices/nm-device.c:1137
#6 0x00005555555dadb6 in nm_device_master_release_slaves (self=self@entry=0x555555bf0cc0 [NMDeviceBond]) at devices/nm-device.c:2344
#7 0x00005555555dd12f in nm_device_cleanup (self=self@entry=0x555555bf0cc0 [NMDeviceBond], reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED, cleanup_type=cleanup_type@entry=CLEANUP_TYPE_DECONFIGURE)
at devices/nm-device.c:9133
#8 0x00005555555de3ea in _set_state_full (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED, quitting=quitting@entry=0) at devices/nm-device.c:9510
#9 0x00005555555dedb7 in nm_device_state_changed (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED)
at devices/nm-device.c:9769
#10 0x00005555555e11b4 in nm_device_unrealize (self=self@entry=0x555555bf0cc0 [NMDeviceBond], remove_resources=remove_resources@entry=0, error=error@entry=0x7fffffffd788) at devices/nm-device.c:2062
#11 0x000055555565c9c5 in _platform_link_cb_idle (data=0x555555c6e2b0) at nm-manager.c:2055
#12 0x00007ffff4ec179a in g_main_context_dispatch (context=0x555555a226c0) at gmain.c:3109
#13 0x00007ffff4ec179a in g_main_context_dispatch (context=context@entry=0x555555a226c0) at gmain.c:3708
#14 0x00007ffff4ec1ae8 in g_main_context_iterate (context=0x555555a226c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3779
#15 0x00007ffff4ec1dba in g_main_loop_run (loop=0x555555a22780) at gmain.c:3973
#16 0x00005555555b3e5f in main (argc=1, argv=0x7fffffffdb18) at main.c:488
2015-12-11 17:23:51 +01:00
|
|
|
nm_device_master_release_one_slave (self, info->slave, configure, reason);
|
2013-05-15 14:39:16 -05:00
|
|
|
}
|
2012-11-14 14:05:30 -06:00
|
|
|
}
|
|
|
|
|
|
2014-10-15 21:17:45 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_is_master:
|
|
|
|
|
* @self: the device
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the device can have slaves
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_is_master (NMDevice *self)
|
|
|
|
|
{
|
2017-06-01 23:08:30 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->is_master;
|
2014-10-15 21:17:45 -05:00
|
|
|
}
|
|
|
|
|
|
2014-01-02 14:46:02 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_get_master:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the device
|
2014-01-02 14:46:02 -05:00
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* If @self has been enslaved by another device, this returns that
|
2014-01-02 14:46:02 -05:00
|
|
|
* device. Otherwise it returns %NULL. (In particular, note that if
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self is in the process of activating as a slave, but has not yet
|
2014-01-02 14:46:02 -05:00
|
|
|
* been enslaved by its master, this will return %NULL.)
|
|
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Returns: (transfer none): @self's master, or %NULL
|
2014-01-02 14:46:02 -05:00
|
|
|
*/
|
|
|
|
|
NMDevice *
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_get_master (NMDevice *self)
|
2014-01-02 14:46:02 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-01-02 14:46:02 -05:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
if (priv->is_enslaved) {
|
|
|
|
|
g_return_val_if_fail (priv->master, NULL);
|
2014-01-02 14:46:02 -05:00
|
|
|
return priv->master;
|
2015-12-02 10:53:16 +01:00
|
|
|
}
|
|
|
|
|
return NULL;
|
2014-01-02 14:46:02 -05:00
|
|
|
}
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2017-10-23 10:26:27 +02:00
|
|
|
static gboolean
|
|
|
|
|
get_ip_config_may_fail (NMDevice *self, int addr_family)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingIPConfig *s_ip = NULL;
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
|
|
|
|
|
/* Fail the connection if the failed IP method is required to complete */
|
|
|
|
|
switch (addr_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
s_ip = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
break;
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
s_ip = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
nm_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return !s_ip || nm_setting_ip_config_get_may_fail (s_ip);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* check_ip_state
|
|
|
|
|
*
|
|
|
|
|
* Transition the device from IP_CONFIG to the next state according to the
|
|
|
|
|
* outcome of IPv4 and IPv6 configuration. @may_fail indicates that we are
|
|
|
|
|
* called just after the initial configuration and thus IPv4/IPv6 are allowed to
|
|
|
|
|
* fail if the ipvx.may-fail properties say so, because the IP methods couldn't
|
|
|
|
|
* even be started.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
check_ip_state (NMDevice *self, gboolean may_fail)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
gboolean ip4_disabled = FALSE, ip6_ignore = FALSE;
|
|
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
|
|
|
|
NMDeviceState state;
|
|
|
|
|
|
|
|
|
|
if (nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-10-23 11:59:23 +02:00
|
|
|
/* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the
|
|
|
|
|
* master to enslave us. */
|
|
|
|
|
if ( nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request))
|
|
|
|
|
&& !priv->is_enslaved)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-10-23 10:26:27 +02:00
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
if (s_ip4 && nm_streq0 (nm_setting_ip_config_get_method (s_ip4),
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_DISABLED))
|
|
|
|
|
ip4_disabled = TRUE;
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
if (s_ip6 && nm_streq0 (nm_setting_ip_config_get_method (s_ip6),
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_IGNORE))
|
|
|
|
|
ip6_ignore = TRUE;
|
|
|
|
|
|
|
|
|
|
if ( priv->ip4_state == IP_DONE
|
|
|
|
|
&& priv->ip6_state == IP_DONE) {
|
|
|
|
|
/* Both method completed (or disabled), proceed with activation */
|
|
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (priv->ip4_state == IP_FAIL || (ip4_disabled && priv->ip4_state == IP_DONE))
|
|
|
|
|
&& (priv->ip6_state == IP_FAIL || (ip6_ignore && priv->ip6_state == IP_DONE))) {
|
|
|
|
|
/* Either both methods failed, or only one failed and the other is
|
|
|
|
|
* disabled */
|
|
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self)) {
|
|
|
|
|
/* We have assumed configuration, but couldn't redo it. No problem,
|
|
|
|
|
* move to check state. */
|
|
|
|
|
_set_ip_state (self, AF_INET, IP_DONE);
|
|
|
|
|
_set_ip_state (self, AF_INET6, IP_DONE);
|
|
|
|
|
state = NM_DEVICE_STATE_IP_CHECK;
|
|
|
|
|
} else if ( may_fail
|
|
|
|
|
&& get_ip_config_may_fail (self, AF_INET)
|
|
|
|
|
&& get_ip_config_may_fail (self, AF_INET6)) {
|
|
|
|
|
/* Couldn't start either IPv6 and IPv4 autoconfiguration,
|
|
|
|
|
* but both are allowed to fail. */
|
|
|
|
|
state = NM_DEVICE_STATE_SECONDARIES;
|
|
|
|
|
} else {
|
|
|
|
|
/* Autoconfiguration attempted without success. */
|
|
|
|
|
state = NM_DEVICE_STATE_FAILED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
state,
|
|
|
|
|
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If a method is still pending but required, wait */
|
|
|
|
|
if (priv->ip4_state != IP_DONE && !get_ip_config_may_fail (self, AF_INET))
|
|
|
|
|
return;
|
|
|
|
|
if (priv->ip6_state != IP_DONE && !get_ip_config_may_fail (self, AF_INET6))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* If at least a method has completed, proceed with activation */
|
|
|
|
|
if ( (priv->ip4_state == IP_DONE && !ip4_disabled)
|
|
|
|
|
|| (priv->ip6_state == IP_DONE && !ip6_ignore)) {
|
|
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
/**
|
2013-10-21 12:50:58 -04:00
|
|
|
* nm_device_slave_notify_enslave:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the slave device
|
2013-10-21 12:50:58 -04:00
|
|
|
* @success: whether the enslaving operation succeeded
|
2012-11-14 14:05:30 -06:00
|
|
|
*
|
2013-10-21 12:50:58 -04:00
|
|
|
* Notifies a slave that either it has been enslaved, or else its master tried
|
|
|
|
|
* to enslave it and failed.
|
2012-11-14 14:05:30 -06:00
|
|
|
*/
|
2013-11-18 12:06:10 -06:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_slave_notify_enslave (NMDevice *self, gboolean success)
|
2012-11-14 14:05:30 -06:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-07-14 16:53:24 +02:00
|
|
|
NMConnection *connection = nm_device_get_applied_connection (self);
|
2014-02-25 16:44:01 -05:00
|
|
|
gboolean activating = (priv->state == NM_DEVICE_STATE_IP_CONFIG);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_fail (priv->master);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2015-08-06 14:17:29 +02:00
|
|
|
if (!priv->is_enslaved) {
|
2014-02-25 16:44:01 -05:00
|
|
|
if (success) {
|
|
|
|
|
if (activating) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DEVICE, "Activation: connection '%s' enslaved, continuing activation",
|
|
|
|
|
nm_connection_get_id (connection));
|
|
|
|
|
} else
|
|
|
|
|
_LOGI (LOGD_DEVICE, "enslaved to %s", nm_device_get_iface (priv->master));
|
2014-02-25 16:44:01 -05:00
|
|
|
|
2015-08-06 14:17:29 +02:00
|
|
|
priv->is_enslaved = TRUE;
|
2017-03-13 15:34:14 +01:00
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_MASTER);
|
|
|
|
|
_notify (priv->master, PROP_SLAVES);
|
2014-02-25 16:44:01 -05:00
|
|
|
} else if (activating) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DEVICE, "Activation: connection '%s' could not be enslaved",
|
|
|
|
|
nm_connection_get_id (connection));
|
2014-02-25 16:44:01 -05:00
|
|
|
}
|
2013-10-21 12:50:58 -04:00
|
|
|
}
|
|
|
|
|
|
2014-02-25 16:44:01 -05:00
|
|
|
if (activating) {
|
device: set a reason when device enslave fails
Otherwise we'd hit an assert and rightly so!
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x5555556b2f80 "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fffffffcd10) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 g_logv (log_domain=0x5555556b2f80 "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fffffffcd10) at gmessages.c:1046
#1 0x00007ffff4a4ea3f in g_log (log_domain=log_domain@entry=0x5555556b2f80 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x7ffff4ac1e4c "%s") at gmessages.c:1079
#2 0x00007ffff4a4ed56 in g_warn_message (domain=domain@entry=0x5555556b2f80 "NetworkManager", file=file@entry=0x5555556aca93 "devices/nm-device.c", line=line@entry=1101,
func=func@entry=0x5555556b22e0 <__FUNCTION__.35443> "nm_device_release_one_slave", warnexpr=warnexpr@entry=0x0) at gmessages.c:1112
#3 0x00005555555ba80a in nm_device_release_one_slave (self=self@entry=0x5555559ec4c0, slave=slave@entry=0x5555559f7800, configure=configure@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE)
at devices/nm-device.c:1101
#4 0x00005555555c264b in slave_state_changed (slave=0x5555559f7800, slave_new_state=NM_DEVICE_STATE_FAILED, slave_old_state=NM_DEVICE_STATE_IP_CONFIG, reason=NM_DEVICE_STATE_REASON_NONE, self=0x5555559ec4c0)
at devices/nm-device.c:1700
#5 0x00007ffff339cdac in ffi_call_unix64 () at ../src/x86/unix64.S:76
#6 0x00007ffff339c6d5 in ffi_call (cif=cif@entry=0x7fffffffd1c0, fn=<optimized out>, rvalue=0x7fffffffd130, avalue=avalue@entry=0x7fffffffd0b0) at ../src/x86/ffi64.c:522
#7 0x00007ffff4d45678 in g_cclosure_marshal_generic (closure=0x5555559b0160, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0)
at gclosure.c:1454
#8 0x00007ffff4d44e38 in g_closure_invoke (closure=0x5555559b0160, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fffffffd3c0,
invocation_hint=invocation_hint@entry=0x7fffffffd360) at gclosure.c:768
#9 0x00007ffff4d5675d in signal_emit_unlocked_R (node=node@entry=0x55555598a6f0, detail=detail@entry=0, instance=instance@entry=0x5555559f7800, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fffffffd3c0) at gsignal.c:3553
#10 0x00007ffff4d5e4c1 in g_signal_emit_valist (instance=instance@entry=0x5555559f7800, signal_id=signal_id@entry=72, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffd5f8) at gsignal.c:3309
#11 0x00007ffff4d5ecc8 in g_signal_emit_by_name (instance=instance@entry=0x5555559f7800, detailed_signal=detailed_signal@entry=0x5555556c0405 "state-changed") at gsignal.c:3405
#12 0x00005555555bd0e0 in _set_state_full (self=self@entry=0x5555559f7800, state=state@entry=NM_DEVICE_STATE_FAILED, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE, quitting=quitting@entry=0)
at devices/nm-device.c:8580
#13 0x00005555555be0e7 in nm_device_state_changed (self=self@entry=0x5555559f7800, state=state@entry=NM_DEVICE_STATE_FAILED, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:8741
#14 0x00005555555c0a45 in queued_set_state (user_data=<optimized out>) at devices/nm-device.c:8765
#15 0x00007ffff4a4779a in g_main_dispatch (context=0x5555559433c0) at gmain.c:3109
#16 g_main_context_dispatch (context=context@entry=0x5555559433c0) at gmain.c:3708
#17 0x00007ffff4a47ae8 in g_main_context_iterate (context=0x5555559433c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3779
#18 0x00007ffff4a47dba in g_main_loop_run (loop=0x555555943480) at gmain.c:3973
#19 0x000055555559713d in main (argc=1, argv=0x7fffffffdb78) at main.c:512
(gdb)
2015-11-06 14:30:32 +01:00
|
|
|
if (success)
|
2017-10-23 11:59:23 +02:00
|
|
|
check_ip_state (self, FALSE);
|
device: set a reason when device enslave fails
Otherwise we'd hit an assert and rightly so!
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x5555556b2f80 "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fffffffcd10) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 g_logv (log_domain=0x5555556b2f80 "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7fffffffcd10) at gmessages.c:1046
#1 0x00007ffff4a4ea3f in g_log (log_domain=log_domain@entry=0x5555556b2f80 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x7ffff4ac1e4c "%s") at gmessages.c:1079
#2 0x00007ffff4a4ed56 in g_warn_message (domain=domain@entry=0x5555556b2f80 "NetworkManager", file=file@entry=0x5555556aca93 "devices/nm-device.c", line=line@entry=1101,
func=func@entry=0x5555556b22e0 <__FUNCTION__.35443> "nm_device_release_one_slave", warnexpr=warnexpr@entry=0x0) at gmessages.c:1112
#3 0x00005555555ba80a in nm_device_release_one_slave (self=self@entry=0x5555559ec4c0, slave=slave@entry=0x5555559f7800, configure=configure@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE)
at devices/nm-device.c:1101
#4 0x00005555555c264b in slave_state_changed (slave=0x5555559f7800, slave_new_state=NM_DEVICE_STATE_FAILED, slave_old_state=NM_DEVICE_STATE_IP_CONFIG, reason=NM_DEVICE_STATE_REASON_NONE, self=0x5555559ec4c0)
at devices/nm-device.c:1700
#5 0x00007ffff339cdac in ffi_call_unix64 () at ../src/x86/unix64.S:76
#6 0x00007ffff339c6d5 in ffi_call (cif=cif@entry=0x7fffffffd1c0, fn=<optimized out>, rvalue=0x7fffffffd130, avalue=avalue@entry=0x7fffffffd0b0) at ../src/x86/ffi64.c:522
#7 0x00007ffff4d45678 in g_cclosure_marshal_generic (closure=0x5555559b0160, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0)
at gclosure.c:1454
#8 0x00007ffff4d44e38 in g_closure_invoke (closure=0x5555559b0160, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fffffffd3c0,
invocation_hint=invocation_hint@entry=0x7fffffffd360) at gclosure.c:768
#9 0x00007ffff4d5675d in signal_emit_unlocked_R (node=node@entry=0x55555598a6f0, detail=detail@entry=0, instance=instance@entry=0x5555559f7800, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fffffffd3c0) at gsignal.c:3553
#10 0x00007ffff4d5e4c1 in g_signal_emit_valist (instance=instance@entry=0x5555559f7800, signal_id=signal_id@entry=72, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffd5f8) at gsignal.c:3309
#11 0x00007ffff4d5ecc8 in g_signal_emit_by_name (instance=instance@entry=0x5555559f7800, detailed_signal=detailed_signal@entry=0x5555556c0405 "state-changed") at gsignal.c:3405
#12 0x00005555555bd0e0 in _set_state_full (self=self@entry=0x5555559f7800, state=state@entry=NM_DEVICE_STATE_FAILED, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE, quitting=quitting@entry=0)
at devices/nm-device.c:8580
#13 0x00005555555be0e7 in nm_device_state_changed (self=self@entry=0x5555559f7800, state=state@entry=NM_DEVICE_STATE_FAILED, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:8741
#14 0x00005555555c0a45 in queued_set_state (user_data=<optimized out>) at devices/nm-device.c:8765
#15 0x00007ffff4a4779a in g_main_dispatch (context=0x5555559433c0) at gmain.c:3109
#16 g_main_context_dispatch (context=context@entry=0x5555559433c0) at gmain.c:3708
#17 0x00007ffff4a47ae8 in g_main_context_iterate (context=0x5555559433c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3779
#18 0x00007ffff4a47dba in g_main_loop_run (loop=0x555555943480) at gmain.c:3973
#19 0x000055555559713d in main (argc=1, argv=0x7fffffffdb78) at main.c:512
(gdb)
2015-11-06 14:30:32 +01:00
|
|
|
else
|
|
|
|
|
nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
|
2014-02-25 16:44:01 -05:00
|
|
|
} else
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_queue_recheck_assume (self);
|
2013-10-21 12:50:58 -04:00
|
|
|
}
|
2013-01-17 15:44:30 -06:00
|
|
|
|
2013-10-21 12:50:58 -04:00
|
|
|
/**
|
|
|
|
|
* nm_device_slave_notify_release:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the slave device
|
2013-12-05 09:13:26 -05:00
|
|
|
* @reason: the reason associated with the state change
|
2013-10-21 12:50:58 -04:00
|
|
|
*
|
2013-12-05 09:13:26 -05:00
|
|
|
* Notifies a slave that it has been released, and why.
|
2013-10-21 12:50:58 -04:00
|
|
|
*/
|
2013-11-18 12:06:10 -06:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason)
|
2013-10-21 12:50:58 -04:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-07-14 16:53:24 +02:00
|
|
|
NMConnection *connection = nm_device_get_applied_connection (self);
|
2013-10-21 12:50:58 -04:00
|
|
|
NMDeviceState new_state;
|
2013-12-05 09:13:26 -05:00
|
|
|
const char *master_status;
|
2013-10-21 12:50:58 -04:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_fail (priv->master);
|
|
|
|
|
|
device: fix disconnecting slave-device when master gets deleted
When deleting a master-device either via `nmcli device delete`
or `ip link delete`, the slave-device would hang.
This seems to be broken for a very long time already.
This is due to the following:
#0 0x00005555555f548c in nm_device_slave_notify_release (self=0x555555dc1300, reason=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:2175
#1 0x00005555555d6de2 in nm_device_release_one_slave (self=0x555555de3dd0, slave=0x555555dc1300, configure=0, reason=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:1117
#2 0x00005555555f02b7 in device_link_changed (self=0x555555dc1300) at devices/nm-device.c:1460
Previously, nm_device_slave_notify_release() being called with reason
"NONE" did not actually transition the device-state, thus keeping the
device wrongly in activated state.
There were two callers that passed configure=FALSE to nm_device_release_one_slave(),
(and thus reason=NONE to nm_device_slave_notify_release()):
- (1) device_link_changed():
nm_device_release_one_slave (priv->master, self, FALSE, /*wrong reason NONE*/);
- (2) nm_device_removed():
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
We should always change the device-state during nm_device_slave_notify_release()
regardless of the reason.
(2) was added by commit c83b40aca76fc0ed624a6c9e71dbd7b0abfa13f2, later
refined by commit 5dd48f7527c67b399ac144f594e035216771d61c. In a way
change the second fix to perform some of the configuration (but still
not unenslaving the device).
2015-12-03 17:18:50 +01:00
|
|
|
if ( priv->state > NM_DEVICE_STATE_DISCONNECTED
|
2013-10-21 12:50:58 -04:00
|
|
|
&& priv->state <= NM_DEVICE_STATE_ACTIVATED) {
|
2017-03-01 17:26:45 +01:00
|
|
|
switch (nm_device_state_reason_check (reason)) {
|
|
|
|
|
case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
|
2013-10-21 12:50:58 -04:00
|
|
|
new_state = NM_DEVICE_STATE_FAILED;
|
2013-12-05 09:13:26 -05:00
|
|
|
master_status = "failed";
|
2017-03-01 17:26:45 +01:00
|
|
|
break;
|
|
|
|
|
case NM_DEVICE_STATE_REASON_USER_REQUESTED:
|
2013-12-05 09:13:26 -05:00
|
|
|
new_state = NM_DEVICE_STATE_DEACTIVATING;
|
|
|
|
|
master_status = "deactivated by user request";
|
2017-03-01 17:26:45 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2013-10-21 12:50:58 -04:00
|
|
|
new_state = NM_DEVICE_STATE_DISCONNECTED;
|
2013-12-05 09:13:26 -05:00
|
|
|
master_status = "deactivated";
|
2017-03-01 17:26:45 +01:00
|
|
|
break;
|
2012-11-14 14:05:30 -06:00
|
|
|
}
|
2013-10-21 12:50:58 -04:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "Activation: connection '%s' master %s",
|
|
|
|
|
nm_connection_get_id (connection),
|
|
|
|
|
master_status);
|
2013-12-05 09:13:26 -05:00
|
|
|
|
2016-06-28 14:12:57 +02:00
|
|
|
/* Cancel any pending activation sources */
|
|
|
|
|
_cancel_activation (self);
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_queue_state (self, new_state, reason);
|
2015-12-02 10:53:16 +01:00
|
|
|
} else
|
|
|
|
|
_LOGI (LOGD_DEVICE, "released from master device %s", nm_device_get_iface (priv->master));
|
2014-01-02 14:46:02 -05:00
|
|
|
|
2015-08-06 14:17:29 +02:00
|
|
|
if (priv->is_enslaved) {
|
|
|
|
|
priv->is_enslaved = FALSE;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_MASTER);
|
|
|
|
|
_notify (priv->master, PROP_SLAVES);
|
2014-01-02 14:46:02 -05:00
|
|
|
}
|
2012-02-28 18:35:30 -06:00
|
|
|
}
|
|
|
|
|
|
2014-11-16 16:07:22 +01:00
|
|
|
/**
|
|
|
|
|
* nm_device_removed:
|
|
|
|
|
* @self: the #NMDevice
|
2016-04-20 17:46:41 +02:00
|
|
|
* @unconfigure_ip_config: whether to clear the IP config objects
|
|
|
|
|
* of the device (provided, it is still not cleared at this point).
|
2014-11-16 16:07:22 +01:00
|
|
|
*
|
|
|
|
|
* Called by the manager when the device was removed. Releases the device from
|
|
|
|
|
* the master in case it's enslaved.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2016-04-20 17:46:41 +02:00
|
|
|
nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config)
|
2014-11-16 16:07:22 +01:00
|
|
|
{
|
2015-12-02 10:53:16 +01:00
|
|
|
NMDevicePrivate *priv;
|
2014-11-16 16:07:22 +01:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
if (priv->master) {
|
device: fix disconnecting slave-device when master gets deleted
When deleting a master-device either via `nmcli device delete`
or `ip link delete`, the slave-device would hang.
This seems to be broken for a very long time already.
This is due to the following:
#0 0x00005555555f548c in nm_device_slave_notify_release (self=0x555555dc1300, reason=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:2175
#1 0x00005555555d6de2 in nm_device_release_one_slave (self=0x555555de3dd0, slave=0x555555dc1300, configure=0, reason=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:1117
#2 0x00005555555f02b7 in device_link_changed (self=0x555555dc1300) at devices/nm-device.c:1460
Previously, nm_device_slave_notify_release() being called with reason
"NONE" did not actually transition the device-state, thus keeping the
device wrongly in activated state.
There were two callers that passed configure=FALSE to nm_device_release_one_slave(),
(and thus reason=NONE to nm_device_slave_notify_release()):
- (1) device_link_changed():
nm_device_release_one_slave (priv->master, self, FALSE, /*wrong reason NONE*/);
- (2) nm_device_removed():
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
We should always change the device-state during nm_device_slave_notify_release()
regardless of the reason.
(2) was added by commit c83b40aca76fc0ed624a6c9e71dbd7b0abfa13f2, later
refined by commit 5dd48f7527c67b399ac144f594e035216771d61c. In a way
change the second fix to perform some of the configuration (but still
not unenslaving the device).
2015-12-03 17:18:50 +01:00
|
|
|
/* this is called when something externally messes with the slave or during shut-down.
|
|
|
|
|
* Release the slave from master, but don't touch the device. */
|
2015-08-06 14:37:12 +02:00
|
|
|
nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
device: fix disconnecting slave-device when master gets deleted
When deleting a master-device either via `nmcli device delete`
or `ip link delete`, the slave-device would hang.
This seems to be broken for a very long time already.
This is due to the following:
#0 0x00005555555f548c in nm_device_slave_notify_release (self=0x555555dc1300, reason=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:2175
#1 0x00005555555d6de2 in nm_device_release_one_slave (self=0x555555de3dd0, slave=0x555555dc1300, configure=0, reason=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:1117
#2 0x00005555555f02b7 in device_link_changed (self=0x555555dc1300) at devices/nm-device.c:1460
Previously, nm_device_slave_notify_release() being called with reason
"NONE" did not actually transition the device-state, thus keeping the
device wrongly in activated state.
There were two callers that passed configure=FALSE to nm_device_release_one_slave(),
(and thus reason=NONE to nm_device_slave_notify_release()):
- (1) device_link_changed():
nm_device_release_one_slave (priv->master, self, FALSE, /*wrong reason NONE*/);
- (2) nm_device_removed():
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
We should always change the device-state during nm_device_slave_notify_release()
regardless of the reason.
(2) was added by commit c83b40aca76fc0ed624a6c9e71dbd7b0abfa13f2, later
refined by commit 5dd48f7527c67b399ac144f594e035216771d61c. In a way
change the second fix to perform some of the configuration (but still
not unenslaving the device).
2015-12-03 17:18:50 +01:00
|
|
|
}
|
2016-04-04 16:58:33 +02:00
|
|
|
|
2016-04-20 17:46:41 +02:00
|
|
|
if (!unconfigure_ip_config)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-09-12 13:45:53 +02:00
|
|
|
nm_device_set_ip4_config (self, NULL, FALSE, NULL);
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
nm_device_set_ip6_config (self, NULL, FALSE);
|
2014-11-16 16:07:22 +01:00
|
|
|
}
|
|
|
|
|
|
2012-11-12 13:29:06 -05:00
|
|
|
static gboolean
|
2015-01-20 20:25:25 +01:00
|
|
|
is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
|
2012-11-12 13:29:06 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2011-10-18 13:48:48 +02:00
|
|
|
|
2017-06-02 00:01:26 +02:00
|
|
|
if ( priv->carrier
|
|
|
|
|
|| priv->ignore_carrier)
|
2015-01-20 21:06:31 +01:00
|
|
|
return TRUE;
|
|
|
|
|
|
2015-12-09 12:08:40 +01:00
|
|
|
if (NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER))
|
2015-01-20 21:06:31 +01:00
|
|
|
return TRUE;
|
|
|
|
|
|
2017-06-02 00:01:26 +02:00
|
|
|
/* master types are always available even without carrier. */
|
|
|
|
|
if (nm_device_is_master (self))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2015-01-20 21:06:31 +01:00
|
|
|
return FALSE;
|
2011-10-18 13:48:48 +02:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2013-07-12 10:43:45 -04:00
|
|
|
/**
|
|
|
|
|
* nm_device_is_available:
|
|
|
|
|
* @self: the #NMDevice
|
2015-01-20 20:25:25 +01:00
|
|
|
* @flags: additional flags to influence the check. Flags have the
|
|
|
|
|
* meaning to increase the availability of a device.
|
2013-07-12 10:43:45 -04:00
|
|
|
*
|
|
|
|
|
* Checks if @self would currently be capable of activating a
|
|
|
|
|
* connection. In particular, it checks that the device is ready (eg,
|
|
|
|
|
* is not missing firmware), that it has carrier (if necessary), and
|
|
|
|
|
* that any necessary external software (eg, ModemManager,
|
|
|
|
|
* wpa_supplicant) is available.
|
|
|
|
|
*
|
|
|
|
|
* @self can only be in a state higher than
|
|
|
|
|
* %NM_DEVICE_STATE_UNAVAILABLE when nm_device_is_available() returns
|
|
|
|
|
* %TRUE. (But note that it can still be %NM_DEVICE_STATE_UNMANAGED
|
|
|
|
|
* when it is available.)
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE or %FALSE
|
|
|
|
|
*/
|
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
|
|
|
gboolean
|
2015-01-20 20:25:25 +01:00
|
|
|
nm_device_is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
|
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
|
|
|
{
|
2010-05-25 10:52:25 -07:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->firmware_missing)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2015-01-20 20:25:25 +01:00
|
|
|
return NM_DEVICE_GET_CLASS (self)->is_available (self, flags);
|
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
|
|
|
}
|
|
|
|
|
|
2017-06-01 22:38:51 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_ignore_carrier_by_default (NMDevice *self)
|
|
|
|
|
{
|
2017-06-01 23:57:03 +02:00
|
|
|
/* master types ignore-carrier by default. */
|
|
|
|
|
return nm_device_is_master (self);
|
2017-06-01 22:38:51 +02:00
|
|
|
}
|
|
|
|
|
|
2011-11-17 23:28:30 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_device_get_enabled (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->get_enabled)
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->get_enabled (self);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-17 23:38:08 -06:00
|
|
|
void
|
|
|
|
|
nm_device_set_enabled (NMDevice *self, gboolean enabled)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->set_enabled)
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled);
|
|
|
|
|
}
|
|
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
NM_UTILS_FLAGS2STR_DEFINE_STATIC (_autoconnect_blocked_flags_to_string, NMDeviceAutoconnectBlockedFlags,
|
2017-11-07 12:36:17 +01:00
|
|
|
NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_NONE, "none"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_USER, "user"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN, "wrong-pin"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_DEVICE_AUTOCONNECT_BLOCKED_MANUAL_DISCONNECT, "manual-disconnect"),
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
NMDeviceAutoconnectBlockedFlags
|
|
|
|
|
nm_device_autoconnect_blocked_get (NMDevice *self, NMDeviceAutoconnectBlockedFlags mask)
|
2011-11-18 12:02:58 -06:00
|
|
|
{
|
2017-02-14 13:57:57 +01:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2011-11-18 12:02:58 -06:00
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
if (mask == 0)
|
|
|
|
|
mask = NM_DEVICE_AUTOCONNECT_BLOCKED_ALL;
|
|
|
|
|
|
2017-02-14 13:57:57 +01:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
return priv->autoconnect_blocked_flags & mask;
|
2011-11-18 12:02:58 -06:00
|
|
|
}
|
|
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
void
|
|
|
|
|
nm_device_autoconnect_blocked_set_full (NMDevice *self, NMDeviceAutoconnectBlockedFlags mask, NMDeviceAutoconnectBlockedFlags value)
|
2014-10-23 14:57:22 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
gboolean changed;
|
|
|
|
|
char buf1[128], buf2[128];
|
2014-10-23 14:57:22 -05:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
nm_assert (mask);
|
|
|
|
|
nm_assert (!NM_FLAGS_ANY (mask, ~NM_DEVICE_AUTOCONNECT_BLOCKED_ALL));
|
|
|
|
|
nm_assert (!NM_FLAGS_ANY (value, ~mask));
|
2014-10-23 14:57:22 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-02-14 13:57:57 +01:00
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
value = (priv->autoconnect_blocked_flags & ~mask) | (mask & value);
|
|
|
|
|
if (value == priv->autoconnect_blocked_flags)
|
|
|
|
|
return;
|
2017-02-14 13:57:57 +01:00
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
changed = ((!value) != (!priv->autoconnect_blocked_flags));
|
2017-02-14 13:57:57 +01:00
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
_LOGT (LOGD_DEVICE, "autoconnect-blocked: set \"%s\" (was \"%s\")",
|
|
|
|
|
_autoconnect_blocked_flags_to_string (value, buf1, sizeof (buf1)),
|
|
|
|
|
_autoconnect_blocked_flags_to_string (priv->autoconnect_blocked_flags, buf2, sizeof (buf2)));
|
|
|
|
|
|
|
|
|
|
priv->autoconnect_blocked_flags = value;
|
|
|
|
|
nm_assert (priv->autoconnect_blocked_flags == value);
|
|
|
|
|
if (changed)
|
|
|
|
|
_notify (self, PROP_AUTOCONNECT);
|
2014-10-23 14:57:22 -05:00
|
|
|
}
|
|
|
|
|
|
2009-07-15 17:22:10 -04:00
|
|
|
static gboolean
|
|
|
|
|
autoconnect_allowed_accumulator (GSignalInvocationHint *ihint,
|
|
|
|
|
GValue *return_accu,
|
|
|
|
|
const GValue *handler_return, gpointer data)
|
|
|
|
|
{
|
|
|
|
|
if (!g_value_get_boolean (handler_return))
|
|
|
|
|
g_value_set_boolean (return_accu, FALSE);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 14:57:22 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_autoconnect_allowed:
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the device can be auto-connected immediately, taking
|
|
|
|
|
* transient conditions into account (like companion devices that may wish to
|
|
|
|
|
* block autoconnect for a time).
|
|
|
|
|
*/
|
2009-07-15 17:22:10 -04:00
|
|
|
gboolean
|
|
|
|
|
nm_device_autoconnect_allowed (NMDevice *self)
|
|
|
|
|
{
|
2009-09-16 13:18:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-02-14 12:45:38 +01:00
|
|
|
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
|
2013-03-22 10:49:19 +01:00
|
|
|
GValue instance = G_VALUE_INIT;
|
|
|
|
|
GValue retval = G_VALUE_INIT;
|
2009-07-15 17:22:10 -04:00
|
|
|
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
if (nm_device_autoconnect_blocked_get (self, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
|
2017-11-02 16:00:41 +01:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ( klass->get_autoconnect_allowed
|
|
|
|
|
&& !klass->get_autoconnect_allowed (self))
|
2016-01-13 17:49:35 +01:00
|
|
|
return FALSE;
|
|
|
|
|
|
2017-11-02 16:33:30 +01:00
|
|
|
if (!nm_device_get_enabled (self))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2017-11-08 11:42:50 +01:00
|
|
|
if (nm_device_is_real (self)) {
|
|
|
|
|
if (priv->state < NM_DEVICE_STATE_DISCONNECTED)
|
|
|
|
|
return FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
/* Unrealized devices can always autoconnect. */
|
|
|
|
|
}
|
2014-10-23 14:57:22 -05:00
|
|
|
|
|
|
|
|
/* The 'autoconnect-allowed' signal is emitted on a device to allow
|
|
|
|
|
* other listeners to block autoconnect on the device if they wish.
|
|
|
|
|
* This is mainly used by the OLPC Mesh devices to block autoconnect
|
|
|
|
|
* on their companion WiFi device as they share radio resources and
|
|
|
|
|
* cannot be connected at the same time.
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-15 17:22:10 -04:00
|
|
|
g_value_init (&instance, G_TYPE_OBJECT);
|
2014-05-05 20:58:27 +02:00
|
|
|
g_value_set_object (&instance, self);
|
2009-07-15 17:22:10 -04:00
|
|
|
|
|
|
|
|
g_value_init (&retval, G_TYPE_BOOLEAN);
|
2016-01-13 17:47:32 +01:00
|
|
|
g_value_set_boolean (&retval, TRUE);
|
2009-07-15 17:22:10 -04:00
|
|
|
|
|
|
|
|
/* Use g_signal_emitv() rather than g_signal_emit() to avoid the return
|
|
|
|
|
* value being changed if no handlers are connected */
|
|
|
|
|
g_signal_emitv (&instance, signals[AUTOCONNECT_ALLOWED], 0, &retval);
|
2014-05-05 20:58:27 +02:00
|
|
|
g_value_unset (&instance);
|
2016-01-13 17:47:32 +01:00
|
|
|
|
2009-07-15 17:22:10 -04:00
|
|
|
return g_value_get_boolean (&retval);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-06 16:16:54 -05:00
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
can_auto_connect (NMDevice *self,
|
2013-03-06 16:16:54 -05:00
|
|
|
NMConnection *connection,
|
|
|
|
|
char **specific_object)
|
|
|
|
|
{
|
2016-09-26 15:34:07 +02:00
|
|
|
nm_assert (!specific_object || !*specific_object);
|
2017-11-02 18:37:32 +01:00
|
|
|
return TRUE;
|
2013-03-06 16:16:54 -05:00
|
|
|
}
|
|
|
|
|
|
2014-08-26 15:10:38 +02:00
|
|
|
/**
|
|
|
|
|
* nm_device_can_auto_connect:
|
|
|
|
|
* @self: an #NMDevice
|
|
|
|
|
* @connection: a #NMConnection
|
|
|
|
|
* @specific_object: (out) (transfer full): on output, the path of an
|
|
|
|
|
* object associated with the returned connection, to be passed to
|
|
|
|
|
* nm_manager_activate_connection(), or %NULL.
|
|
|
|
|
*
|
|
|
|
|
* Checks if @connection can be auto-activated on @self right now.
|
|
|
|
|
* This requires, at a minimum, that the connection be compatible with
|
|
|
|
|
* @self, and that it have the #NMSettingConnection:autoconnect property
|
2014-10-23 14:57:22 -05:00
|
|
|
* set, and that the device allow auto connections. Some devices impose
|
|
|
|
|
* additional requirements. (Eg, a Wi-Fi connection can only be activated
|
|
|
|
|
* if its SSID was seen in the last scan.)
|
2014-08-26 15:10:38 +02:00
|
|
|
*
|
|
|
|
|
* Returns: %TRUE, if the @connection can be auto-activated.
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_can_auto_connect (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
char **specific_object)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
|
2017-11-02 18:37:32 +01:00
|
|
|
g_return_val_if_fail (!specific_object || !*specific_object, FALSE);
|
2014-08-26 15:10:38 +02:00
|
|
|
|
2017-11-02 18:48:02 +01:00
|
|
|
/* the caller must ensure that nm_device_autoconnect_allowed() returns
|
|
|
|
|
* TRUE as well. This is done, because nm_device_can_auto_connect()
|
|
|
|
|
* has only one caller, and it iterates over a list of available
|
|
|
|
|
* connections.
|
|
|
|
|
*
|
|
|
|
|
* Hence, we don't need to re-check nm_device_autoconnect_allowed()
|
|
|
|
|
* over and over again. The caller is supposed to do that. */
|
|
|
|
|
nm_assert (nm_device_autoconnect_allowed (self));
|
2017-11-02 18:37:32 +01:00
|
|
|
|
|
|
|
|
if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2014-08-26 15:10:38 +02:00
|
|
|
}
|
|
|
|
|
|
2013-06-27 14:39:13 +02:00
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
device_has_config (NMDevice *self)
|
2013-06-27 14:39:13 +02:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-06-27 14:39:13 +02:00
|
|
|
|
|
|
|
|
/* Check for IP configuration. */
|
|
|
|
|
if (priv->ip4_config && nm_ip4_config_get_num_addresses (priv->ip4_config))
|
|
|
|
|
return TRUE;
|
|
|
|
|
if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
/* The existence of a software device is good enough. */
|
2014-09-05 08:50:02 -05:00
|
|
|
if (nm_device_is_software (self) && nm_device_is_real (self))
|
2013-06-27 14:39:13 +02:00
|
|
|
return TRUE;
|
|
|
|
|
|
2016-09-23 20:26:07 +02:00
|
|
|
/* Master-slave relationship is also a configuration */
|
2017-05-13 21:57:51 +02:00
|
|
|
if ( !c_list_is_empty (&priv->slaves)
|
|
|
|
|
|| nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) > 0)
|
2013-11-07 01:11:51 -06:00
|
|
|
return TRUE;
|
|
|
|
|
|
2013-06-27 14:39:13 +02:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-18 20:17:57 +02:00
|
|
|
/**
|
|
|
|
|
* nm_device_master_update_slave_connection:
|
|
|
|
|
* @self: the master #NMDevice
|
|
|
|
|
* @slave: the slave #NMDevice
|
|
|
|
|
* @connection: the #NMConnection to update with the slave settings
|
|
|
|
|
* @GError: (out): error description
|
|
|
|
|
*
|
|
|
|
|
* Reads the slave configuration for @slave and updates @connection with those
|
|
|
|
|
* properties. This invokes a virtual function on the master device @self.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the configuration was read and @connection updated,
|
|
|
|
|
* %FALSE on failure.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_master_update_slave_connection (NMDevice *self,
|
|
|
|
|
NMDevice *slave,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
NMDeviceClass *klass;
|
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self, FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (slave, FALSE);
|
|
|
|
|
g_return_val_if_fail (connection, FALSE);
|
|
|
|
|
g_return_val_if_fail (!error || !*error, FALSE);
|
|
|
|
|
g_return_val_if_fail (nm_connection_get_setting_connection (connection), FALSE);
|
|
|
|
|
|
2014-08-02 00:48:35 +02:00
|
|
|
g_return_val_if_fail (nm_device_get_iface (self), FALSE);
|
2014-06-18 20:17:57 +02:00
|
|
|
|
|
|
|
|
klass = NM_DEVICE_GET_CLASS (self);
|
|
|
|
|
if (klass->master_update_slave_connection) {
|
|
|
|
|
success = klass->master_update_slave_connection (self, slave, connection, error);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (!error || (success && !*error) || *error, success);
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
2014-10-15 13:47:29 -04:00
|
|
|
NM_DEVICE_ERROR_FAILED,
|
2014-06-18 20:17:57 +02:00
|
|
|
"master device '%s' cannot update a slave connection for slave device '%s' (master type not supported?)",
|
2014-08-02 00:48:35 +02:00
|
|
|
nm_device_get_iface (self), nm_device_get_iface (slave));
|
2014-06-18 20:17:57 +02:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-27 14:39:13 +02:00
|
|
|
NMConnection *
|
2017-06-07 17:04:33 +02:00
|
|
|
nm_device_generate_connection (NMDevice *self,
|
|
|
|
|
NMDevice *master,
|
|
|
|
|
gboolean *out_maybe_later,
|
|
|
|
|
GError **error)
|
2013-06-27 14:39:13 +02:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
const char *ifname = nm_device_get_iface (self);
|
2017-06-07 17:04:33 +02:00
|
|
|
gs_unref_object NMConnection *connection = NULL;
|
2013-06-27 14:39:13 +02:00
|
|
|
NMSetting *s_con;
|
|
|
|
|
NMSetting *s_ip4;
|
|
|
|
|
NMSetting *s_ip6;
|
2017-02-28 16:05:39 +01:00
|
|
|
char uuid[37];
|
2013-11-08 00:35:42 -06:00
|
|
|
const char *ip4_method, *ip6_method;
|
2017-06-07 17:04:33 +02:00
|
|
|
GError *local = NULL;
|
2016-04-30 16:49:43 +02:00
|
|
|
const NMPlatformLink *pllink;
|
2013-06-27 14:39:13 +02:00
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
NM_SET_OUT (out_maybe_later, FALSE);
|
|
|
|
|
|
2013-06-27 14:39:13 +02:00
|
|
|
/* If update_connection() is not implemented, just fail. */
|
2017-06-07 17:04:33 +02:00
|
|
|
if (!klass->update_connection) {
|
|
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"device class %s does not support generating a connection",
|
|
|
|
|
G_OBJECT_TYPE_NAME (self));
|
2013-06-27 14:39:13 +02:00
|
|
|
return NULL;
|
2017-06-07 17:04:33 +02:00
|
|
|
}
|
2013-06-27 14:39:13 +02:00
|
|
|
|
|
|
|
|
/* Return NULL if device is unconfigured. */
|
2014-07-15 13:36:24 +02:00
|
|
|
if (!device_has_config (self)) {
|
2017-06-07 17:04:33 +02:00
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"device has no existing configuration");
|
2013-06-27 14:39:13 +02:00
|
|
|
return NULL;
|
2013-11-14 10:01:24 -06:00
|
|
|
}
|
2013-06-27 14:39:13 +02:00
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2013-06-27 14:39:13 +02:00
|
|
|
s_con = nm_setting_connection_new ();
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
2017-02-28 16:05:39 +01:00
|
|
|
NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid),
|
2014-07-26 02:30:22 +02:00
|
|
|
NM_SETTING_CONNECTION_ID, ifname,
|
2013-06-27 14:39:13 +02:00
|
|
|
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
|
2014-03-18 14:21:59 +01:00
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
|
2013-06-27 14:39:13 +02:00
|
|
|
NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
|
|
|
|
|
NULL);
|
|
|
|
|
if (klass->connection_type)
|
|
|
|
|
g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, klass->connection_type, NULL);
|
|
|
|
|
nm_connection_add_setting (connection, s_con);
|
2013-11-06 14:13:59 -06:00
|
|
|
|
2013-08-22 20:41:01 +02:00
|
|
|
/* If the device is a slave, update various slave settings */
|
2014-06-18 20:17:57 +02:00
|
|
|
if (master) {
|
|
|
|
|
if (!nm_device_master_update_slave_connection (master,
|
2014-07-15 13:36:24 +02:00
|
|
|
self,
|
2014-06-18 20:17:57 +02:00
|
|
|
connection,
|
2017-06-07 17:04:33 +02:00
|
|
|
&local)) {
|
|
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"master device '%s' failed to update slave connection: %s",
|
|
|
|
|
nm_device_get_iface (master), local->message);
|
|
|
|
|
g_error_free (local);
|
2014-06-18 20:17:57 +02:00
|
|
|
return NULL;
|
2013-08-22 20:41:01 +02:00
|
|
|
}
|
2013-11-14 10:01:24 -06:00
|
|
|
} else {
|
|
|
|
|
/* Only regular and master devices get IP configuration; slaves do not */
|
2014-05-19 10:24:15 -04:00
|
|
|
s_ip4 = nm_ip4_config_create_setting (priv->ip4_config);
|
2013-11-14 10:01:24 -06:00
|
|
|
nm_connection_add_setting (connection, s_ip4);
|
|
|
|
|
|
2014-05-19 10:24:15 -04:00
|
|
|
s_ip6 = nm_ip6_config_create_setting (priv->ip6_config);
|
2013-11-14 10:01:24 -06:00
|
|
|
nm_connection_add_setting (connection, s_ip6);
|
2016-04-30 16:49:43 +02:00
|
|
|
|
2017-10-27 18:24:19 +02:00
|
|
|
nm_connection_add_setting (connection, nm_setting_proxy_new ());
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
pllink = nm_platform_link_get (nm_device_get_platform (self), priv->ifindex);
|
2016-04-30 16:49:43 +02:00
|
|
|
if (pllink && pllink->inet6_token.id) {
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, NM_IN6_ADDR_GEN_MODE_EUI64,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_TOKEN, nm_utils_inet6_interface_identifier_to_token (pllink->inet6_token, NULL),
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2013-08-22 20:41:01 +02:00
|
|
|
}
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
klass->update_connection (self, connection);
|
2013-06-27 14:39:13 +02:00
|
|
|
|
2017-06-07 17:04:33 +02:00
|
|
|
if (!nm_connection_verify (connection, &local)) {
|
|
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"generated connection does not verify: %s",
|
|
|
|
|
local->message);
|
|
|
|
|
g_error_free (local);
|
2014-03-26 12:39:13 -04:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2013-06-27 14:39:13 +02:00
|
|
|
|
2013-11-08 00:35:42 -06:00
|
|
|
/* Ignore the connection if it has no IP configuration,
|
|
|
|
|
* no slave configuration, and is not a master interface.
|
|
|
|
|
*/
|
2013-11-14 10:01:24 -06:00
|
|
|
ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
ip6_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
if ( g_strcmp0 (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0
|
|
|
|
|
&& g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0
|
2014-12-05 17:49:11 +01:00
|
|
|
&& !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con))
|
2017-05-13 21:57:51 +02:00
|
|
|
&& c_list_is_empty (&priv->slaves)) {
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
NM_SET_OUT (out_maybe_later, TRUE);
|
2017-06-07 17:04:33 +02:00
|
|
|
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"ignoring generated connection (no IP and not in master-slave relationship)");
|
|
|
|
|
return NULL;
|
2015-05-20 11:36:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ignore any IPv6LL-only, not master connections without slaves,
|
|
|
|
|
* unless they are in the assume-ipv6ll-only list.
|
|
|
|
|
*/
|
2017-06-07 17:04:33 +02:00
|
|
|
if ( g_strcmp0 (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0
|
2015-05-20 11:36:37 +02:00
|
|
|
&& g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0
|
|
|
|
|
&& !nm_setting_connection_get_master (NM_SETTING_CONNECTION (s_con))
|
2017-05-13 21:57:51 +02:00
|
|
|
&& c_list_is_empty (&priv->slaves)
|
2015-06-09 08:47:41 +02:00
|
|
|
&& !nm_config_data_get_assume_ipv6ll_only (NM_CONFIG_GET_DATA, self)) {
|
2015-05-20 11:36:37 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "ignoring generated connection (IPv6LL-only and not in master-slave relationship)");
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
NM_SET_OUT (out_maybe_later, TRUE);
|
2017-06-07 17:04:33 +02:00
|
|
|
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"ignoring generated connection (IPv6LL-only and not in master-slave relationship)");
|
|
|
|
|
return NULL;
|
2013-11-08 00:35:42 -06:00
|
|
|
}
|
|
|
|
|
|
2017-06-07 17:04:33 +02:00
|
|
|
return g_steal_pointer (&connection);
|
2013-06-27 14:39:13 +02:00
|
|
|
}
|
|
|
|
|
|
2011-01-10 23:39:12 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_device_complete_connection (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
const char *specific_object,
|
|
|
|
|
const GSList *existing_connections,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
gboolean success = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (connection != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!NM_DEVICE_GET_CLASS (self)->complete_connection) {
|
2014-10-15 13:47:29 -04:00
|
|
|
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
|
2011-01-10 23:39:12 -06:00
|
|
|
"Device class %s had no complete_connection method",
|
|
|
|
|
G_OBJECT_TYPE_NAME (self));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
success = NM_DEVICE_GET_CLASS (self)->complete_connection (self,
|
|
|
|
|
connection,
|
|
|
|
|
specific_object,
|
|
|
|
|
existing_connections,
|
|
|
|
|
error);
|
|
|
|
|
if (success)
|
|
|
|
|
success = nm_connection_verify (connection, error);
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-27 09:40:45 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_match_parent (NMDevice *self, const char *parent)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *parent_device;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (parent, FALSE);
|
|
|
|
|
|
|
|
|
|
parent_device = nm_device_parent_get_device (self);
|
|
|
|
|
if (!parent_device)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (nm_utils_is_uuid (parent)) {
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
|
2017-09-27 10:23:31 +02:00
|
|
|
/* If the parent is a UUID, the connection matches when there is
|
|
|
|
|
* no connection active on the device or when a connection with
|
|
|
|
|
* that UUID is active.
|
2017-09-27 09:40:45 +02:00
|
|
|
*/
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (!connection)
|
2017-09-27 10:23:31 +02:00
|
|
|
return TRUE;
|
2017-09-27 09:40:45 +02:00
|
|
|
|
|
|
|
|
if (!nm_streq0 (parent, nm_connection_get_uuid (connection)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
/* Interface name */
|
|
|
|
|
if (!nm_streq0 (parent, nm_device_get_ip_iface (parent_device)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-27 09:47:22 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_match_hwaddr (NMDevice *device,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
gboolean fail_if_no_hwaddr)
|
|
|
|
|
{
|
|
|
|
|
NMSettingWired *s_wired;
|
|
|
|
|
NMDevice *parent_device;
|
|
|
|
|
const char *setting_mac;
|
|
|
|
|
const char *parent_mac;
|
|
|
|
|
|
|
|
|
|
s_wired = nm_connection_get_setting_wired (connection);
|
|
|
|
|
if (!s_wired)
|
|
|
|
|
return !fail_if_no_hwaddr;
|
|
|
|
|
|
|
|
|
|
setting_mac = nm_setting_wired_get_mac_address (s_wired);
|
|
|
|
|
if (!setting_mac)
|
|
|
|
|
return !fail_if_no_hwaddr;
|
|
|
|
|
|
|
|
|
|
parent_device = nm_device_parent_get_device (device);
|
|
|
|
|
if (!parent_device)
|
|
|
|
|
return !fail_if_no_hwaddr;
|
|
|
|
|
|
|
|
|
|
parent_mac = nm_device_get_permanent_hw_address (parent_device);
|
|
|
|
|
return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-07 07:44:36 -05:00
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
check_connection_compatible (NMDevice *self, NMConnection *connection)
|
2013-03-07 07:44:36 -05:00
|
|
|
{
|
2016-02-16 15:07:57 +01:00
|
|
|
const char *device_iface = nm_device_get_iface (self);
|
|
|
|
|
gs_free char *conn_iface = nm_manager_get_connection_iface (nm_manager_get (),
|
|
|
|
|
connection,
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
|
|
/* We always need a interface name for virtual devices, but for
|
|
|
|
|
* physical ones a connection without interface name is fine for
|
|
|
|
|
* any device. */
|
|
|
|
|
if (!conn_iface)
|
|
|
|
|
return !nm_connection_is_virtual (connection);
|
|
|
|
|
|
|
|
|
|
if (strcmp (conn_iface, device_iface) != 0)
|
2013-03-07 07:44:36 -05:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-13 13:52:55 -04:00
|
|
|
/**
|
|
|
|
|
* nm_device_check_connection_compatible:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: an #NMDevice
|
2013-03-13 13:52:55 -04:00
|
|
|
* @connection: an #NMConnection
|
|
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Checks if @connection could potentially be activated on @self.
|
|
|
|
|
* This means only that @self has the proper capabilities, and that
|
2013-03-13 13:52:55 -04:00
|
|
|
* @connection is not locked to some other device. It does not
|
2014-07-15 13:36:24 +02:00
|
|
|
* necessarily mean that @connection could be activated on @self
|
2013-03-13 13:52:55 -04:00
|
|
|
* right now. (Eg, it might refer to a Wi-Fi network that is not
|
|
|
|
|
* currently available.)
|
|
|
|
|
*
|
|
|
|
|
* Returns: #TRUE if @connection could potentially be activated on
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self.
|
2013-03-13 13:52:55 -04:00
|
|
|
*/
|
2011-11-17 23:04:47 -06:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection)
|
2011-11-17 23:04:47 -06:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2011-11-17 23:04:47 -06:00
|
|
|
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
return NM_DEVICE_GET_CLASS (self)->check_connection_compatible (self, connection);
|
2011-11-17 23:04:47 -06:00
|
|
|
}
|
|
|
|
|
|
2014-10-15 21:17:45 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
const char *connection_type, *slave_type;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_CONNECTION (slave), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-06-01 23:08:30 +02:00
|
|
|
if (!nm_device_is_master (self))
|
2014-10-15 21:17:45 -05:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* All masters should have connection type set */
|
|
|
|
|
connection_type = NM_DEVICE_GET_CLASS (self)->connection_type;
|
|
|
|
|
g_return_val_if_fail (connection_type, FALSE);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (slave);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
slave_type = nm_setting_connection_get_slave_type (s_con);
|
|
|
|
|
if (!slave_type)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return strcmp (connection_type, slave_type) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-27 14:39:13 +02:00
|
|
|
/**
|
|
|
|
|
* nm_device_can_assume_connections:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: #NMDevice instance
|
2013-06-27 14:39:13 +02:00
|
|
|
*
|
|
|
|
|
* This is a convenience function to determine whether connection assumption
|
|
|
|
|
* is available for this device.
|
|
|
|
|
*
|
core: don't do anything interesting in NMDevice dispose()
The NMDevice dispose() function contained some badly-duplicated logic
about when to deactivate a device on its last ref. This logic should
only run when the device is removed by the manager, since the manager
controls the device's life-cycle, and the manager knows best when to
clean up the device. But since it was tied to the device's refcount,
it could have run later than the manager wanted, or not at all.
It gets better. Dispose duplicated logic that was already done in
nm_device_cleanup(), and then *called* nm_device_cleanup() if the
device was still activated and managed. But the manager already
unmanages the device when removing it, which triggers a call to
nm_device_cleanup(), takes the device down, and resets the IPv6
sysctl properties, which dispose() duplicated too. So by the time
dispose() runs, the device should already be unmanaged if the
manager wants to deconfigure it, and most of the dispose() code
should be a no-op.
Clean all that up and remove duplicated functions. Now, the flow
should be like this:
1) manager decides to remove the device and calls remove_device()
2) if the device should be deconfigured, the manager unmanages
the device
3) the NMDevice state change handler tears down the active connection
via nm_device_cleanup() and resets IPv6 sysctl properties
4) when the device's last reference is finally released, only internal
data members are freed in dispose() because the device should
already have been cleaned up by the manager and be unmanaged
5) if the device should be left running because it has an assumable
connection, then the device is not unmanaged, and no cleanup
happens in the state change handler or in dispose()
2014-05-23 15:41:46 -05:00
|
|
|
* Returns: %TRUE if the device is capable of assuming connections, %FALSE if not
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_can_assume_connections (NMDevice *self)
|
core: don't do anything interesting in NMDevice dispose()
The NMDevice dispose() function contained some badly-duplicated logic
about when to deactivate a device on its last ref. This logic should
only run when the device is removed by the manager, since the manager
controls the device's life-cycle, and the manager knows best when to
clean up the device. But since it was tied to the device's refcount,
it could have run later than the manager wanted, or not at all.
It gets better. Dispose duplicated logic that was already done in
nm_device_cleanup(), and then *called* nm_device_cleanup() if the
device was still activated and managed. But the manager already
unmanages the device when removing it, which triggers a call to
nm_device_cleanup(), takes the device down, and resets the IPv6
sysctl properties, which dispose() duplicated too. So by the time
dispose() runs, the device should already be unmanaged if the
manager wants to deconfigure it, and most of the dispose() code
should be a no-op.
Clean all that up and remove duplicated functions. Now, the flow
should be like this:
1) manager decides to remove the device and calls remove_device()
2) if the device should be deconfigured, the manager unmanages
the device
3) the NMDevice state change handler tears down the active connection
via nm_device_cleanup() and resets IPv6 sysctl properties
4) when the device's last reference is finally released, only internal
data members are freed in dispose() because the device should
already have been cleaned up by the manager and be unmanaged
5) if the device should be left running because it has an assumable
connection, then the device is not unmanaged, and no cleanup
happens in the state change handler or in dispose()
2014-05-23 15:41:46 -05:00
|
|
|
{
|
2016-06-21 11:04:38 +02:00
|
|
|
return !!NM_DEVICE_GET_CLASS (self)->update_connection;
|
core: don't do anything interesting in NMDevice dispose()
The NMDevice dispose() function contained some badly-duplicated logic
about when to deactivate a device on its last ref. This logic should
only run when the device is removed by the manager, since the manager
controls the device's life-cycle, and the manager knows best when to
clean up the device. But since it was tied to the device's refcount,
it could have run later than the manager wanted, or not at all.
It gets better. Dispose duplicated logic that was already done in
nm_device_cleanup(), and then *called* nm_device_cleanup() if the
device was still activated and managed. But the manager already
unmanages the device when removing it, which triggers a call to
nm_device_cleanup(), takes the device down, and resets the IPv6
sysctl properties, which dispose() duplicated too. So by the time
dispose() runs, the device should already be unmanaged if the
manager wants to deconfigure it, and most of the dispose() code
should be a no-op.
Clean all that up and remove duplicated functions. Now, the flow
should be like this:
1) manager decides to remove the device and calls remove_device()
2) if the device should be deconfigured, the manager unmanages
the device
3) the NMDevice state change handler tears down the active connection
via nm_device_cleanup() and resets IPv6 sysctl properties
4) when the device's last reference is finally released, only internal
data members are freed in dispose() because the device should
already have been cleaned up by the manager and be unmanaged
5) if the device should be left running because it has an assumable
connection, then the device is not unmanaged, and no cleanup
happens in the state change handler or in dispose()
2014-05-23 15:41:46 -05:00
|
|
|
}
|
|
|
|
|
|
2016-06-21 11:04:38 +02:00
|
|
|
static gboolean
|
2016-10-11 14:42:35 +02:00
|
|
|
unmanaged_on_quit (NMDevice *self)
|
2011-11-17 23:10:11 -06:00
|
|
|
{
|
core: don't do anything interesting in NMDevice dispose()
The NMDevice dispose() function contained some badly-duplicated logic
about when to deactivate a device on its last ref. This logic should
only run when the device is removed by the manager, since the manager
controls the device's life-cycle, and the manager knows best when to
clean up the device. But since it was tied to the device's refcount,
it could have run later than the manager wanted, or not at all.
It gets better. Dispose duplicated logic that was already done in
nm_device_cleanup(), and then *called* nm_device_cleanup() if the
device was still activated and managed. But the manager already
unmanages the device when removing it, which triggers a call to
nm_device_cleanup(), takes the device down, and resets the IPv6
sysctl properties, which dispose() duplicated too. So by the time
dispose() runs, the device should already be unmanaged if the
manager wants to deconfigure it, and most of the dispose() code
should be a no-op.
Clean all that up and remove duplicated functions. Now, the flow
should be like this:
1) manager decides to remove the device and calls remove_device()
2) if the device should be deconfigured, the manager unmanages
the device
3) the NMDevice state change handler tears down the active connection
via nm_device_cleanup() and resets IPv6 sysctl properties
4) when the device's last reference is finally released, only internal
data members are freed in dispose() because the device should
already have been cleaned up by the manager and be unmanaged
5) if the device should be left running because it has an assumable
connection, then the device is not unmanaged, and no cleanup
happens in the state change handler or in dispose()
2014-05-23 15:41:46 -05:00
|
|
|
NMConnection *connection;
|
|
|
|
|
|
2016-10-11 14:42:35 +02:00
|
|
|
/* NMDeviceWifi overwrites this function to always unmanage wifi devices.
|
|
|
|
|
*
|
|
|
|
|
* For all other types, if the device type can assume connections, we leave
|
|
|
|
|
* it up on quit.
|
|
|
|
|
*
|
|
|
|
|
* Originally, we would only keep devices up that can be assumed afterwards.
|
|
|
|
|
* However, that meant we unmanged layer-2 only devices. So, this was step
|
|
|
|
|
* by step refined to unmanage less (commit 25aaaab3, rh#1311988, rh#1333983).
|
|
|
|
|
* But there are more scenarios where we also want to keep the device up
|
|
|
|
|
* (rh#1378418, rh#1371126). */
|
2014-07-15 13:36:24 +02:00
|
|
|
if (!nm_device_can_assume_connections (self))
|
2016-10-11 14:42:35 +02:00
|
|
|
return TRUE;
|
core: don't do anything interesting in NMDevice dispose()
The NMDevice dispose() function contained some badly-duplicated logic
about when to deactivate a device on its last ref. This logic should
only run when the device is removed by the manager, since the manager
controls the device's life-cycle, and the manager knows best when to
clean up the device. But since it was tied to the device's refcount,
it could have run later than the manager wanted, or not at all.
It gets better. Dispose duplicated logic that was already done in
nm_device_cleanup(), and then *called* nm_device_cleanup() if the
device was still activated and managed. But the manager already
unmanages the device when removing it, which triggers a call to
nm_device_cleanup(), takes the device down, and resets the IPv6
sysctl properties, which dispose() duplicated too. So by the time
dispose() runs, the device should already be unmanaged if the
manager wants to deconfigure it, and most of the dispose() code
should be a no-op.
Clean all that up and remove duplicated functions. Now, the flow
should be like this:
1) manager decides to remove the device and calls remove_device()
2) if the device should be deconfigured, the manager unmanages
the device
3) the NMDevice state change handler tears down the active connection
via nm_device_cleanup() and resets IPv6 sysctl properties
4) when the device's last reference is finally released, only internal
data members are freed in dispose() because the device should
already have been cleaned up by the manager and be unmanaged
5) if the device should be left running because it has an assumable
connection, then the device is not unmanaged, and no cleanup
happens in the state change handler or in dispose()
2014-05-23 15:41:46 -05:00
|
|
|
|
2016-10-11 14:42:35 +02:00
|
|
|
/* the only exception are IPv4 shared connections. We unmanage them on quit. */
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2016-10-11 14:42:35 +02:00
|
|
|
if (connection) {
|
|
|
|
|
if (NM_IN_STRSET (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG),
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
|
|
|
|
|
/* shared connections are to be unmangaed. */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2016-06-21 11:04:38 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-11 14:42:35 +02:00
|
|
|
return FALSE;
|
2016-06-21 11:04:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_unmanage_on_quit (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->unmanaged_on_quit (self);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-28 10:18:34 -04:00
|
|
|
static gboolean
|
2015-12-07 16:34:48 +01:00
|
|
|
nm_device_emit_recheck_assume (gpointer user_data)
|
2014-05-28 10:18:34 -04:00
|
|
|
{
|
2015-12-07 16:34:48 +01:00
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-28 10:18:34 -04:00
|
|
|
|
|
|
|
|
priv->recheck_assume_id = 0;
|
2017-06-07 13:44:07 +02:00
|
|
|
if (!nm_device_get_act_request (self))
|
2014-05-28 10:18:34 -04:00
|
|
|
g_signal_emit (self, signals[RECHECK_ASSUME], 0);
|
2017-06-07 13:44:07 +02:00
|
|
|
|
2014-05-28 10:18:34 -04:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_queue_recheck_assume (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
if ( !priv->recheck_assume_id
|
|
|
|
|
&& nm_device_can_assume_connections (self))
|
2014-05-28 10:18:34 -04:00
|
|
|
priv->recheck_assume_id = g_idle_add (nm_device_emit_recheck_assume, self);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 17:16:55 -05:00
|
|
|
static gboolean
|
|
|
|
|
recheck_available (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-03-01 17:26:45 +01:00
|
|
|
gboolean now_available;
|
2015-04-13 17:16:55 -05:00
|
|
|
NMDeviceState state = nm_device_get_state (self);
|
|
|
|
|
NMDeviceState new_state = NM_DEVICE_STATE_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
priv->recheck_available.call_id = 0;
|
|
|
|
|
|
2017-03-01 17:26:45 +01:00
|
|
|
now_available = nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
|
|
|
|
|
2015-04-13 17:16:55 -05:00
|
|
|
if (state == NM_DEVICE_STATE_UNAVAILABLE && now_available) {
|
|
|
|
|
new_state = NM_DEVICE_STATE_DISCONNECTED;
|
|
|
|
|
nm_device_queue_state (self, new_state, priv->recheck_available.available_reason);
|
|
|
|
|
} else if (state >= NM_DEVICE_STATE_DISCONNECTED && !now_available) {
|
|
|
|
|
new_state = NM_DEVICE_STATE_UNAVAILABLE;
|
|
|
|
|
nm_device_queue_state (self, new_state, priv->recheck_available.unavailable_reason);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 13:42:42 -05:00
|
|
|
if (new_state > NM_DEVICE_STATE_UNKNOWN) {
|
2016-03-03 09:20:00 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "is %savailable, %s %s",
|
2017-01-02 09:27:20 +01:00
|
|
|
now_available ? "" : "not ",
|
|
|
|
|
new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state));
|
2015-10-22 13:42:42 -05:00
|
|
|
|
|
|
|
|
priv->recheck_available.available_reason = NM_DEVICE_STATE_REASON_NONE;
|
|
|
|
|
priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-27 13:52:26 +01:00
|
|
|
if (priv->recheck_available.call_id == 0)
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_RECHECK_AVAILABLE, TRUE);
|
2017-01-27 13:52:26 +01:00
|
|
|
|
2015-04-13 17:16:55 -05:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_queue_recheck_available (NMDevice *self,
|
|
|
|
|
NMDeviceStateReason available_reason,
|
|
|
|
|
NMDeviceStateReason unavailable_reason)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->recheck_available.available_reason = available_reason;
|
|
|
|
|
priv->recheck_available.unavailable_reason = unavailable_reason;
|
2017-01-27 13:52:26 +01:00
|
|
|
if (!priv->recheck_available.call_id) {
|
2015-04-13 17:16:55 -05:00
|
|
|
priv->recheck_available.call_id = g_idle_add (recheck_available, self);
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_add_pending_action (self, NM_PENDING_ACTION_RECHECK_AVAILABLE,
|
2017-01-27 13:52:26 +01:00
|
|
|
FALSE /* cannot assert, because of how recheck_available() first clears
|
|
|
|
|
the call-id and postpones removing the pending-action. */);
|
|
|
|
|
}
|
2015-04-13 17:16:55 -05:00
|
|
|
}
|
|
|
|
|
|
2014-02-24 18:10:18 -06:00
|
|
|
void
|
|
|
|
|
nm_device_emit_recheck_auto_activate (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_signal_emit (self, signals[RECHECK_AUTO_ACTIVATE], 0);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-29 20:58:52 +00:00
|
|
|
static void
|
|
|
|
|
dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
|
case NM_DNSMASQ_STATUS_DEAD:
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
|
2008-05-29 20:58:52 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
activation_source_handle_cb4 (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
activation_source_handle_cb (user_data, AF_INET);
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
activation_source_handle_cb6 (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
activation_source_handle_cb (user_data, AF_INET6);
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ActivationHandleData *
|
|
|
|
|
activation_source_get_by_family (NMDevice *self,
|
2017-10-02 13:55:27 +02:00
|
|
|
int addr_family,
|
2015-10-06 11:05:14 +02:00
|
|
|
GSourceFunc *out_idle_func)
|
2009-03-23 17:36:52 -04:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2009-07-29 12:12:41 -04:00
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
switch (addr_family) {
|
|
|
|
|
case AF_INET6:
|
2015-10-06 11:05:14 +02:00
|
|
|
NM_SET_OUT (out_idle_func, activation_source_handle_cb6);
|
|
|
|
|
return &priv->act_handle6;
|
2017-10-02 13:55:27 +02:00
|
|
|
case AF_INET:
|
2015-10-06 11:05:14 +02:00
|
|
|
NM_SET_OUT (out_idle_func, activation_source_handle_cb4);
|
|
|
|
|
return &priv->act_handle4;
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
2017-10-02 13:55:27 +02:00
|
|
|
g_return_val_if_reached (NULL);
|
2015-10-06 11:05:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-10-02 13:55:27 +02:00
|
|
|
activation_source_clear (NMDevice *self,
|
|
|
|
|
int addr_family)
|
2015-10-06 11:05:14 +02:00
|
|
|
{
|
|
|
|
|
ActivationHandleData *act_data;
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
act_data = activation_source_get_by_family (self, addr_family, NULL);
|
2009-03-23 17:36:52 -04:00
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
if (act_data->id) {
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "activation-stage: clear %s,v%c (id %u)",
|
|
|
|
|
_activation_func_to_string (act_data->func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
act_data->id);
|
2015-10-06 11:05:14 +02:00
|
|
|
nm_clear_g_source (&act_data->id);
|
|
|
|
|
act_data->func = NULL;
|
2009-03-23 17:36:52 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-10-02 13:55:27 +02:00
|
|
|
activation_source_handle_cb (NMDevice *self,
|
|
|
|
|
int addr_family)
|
2009-03-23 17:36:52 -04:00
|
|
|
{
|
2015-10-06 11:05:14 +02:00
|
|
|
ActivationHandleData *act_data, a;
|
2009-03-23 17:36:52 -04:00
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
act_data = activation_source_get_by_family (self, addr_family, NULL);
|
2015-10-06 11:05:14 +02:00
|
|
|
|
|
|
|
|
g_return_if_fail (act_data->id);
|
|
|
|
|
g_return_if_fail (act_data->func);
|
|
|
|
|
|
|
|
|
|
a = *act_data;
|
|
|
|
|
|
|
|
|
|
act_data->func = NULL;
|
|
|
|
|
act_data->id = 0;
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "activation-stage: invoke %s,v%c (id %u)",
|
|
|
|
|
_activation_func_to_string (a.func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
a.id);
|
2015-10-06 11:05:14 +02:00
|
|
|
|
|
|
|
|
a.func (self);
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "activation-stage: complete %s,v%c (id %u)",
|
|
|
|
|
_activation_func_to_string (a.func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
a.id);
|
2015-10-06 11:05:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-10-02 13:55:27 +02:00
|
|
|
activation_source_schedule (NMDevice *self, ActivationHandleFunc func, int addr_family)
|
2015-10-06 11:05:14 +02:00
|
|
|
{
|
|
|
|
|
ActivationHandleData *act_data;
|
|
|
|
|
GSourceFunc source_func;
|
|
|
|
|
guint new_id = 0;
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
act_data = activation_source_get_by_family (self, addr_family, &source_func);
|
2015-10-06 11:05:14 +02:00
|
|
|
|
2016-12-08 13:24:42 +01:00
|
|
|
if (act_data->id && act_data->func == func) {
|
2015-10-06 11:05:14 +02:00
|
|
|
/* Don't bother rescheduling the same function that's about to
|
|
|
|
|
* run anyway. Fixes issues with crappy wireless drivers sending
|
|
|
|
|
* streams of associate events before NM has had a chance to process
|
|
|
|
|
* the first one.
|
|
|
|
|
*/
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "activation-stage: already scheduled %s,v%c (id %u)",
|
|
|
|
|
_activation_func_to_string (func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
act_data->id);
|
2015-10-06 11:05:14 +02:00
|
|
|
return;
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
new_id = g_idle_add (source_func, self);
|
|
|
|
|
|
|
|
|
|
if (act_data->id) {
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGW (LOGD_DEVICE, "activation-stage: schedule %s,v%c which replaces %s,v%c (id %u -> %u)",
|
|
|
|
|
_activation_func_to_string (func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
_activation_func_to_string (act_data->func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
2015-10-06 11:05:14 +02:00
|
|
|
act_data->id, new_id);
|
|
|
|
|
nm_clear_g_source (&act_data->id);
|
|
|
|
|
} else {
|
2017-10-02 13:55:27 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "activation-stage: schedule %s,v%c (id %u)",
|
|
|
|
|
_activation_func_to_string (func),
|
|
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
|
|
|
|
new_id);
|
2009-03-23 17:36:52 -04:00
|
|
|
}
|
2015-10-07 15:19:21 +02:00
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
act_data->func = func;
|
|
|
|
|
act_data->id = new_id;
|
2009-03-23 17:36:52 -04:00
|
|
|
}
|
|
|
|
|
|
2016-04-28 22:48:39 +02:00
|
|
|
static gboolean
|
2017-10-02 13:55:27 +02:00
|
|
|
activation_source_is_scheduled (NMDevice *self,
|
|
|
|
|
ActivationHandleFunc func,
|
|
|
|
|
int addr_family)
|
2016-04-28 22:48:39 +02:00
|
|
|
{
|
|
|
|
|
ActivationHandleData *act_data;
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
act_data = activation_source_get_by_family (self, addr_family, NULL);
|
2016-04-28 22:48:39 +02:00
|
|
|
return act_data->func == func;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2013-09-11 09:21:17 -05:00
|
|
|
static void
|
2015-10-01 16:48:32 +02:00
|
|
|
master_ready (NMDevice *self,
|
|
|
|
|
NMActiveConnection *active)
|
2013-09-11 09:21:17 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-12-02 10:53:16 +01:00
|
|
|
NMActiveConnection *master_connection;
|
|
|
|
|
NMDevice *master;
|
2013-09-11 09:21:17 -05:00
|
|
|
|
2015-10-01 16:48:32 +02:00
|
|
|
g_return_if_fail (priv->state == NM_DEVICE_STATE_PREPARE);
|
|
|
|
|
g_return_if_fail (!priv->master_ready_handled);
|
2013-09-11 09:21:17 -05:00
|
|
|
|
|
|
|
|
/* Notify a master device that it has a new slave */
|
2015-10-01 16:48:32 +02:00
|
|
|
g_return_if_fail (nm_active_connection_get_master_ready (active));
|
2015-12-02 10:53:16 +01:00
|
|
|
master_connection = nm_active_connection_get_master (active);
|
2013-09-11 09:21:17 -05:00
|
|
|
|
2015-10-01 16:48:32 +02:00
|
|
|
priv->master_ready_handled = TRUE;
|
|
|
|
|
nm_clear_g_signal_handler (active, &priv->master_ready_id);
|
|
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
master = nm_active_connection_get_device (master_connection);
|
2013-09-11 09:21:17 -05:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "master connection ready; master device %s",
|
2015-12-07 21:35:20 +01:00
|
|
|
nm_device_get_iface (master));
|
2013-09-11 09:21:17 -05:00
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
if (priv->master && priv->master != master)
|
|
|
|
|
nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
|
|
|
|
|
|
|
|
|
/* If the master didn't change, add-slave only rechecks whether to assume a connection. */
|
|
|
|
|
nm_device_master_add_slave (master,
|
|
|
|
|
self,
|
2017-03-13 15:34:14 +01:00
|
|
|
!nm_device_sys_iface_state_is_external_or_assume (self));
|
2015-10-01 16:48:32 +02:00
|
|
|
}
|
2013-09-11 09:21:17 -05:00
|
|
|
|
2015-10-01 16:48:32 +02:00
|
|
|
static void
|
|
|
|
|
master_ready_cb (NMActiveConnection *active,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
master_ready (self, active);
|
2013-09-11 09:21:17 -05:00
|
|
|
nm_device_activate_schedule_stage2_device_config (self);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 11:48:38 +02:00
|
|
|
static void
|
|
|
|
|
lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_LLDP_NEIGHBORS);
|
2015-10-07 11:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
lldp_rx_enabled (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingConnectionLldp lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT;
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
g_return_val_if_fail (connection, FALSE);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
g_return_val_if_fail (s_con, FALSE);
|
|
|
|
|
|
|
|
|
|
lldp = nm_setting_connection_get_lldp (s_con);
|
|
|
|
|
if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT) {
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"connection.lldp",
|
|
|
|
|
self);
|
|
|
|
|
lldp = _nm_utils_ascii_str_to_int64 (value, 10,
|
|
|
|
|
NM_SETTING_CONNECTION_LLDP_DEFAULT,
|
|
|
|
|
NM_SETTING_CONNECTION_LLDP_ENABLE_RX,
|
|
|
|
|
NM_SETTING_CONNECTION_LLDP_DEFAULT);
|
|
|
|
|
if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT)
|
|
|
|
|
lldp = NM_SETTING_CONNECTION_LLDP_DISABLE;
|
|
|
|
|
}
|
|
|
|
|
return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-14 00:45:10 -08:00
|
|
|
static NMActStageReturn
|
2017-02-22 17:04:00 +01:00
|
|
|
act_stage1_prepare (NMDevice *self, NMDeviceStateReason *out_failure_reason)
|
2010-01-14 00:45:10 -08:00
|
|
|
{
|
2013-11-07 01:08:02 -06:00
|
|
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
2011-10-18 13:48:48 +02:00
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/*
|
2015-10-07 12:07:51 +02:00
|
|
|
* activate_stage1_device_prepare
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
|
|
|
|
* Prepare for device activation
|
|
|
|
|
*
|
|
|
|
|
*/
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2015-10-07 12:07:51 +02:00
|
|
|
activate_stage1_device_prepare (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2010-01-27 16:20:09 -08:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-11-07 01:08:02 -06:00
|
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_NONE);
|
|
|
|
|
_set_ip_state (self, AF_INET6, IP_NONE);
|
2010-01-27 16:20:09 -08:00
|
|
|
|
2014-03-20 11:22:19 -05:00
|
|
|
/* Notify the new ActiveConnection along with the state change */
|
2017-01-24 19:43:52 +01:00
|
|
|
priv->act_request_public = TRUE;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_ACTIVE_CONNECTION);
|
2014-03-20 11:22:19 -05:00
|
|
|
|
2008-07-11 10:28:53 +00:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2013-11-07 01:08:02 -06:00
|
|
|
/* Assumed connections were already set up outside NetworkManager */
|
2017-03-13 15:34:14 +01:00
|
|
|
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2017-02-23 15:19:03 +01:00
|
|
|
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
|
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &failure_reason);
|
2013-11-07 01:08:02 -06:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2013-11-07 01:08:02 -06:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2013-11-07 01:08:02 -06:00
|
|
|
}
|
2017-02-22 17:04:00 +01:00
|
|
|
g_return_if_fail (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
2006-01-03 17:07:07 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2015-10-01 16:48:32 +02:00
|
|
|
nm_device_activate_schedule_stage2_device_config (self);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage1_device_prepare
|
|
|
|
|
*
|
|
|
|
|
* Prepare a device for activation
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
2007-06-11 13:36:34 +00:00
|
|
|
nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2007-06-11 13:36:34 +00:00
|
|
|
NMDevicePrivate *priv;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
g_return_if_fail (priv->act_request);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2015-10-07 12:07:51 +02:00
|
|
|
activation_source_schedule (self, activate_stage1_device_prepare, AF_INET);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-03 17:07:07 +00:00
|
|
|
static NMActStageReturn
|
2017-02-22 17:04:00 +01:00
|
|
|
act_stage2_config (NMDevice *self, NMDeviceStateReason *out_failure_reason)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2006-01-03 17:07:07 +00:00
|
|
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-06 17:48:01 +01:00
|
|
|
static void
|
|
|
|
|
lldp_init (NMDevice *self, gboolean restart)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->ifindex > 0 && lldp_rx_enabled (self)) {
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gconstpointer addr;
|
|
|
|
|
size_t addr_length;
|
|
|
|
|
|
|
|
|
|
if (priv->lldp_listener) {
|
|
|
|
|
if (restart && nm_lldp_listener_is_running (priv->lldp_listener))
|
|
|
|
|
nm_lldp_listener_stop (priv->lldp_listener);
|
|
|
|
|
} else {
|
|
|
|
|
priv->lldp_listener = nm_lldp_listener_new ();
|
|
|
|
|
g_signal_connect (priv->lldp_listener,
|
|
|
|
|
"notify::" NM_LLDP_LISTENER_NEIGHBORS,
|
|
|
|
|
G_CALLBACK (lldp_neighbors_changed),
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nm_lldp_listener_is_running (priv->lldp_listener)) {
|
2017-04-17 20:17:45 +02:00
|
|
|
addr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &addr_length);
|
2017-03-06 17:48:01 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error))
|
|
|
|
|
_LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener);
|
|
|
|
|
else {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s",
|
|
|
|
|
priv->lldp_listener, error->message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (priv->lldp_listener)
|
|
|
|
|
nm_lldp_listener_stop (priv->lldp_listener);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/*
|
2015-10-07 12:07:51 +02:00
|
|
|
* activate_stage2_device_config
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
|
|
|
|
* Determine device parameters and set those on the device, ie
|
2007-06-27 16:18:52 +00:00
|
|
|
* for wireless devices, set SSID, keys, etc.
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
|
|
|
|
*/
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2015-10-07 12:07:51 +02:00
|
|
|
activate_stage2_device_config (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2013-11-07 01:08:02 -06:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2007-01-04 12:06:26 +00:00
|
|
|
NMActStageReturn ret;
|
2008-08-18 18:29:47 +00:00
|
|
|
gboolean no_firmware = FALSE;
|
2017-05-13 21:57:51 +02:00
|
|
|
CList *iter;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2008-07-11 10:28:53 +00:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2013-11-07 01:08:02 -06:00
|
|
|
/* Assumed connections were already set up outside NetworkManager */
|
2017-03-13 15:34:14 +01:00
|
|
|
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
|
|
|
|
|
2013-11-07 01:08:02 -06:00
|
|
|
if (!nm_device_bring_up (self, FALSE, &no_firmware)) {
|
|
|
|
|
if (no_firmware)
|
|
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING);
|
|
|
|
|
else
|
|
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2013-11-07 01:08:02 -06:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &failure_reason);
|
2013-11-07 01:08:02 -06:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2013-11-07 01:08:02 -06:00
|
|
|
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2013-11-07 01:08:02 -06:00
|
|
|
}
|
|
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
2007-03-12 04:49:29 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2013-11-07 01:08:02 -06:00
|
|
|
/* If we have slaves that aren't yet enslaved, do that now */
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_for_each (iter, &priv->slaves) {
|
|
|
|
|
SlaveInfo *info = c_list_entry (iter, SlaveInfo, lst_slave);
|
2014-06-05 13:31:46 -04:00
|
|
|
NMDeviceState slave_state = nm_device_get_state (info->slave);
|
2013-11-07 01:08:02 -06:00
|
|
|
|
2014-06-05 13:31:46 -04:00
|
|
|
if (slave_state == NM_DEVICE_STATE_IP_CONFIG)
|
2015-08-06 14:37:12 +02:00
|
|
|
nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave));
|
2017-03-13 15:34:14 +01:00
|
|
|
else if ( priv->act_request
|
|
|
|
|
&& nm_device_sys_iface_state_is_external (self)
|
2014-06-05 13:31:46 -04:00
|
|
|
&& slave_state <= NM_DEVICE_STATE_DISCONNECTED)
|
|
|
|
|
nm_device_queue_recheck_assume (info->slave);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2017-03-06 17:48:01 +01:00
|
|
|
lldp_init (self, TRUE);
|
2007-06-11 13:36:34 +00:00
|
|
|
nm_device_activate_schedule_stage3_ip_config_start (self);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage2_device_config
|
|
|
|
|
*
|
|
|
|
|
* Schedule setup of the hardware device
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
2007-06-11 13:36:34 +00:00
|
|
|
nm_device_activate_schedule_stage2_device_config (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2007-06-11 13:36:34 +00:00
|
|
|
NMDevicePrivate *priv;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
g_return_if_fail (priv->act_request);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2015-10-06 12:03:51 +02:00
|
|
|
if (!priv->master_ready_handled) {
|
|
|
|
|
NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
|
2016-06-29 14:20:02 +02:00
|
|
|
NMActiveConnection *master;
|
2015-10-06 12:03:51 +02:00
|
|
|
|
2016-06-29 14:20:02 +02:00
|
|
|
master = nm_active_connection_get_master (active);
|
|
|
|
|
|
|
|
|
|
if (!master) {
|
2015-10-06 14:18:48 +02:00
|
|
|
g_warn_if_fail (!priv->master_ready_id);
|
2015-10-06 12:03:51 +02:00
|
|
|
priv->master_ready_handled = TRUE;
|
2015-10-06 14:18:48 +02:00
|
|
|
} else {
|
2015-10-06 12:03:51 +02:00
|
|
|
/* If the master connection is ready for slaves, attach ourselves */
|
|
|
|
|
if (nm_active_connection_get_master_ready (active))
|
|
|
|
|
master_ready (self, active);
|
2016-06-29 14:20:02 +02:00
|
|
|
else if (nm_active_connection_get_state (master) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "master connection is deactivating");
|
|
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
|
|
|
|
|
} else {
|
2015-10-06 12:03:51 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "waiting for master connection to become ready");
|
|
|
|
|
|
|
|
|
|
if (priv->master_ready_id == 0) {
|
|
|
|
|
priv->master_ready_id = g_signal_connect (active,
|
|
|
|
|
"notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
|
|
|
|
|
(GCallback) master_ready_cb,
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
/* Postpone */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 12:07:51 +02:00
|
|
|
activation_source_schedule (self, activate_stage2_device_config, AF_INET);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
void
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_device_ip_method_failed (NMDevice *self,
|
|
|
|
|
int addr_family,
|
|
|
|
|
NMDeviceStateReason reason)
|
2016-04-07 13:48:34 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2017-10-02 13:55:27 +02:00
|
|
|
g_return_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
2016-08-29 14:27:46 +02:00
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
_set_ip_state (self, addr_family, IP_FAIL);
|
2016-04-07 13:48:34 +02:00
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
if (get_ip_config_may_fail (self, addr_family))
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2016-04-07 13:48:34 +02:00
|
|
|
else
|
|
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-12-23 14:15:05 +01:00
|
|
|
/* IPv4 DAD stuff */
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
get_ipv4_dad_timeout (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingIPConfig *s_ip4 = NULL;
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
gint ret = 0;
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (connection)
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
|
|
|
|
|
if (s_ip4) {
|
|
|
|
|
ret = nm_setting_ip_config_get_dad_timeout (s_ip4);
|
|
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"ipv4.dad-timeout", self);
|
|
|
|
|
ret = _nm_utils_ascii_str_to_int64 (value, 10, -1,
|
|
|
|
|
NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX,
|
|
|
|
|
-1);
|
|
|
|
|
ret = ret < 0 ? 0 : ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
arping_data_destroy (gpointer ptr, GClosure *closure)
|
|
|
|
|
{
|
|
|
|
|
ArpingData *data = ptr;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (data) {
|
|
|
|
|
for (i = 0; data->configs && data->configs[i]; i++)
|
|
|
|
|
g_object_unref (data->configs[i]);
|
|
|
|
|
g_free (data->configs);
|
|
|
|
|
g_slice_free (ArpingData, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ipv4_manual_method_apply (NMDevice *self, NMIP4Config **configs, gboolean success)
|
|
|
|
|
{
|
|
|
|
|
NMIP4Config *empty;
|
|
|
|
|
|
|
|
|
|
if (success) {
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
empty = _ip4_config_new (self);
|
2015-12-23 14:15:05 +01:00
|
|
|
nm_device_activate_schedule_ip4_config_result (self, empty);
|
|
|
|
|
g_object_unref (empty);
|
|
|
|
|
} else {
|
2017-11-02 14:08:55 +01:00
|
|
|
nm_device_ip_method_failed (self, AF_INET,
|
2017-11-02 14:22:10 +01:00
|
|
|
NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
|
2015-12-23 14:15:05 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
arping_manager_probe_terminated (NMArpingManager *arping_manager, ArpingData *data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self;
|
|
|
|
|
NMDevicePrivate *priv;
|
2017-07-07 23:34:41 +02:00
|
|
|
NMDedupMultiIter ipconf_iter;
|
2015-12-23 14:15:05 +01:00
|
|
|
const NMPlatformIP4Address *address;
|
|
|
|
|
gboolean result, success = TRUE;
|
2017-07-07 23:34:41 +02:00
|
|
|
int i;
|
2015-12-23 14:15:05 +01:00
|
|
|
|
|
|
|
|
g_assert (data);
|
|
|
|
|
self = data->device;
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
for (i = 0; data->configs && data->configs[i]; i++) {
|
2017-07-07 23:34:41 +02:00
|
|
|
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, data->configs[i], &address) {
|
2015-12-23 14:15:05 +01:00
|
|
|
result = nm_arping_manager_check_address (arping_manager, address->address);
|
|
|
|
|
success &= result;
|
|
|
|
|
|
|
|
|
|
_NMLOG (result ? LOGL_DEBUG : LOGL_WARN,
|
|
|
|
|
LOGD_DEVICE,
|
|
|
|
|
"IPv4 DAD result: address %s is %s",
|
|
|
|
|
nm_utils_inet4_ntop (address->address, NULL),
|
|
|
|
|
result ? "unique" : "duplicate");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->callback (self, data->configs, success);
|
|
|
|
|
|
|
|
|
|
priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager);
|
|
|
|
|
nm_arping_manager_destroy (arping_manager);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ipv4_dad_start:
|
|
|
|
|
* @self: device instance
|
|
|
|
|
* @configs: NULL-terminated array of IPv4 configurations
|
|
|
|
|
* @cb: callback function
|
|
|
|
|
*
|
|
|
|
|
* Start IPv4 DAD on device @self, check addresses in @configs and call @cb
|
|
|
|
|
* when the procedure ends. @cb will be called in any case, even if DAD can't
|
|
|
|
|
* be started. @configs will be unreferenced after @cb has been called.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMArpingManager *arping_manager;
|
|
|
|
|
const NMPlatformIP4Address *address;
|
2017-07-07 23:34:41 +02:00
|
|
|
NMDedupMultiIter ipconf_iter;
|
2015-12-23 14:15:05 +01:00
|
|
|
ArpingData *data;
|
|
|
|
|
guint timeout;
|
|
|
|
|
gboolean ret, addr_found;
|
|
|
|
|
const guint8 *hw_addr;
|
|
|
|
|
size_t hw_addr_len = 0;
|
|
|
|
|
GError *error = NULL;
|
2017-07-07 23:34:41 +02:00
|
|
|
guint i;
|
2015-12-23 14:15:05 +01:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
g_return_if_fail (configs);
|
|
|
|
|
g_return_if_fail (cb);
|
|
|
|
|
|
|
|
|
|
for (i = 0, addr_found = FALSE; configs[i]; i++) {
|
|
|
|
|
if (nm_ip4_config_get_num_addresses (configs[i]) > 0) {
|
|
|
|
|
addr_found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
timeout = get_ipv4_dad_timeout (self);
|
2017-04-17 20:17:45 +02:00
|
|
|
hw_addr = nm_platform_link_get_address (nm_device_get_platform (self),
|
2015-12-23 14:15:05 +01:00
|
|
|
nm_device_get_ip_ifindex (self),
|
|
|
|
|
&hw_addr_len);
|
|
|
|
|
|
|
|
|
|
if ( !timeout
|
|
|
|
|
|| !hw_addr
|
|
|
|
|
|| !hw_addr_len
|
|
|
|
|
|| !addr_found
|
2017-03-13 15:34:14 +01:00
|
|
|
|| nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2015-12-23 14:15:05 +01:00
|
|
|
|
|
|
|
|
/* DAD not needed, signal success */
|
|
|
|
|
cb (self, configs, TRUE);
|
|
|
|
|
|
|
|
|
|
for (i = 0; configs[i]; i++)
|
|
|
|
|
g_object_unref (configs[i]);
|
|
|
|
|
g_free (configs);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* don't take additional references of @arping_manager that outlive @self.
|
|
|
|
|
* Otherwise, the callback can be invoked on a dangling pointer as we don't
|
|
|
|
|
* disconnect the handler. */
|
|
|
|
|
arping_manager = nm_arping_manager_new (nm_device_get_ip_ifindex (self));
|
|
|
|
|
priv->arping.dad_list = g_slist_append (priv->arping.dad_list, arping_manager);
|
|
|
|
|
|
|
|
|
|
data = g_slice_new0 (ArpingData);
|
|
|
|
|
data->configs = configs;
|
|
|
|
|
data->callback = cb;
|
|
|
|
|
data->device = self;
|
|
|
|
|
|
|
|
|
|
for (i = 0; configs[i]; i++) {
|
2017-07-07 23:34:41 +02:00
|
|
|
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, configs[i], &address)
|
2015-12-23 14:15:05 +01:00
|
|
|
nm_arping_manager_add_address (arping_manager, address->address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_signal_connect_data (arping_manager, NM_ARPING_MANAGER_PROBE_TERMINATED,
|
|
|
|
|
G_CALLBACK (arping_manager_probe_terminated), data,
|
|
|
|
|
arping_data_destroy, 0);
|
|
|
|
|
|
|
|
|
|
ret = nm_arping_manager_start_probe (arping_manager, timeout, &error);
|
|
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
|
_LOGW (LOGD_DEVICE, "arping probe failed: %s", error->message);
|
|
|
|
|
|
|
|
|
|
/* DAD could not be started, signal success */
|
|
|
|
|
cb (self, configs, TRUE);
|
|
|
|
|
|
|
|
|
|
priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager);
|
|
|
|
|
nm_arping_manager_destroy (arping_manager);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-04-08 14:00:11 +02:00
|
|
|
/* IPv4LL stuff */
|
2011-10-07 11:50:37 -05:00
|
|
|
|
2008-07-09 14:05:49 +00:00
|
|
|
static void
|
2015-04-08 14:00:11 +02:00
|
|
|
ipv4ll_cleanup (NMDevice *self)
|
2008-07-09 14:05:49 +00:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
if (priv->ipv4ll) {
|
|
|
|
|
sd_ipv4ll_set_callback (priv->ipv4ll, NULL, NULL);
|
|
|
|
|
sd_ipv4ll_stop (priv->ipv4ll);
|
|
|
|
|
priv->ipv4ll = sd_ipv4ll_unref (priv->ipv4ll);
|
2008-07-27 19:42:54 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-07 17:40:34 +02:00
|
|
|
nm_clear_g_source (&priv->ipv4ll_timeout);
|
2008-07-09 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMIP4Config *
|
2015-04-08 14:00:11 +02:00
|
|
|
ipv4ll_get_ip4_config (NMDevice *self, guint32 lla)
|
2008-07-09 14:05:49 +00:00
|
|
|
{
|
|
|
|
|
NMIP4Config *config = NULL;
|
2013-06-29 13:33:36 +02:00
|
|
|
NMPlatformIP4Address address;
|
2013-07-31 23:07:32 +02:00
|
|
|
NMPlatformIP4Route route;
|
2008-07-09 14:05:49 +00:00
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
config = _ip4_config_new (self);
|
2011-10-09 22:50:04 -05:00
|
|
|
g_assert (config);
|
2008-07-11 10:28:53 +00:00
|
|
|
|
2013-06-29 13:33:36 +02:00
|
|
|
memset (&address, 0, sizeof (address));
|
2015-10-21 23:17:11 +02:00
|
|
|
nm_platform_ip4_address_set_addr (&address, lla, 16);
|
2016-04-11 13:09:52 +02:00
|
|
|
address.addr_source = NM_IP_CONFIG_SOURCE_IP4LL;
|
2013-06-29 13:33:36 +02:00
|
|
|
nm_ip4_config_add_address (config, &address);
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2010-06-09 15:01:23 +02:00
|
|
|
/* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */
|
2013-07-31 23:07:32 +02:00
|
|
|
memset (&route, 0, sizeof (route));
|
|
|
|
|
route.network = htonl (0xE0000000L);
|
|
|
|
|
route.plen = 4;
|
2016-04-11 13:09:52 +02:00
|
|
|
route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL;
|
2017-09-28 14:40:12 +02:00
|
|
|
route.table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (self, AF_INET, TRUE));
|
2017-09-28 17:14:24 +02:00
|
|
|
route.metric = nm_device_get_route_metric (self, AF_INET);
|
2017-09-05 10:36:50 +02:00
|
|
|
nm_ip4_config_add_route (config, &route, NULL);
|
2010-06-09 15:01:23 +02:00
|
|
|
|
2013-07-31 23:07:32 +02:00
|
|
|
return config;
|
2008-07-09 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
|
|
|
|
|
#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
|
|
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
static void
|
|
|
|
|
nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
|
2008-07-09 14:05:49 +00:00
|
|
|
{
|
2015-04-20 18:13:41 +02:00
|
|
|
NMDevice *self = data;
|
2011-10-09 23:48:13 -05:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2008-07-09 14:05:49 +00:00
|
|
|
NMConnection *connection = NULL;
|
2014-02-12 23:54:26 +01:00
|
|
|
const char *method;
|
2015-04-20 18:13:41 +02:00
|
|
|
struct in_addr address;
|
|
|
|
|
NMIP4Config *config;
|
|
|
|
|
int r;
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
if (priv->act_request == NULL)
|
2008-07-09 14:05:49 +00:00
|
|
|
return;
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_act_request_get_applied_connection (priv->act_request);
|
2011-10-09 23:48:13 -05:00
|
|
|
g_assert (connection);
|
2008-07-09 14:05:49 +00:00
|
|
|
|
|
|
|
|
/* Ignore if the connection isn't an AutoIP connection */
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0)
|
2008-07-09 14:05:49 +00:00
|
|
|
return;
|
|
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
switch (event) {
|
2015-10-07 10:07:17 +02:00
|
|
|
case SD_IPV4LL_EVENT_BIND:
|
2015-04-20 18:13:41 +02:00
|
|
|
r = sd_ipv4ll_get_address (ll, &address);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r);
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED);
|
2008-07-09 14:05:49 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr);
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
|
2008-07-09 14:05:49 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
config = ipv4ll_get_ip4_config (self, address.s_addr);
|
2011-10-09 22:50:04 -05:00
|
|
|
if (config == NULL) {
|
2015-04-08 14:00:11 +02:00
|
|
|
_LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config");
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
|
2011-10-09 22:50:04 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
if (priv->ip4_state == IP_CONF) {
|
2015-10-07 17:40:34 +02:00
|
|
|
nm_clear_g_source (&priv->ipv4ll_timeout);
|
2011-10-09 22:50:04 -05:00
|
|
|
nm_device_activate_schedule_ip4_config_result (self, config);
|
2011-10-09 23:48:13 -05:00
|
|
|
} else if (priv->ip4_state == IP_DONE) {
|
2017-09-28 14:22:07 +02:00
|
|
|
g_clear_object (&priv->dev_ip4_config);
|
|
|
|
|
priv->dev_ip4_config = g_object_ref (config);
|
|
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change.");
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
|
2013-08-01 10:34:46 -05:00
|
|
|
}
|
2011-10-09 23:48:13 -05:00
|
|
|
} else
|
|
|
|
|
g_assert_not_reached ();
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
g_object_unref (config);
|
2015-04-20 18:13:41 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
_LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event);
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
|
2008-07-09 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2015-04-08 14:00:11 +02:00
|
|
|
ipv4ll_timeout_cb (gpointer user_data)
|
2008-07-09 14:05:49 +00:00
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-04-08 14:00:11 +02:00
|
|
|
if (priv->ipv4ll_timeout) {
|
2015-04-20 18:13:41 +02:00
|
|
|
_LOGI (LOGD_AUTOIP4, "IPv4LL configuration timed out.");
|
2015-04-08 14:00:11 +02:00
|
|
|
priv->ipv4ll_timeout = 0;
|
|
|
|
|
ipv4ll_cleanup (self);
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
if (priv->ip4_state == IP_CONF)
|
|
|
|
|
nm_device_activate_schedule_ip4_config_timeout (self);
|
|
|
|
|
}
|
2008-07-09 14:05:49 +00:00
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-09 22:50:04 -05:00
|
|
|
static NMActStageReturn
|
2017-02-22 17:04:00 +01:00
|
|
|
ipv4ll_start (NMDevice *self)
|
2008-07-09 14:05:49 +00:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-04-20 18:13:41 +02:00
|
|
|
const struct ether_addr *addr;
|
|
|
|
|
int ifindex, r;
|
|
|
|
|
size_t addr_len;
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2015-04-08 14:00:11 +02:00
|
|
|
ipv4ll_cleanup (self);
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
r = sd_ipv4ll_new (&priv->ipv4ll);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r);
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-20 18:13:41 +02:00
|
|
|
r = sd_ipv4ll_attach_event (priv->ipv4ll, NULL, 0);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r);
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2015-04-20 18:13:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
2017-04-17 20:17:45 +02:00
|
|
|
addr = nm_platform_link_get_address (nm_device_get_platform (self), ifindex, &addr_len);
|
2015-04-20 18:13:41 +02:00
|
|
|
if (!addr || addr_len != ETH_ALEN) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address");
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2015-04-20 18:13:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = sd_ipv4ll_set_mac (priv->ipv4ll, addr);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r);
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2015-04-20 18:13:41 +02:00
|
|
|
}
|
|
|
|
|
|
2016-05-31 11:10:46 +02:00
|
|
|
r = sd_ipv4ll_set_ifindex (priv->ipv4ll, ifindex);
|
2015-04-20 18:13:41 +02:00
|
|
|
if (r < 0) {
|
2016-05-31 11:10:46 +02:00
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r);
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2015-04-20 18:13:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = sd_ipv4ll_set_callback (priv->ipv4ll, nm_device_handle_ipv4ll_event, self);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r);
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2015-04-20 18:13:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = sd_ipv4ll_start (priv->ipv4ll);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
_LOGE (LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r);
|
2017-02-22 17:04:00 +01:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
2015-04-20 18:13:41 +02:00
|
|
|
}
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2015-10-06 14:27:03 +02:00
|
|
|
_LOGI (LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started");
|
2008-07-09 14:05:49 +00:00
|
|
|
|
|
|
|
|
/* Start a timeout to bound the address attempt */
|
2015-04-08 14:00:11 +02:00
|
|
|
priv->ipv4ll_timeout = g_timeout_add_seconds (20, ipv4ll_timeout_cb, self);
|
2011-10-09 22:50:04 -05:00
|
|
|
return NM_ACT_STAGE_RETURN_POSTPONE;
|
2008-07-09 14:05:49 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-08-29 00:03:47 +02:00
|
|
|
|
2014-11-21 13:13:48 +01:00
|
|
|
static void
|
2015-06-24 09:42:58 +00:00
|
|
|
ensure_con_ip4_config (NMDevice *self)
|
2014-11-21 13:13:48 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
|
|
|
|
|
if (priv->con_ip4_config)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2014-11-21 13:13:48 +01:00
|
|
|
if (!connection)
|
|
|
|
|
return;
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->con_ip4_config = _ip4_config_new (self);
|
2014-11-21 13:13:48 +01:00
|
|
|
nm_ip4_config_merge_setting (priv->con_ip4_config,
|
|
|
|
|
nm_connection_get_setting_ip4_config (connection),
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET));
|
2014-11-21 13:13:48 +01:00
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2014-11-21 13:13:48 +01:00
|
|
|
/* For assumed connections ignore all addresses and routes. */
|
|
|
|
|
nm_ip4_config_reset_addresses (priv->con_ip4_config);
|
|
|
|
|
nm_ip4_config_reset_routes (priv->con_ip4_config);
|
2015-06-24 09:42:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ensure_con_ip6_config (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
2014-11-21 13:13:48 +01:00
|
|
|
|
2015-06-24 09:42:58 +00:00
|
|
|
if (priv->con_ip6_config)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2015-06-24 09:42:58 +00:00
|
|
|
if (!connection)
|
|
|
|
|
return;
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->con_ip6_config = _ip6_config_new (self);
|
2015-06-24 09:42:58 +00:00
|
|
|
nm_ip6_config_merge_setting (priv->con_ip6_config,
|
|
|
|
|
nm_connection_get_setting_ip6_config (connection),
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET6, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET6));
|
2015-06-24 09:42:58 +00:00
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2015-06-24 09:42:58 +00:00
|
|
|
/* For assumed connections ignore all addresses and routes. */
|
2014-11-21 13:13:48 +01:00
|
|
|
nm_ip6_config_reset_addresses (priv->con_ip6_config);
|
|
|
|
|
nm_ip6_config_reset_routes (priv->con_ip6_config);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2011-10-07 11:50:37 -05:00
|
|
|
/* DHCPv4 stuff */
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
nm_clear_g_source (&priv->dhcp4.restart_id);
|
2017-03-07 14:34:17 +01:00
|
|
|
g_clear_pointer (&priv->dhcp4.pac_url, g_free);
|
2015-07-18 10:05:05 +02:00
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
if (priv->dhcp4.client) {
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Stop any ongoing DHCP transaction on this device */
|
2016-04-07 14:34:31 +02:00
|
|
|
nm_clear_g_signal_handler (priv->dhcp4.client, &priv->dhcp4.state_sigid);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE
|
|
|
|
|
|| cleanup_type == CLEANUP_TYPE_REMOVED)
|
2016-04-07 14:34:31 +02:00
|
|
|
nm_dhcp_client_stop (priv->dhcp4.client, release);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
g_clear_object (&priv->dhcp4.client);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
core: fix dhcp4_cleanup() to clear dhcp4_client first (avoids assert accessing NM_DEVICE_DHCP4_CONFIG)
dhcp4_cleanup() should first clear @dhcp4_client variables before
clearing @dhcp4_config. Otherwise the following assert fails [1] and
the DBUS property NM_DEVICE_DHCP4_CONFIG is set to %NULL.
Analog to dhcp6_cleanup(), dhcp6_client, and NM_DEVICE_DHCP6_CONFIG.
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c148c "unrecognized-specs-changed", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fff4710ed60) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x3370cbc89a "%s: assertion '%s' failed") at gmessages.c:1025
#2 0x0000003370c50679 in g_return_if_fail_warning (log_domain=log_domain@entry=0x4c144c "NetworkManager", pretty_function=pretty_function@entry=0x4c6140 <__PRETTY_FUNCTION__.15969> "nm_dhcp4_config_get_dbus_path",
expression=expression@entry=0x4c60d9 "NM_IS_DHCP4_CONFIG (self)") at gmessages.c:1034
#3 0x000000000046b1d4 in nm_dhcp4_config_get_dbus_path (self=0x0) at nm-dhcp4-config.c:115
#4 0x0000000000434791 in get_property (object=0x9d2320, prop_id=13, value=0x9618a0, pspec=0x9bbc20) at devices/nm-device.c:7539
#5 0x0000003371c18e73 in object_get_property (value=0x9618a0, pspec=<optimized out>, object=0x9d2320) at gobject.c:1303
#6 g_object_get_property (object=0x9d2320, property_name=<optimized out>, value=0x9618a0) at gobject.c:2402
#7 0x000000000048482c in idle_id_reset (data=<optimized out>) at nm-properties-changed-signal.c:123
#8 0x0000003371c13055 in g_cclosure_marshal_VOID__PARAM (closure=0x9618a0, return_value=0xffffffff, n_param_values=0, param_values=0x7fff4710f130, invocation_hint=0x0, marshal_data=0x4b5201) at gmarshal.c:1037
#9 0x0000003371c10298 in g_closure_invoke (closure=0x2, closure@entry=0x919d00, return_value=return_value@entry=0x0, n_param_values=1192292656, param_values=0x9d2320, param_values@entry=0x7fff4710f130,
invocation_hint=invocation_hint@entry=0x7fff4710f0d0) at gclosure.c:777
#10 0x0000003371c21b87 in signal_emit_unlocked_R (node=node@entry=0x919d90, detail=detail@entry=667, instance=instance@entry=0x9d2320, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff4710f130) at gsignal.c:3516
#11 0x0000003371c2a0f2 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fff4710f2c0) at gsignal.c:3330
#12 0x0000003371c2a3af in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3386
#13 0x0000003371c14945 in g_object_dispatch_properties_changed (object=0x9d2320, n_pspecs=4294967295, pspecs=0x0) at gobject.c:1047
#14 0x0000003371c17019 in g_object_notify_by_spec_internal (pspec=<optimized out>, object=0x9d2320) at gobject.c:1141
#15 g_object_notify (object=0x9d2320, property_name=property_name@entry=0x4c400f "dhcp4-config") at gobject.c:1183
#16 0x0000000000434332 in dhcp4_cleanup (self=self@entry=0x9d2320, stop=stop@entry=1, release=release@entry=0) at devices/nm-device.c:2581
#17 0x0000000000434cab in _cleanup_generic_pre (self=self@entry=0x9d2320, deconfigure=deconfigure@entry=1) at devices/nm-device.c:6448
#18 0x0000000000436db1 in nm_device_cleanup (self=self@entry=0x9d2320, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6524
#19 0x0000000000437358 in _set_state_full (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6641
#20 0x000000000043797c in nm_device_state_changed (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#21 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0x9d2320, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#22 0x000000000043a193 in nm_device_set_unmanaged_quitting (device=0x9d2320) at devices/nm-device.c:5998
#23 0x00000000004799f9 in remove_device (manager=0x9b2150, device=0x9d2320, quitting=1) at nm-manager.c:775
#24 0x000000000047bf47 in dispose (object=0x9b2150) at nm-manager.c:4935
#25 0x0000003371c14ee8 in g_object_unref (_object=0x9b2150) at gobject.c:3160
#26 0x0000000000429f43 in main (argc=1, argv=0x7fff4710f9a8) at main.c:681
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 10:32:32 +02:00
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
if (priv->dhcp4.config) {
|
|
|
|
|
nm_exported_object_clear_and_unexport (&priv->dhcp4.config);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DHCP4_CONFIG);
|
core: fix dhcp4_cleanup() to clear dhcp4_client first (avoids assert accessing NM_DEVICE_DHCP4_CONFIG)
dhcp4_cleanup() should first clear @dhcp4_client variables before
clearing @dhcp4_config. Otherwise the following assert fails [1] and
the DBUS property NM_DEVICE_DHCP4_CONFIG is set to %NULL.
Analog to dhcp6_cleanup(), dhcp6_client, and NM_DEVICE_DHCP6_CONFIG.
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c148c "unrecognized-specs-changed", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fff4710ed60) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x3370cbc89a "%s: assertion '%s' failed") at gmessages.c:1025
#2 0x0000003370c50679 in g_return_if_fail_warning (log_domain=log_domain@entry=0x4c144c "NetworkManager", pretty_function=pretty_function@entry=0x4c6140 <__PRETTY_FUNCTION__.15969> "nm_dhcp4_config_get_dbus_path",
expression=expression@entry=0x4c60d9 "NM_IS_DHCP4_CONFIG (self)") at gmessages.c:1034
#3 0x000000000046b1d4 in nm_dhcp4_config_get_dbus_path (self=0x0) at nm-dhcp4-config.c:115
#4 0x0000000000434791 in get_property (object=0x9d2320, prop_id=13, value=0x9618a0, pspec=0x9bbc20) at devices/nm-device.c:7539
#5 0x0000003371c18e73 in object_get_property (value=0x9618a0, pspec=<optimized out>, object=0x9d2320) at gobject.c:1303
#6 g_object_get_property (object=0x9d2320, property_name=<optimized out>, value=0x9618a0) at gobject.c:2402
#7 0x000000000048482c in idle_id_reset (data=<optimized out>) at nm-properties-changed-signal.c:123
#8 0x0000003371c13055 in g_cclosure_marshal_VOID__PARAM (closure=0x9618a0, return_value=0xffffffff, n_param_values=0, param_values=0x7fff4710f130, invocation_hint=0x0, marshal_data=0x4b5201) at gmarshal.c:1037
#9 0x0000003371c10298 in g_closure_invoke (closure=0x2, closure@entry=0x919d00, return_value=return_value@entry=0x0, n_param_values=1192292656, param_values=0x9d2320, param_values@entry=0x7fff4710f130,
invocation_hint=invocation_hint@entry=0x7fff4710f0d0) at gclosure.c:777
#10 0x0000003371c21b87 in signal_emit_unlocked_R (node=node@entry=0x919d90, detail=detail@entry=667, instance=instance@entry=0x9d2320, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff4710f130) at gsignal.c:3516
#11 0x0000003371c2a0f2 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fff4710f2c0) at gsignal.c:3330
#12 0x0000003371c2a3af in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3386
#13 0x0000003371c14945 in g_object_dispatch_properties_changed (object=0x9d2320, n_pspecs=4294967295, pspecs=0x0) at gobject.c:1047
#14 0x0000003371c17019 in g_object_notify_by_spec_internal (pspec=<optimized out>, object=0x9d2320) at gobject.c:1141
#15 g_object_notify (object=0x9d2320, property_name=property_name@entry=0x4c400f "dhcp4-config") at gobject.c:1183
#16 0x0000000000434332 in dhcp4_cleanup (self=self@entry=0x9d2320, stop=stop@entry=1, release=release@entry=0) at devices/nm-device.c:2581
#17 0x0000000000434cab in _cleanup_generic_pre (self=self@entry=0x9d2320, deconfigure=deconfigure@entry=1) at devices/nm-device.c:6448
#18 0x0000000000436db1 in nm_device_cleanup (self=self@entry=0x9d2320, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6524
#19 0x0000000000437358 in _set_state_full (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6641
#20 0x000000000043797c in nm_device_state_changed (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#21 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0x9d2320, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#22 0x000000000043a193 in nm_device_set_unmanaged_quitting (device=0x9d2320) at devices/nm-device.c:5998
#23 0x00000000004799f9 in remove_device (manager=0x9b2150, device=0x9d2320, quitting=1) at nm-manager.c:775
#24 0x000000000047bf47 in dispose (object=0x9b2150) at nm-manager.c:4935
#25 0x0000003371c14ee8 in g_object_unref (_object=0x9b2150) at gobject.c:3160
#26 0x0000000000429f43 in main (argc=1, argv=0x7fff4710f9a8) at main.c:681
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 10:32:32 +02:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
2013-08-01 10:34:46 -05:00
|
|
|
static gboolean
|
|
|
|
|
ip4_config_merge_and_apply (NMDevice *self,
|
2017-02-22 20:20:22 +01:00
|
|
|
gboolean commit)
|
2010-01-12 22:09:28 -08:00
|
|
|
{
|
2013-08-01 10:34:46 -05:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2010-01-12 22:09:28 -08:00
|
|
|
NMConnection *connection;
|
2013-08-01 10:34:46 -05:00
|
|
|
gboolean success;
|
|
|
|
|
NMIP4Config *composite;
|
2015-08-05 10:15:20 +02:00
|
|
|
gboolean ignore_auto_routes = FALSE;
|
|
|
|
|
gboolean ignore_auto_dns = FALSE;
|
2017-10-04 15:21:21 +02:00
|
|
|
gboolean ignore_default_routes = FALSE;
|
2017-05-26 22:46:57 +02:00
|
|
|
GSList *iter;
|
2017-09-12 13:45:53 +02:00
|
|
|
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
2010-01-12 22:09:28 -08:00
|
|
|
|
2015-08-05 10:15:20 +02:00
|
|
|
/* Apply ignore-auto-routes and ignore-auto-dns settings */
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2015-08-05 10:15:20 +02:00
|
|
|
if (connection) {
|
|
|
|
|
NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
|
|
|
|
|
if (s_ip4) {
|
|
|
|
|
ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip4);
|
|
|
|
|
ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip4);
|
2017-10-24 20:46:24 +02:00
|
|
|
|
|
|
|
|
/* if the connection has an explicit gateway, we also ignore
|
|
|
|
|
* the default routes from other sources. */
|
|
|
|
|
ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip4)
|
|
|
|
|
|| nm_setting_ip_config_get_gateway (s_ip4);
|
2015-08-05 10:15:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
composite = _ip4_config_new (self);
|
2016-05-09 16:30:41 +02:00
|
|
|
init_ip4_config_dns_priority (self, composite);
|
2014-11-21 13:13:48 +01:00
|
|
|
|
2017-05-12 12:00:20 +02:00
|
|
|
if (commit) {
|
2017-09-22 12:11:32 +02:00
|
|
|
if (priv->queued_ip4_config_id)
|
|
|
|
|
update_ext_ip_config (self, AF_INET, FALSE, FALSE);
|
2015-06-24 09:42:58 +00:00
|
|
|
ensure_con_ip4_config (self);
|
2017-05-12 12:00:20 +02:00
|
|
|
}
|
2014-11-21 13:13:48 +01:00
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
if (commit)
|
|
|
|
|
priv->default_route_metric_penalty_ip4_has = default_route_metric_penalty_detect (self);
|
|
|
|
|
|
2015-08-05 10:15:20 +02:00
|
|
|
if (priv->dev_ip4_config) {
|
|
|
|
|
nm_ip4_config_merge (composite, priv->dev_ip4_config,
|
|
|
|
|
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
|
2017-10-04 15:21:21 +02:00
|
|
|
| (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
|
|
|
|
|
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
2015-08-05 10:15:20 +02:00
|
|
|
}
|
2015-08-19 23:07:13 +02:00
|
|
|
|
2017-05-26 22:46:57 +02:00
|
|
|
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip4_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0);
|
2015-08-19 23:07:13 +02:00
|
|
|
|
2013-08-01 15:44:53 -05:00
|
|
|
if (priv->ext_ip4_config)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
|
2010-01-14 00:45:10 -08:00
|
|
|
|
2014-07-15 17:16:56 -05:00
|
|
|
/* Merge WWAN config *last* to ensure modem-given settings overwrite
|
|
|
|
|
* any external stuff set by pppd or other scripts.
|
|
|
|
|
*/
|
2015-08-05 10:15:20 +02:00
|
|
|
if (priv->wwan_ip4_config) {
|
|
|
|
|
nm_ip4_config_merge (composite, priv->wwan_ip4_config,
|
|
|
|
|
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
|
2017-10-04 15:21:21 +02:00
|
|
|
| (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
|
|
|
|
|
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
2015-06-25 11:24:32 +02:00
|
|
|
}
|
|
|
|
|
|
2015-05-27 11:52:39 +02:00
|
|
|
/* Merge user overrides into the composite config. For assumed connections,
|
2014-11-21 13:13:48 +01:00
|
|
|
* con_ip4_config is empty. */
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->con_ip4_config) {
|
|
|
|
|
nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
2017-09-18 09:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-12 13:45:53 +02:00
|
|
|
if (commit) {
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip4_config_add_dependent_routes (composite,
|
|
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
|
|
|
|
nm_device_get_route_metric (self, AF_INET),
|
|
|
|
|
&ip4_dev_route_blacklist);
|
2017-09-12 13:45:53 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-01 15:44:53 -05:00
|
|
|
if (commit) {
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
|
|
|
|
|
}
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2017-09-12 13:45:53 +02:00
|
|
|
success = nm_device_set_ip4_config (self, composite, commit, ip4_dev_route_blacklist);
|
2013-08-01 10:34:46 -05:00
|
|
|
g_object_unref (composite);
|
2015-07-22 11:56:05 +02:00
|
|
|
|
|
|
|
|
if (commit)
|
|
|
|
|
priv->v4_commit_first_time = FALSE;
|
2013-08-01 10:34:46 -05:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
static gboolean
|
2013-08-01 10:34:46 -05:00
|
|
|
dhcp4_lease_change (NMDevice *self, NMIP4Config *config)
|
|
|
|
|
{
|
2017-09-28 14:22:07 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
g_return_val_if_fail (config, FALSE);
|
2013-08-01 10:34:46 -05:00
|
|
|
|
2017-09-28 14:22:07 +02:00
|
|
|
g_clear_object (&priv->dev_ip4_config);
|
|
|
|
|
priv->dev_ip4_config = g_object_ref (config);
|
|
|
|
|
|
|
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change.");
|
2016-04-07 13:48:34 +02:00
|
|
|
return FALSE;
|
2013-08-01 10:34:46 -05:00
|
|
|
}
|
2016-04-07 13:48:34 +02:00
|
|
|
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE,
|
|
|
|
|
self,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL, NULL, NULL);
|
2016-04-07 13:48:34 +02:00
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
|
2016-05-10 16:34:50 +02:00
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
return TRUE;
|
2010-01-12 22:09:28 -08:00
|
|
|
}
|
|
|
|
|
|
2015-07-18 10:05:05 +02:00
|
|
|
static gboolean
|
|
|
|
|
dhcp4_restart_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-04-07 14:34:31 +02:00
|
|
|
priv->dhcp4.restart_id = 0;
|
2015-07-18 10:05:05 +02:00
|
|
|
|
2017-09-11 10:43:48 +02:00
|
|
|
if (dhcp4_start (self) == NM_ACT_STAGE_RETURN_FAILURE)
|
2015-12-14 15:15:23 +01:00
|
|
|
dhcp_schedule_restart (self, AF_INET, NULL);
|
2015-07-18 10:05:05 +02:00
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-07 12:23:35 -05:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp4_fail (NMDevice *self, gboolean timeout)
|
2011-10-07 12:23:35 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2011-10-07 12:23:35 -05:00
|
|
|
|
2016-04-07 15:00:47 +02:00
|
|
|
_LOGD (LOGD_DHCP4, "DHCPv4 failed: timeout %d, num tries left %u",
|
|
|
|
|
timeout, priv->dhcp4.num_tries_left);
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE);
|
2015-07-18 10:05:05 +02:00
|
|
|
|
|
|
|
|
/* Don't fail if there are static addresses configured on
|
|
|
|
|
* the device, instead retry after some time.
|
|
|
|
|
*/
|
|
|
|
|
if ( priv->ip4_state == IP_DONE
|
|
|
|
|
&& priv->con_ip4_config
|
|
|
|
|
&& nm_ip4_config_get_num_addresses (priv->con_ip4_config) > 0) {
|
2015-12-14 15:15:23 +01:00
|
|
|
dhcp_schedule_restart (self, AF_INET, "device has IP addresses");
|
2015-07-18 10:05:05 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 15:00:47 +02:00
|
|
|
if ( priv->dhcp4.num_tries_left == DHCP_NUM_TRIES_MAX
|
2017-05-04 10:05:25 +02:00
|
|
|
&& (timeout || (priv->ip4_state == IP_CONF))
|
|
|
|
|
&& !priv->dhcp4.was_active)
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_activate_schedule_ip4_config_timeout (self);
|
2017-05-04 10:05:25 +02:00
|
|
|
else if (priv->ip4_state == IP_DONE || priv->dhcp4.was_active) {
|
2016-04-07 15:00:47 +02:00
|
|
|
/* Don't fail immediately when the lease expires but try to
|
|
|
|
|
* restart DHCP for a predefined number of times.
|
|
|
|
|
*/
|
|
|
|
|
if (priv->dhcp4.num_tries_left) {
|
|
|
|
|
priv->dhcp4.num_tries_left--;
|
2015-12-14 15:15:23 +01:00
|
|
|
dhcp_schedule_restart (self, AF_INET, "lease expired");
|
2016-04-07 15:00:47 +02:00
|
|
|
} else
|
|
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
|
|
|
|
|
} else
|
2014-09-23 15:38:33 -05:00
|
|
|
g_warn_if_reached ();
|
2011-10-07 12:23:35 -05:00
|
|
|
}
|
|
|
|
|
|
2015-12-23 17:59:08 +01:00
|
|
|
static void
|
|
|
|
|
dhcp4_dad_cb (NMDevice *self, NMIP4Config **configs, gboolean success)
|
|
|
|
|
{
|
|
|
|
|
if (success)
|
|
|
|
|
nm_device_activate_schedule_ip4_config_result (self, configs[1]);
|
|
|
|
|
else {
|
2017-11-02 14:08:55 +01:00
|
|
|
nm_device_ip_method_failed (self, AF_INET,
|
2017-11-02 14:22:10 +01:00
|
|
|
NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
|
2015-12-23 17:59:08 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-12 22:09:28 -08:00
|
|
|
static void
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
dhcp4_state_changed (NMDhcpClient *client,
|
2014-05-15 12:49:11 -05:00
|
|
|
NMDhcpState state,
|
2014-07-01 09:48:58 -05:00
|
|
|
NMIP4Config *ip4_config,
|
2014-07-01 12:30:29 -05:00
|
|
|
GHashTable *options,
|
2015-08-04 11:30:03 +02:00
|
|
|
const char *event_id,
|
2011-10-07 12:05:51 -05:00
|
|
|
gpointer user_data)
|
2010-01-12 22:09:28 -08:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-12-23 17:59:08 +01:00
|
|
|
NMIP4Config *manual, **configs;
|
|
|
|
|
NMConnection *connection;
|
2010-01-12 22:09:28 -08:00
|
|
|
|
2017-09-11 11:30:48 +02:00
|
|
|
g_return_if_fail (nm_dhcp_client_get_addr_family (client) == AF_INET);
|
2014-07-01 09:48:58 -05:00
|
|
|
g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config));
|
2010-01-12 22:09:28 -08:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DHCP4, "new DHCPv4 client state %d", state);
|
2011-10-07 12:05:51 -05:00
|
|
|
|
2010-01-12 22:09:28 -08:00
|
|
|
switch (state) {
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_BOUND:
|
2014-07-01 09:48:58 -05:00
|
|
|
if (!ip4_config) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event.");
|
2016-04-07 13:48:34 +02:00
|
|
|
dhcp4_fail (self, FALSE);
|
2013-08-01 10:34:46 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-07 14:34:17 +01:00
|
|
|
g_free (priv->dhcp4.pac_url);
|
|
|
|
|
priv->dhcp4.pac_url = g_strdup (g_hash_table_lookup (options, "wpad"));
|
|
|
|
|
nm_device_set_proxy_config (self, priv->dhcp4.pac_url);
|
2016-08-16 05:55:58 +05:30
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
nm_dhcp4_config_set_options (priv->dhcp4.config, options);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DHCP4_CONFIG);
|
2016-04-07 15:00:47 +02:00
|
|
|
priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX;
|
2014-01-06 16:01:22 -06:00
|
|
|
|
2015-12-23 17:59:08 +01:00
|
|
|
if (priv->ip4_state == IP_CONF) {
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
g_assert (connection);
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
manual = _ip4_config_new (self);
|
2015-12-23 17:59:08 +01:00
|
|
|
nm_ip4_config_merge_setting (manual,
|
|
|
|
|
nm_connection_get_setting_ip4_config (connection),
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET));
|
2015-12-23 17:59:08 +01:00
|
|
|
|
|
|
|
|
configs = g_new0 (NMIP4Config *, 3);
|
|
|
|
|
configs[0] = manual;
|
|
|
|
|
configs[1] = g_object_ref (ip4_config);
|
|
|
|
|
|
|
|
|
|
ipv4_dad_start (self, configs, dhcp4_dad_cb);
|
|
|
|
|
} else if (priv->ip4_state == IP_DONE) {
|
2016-04-07 13:48:34 +02:00
|
|
|
if (dhcp4_lease_change (self, ip4_config))
|
|
|
|
|
nm_device_update_metered (self);
|
|
|
|
|
else
|
|
|
|
|
dhcp4_fail (self, FALSE);
|
2015-04-30 14:18:14 +02:00
|
|
|
}
|
2010-01-12 22:09:28 -08:00
|
|
|
break;
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_TIMEOUT:
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp4_fail (self, TRUE);
|
2010-01-12 22:09:28 -08:00
|
|
|
break;
|
core: better handle DHCP expiry/nak during initial lease acquisition (bgo #739482)
When dhclient trieds to request a previous lease and the server NAKs that
lease, dhclient emits the EXPIRE state. dhcpcd has also been known to emit
the 'nak' state for the same reason.
(systemd's DHCP client code does not push a NAK up to NetworkManager, but
jumps to the REBOOT state instead, so it is unaffected by this issue.)
NetworkManager saw the expire during IP configuration and treated that as
full activation failure. The connection would be restarted, the same lease
requested, and the same NAK delivered, over and over. Before a lease is
acquired, there is (by definition) no lease to expire, so these events
should be ignored.
We do, however, still want to handle abnormal failures, which is why
this patch splits the EXPIRE case from the FAIL case and handles them
separately.
https://bugzilla.gnome.org/show_bug.cgi?id=739482
2014-12-11 15:36:27 -06:00
|
|
|
case NM_DHCP_STATE_EXPIRE:
|
|
|
|
|
/* Ignore expiry before we even have a lease (NAK, old lease, etc) */
|
|
|
|
|
if (priv->ip4_state == IP_CONF)
|
|
|
|
|
break;
|
2017-02-06 14:42:47 +01:00
|
|
|
/* fall through */
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_DONE:
|
|
|
|
|
case NM_DHCP_STATE_FAIL:
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp4_fail (self, FALSE);
|
2010-01-12 22:09:28 -08:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-12 10:56:16 +02:00
|
|
|
static int
|
2017-09-11 10:43:48 +02:00
|
|
|
get_dhcp_timeout (NMDevice *self, int addr_family)
|
2015-10-12 10:56:16 +02:00
|
|
|
{
|
2017-09-11 10:43:48 +02:00
|
|
|
NMDeviceClass *klass;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingIPConfig *s_ip;
|
|
|
|
|
guint32 timeout;
|
2015-10-12 10:56:16 +02:00
|
|
|
|
2017-09-11 10:43:48 +02:00
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_assert_addr_family (addr_family);
|
2015-10-12 10:56:16 +02:00
|
|
|
|
2017-09-11 10:43:48 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
|
|
|
|
|
if (addr_family == AF_INET)
|
|
|
|
|
s_ip = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
else
|
|
|
|
|
s_ip = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
|
|
|
|
|
timeout = nm_setting_ip_config_get_dhcp_timeout (s_ip);
|
2015-10-12 10:56:16 +02:00
|
|
|
if (timeout)
|
|
|
|
|
return timeout;
|
|
|
|
|
|
2017-09-11 10:43:48 +02:00
|
|
|
{
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
addr_family == AF_INET
|
|
|
|
|
? "ipv4.dhcp-timeout"
|
|
|
|
|
: "ipv6.dhcp-timeout",
|
|
|
|
|
self);
|
|
|
|
|
timeout = _nm_utils_ascii_str_to_int64 (value, 10,
|
|
|
|
|
0, G_MAXINT32, 0);
|
|
|
|
|
if (timeout)
|
|
|
|
|
return timeout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
klass = NM_DEVICE_GET_CLASS (self);
|
|
|
|
|
if (klass->get_dhcp_timeout)
|
|
|
|
|
timeout = klass->get_dhcp_timeout (self, addr_family);
|
|
|
|
|
|
|
|
|
|
return timeout ?: NM_DHCP_TIMEOUT_DEFAULT;
|
2015-10-12 10:56:16 +02:00
|
|
|
}
|
|
|
|
|
|
2011-01-05 14:07:32 -06:00
|
|
|
static NMActStageReturn
|
2017-09-11 10:43:48 +02:00
|
|
|
dhcp4_start (NMDevice *self)
|
2011-01-05 14:07:32 -06:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4;
|
2014-04-10 18:02:52 -05:00
|
|
|
const guint8 *hw_addr;
|
|
|
|
|
size_t hw_addr_len = 0;
|
2012-06-13 13:28:55 -05:00
|
|
|
GByteArray *tmp = NULL;
|
2017-09-11 10:43:48 +02:00
|
|
|
NMConnection *connection;
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
g_return_val_if_fail (connection, FALSE);
|
2011-01-05 14:07:32 -06:00
|
|
|
|
2011-12-05 12:27:47 +01:00
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
2011-01-05 14:07:32 -06:00
|
|
|
|
|
|
|
|
/* Clear old exported DHCP options */
|
2016-04-07 14:34:31 +02:00
|
|
|
nm_exported_object_clear_and_unexport (&priv->dhcp4.config);
|
|
|
|
|
priv->dhcp4.config = nm_dhcp4_config_new ();
|
2011-01-05 14:07:32 -06:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len);
|
2014-04-10 18:02:52 -05:00
|
|
|
if (hw_addr_len) {
|
|
|
|
|
tmp = g_byte_array_sized_new (hw_addr_len);
|
|
|
|
|
g_byte_array_append (tmp, hw_addr, hw_addr_len);
|
2012-06-13 13:28:55 -05:00
|
|
|
}
|
|
|
|
|
|
2011-01-05 16:23:00 -06:00
|
|
|
/* Begin DHCP on the interface */
|
2016-04-07 14:34:31 +02:00
|
|
|
g_warn_if_fail (priv->dhcp4.client == NULL);
|
|
|
|
|
priv->dhcp4.client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (),
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
nm_netns_get_multi_idx (nm_device_get_netns (self)),
|
2011-01-05 14:07:32 -06:00
|
|
|
nm_device_get_ip_iface (self),
|
2014-04-03 13:13:17 -05:00
|
|
|
nm_device_get_ip_ifindex (self),
|
2012-06-13 13:28:55 -05:00
|
|
|
tmp,
|
2011-03-08 13:41:28 +01:00
|
|
|
nm_connection_get_uuid (connection),
|
2017-09-28 14:40:12 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET),
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_get_dhcp_send_hostname (s_ip4),
|
|
|
|
|
nm_setting_ip_config_get_dhcp_hostname (s_ip4),
|
2015-10-13 15:13:26 +02:00
|
|
|
nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)),
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)),
|
2017-09-11 10:43:48 +02:00
|
|
|
get_dhcp_timeout (self, AF_INET),
|
2014-11-03 22:35:22 -06:00
|
|
|
priv->dhcp_anycast_address,
|
|
|
|
|
NULL);
|
2012-06-13 13:28:55 -05:00
|
|
|
|
|
|
|
|
if (tmp)
|
|
|
|
|
g_byte_array_free (tmp, TRUE);
|
|
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
if (!priv->dhcp4.client)
|
2011-01-05 14:07:32 -06:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
|
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
priv->dhcp4.state_sigid = g_signal_connect (priv->dhcp4.client,
|
2014-03-11 14:02:24 +01:00
|
|
|
NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED,
|
2011-10-07 12:05:51 -05:00
|
|
|
G_CALLBACK (dhcp4_state_changed),
|
2011-01-05 14:07:32 -06:00
|
|
|
self);
|
|
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP4, TRUE);
|
2014-04-14 17:57:56 +02:00
|
|
|
|
2017-05-08 08:44:51 +02:00
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self))
|
2017-05-04 10:05:25 +02:00
|
|
|
priv->dhcp4.was_active = TRUE;
|
|
|
|
|
|
2011-01-05 14:07:32 -06:00
|
|
|
/* DHCP devices will be notified by the DHCP manager when stuff happens */
|
|
|
|
|
return NM_ACT_STAGE_RETURN_POSTPONE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-05 16:23:00 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_device_dhcp4_renew (NMDevice *self, gboolean release)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
g_return_val_if_fail (priv->dhcp4.client != NULL, FALSE);
|
2011-01-05 16:23:00 -06:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DHCP4, "DHCPv4 lease renewal requested");
|
2011-09-21 00:30:38 -05:00
|
|
|
|
2011-01-05 16:23:00 -06:00
|
|
|
/* Terminate old DHCP instance and release the old lease */
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, release);
|
2011-01-05 16:23:00 -06:00
|
|
|
|
|
|
|
|
/* Start DHCP again on the interface */
|
2017-09-11 10:43:48 +02:00
|
|
|
return dhcp4_start (self) != NM_ACT_STAGE_RETURN_FAILURE;
|
2011-01-05 16:23:00 -06:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2011-10-07 11:50:37 -05:00
|
|
|
|
|
|
|
|
static GHashTable *shared_ips = NULL;
|
|
|
|
|
|
|
|
|
|
static void
|
2017-05-28 11:28:23 +02:00
|
|
|
shared_ip_release (gpointer data)
|
2011-10-07 11:50:37 -05:00
|
|
|
{
|
|
|
|
|
g_hash_table_remove (shared_ips, data);
|
2017-05-28 11:28:23 +02:00
|
|
|
if (!g_hash_table_size (shared_ips))
|
|
|
|
|
g_clear_pointer (&shared_ips, g_hash_table_unref);
|
2011-10-07 11:50:37 -05:00
|
|
|
}
|
|
|
|
|
|
2017-05-28 11:28:23 +02:00
|
|
|
static NMIP4Config *
|
|
|
|
|
shared4_new_config (NMDevice *self, NMConnection *connection)
|
2011-10-07 11:50:37 -05:00
|
|
|
{
|
2017-05-28 11:28:23 +02:00
|
|
|
NMIP4Config *config = NULL;
|
|
|
|
|
gboolean is_generated = FALSE;
|
|
|
|
|
NMSettingIPConfig *s_ip4;
|
|
|
|
|
NMPlatformIP4Address address = {
|
|
|
|
|
.addr_source = NM_IP_CONFIG_SOURCE_SHARED,
|
|
|
|
|
};
|
2012-10-12 15:25:23 -05:00
|
|
|
|
2017-05-28 11:28:23 +02:00
|
|
|
g_return_val_if_fail (self, NULL);
|
|
|
|
|
g_return_val_if_fail (connection, NULL);
|
2011-10-07 11:50:37 -05:00
|
|
|
|
2017-05-28 11:28:23 +02:00
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
2014-10-19 17:30:10 -04:00
|
|
|
if (s_ip4 && nm_setting_ip_config_get_num_addresses (s_ip4)) {
|
2012-10-12 15:25:23 -05:00
|
|
|
/* Use the first user-supplied address */
|
2014-10-19 17:30:10 -04:00
|
|
|
NMIPAddress *user = nm_setting_ip_config_get_address (s_ip4, 0);
|
2015-10-21 23:17:11 +02:00
|
|
|
in_addr_t a;
|
2012-10-12 15:25:23 -05:00
|
|
|
|
2015-10-21 23:17:11 +02:00
|
|
|
nm_ip_address_get_address_binary (user, &a);
|
2017-05-28 11:28:23 +02:00
|
|
|
nm_platform_ip4_address_set_addr (&address, a, nm_ip_address_get_prefix (user));
|
2012-10-12 15:25:23 -05:00
|
|
|
} else {
|
|
|
|
|
/* Find an unused address in the 10.42.x.x range */
|
|
|
|
|
guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */
|
|
|
|
|
guint32 count = 0;
|
|
|
|
|
|
2017-05-28 11:28:23 +02:00
|
|
|
if (G_UNLIKELY (!shared_ips))
|
|
|
|
|
shared_ips = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
|
else {
|
|
|
|
|
while (g_hash_table_lookup (shared_ips, GUINT_TO_POINTER (start + count))) {
|
|
|
|
|
count += ntohl (0x100);
|
|
|
|
|
if (count > ntohl (0xFE00)) {
|
|
|
|
|
_LOGE (LOGD_SHARING, "ran out of shared IP addresses!");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2012-10-12 15:25:23 -05:00
|
|
|
}
|
2011-10-07 11:50:37 -05:00
|
|
|
}
|
2017-05-28 11:28:23 +02:00
|
|
|
nm_platform_ip4_address_set_addr (&address, start + count, 24);
|
|
|
|
|
g_hash_table_add (shared_ips, GUINT_TO_POINTER (address.address));
|
|
|
|
|
is_generated = TRUE;
|
2011-10-07 11:50:37 -05:00
|
|
|
}
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
config = _ip4_config_new (self);
|
2013-06-29 13:33:36 +02:00
|
|
|
nm_ip4_config_add_address (config, &address);
|
2017-05-28 11:28:23 +02:00
|
|
|
if (is_generated) {
|
|
|
|
|
/* Remove the address lock when the object gets disposed */
|
|
|
|
|
g_object_set_qdata_full (G_OBJECT (config), NM_CACHED_QUARK ("shared-ip"),
|
|
|
|
|
GUINT_TO_POINTER (address.address),
|
|
|
|
|
shared_ip_release);
|
|
|
|
|
}
|
2011-10-07 11:50:37 -05:00
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2011-10-07 11:50:37 -05:00
|
|
|
|
2014-10-13 17:29:53 -05:00
|
|
|
static gboolean
|
|
|
|
|
connection_ip4_method_requires_carrier (NMConnection *connection,
|
|
|
|
|
gboolean *out_ip4_enabled)
|
|
|
|
|
{
|
|
|
|
|
const char *method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
static const char *ip4_carrier_methods[] = {
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (out_ip4_enabled)
|
|
|
|
|
*out_ip4_enabled = !!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
|
2016-06-17 11:40:50 +02:00
|
|
|
return g_strv_contains (ip4_carrier_methods, method);
|
2014-10-13 17:29:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
connection_ip6_method_requires_carrier (NMConnection *connection,
|
|
|
|
|
gboolean *out_ip6_enabled)
|
|
|
|
|
{
|
|
|
|
|
const char *method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
static const char *ip6_carrier_methods[] = {
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_DHCP,
|
2016-11-03 12:15:32 +01:00
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_SHARED,
|
2014-10-13 17:29:53 -05:00
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (out_ip6_enabled)
|
|
|
|
|
*out_ip6_enabled = !!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
|
2016-06-17 11:40:50 +02:00
|
|
|
return g_strv_contains (ip6_carrier_methods, method);
|
2014-10-13 17:29:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
connection_requires_carrier (NMConnection *connection)
|
|
|
|
|
{
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
2017-10-26 19:56:52 +02:00
|
|
|
NMSettingConnection *s_con;
|
2014-10-13 17:29:53 -05:00
|
|
|
gboolean ip4_carrier_wanted, ip6_carrier_wanted;
|
|
|
|
|
gboolean ip4_used = FALSE, ip6_used = FALSE;
|
|
|
|
|
|
2017-10-26 19:56:52 +02:00
|
|
|
/* We can progress to IP_CONFIG now, so that we're enslaved.
|
|
|
|
|
* That may actually cause carrier to go up and thus continue acivation. */
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
if (nm_setting_connection_get_master (s_con))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2014-10-13 17:29:53 -05:00
|
|
|
ip4_carrier_wanted = connection_ip4_method_requires_carrier (connection, &ip4_used);
|
|
|
|
|
if (ip4_carrier_wanted) {
|
|
|
|
|
/* If IPv4 wants a carrier and cannot fail, the whole connection
|
|
|
|
|
* requires a carrier regardless of the IPv6 method.
|
|
|
|
|
*/
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
2014-10-19 17:30:10 -04:00
|
|
|
if (s_ip4 && !nm_setting_ip_config_get_may_fail (s_ip4))
|
2014-10-13 17:29:53 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ip6_carrier_wanted = connection_ip6_method_requires_carrier (connection, &ip6_used);
|
|
|
|
|
if (ip6_carrier_wanted) {
|
|
|
|
|
/* If IPv6 wants a carrier and cannot fail, the whole connection
|
|
|
|
|
* requires a carrier regardless of the IPv4 method.
|
|
|
|
|
*/
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
2014-10-19 17:30:10 -04:00
|
|
|
if (s_ip6 && !nm_setting_ip_config_get_may_fail (s_ip6))
|
2014-10-13 17:29:53 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-17 15:57:50 +02:00
|
|
|
/* If an IP version wants a carrier and the other IP version isn't
|
2014-10-13 17:29:53 -05:00
|
|
|
* used, the connection requires carrier since it will just fail without one.
|
|
|
|
|
*/
|
|
|
|
|
if (ip4_carrier_wanted && !ip6_used)
|
|
|
|
|
return TRUE;
|
|
|
|
|
if (ip6_carrier_wanted && !ip4_used)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
/* If both want a carrier, the whole connection wants a carrier */
|
|
|
|
|
return ip4_carrier_wanted && ip6_carrier_wanted;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-25 11:59:05 -06:00
|
|
|
static gboolean
|
2017-05-14 09:52:18 +02:00
|
|
|
have_any_ready_slaves (NMDevice *self)
|
2013-01-25 11:59:05 -06:00
|
|
|
{
|
2017-05-14 09:52:18 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
SlaveInfo *info;
|
|
|
|
|
CList *iter;
|
2013-01-25 11:59:05 -06:00
|
|
|
|
|
|
|
|
/* Any enslaved slave is "ready" in the generic case as it's
|
|
|
|
|
* at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2
|
|
|
|
|
* properties set up.
|
|
|
|
|
*/
|
2017-05-14 09:52:18 +02:00
|
|
|
c_list_for_each (iter, &priv->slaves) {
|
|
|
|
|
info = c_list_entry (iter, SlaveInfo, lst_slave);
|
|
|
|
|
if (NM_DEVICE_GET_PRIVATE (info->slave)->is_enslaved)
|
2013-01-25 11:59:05 -06:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
ip4_requires_slaves (NMConnection *connection)
|
|
|
|
|
{
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
const char *method;
|
2013-01-25 11:59:05 -06:00
|
|
|
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
2013-09-26 17:34:23 -04:00
|
|
|
return strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0;
|
2013-01-25 11:59:05 -06:00
|
|
|
}
|
|
|
|
|
|
2006-01-03 17:47:38 +00:00
|
|
|
static NMActStageReturn
|
2012-09-27 12:12:15 -04:00
|
|
|
act_stage3_ip4_config_start (NMDevice *self,
|
|
|
|
|
NMIP4Config **out_config,
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason *out_failure_reason)
|
2007-06-06 13:33:51 +00:00
|
|
|
{
|
2010-04-23 12:56:33 -07:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2009-05-03 00:51:09 -04:00
|
|
|
NMConnection *connection;
|
2011-12-06 17:00:40 -06:00
|
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
const char *method;
|
2008-07-09 14:05:49 +00:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2017-02-22 17:04:00 +01:00
|
|
|
g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE);
|
2013-06-07 15:11:23 -05:00
|
|
|
|
2014-10-14 11:41:36 -05:00
|
|
|
if ( connection_ip4_method_requires_carrier (connection, NULL)
|
2017-06-01 23:08:30 +02:00
|
|
|
&& nm_device_is_master (self)
|
2014-02-25 18:00:34 -06:00
|
|
|
&& !priv->carrier) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_IP4 | LOGD_DEVICE,
|
|
|
|
|
"IPv4 config waiting until carrier is on");
|
2016-08-31 18:51:16 +02:00
|
|
|
return NM_ACT_STAGE_RETURN_IP_WAIT;
|
2013-05-07 10:23:44 -04:00
|
|
|
}
|
|
|
|
|
|
2017-06-01 23:08:30 +02:00
|
|
|
if (nm_device_is_master (self) && ip4_requires_slaves (connection)) {
|
2013-01-25 11:59:05 -06:00
|
|
|
/* If the master has no ready slaves, and depends on slaves for
|
|
|
|
|
* a successful IPv4 attempt, then postpone IPv4 addressing.
|
|
|
|
|
*/
|
2017-05-14 09:52:18 +02:00
|
|
|
if (!have_any_ready_slaves (self)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DEVICE | LOGD_IP4,
|
|
|
|
|
"IPv4 config waiting until slaves are ready");
|
2016-08-31 18:51:16 +02:00
|
|
|
return NM_ACT_STAGE_RETURN_IP_WAIT;
|
2013-01-25 11:59:05 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-14 11:41:36 -05:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
2016-04-07 15:00:47 +02:00
|
|
|
priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX;
|
2014-10-14 11:41:36 -05:00
|
|
|
|
2011-10-09 22:50:04 -05:00
|
|
|
/* Start IPv4 addressing based on the method requested */
|
2017-02-22 17:04:00 +01:00
|
|
|
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) {
|
2017-09-11 10:43:48 +02:00
|
|
|
ret = dhcp4_start (self);
|
2017-02-22 17:04:00 +01:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_FAILURE)
|
|
|
|
|
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
|
|
|
|
|
} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) {
|
|
|
|
|
ret = ipv4ll_start (self);
|
|
|
|
|
if (ret == NM_ACT_STAGE_RETURN_FAILURE)
|
|
|
|
|
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED);
|
|
|
|
|
} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
|
2015-12-23 14:15:05 +01:00
|
|
|
NMIP4Config **configs, *config;
|
|
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
config = _ip4_config_new (self);
|
2015-12-23 14:15:05 +01:00
|
|
|
nm_ip4_config_merge_setting (config,
|
|
|
|
|
nm_connection_get_setting_ip4_config (connection),
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET));
|
2015-12-23 14:15:05 +01:00
|
|
|
|
|
|
|
|
configs = g_new0 (NMIP4Config *, 2);
|
|
|
|
|
configs[0] = config;
|
|
|
|
|
ipv4_dad_start (self, configs, ipv4_manual_method_apply);
|
|
|
|
|
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
2011-10-09 22:50:04 -05:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
|
2016-08-31 20:01:12 +02:00
|
|
|
if (out_config) {
|
2017-02-22 17:04:00 +01:00
|
|
|
*out_config = shared4_new_config (self, connection);
|
2016-08-31 20:01:12 +02:00
|
|
|
if (*out_config) {
|
|
|
|
|
priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self));
|
|
|
|
|
ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
2017-02-22 17:04:00 +01:00
|
|
|
} else {
|
|
|
|
|
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
2016-08-31 20:01:12 +02:00
|
|
|
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
2017-02-22 17:04:00 +01:00
|
|
|
}
|
2011-12-06 17:00:40 -06:00
|
|
|
} else
|
2016-08-31 20:01:12 +02:00
|
|
|
g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE);
|
2017-01-20 16:12:21 +01:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0)
|
device: don't set ip4_state=IP_FAIL for ipv4.method=disabled
... and don't set ip6_state=IP_FAIL for ipv6.method=ignore.
The disabled state is like having an empty NMIP4Config object.
It should not result in %IP_FAIL state. Instead, we just want
to proceed and commit an empty NMIP4Config instance.
This was introduced by commit 0652d9c5961e4636eab87647af890aaf8c3e3269,
which I think was wrong.
Likewise, for ipv6.method=ignore we also don't want to mark the
IP state as failed. Instead, we want to proceed and set IP_DONE
right away -- without commiting anything, which is a difference
to the IPv4 case.
This is especially important, because an ip4_state/ip6_state of IP_FAIL
causes nm_device_can_assume_active_connection() to return FALSE, which
means we unmanage devices at shutdown. Ony might say that it doesn't
matter so much for a device without IP configuration, but imagine a
bond with VLANs on top that only has Layer 2 configuration. This will
bring down the entire stack.
With this change, devices with IP methods disabled/ignore stay up on
exit of NetworkManager (rh#1371126). Of course, that means on restart
software devices stay unamanged due to external-down (because since
commit e1edcda, devices without IP address are also external-down).
So, this really just fixes one scenario, breaking another one.
This should be fixed with bgo#746440 by not assuming connections.
https://bugzilla.redhat.com/show_bug.cgi?id=1371126
2016-08-29 15:37:55 +02:00
|
|
|
ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
2017-01-20 16:12:21 +01:00
|
|
|
else
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_IP4, "unhandled IPv4 config method '%s'; will fail", method);
|
2007-02-05 09:50:11 +00:00
|
|
|
|
2006-01-03 17:47:38 +00:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2011-10-07 11:53:09 -05:00
|
|
|
/* DHCPv6 stuff */
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
|
2016-04-07 14:45:57 +02:00
|
|
|
g_clear_object (&priv->dhcp6.ip6_config);
|
|
|
|
|
g_clear_pointer (&priv->dhcp6.event_id, g_free);
|
|
|
|
|
nm_clear_g_source (&priv->dhcp6.restart_id);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.client) {
|
|
|
|
|
nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.state_sigid);
|
2016-11-03 12:05:12 +01:00
|
|
|
nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.prefix_sigid);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE
|
|
|
|
|
|| cleanup_type == CLEANUP_TYPE_REMOVED)
|
2016-04-07 14:45:57 +02:00
|
|
|
nm_dhcp_client_stop (priv->dhcp6.client, release);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
g_clear_object (&priv->dhcp6.client);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
core: fix dhcp4_cleanup() to clear dhcp4_client first (avoids assert accessing NM_DEVICE_DHCP4_CONFIG)
dhcp4_cleanup() should first clear @dhcp4_client variables before
clearing @dhcp4_config. Otherwise the following assert fails [1] and
the DBUS property NM_DEVICE_DHCP4_CONFIG is set to %NULL.
Analog to dhcp6_cleanup(), dhcp6_client, and NM_DEVICE_DHCP6_CONFIG.
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c148c "unrecognized-specs-changed", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fff4710ed60) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x3370cbc89a "%s: assertion '%s' failed") at gmessages.c:1025
#2 0x0000003370c50679 in g_return_if_fail_warning (log_domain=log_domain@entry=0x4c144c "NetworkManager", pretty_function=pretty_function@entry=0x4c6140 <__PRETTY_FUNCTION__.15969> "nm_dhcp4_config_get_dbus_path",
expression=expression@entry=0x4c60d9 "NM_IS_DHCP4_CONFIG (self)") at gmessages.c:1034
#3 0x000000000046b1d4 in nm_dhcp4_config_get_dbus_path (self=0x0) at nm-dhcp4-config.c:115
#4 0x0000000000434791 in get_property (object=0x9d2320, prop_id=13, value=0x9618a0, pspec=0x9bbc20) at devices/nm-device.c:7539
#5 0x0000003371c18e73 in object_get_property (value=0x9618a0, pspec=<optimized out>, object=0x9d2320) at gobject.c:1303
#6 g_object_get_property (object=0x9d2320, property_name=<optimized out>, value=0x9618a0) at gobject.c:2402
#7 0x000000000048482c in idle_id_reset (data=<optimized out>) at nm-properties-changed-signal.c:123
#8 0x0000003371c13055 in g_cclosure_marshal_VOID__PARAM (closure=0x9618a0, return_value=0xffffffff, n_param_values=0, param_values=0x7fff4710f130, invocation_hint=0x0, marshal_data=0x4b5201) at gmarshal.c:1037
#9 0x0000003371c10298 in g_closure_invoke (closure=0x2, closure@entry=0x919d00, return_value=return_value@entry=0x0, n_param_values=1192292656, param_values=0x9d2320, param_values@entry=0x7fff4710f130,
invocation_hint=invocation_hint@entry=0x7fff4710f0d0) at gclosure.c:777
#10 0x0000003371c21b87 in signal_emit_unlocked_R (node=node@entry=0x919d90, detail=detail@entry=667, instance=instance@entry=0x9d2320, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff4710f130) at gsignal.c:3516
#11 0x0000003371c2a0f2 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fff4710f2c0) at gsignal.c:3330
#12 0x0000003371c2a3af in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3386
#13 0x0000003371c14945 in g_object_dispatch_properties_changed (object=0x9d2320, n_pspecs=4294967295, pspecs=0x0) at gobject.c:1047
#14 0x0000003371c17019 in g_object_notify_by_spec_internal (pspec=<optimized out>, object=0x9d2320) at gobject.c:1141
#15 g_object_notify (object=0x9d2320, property_name=property_name@entry=0x4c400f "dhcp4-config") at gobject.c:1183
#16 0x0000000000434332 in dhcp4_cleanup (self=self@entry=0x9d2320, stop=stop@entry=1, release=release@entry=0) at devices/nm-device.c:2581
#17 0x0000000000434cab in _cleanup_generic_pre (self=self@entry=0x9d2320, deconfigure=deconfigure@entry=1) at devices/nm-device.c:6448
#18 0x0000000000436db1 in nm_device_cleanup (self=self@entry=0x9d2320, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6524
#19 0x0000000000437358 in _set_state_full (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6641
#20 0x000000000043797c in nm_device_state_changed (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#21 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0x9d2320, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#22 0x000000000043a193 in nm_device_set_unmanaged_quitting (device=0x9d2320) at devices/nm-device.c:5998
#23 0x00000000004799f9 in remove_device (manager=0x9b2150, device=0x9d2320, quitting=1) at nm-manager.c:775
#24 0x000000000047bf47 in dispose (object=0x9b2150) at nm-manager.c:4935
#25 0x0000003371c14ee8 in g_object_unref (_object=0x9b2150) at gobject.c:3160
#26 0x0000000000429f43 in main (argc=1, argv=0x7fff4710f9a8) at main.c:681
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 10:32:32 +02:00
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE);
|
2014-11-14 16:04:44 -06:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.config) {
|
|
|
|
|
nm_exported_object_clear_and_unexport (&priv->dhcp6.config);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DHCP6_CONFIG);
|
core: fix dhcp4_cleanup() to clear dhcp4_client first (avoids assert accessing NM_DEVICE_DHCP4_CONFIG)
dhcp4_cleanup() should first clear @dhcp4_client variables before
clearing @dhcp4_config. Otherwise the following assert fails [1] and
the DBUS property NM_DEVICE_DHCP4_CONFIG is set to %NULL.
Analog to dhcp6_cleanup(), dhcp6_client, and NM_DEVICE_DHCP6_CONFIG.
[1] backtrace:
#0 0x0000003370c504e9 in g_logv (log_domain=0x4c148c "unrecognized-specs-changed", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fff4710ed60) at gmessages.c:989
#1 0x0000003370c5063f in g_log (log_domain=log_domain@entry=0x4c144c "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x3370cbc89a "%s: assertion '%s' failed") at gmessages.c:1025
#2 0x0000003370c50679 in g_return_if_fail_warning (log_domain=log_domain@entry=0x4c144c "NetworkManager", pretty_function=pretty_function@entry=0x4c6140 <__PRETTY_FUNCTION__.15969> "nm_dhcp4_config_get_dbus_path",
expression=expression@entry=0x4c60d9 "NM_IS_DHCP4_CONFIG (self)") at gmessages.c:1034
#3 0x000000000046b1d4 in nm_dhcp4_config_get_dbus_path (self=0x0) at nm-dhcp4-config.c:115
#4 0x0000000000434791 in get_property (object=0x9d2320, prop_id=13, value=0x9618a0, pspec=0x9bbc20) at devices/nm-device.c:7539
#5 0x0000003371c18e73 in object_get_property (value=0x9618a0, pspec=<optimized out>, object=0x9d2320) at gobject.c:1303
#6 g_object_get_property (object=0x9d2320, property_name=<optimized out>, value=0x9618a0) at gobject.c:2402
#7 0x000000000048482c in idle_id_reset (data=<optimized out>) at nm-properties-changed-signal.c:123
#8 0x0000003371c13055 in g_cclosure_marshal_VOID__PARAM (closure=0x9618a0, return_value=0xffffffff, n_param_values=0, param_values=0x7fff4710f130, invocation_hint=0x0, marshal_data=0x4b5201) at gmarshal.c:1037
#9 0x0000003371c10298 in g_closure_invoke (closure=0x2, closure@entry=0x919d00, return_value=return_value@entry=0x0, n_param_values=1192292656, param_values=0x9d2320, param_values@entry=0x7fff4710f130,
invocation_hint=invocation_hint@entry=0x7fff4710f0d0) at gclosure.c:777
#10 0x0000003371c21b87 in signal_emit_unlocked_R (node=node@entry=0x919d90, detail=detail@entry=667, instance=instance@entry=0x9d2320, emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fff4710f130) at gsignal.c:3516
#11 0x0000003371c2a0f2 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fff4710f2c0) at gsignal.c:3330
#12 0x0000003371c2a3af in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3386
#13 0x0000003371c14945 in g_object_dispatch_properties_changed (object=0x9d2320, n_pspecs=4294967295, pspecs=0x0) at gobject.c:1047
#14 0x0000003371c17019 in g_object_notify_by_spec_internal (pspec=<optimized out>, object=0x9d2320) at gobject.c:1141
#15 g_object_notify (object=0x9d2320, property_name=property_name@entry=0x4c400f "dhcp4-config") at gobject.c:1183
#16 0x0000000000434332 in dhcp4_cleanup (self=self@entry=0x9d2320, stop=stop@entry=1, release=release@entry=0) at devices/nm-device.c:2581
#17 0x0000000000434cab in _cleanup_generic_pre (self=self@entry=0x9d2320, deconfigure=deconfigure@entry=1) at devices/nm-device.c:6448
#18 0x0000000000436db1 in nm_device_cleanup (self=self@entry=0x9d2320, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6524
#19 0x0000000000437358 in _set_state_full (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED, quitting=quitting@entry=0) at devices/nm-device.c:6641
#20 0x000000000043797c in nm_device_state_changed (device=device@entry=0x9d2320, state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:6823
#21 0x0000000000439fe7 in nm_device_set_unmanaged (device=device@entry=0x9d2320, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_REMOVED) at devices/nm-device.c:5983
#22 0x000000000043a193 in nm_device_set_unmanaged_quitting (device=0x9d2320) at devices/nm-device.c:5998
#23 0x00000000004799f9 in remove_device (manager=0x9b2150, device=0x9d2320, quitting=1) at nm-manager.c:775
#24 0x000000000047bf47 in dispose (object=0x9b2150) at nm-manager.c:4935
#25 0x0000003371c14ee8 in g_object_unref (_object=0x9b2150) at gobject.c:3160
#26 0x0000000000429f43 in main (argc=1, argv=0x7fff4710f9a8) at main.c:681
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-06-23 10:32:32 +02:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
2011-10-21 14:25:35 -05:00
|
|
|
static gboolean
|
|
|
|
|
ip6_config_merge_and_apply (NMDevice *self,
|
2017-02-22 20:20:22 +01:00
|
|
|
gboolean commit)
|
2011-10-21 14:25:35 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
2012-05-24 15:37:40 +02:00
|
|
|
gboolean success;
|
2011-10-21 14:25:35 -05:00
|
|
|
NMIP6Config *composite;
|
2015-08-05 10:15:20 +02:00
|
|
|
gboolean ignore_auto_routes = FALSE;
|
|
|
|
|
gboolean ignore_auto_dns = FALSE;
|
2017-10-04 15:21:21 +02:00
|
|
|
gboolean ignore_default_routes = FALSE;
|
2016-05-11 12:19:28 +02:00
|
|
|
const char *token = NULL;
|
2017-05-26 22:46:57 +02:00
|
|
|
GSList *iter;
|
2015-08-05 10:15:20 +02:00
|
|
|
|
|
|
|
|
/* Apply ignore-auto-routes and ignore-auto-dns settings */
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2015-08-05 10:15:20 +02:00
|
|
|
if (connection) {
|
|
|
|
|
NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
|
|
|
|
|
if (s_ip6) {
|
2016-05-11 12:19:28 +02:00
|
|
|
NMSettingIP6Config *ip6 = NM_SETTING_IP6_CONFIG (s_ip6);
|
|
|
|
|
|
2015-08-05 10:15:20 +02:00
|
|
|
ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip6);
|
|
|
|
|
ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip6);
|
2017-10-24 20:46:24 +02:00
|
|
|
|
|
|
|
|
/* if the connection has an explicit gateway, we also ignore
|
|
|
|
|
* the default routes from other sources. */
|
|
|
|
|
ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip6)
|
|
|
|
|
|| nm_setting_ip_config_get_gateway (s_ip6);
|
2016-03-15 12:03:23 +01:00
|
|
|
|
2016-05-11 12:19:28 +02:00
|
|
|
if (nm_setting_ip6_config_get_addr_gen_mode (ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64)
|
|
|
|
|
token = nm_setting_ip6_config_get_token (ip6);
|
2015-08-05 10:15:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-21 14:25:35 -05:00
|
|
|
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
composite = _ip6_config_new (self);
|
2016-11-18 11:52:53 +01:00
|
|
|
nm_ip6_config_set_privacy (composite,
|
|
|
|
|
priv->ndisc ?
|
|
|
|
|
priv->ndisc_use_tempaddr :
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
2016-05-09 16:30:41 +02:00
|
|
|
init_ip6_config_dns_priority (self, composite);
|
2014-11-21 13:13:48 +01:00
|
|
|
|
2017-05-12 12:00:20 +02:00
|
|
|
if (commit) {
|
2017-09-22 12:11:32 +02:00
|
|
|
if (priv->queued_ip6_config_id)
|
|
|
|
|
update_ext_ip_config (self, AF_INET6, FALSE, FALSE);
|
2015-06-24 09:42:58 +00:00
|
|
|
ensure_con_ip6_config (self);
|
2017-05-12 12:00:20 +02:00
|
|
|
}
|
2016-05-09 16:30:41 +02:00
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
if (commit)
|
|
|
|
|
priv->default_route_metric_penalty_ip6_has = default_route_metric_penalty_detect (self);
|
|
|
|
|
|
2013-08-01 10:59:42 -05:00
|
|
|
/* Merge all the IP configs into the composite config */
|
2015-08-05 10:15:20 +02:00
|
|
|
if (priv->ac_ip6_config) {
|
|
|
|
|
nm_ip6_config_merge (composite, priv->ac_ip6_config,
|
|
|
|
|
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
|
2017-10-04 15:21:21 +02:00
|
|
|
| (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
|
|
|
|
|
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
2015-08-05 10:15:20 +02:00
|
|
|
}
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.ip6_config) {
|
|
|
|
|
nm_ip6_config_merge (composite, priv->dhcp6.ip6_config,
|
2015-08-05 10:15:20 +02:00
|
|
|
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
|
2017-10-04 15:21:21 +02:00
|
|
|
| (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
|
|
|
|
|
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
2015-08-05 10:15:20 +02:00
|
|
|
}
|
2015-08-19 23:07:13 +02:00
|
|
|
|
2017-05-26 22:46:57 +02:00
|
|
|
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip6_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0);
|
2015-08-19 23:07:13 +02:00
|
|
|
|
2013-08-15 12:55:56 -05:00
|
|
|
if (priv->ext_ip6_config)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
|
2011-10-21 14:25:35 -05:00
|
|
|
|
2013-10-15 21:03:42 -05:00
|
|
|
/* Merge WWAN config *last* to ensure modem-given settings overwrite
|
|
|
|
|
* any external stuff set by pppd or other scripts.
|
|
|
|
|
*/
|
2015-08-05 10:15:20 +02:00
|
|
|
if (priv->wwan_ip6_config) {
|
|
|
|
|
nm_ip6_config_merge (composite, priv->wwan_ip6_config,
|
|
|
|
|
(ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
|
2017-10-04 15:21:21 +02:00
|
|
|
| (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
|
|
|
|
|
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
2015-06-25 11:24:32 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-13 16:45:22 +02:00
|
|
|
if (priv->rt6_temporary_not_available) {
|
|
|
|
|
const NMPObject *o;
|
|
|
|
|
GHashTableIter hiter;
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&hiter, priv->rt6_temporary_not_available);
|
|
|
|
|
while (g_hash_table_iter_next (&hiter, (gpointer *) &o, NULL)) {
|
|
|
|
|
nm_ip6_config_add_route (composite,
|
|
|
|
|
NMP_OBJECT_CAST_IP6_ROUTE (o),
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-21 13:13:48 +01:00
|
|
|
/* Merge user overrides into the composite config. For assumed connections,
|
|
|
|
|
* con_ip6_config is empty. */
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->con_ip6_config) {
|
|
|
|
|
nm_ip6_config_merge (composite, priv->con_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
2017-09-18 09:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-19 09:40:13 +02:00
|
|
|
if (commit) {
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip6_config_add_dependent_routes (composite,
|
|
|
|
|
nm_device_get_route_table (self, AF_INET6, TRUE),
|
|
|
|
|
nm_device_get_route_metric (self, AF_INET6));
|
2017-09-19 09:40:13 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-13 14:24:45 -05:00
|
|
|
/* Allow setting MTU etc */
|
|
|
|
|
if (commit) {
|
2016-05-11 12:19:28 +02:00
|
|
|
NMUtilsIPv6IfaceId iid;
|
|
|
|
|
|
|
|
|
|
if (token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, token)) {
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_set_ipv6_token (nm_device_get_platform (self),
|
2016-05-11 12:19:28 +02:00
|
|
|
nm_device_get_ip_ifindex (self),
|
|
|
|
|
iid);
|
|
|
|
|
}
|
2014-08-13 14:24:45 -05:00
|
|
|
}
|
|
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
success = nm_device_set_ip6_config (self, composite, commit);
|
2011-10-21 14:25:35 -05:00
|
|
|
g_object_unref (composite);
|
2015-07-22 11:56:05 +02:00
|
|
|
if (commit)
|
|
|
|
|
priv->v6_commit_first_time = FALSE;
|
2011-10-21 14:25:35 -05:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp6_lease_change (NMDevice *self)
|
2011-10-07 12:06:26 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-07-14 16:53:24 +02:00
|
|
|
NMSettingsConnection *settings_connection;
|
2011-10-07 12:06:26 -05:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.ip6_config == NULL) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DHCP6, "failed to get DHCPv6 config for rebind");
|
2016-04-07 13:48:34 +02:00
|
|
|
return FALSE;
|
2011-10-07 12:06:26 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
g_assert (priv->dhcp6.client); /* sanity check */
|
2011-10-07 12:05:51 -05:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
settings_connection = nm_device_get_settings_connection (self);
|
|
|
|
|
g_assert (settings_connection);
|
2011-10-07 12:05:51 -05:00
|
|
|
|
2011-10-21 14:25:35 -05:00
|
|
|
/* Apply the updated config */
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE)) {
|
2016-04-07 13:48:34 +02:00
|
|
|
_LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event");
|
|
|
|
|
return FALSE;
|
2011-10-07 12:05:51 -05:00
|
|
|
}
|
2016-04-07 13:48:34 +02:00
|
|
|
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP6_CHANGE,
|
|
|
|
|
self,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL, NULL, NULL);
|
2016-04-07 13:48:34 +02:00
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE);
|
2016-05-10 16:34:50 +02:00
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
return TRUE;
|
2011-10-07 12:05:51 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-18 10:05:05 +02:00
|
|
|
static gboolean
|
|
|
|
|
dhcp6_restart_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-04-07 14:45:57 +02:00
|
|
|
priv->dhcp6.restart_id = 0;
|
2015-07-18 10:05:05 +02:00
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
if (!dhcp6_start (self, FALSE))
|
2015-12-14 15:15:23 +01:00
|
|
|
dhcp_schedule_restart (self, AF_INET6, NULL);
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-10-02 13:11:31 +02:00
|
|
|
dhcp_schedule_restart (NMDevice *self,
|
|
|
|
|
int addr_family,
|
|
|
|
|
const char *reason)
|
2015-12-14 15:15:23 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
guint tries_left;
|
2017-10-02 13:11:31 +02:00
|
|
|
char tries_str[255];
|
2015-12-14 15:15:23 +01:00
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_assert_addr_family (addr_family);
|
2015-12-14 15:15:23 +01:00
|
|
|
|
2017-10-02 13:11:31 +02:00
|
|
|
tries_left = (addr_family == AF_INET)
|
|
|
|
|
? priv->dhcp4.num_tries_left
|
|
|
|
|
: priv->dhcp6.num_tries_left;
|
2015-12-14 15:15:23 +01:00
|
|
|
|
2017-10-02 13:11:31 +02:00
|
|
|
_LOGI ((addr_family == AF_INET) ? LOGD_DHCP4 : LOGD_DHCP6,
|
2015-12-14 15:15:23 +01:00
|
|
|
"scheduling DHCPv%c restart in %u seconds%s%s%s%s",
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_utils_addr_family_to_char (addr_family),
|
2015-12-14 15:15:23 +01:00
|
|
|
DHCP_RESTART_TIMEOUT,
|
2017-10-02 13:11:31 +02:00
|
|
|
(tries_left != DHCP_NUM_TRIES_MAX)
|
|
|
|
|
? nm_sprintf_buf (tries_str, ", %u tries left", tries_left + 1)
|
|
|
|
|
: "",
|
2015-12-14 15:15:23 +01:00
|
|
|
NM_PRINT_FMT_QUOTED (reason, " (reason: ", reason, ")", ""));
|
|
|
|
|
|
2017-10-02 13:11:31 +02:00
|
|
|
if (addr_family == AF_INET) {
|
2015-12-14 15:15:23 +01:00
|
|
|
priv->dhcp4.restart_id = g_timeout_add_seconds (DHCP_RESTART_TIMEOUT,
|
|
|
|
|
dhcp4_restart_cb, self);
|
|
|
|
|
} else {
|
2016-04-07 15:09:54 +02:00
|
|
|
priv->dhcp6.restart_id = g_timeout_add_seconds (DHCP_RESTART_TIMEOUT,
|
|
|
|
|
dhcp6_restart_cb, self);
|
|
|
|
|
}
|
2015-07-18 10:05:05 +02:00
|
|
|
}
|
|
|
|
|
|
2011-10-07 12:23:35 -05:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp6_fail (NMDevice *self, gboolean timeout)
|
2011-10-07 12:23:35 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2011-10-07 12:23:35 -05:00
|
|
|
|
2016-04-07 15:09:54 +02:00
|
|
|
_LOGD (LOGD_DHCP6, "DHCPv6 failed: timeout %d, num tries left %u",
|
|
|
|
|
timeout, priv->dhcp6.num_tries_left);
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE);
|
2014-07-23 14:03:42 -05:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) {
|
2015-07-18 10:05:05 +02:00
|
|
|
/* Don't fail if there are static addresses configured on
|
|
|
|
|
* the device, instead retry after some time.
|
|
|
|
|
*/
|
|
|
|
|
if ( priv->ip6_state == IP_DONE
|
|
|
|
|
&& priv->con_ip6_config
|
|
|
|
|
&& nm_ip6_config_get_num_addresses (priv->con_ip6_config)) {
|
2015-12-14 15:15:23 +01:00
|
|
|
dhcp_schedule_restart (self, AF_INET6, "device has IP addresses");
|
2015-07-18 10:05:05 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 15:09:54 +02:00
|
|
|
if ( priv->dhcp6.num_tries_left == DHCP_NUM_TRIES_MAX
|
2017-05-04 10:05:25 +02:00
|
|
|
&& (timeout || (priv->ip6_state == IP_CONF))
|
|
|
|
|
&& !priv->dhcp6.was_active)
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_activate_schedule_ip6_config_timeout (self);
|
2017-05-04 10:05:25 +02:00
|
|
|
else if (priv->ip6_state == IP_DONE || priv->dhcp6.was_active) {
|
2016-04-07 15:09:54 +02:00
|
|
|
/* Don't fail immediately when the lease expires but try to
|
|
|
|
|
* restart DHCP for a predefined number of times.
|
|
|
|
|
*/
|
|
|
|
|
if (priv->dhcp6.num_tries_left) {
|
|
|
|
|
priv->dhcp6.num_tries_left--;
|
2015-12-14 15:15:23 +01:00
|
|
|
dhcp_schedule_restart (self, AF_INET6, "lease expired");
|
2016-04-07 15:09:54 +02:00
|
|
|
} else
|
|
|
|
|
nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
|
|
|
|
|
} else
|
2014-09-23 15:38:33 -05:00
|
|
|
g_warn_if_reached ();
|
2014-07-23 14:03:42 -05:00
|
|
|
} else {
|
|
|
|
|
/* not a hard failure; just live with the RA info */
|
|
|
|
|
if (priv->ip6_state == IP_CONF)
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
2014-07-23 14:03:42 -05:00
|
|
|
}
|
2011-10-07 12:23:35 -05:00
|
|
|
}
|
|
|
|
|
|
2014-05-15 14:11:48 -05:00
|
|
|
static void
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
dhcp6_timeout (NMDevice *self, NMDhcpClient *client)
|
2014-05-15 14:11:48 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED)
|
2014-05-15 14:11:48 -05:00
|
|
|
dhcp6_fail (self, TRUE);
|
|
|
|
|
else {
|
|
|
|
|
/* not a hard failure; just live with the RA info */
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE);
|
2014-05-15 14:11:48 -05:00
|
|
|
if (priv->ip6_state == IP_CONF)
|
|
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-07 12:05:51 -05:00
|
|
|
static void
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
dhcp6_state_changed (NMDhcpClient *client,
|
2014-05-15 12:49:11 -05:00
|
|
|
NMDhcpState state,
|
2014-07-01 09:48:58 -05:00
|
|
|
NMIP6Config *ip6_config,
|
2014-07-01 12:30:29 -05:00
|
|
|
GHashTable *options,
|
2015-08-04 11:30:03 +02:00
|
|
|
const char *event_id,
|
2011-10-07 12:05:51 -05:00
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2011-10-07 12:05:51 -05:00
|
|
|
|
2017-09-11 11:30:48 +02:00
|
|
|
g_return_if_fail (nm_dhcp_client_get_addr_family (client) == AF_INET6);
|
2014-07-01 09:48:58 -05:00
|
|
|
g_return_if_fail (!ip6_config || NM_IS_IP6_CONFIG (ip6_config));
|
2011-10-07 12:05:51 -05:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DHCP6, "new DHCPv6 client state %d", state);
|
2011-10-07 12:05:51 -05:00
|
|
|
|
|
|
|
|
switch (state) {
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_BOUND:
|
2015-08-04 11:30:03 +02:00
|
|
|
/* If the server sends multiple IPv6 addresses, we receive a state
|
|
|
|
|
* changed event for each of them. Use the event ID to merge IPv6
|
|
|
|
|
* addresses from the same transaction into a single configuration.
|
|
|
|
|
*/
|
|
|
|
|
if ( ip6_config
|
|
|
|
|
&& event_id
|
2016-04-07 14:45:57 +02:00
|
|
|
&& priv->dhcp6.event_id
|
|
|
|
|
&& !strcmp (event_id, priv->dhcp6.event_id)) {
|
2017-07-07 23:34:41 +02:00
|
|
|
NMDedupMultiIter ipconf_iter;
|
|
|
|
|
const NMPlatformIP6Address *a;
|
|
|
|
|
|
|
|
|
|
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6_config, &a)
|
|
|
|
|
nm_ip6_config_add_address (priv->dhcp6.ip6_config, a);
|
2015-08-04 11:30:03 +02:00
|
|
|
} else {
|
2016-04-07 14:45:57 +02:00
|
|
|
g_clear_object (&priv->dhcp6.ip6_config);
|
|
|
|
|
g_clear_pointer (&priv->dhcp6.event_id, g_free);
|
2015-08-04 11:30:03 +02:00
|
|
|
if (ip6_config) {
|
2016-04-07 14:45:57 +02:00
|
|
|
priv->dhcp6.ip6_config = g_object_ref (ip6_config);
|
|
|
|
|
priv->dhcp6.event_id = g_strdup (event_id);
|
|
|
|
|
nm_dhcp6_config_set_options (priv->dhcp6.config, options);
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_DHCP6_CONFIG);
|
2015-08-04 11:30:03 +02:00
|
|
|
}
|
2014-01-06 16:06:49 -06:00
|
|
|
}
|
|
|
|
|
|
2016-04-07 15:09:54 +02:00
|
|
|
priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX;
|
|
|
|
|
|
2013-06-14 21:42:22 +02:00
|
|
|
if (priv->ip6_state == IP_CONF) {
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.ip6_config == NULL) {
|
2016-04-07 13:48:34 +02:00
|
|
|
nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED);
|
2013-06-14 21:42:22 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
2013-06-14 21:42:22 +02:00
|
|
|
} else if (priv->ip6_state == IP_DONE)
|
2016-04-07 13:48:34 +02:00
|
|
|
if (!dhcp6_lease_change (self))
|
|
|
|
|
dhcp6_fail (self, FALSE);
|
2011-10-07 12:05:51 -05:00
|
|
|
break;
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_TIMEOUT:
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp6_timeout (self, client);
|
2011-10-07 12:05:51 -05:00
|
|
|
break;
|
core: better handle DHCP expiry/nak during initial lease acquisition (bgo #739482)
When dhclient trieds to request a previous lease and the server NAKs that
lease, dhclient emits the EXPIRE state. dhcpcd has also been known to emit
the 'nak' state for the same reason.
(systemd's DHCP client code does not push a NAK up to NetworkManager, but
jumps to the REBOOT state instead, so it is unaffected by this issue.)
NetworkManager saw the expire during IP configuration and treated that as
full activation failure. The connection would be restarted, the same lease
requested, and the same NAK delivered, over and over. Before a lease is
acquired, there is (by definition) no lease to expire, so these events
should be ignored.
We do, however, still want to handle abnormal failures, which is why
this patch splits the EXPIRE case from the FAIL case and handles them
separately.
https://bugzilla.gnome.org/show_bug.cgi?id=739482
2014-12-11 15:36:27 -06:00
|
|
|
case NM_DHCP_STATE_EXPIRE:
|
|
|
|
|
/* Ignore expiry before we even have a lease (NAK, old lease, etc) */
|
|
|
|
|
if (priv->ip6_state != IP_CONF)
|
|
|
|
|
dhcp6_fail (self, FALSE);
|
|
|
|
|
break;
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_DONE:
|
2011-10-07 12:05:51 -05:00
|
|
|
/* In IPv6 info-only mode, the client doesn't handle leases so it
|
|
|
|
|
* may exit right after getting a response from the server. That's
|
|
|
|
|
* normal. In that case we just ignore the exit.
|
|
|
|
|
*/
|
2016-10-13 11:06:25 +00:00
|
|
|
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF)
|
2011-10-07 12:05:51 -05:00
|
|
|
break;
|
2017-02-06 14:42:47 +01:00
|
|
|
/* fall through */
|
2014-05-15 12:49:11 -05:00
|
|
|
case NM_DHCP_STATE_FAIL:
|
2014-07-15 13:36:24 +02:00
|
|
|
dhcp6_fail (self, FALSE);
|
2011-10-07 12:05:51 -05:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-03 12:05:12 +01:00
|
|
|
static void
|
|
|
|
|
dhcp6_prefix_delegated (NMDhcpClient *client,
|
|
|
|
|
NMPlatformIP6Address *prefix,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
|
|
|
|
|
/* Just re-emit. The device just contributes the prefix to the
|
|
|
|
|
* pool in NMPolicy, which decides about subnet allocation
|
|
|
|
|
* on the shared devices. */
|
|
|
|
|
g_signal_emit (self, signals[IP6_PREFIX_DELEGATED], 0, prefix);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-14 16:04:44 -06:00
|
|
|
static gboolean
|
|
|
|
|
dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
|
2010-01-27 16:20:09 -08:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-11-14 16:04:44 -06:00
|
|
|
NMSettingIPConfig *s_ip6;
|
2012-06-13 13:28:55 -05:00
|
|
|
GByteArray *tmp = NULL;
|
2014-04-10 18:02:52 -05:00
|
|
|
const guint8 *hw_addr;
|
|
|
|
|
size_t hw_addr_len = 0;
|
2016-01-30 22:31:37 +01:00
|
|
|
const NMPlatformIP6Address *ll_addr = NULL;
|
2010-01-27 16:20:09 -08:00
|
|
|
|
2014-11-14 16:04:44 -06:00
|
|
|
g_assert (connection);
|
2014-07-11 12:50:17 -05:00
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
g_assert (s_ip6);
|
2010-01-27 16:20:09 -08:00
|
|
|
|
2017-03-14 23:35:35 +01:00
|
|
|
if (priv->ext_ip6_config_captured)
|
|
|
|
|
ll_addr = nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE);
|
|
|
|
|
|
|
|
|
|
if (!ll_addr) {
|
|
|
|
|
_LOGW (LOGD_DHCP6, "can't start DHCPv6: no link-local address");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len);
|
2014-04-10 18:02:52 -05:00
|
|
|
if (hw_addr_len) {
|
|
|
|
|
tmp = g_byte_array_sized_new (hw_addr_len);
|
|
|
|
|
g_byte_array_append (tmp, hw_addr, hw_addr_len);
|
2012-06-13 13:28:55 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
priv->dhcp6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (),
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
nm_device_get_multi_index (self),
|
2012-06-13 13:28:55 -05:00
|
|
|
nm_device_get_ip_iface (self),
|
2014-04-03 13:13:17 -05:00
|
|
|
nm_device_get_ip_ifindex (self),
|
2012-06-13 13:28:55 -05:00
|
|
|
tmp,
|
2016-01-30 22:31:37 +01:00
|
|
|
&ll_addr->address,
|
2011-03-08 13:41:28 +01:00
|
|
|
nm_connection_get_uuid (connection),
|
2017-09-28 14:40:12 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET6, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET6),
|
2014-11-04 10:46:05 -05:00
|
|
|
nm_setting_ip_config_get_dhcp_send_hostname (s_ip6),
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_get_dhcp_hostname (s_ip6),
|
2017-09-11 10:43:48 +02:00
|
|
|
get_dhcp_timeout (self, AF_INET6),
|
2014-03-10 16:11:21 +01:00
|
|
|
priv->dhcp_anycast_address,
|
2016-10-13 11:06:25 +00:00
|
|
|
(priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE,
|
2016-10-31 23:30:37 +01:00
|
|
|
nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)),
|
2016-11-03 12:05:12 +01:00
|
|
|
priv->dhcp6.needed_prefixes);
|
2012-06-13 13:28:55 -05:00
|
|
|
if (tmp)
|
|
|
|
|
g_byte_array_free (tmp, TRUE);
|
|
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.client) {
|
|
|
|
|
priv->dhcp6.state_sigid = g_signal_connect (priv->dhcp6.client,
|
2014-03-11 14:02:24 +01:00
|
|
|
NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED,
|
2011-10-07 12:05:51 -05:00
|
|
|
G_CALLBACK (dhcp6_state_changed),
|
2010-01-27 16:20:09 -08:00
|
|
|
self);
|
2016-11-03 12:05:12 +01:00
|
|
|
priv->dhcp6.prefix_sigid = g_signal_connect (priv->dhcp6.client,
|
|
|
|
|
NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
|
|
|
|
|
G_CALLBACK (dhcp6_prefix_delegated),
|
|
|
|
|
self);
|
2014-11-14 16:04:44 -06:00
|
|
|
}
|
2010-01-27 16:20:09 -08:00
|
|
|
|
2017-05-08 08:44:51 +02:00
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self))
|
2017-10-06 10:28:15 +02:00
|
|
|
priv->dhcp6.was_active = TRUE;
|
2017-05-04 10:05:25 +02:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
return !!priv->dhcp6.client;
|
2014-11-14 16:04:44 -06:00
|
|
|
}
|
2014-04-14 17:57:56 +02:00
|
|
|
|
2014-11-14 16:04:44 -06:00
|
|
|
static gboolean
|
2017-02-22 17:04:00 +01:00
|
|
|
dhcp6_start (NMDevice *self, gboolean wait_for_ll)
|
2014-11-14 16:04:44 -06:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingIPConfig *s_ip6;
|
|
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
nm_exported_object_clear_and_unexport (&priv->dhcp6.config);
|
|
|
|
|
priv->dhcp6.config = nm_dhcp6_config_new ();
|
2014-11-14 16:04:44 -06:00
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
g_warn_if_fail (priv->dhcp6.ip6_config == NULL);
|
|
|
|
|
g_clear_object (&priv->dhcp6.ip6_config);
|
|
|
|
|
g_clear_pointer (&priv->dhcp6.event_id, g_free);
|
2014-11-14 16:04:44 -06:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2014-11-14 16:04:44 -06:00
|
|
|
g_assert (connection);
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
if (!nm_setting_ip_config_get_may_fail (s_ip6) ||
|
|
|
|
|
!strcmp (nm_setting_ip_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_DHCP))
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP6, TRUE);
|
2014-11-14 16:04:44 -06:00
|
|
|
|
|
|
|
|
if (wait_for_ll) {
|
|
|
|
|
NMActStageReturn ret;
|
|
|
|
|
|
|
|
|
|
/* ensure link local is ready... */
|
|
|
|
|
ret = linklocal6_start (self);
|
|
|
|
|
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
|
|
|
|
|
/* success; wait for the LL address to show up */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* success; already have the LL address; kick off DHCP */
|
2016-08-29 15:33:33 +02:00
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
2014-11-14 16:04:44 -06:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
if (!dhcp6_start_with_link_ready (self, connection))
|
2014-11-14 16:04:44 -06:00
|
|
|
return FALSE;
|
2010-01-27 16:20:09 -08:00
|
|
|
|
2014-11-14 16:04:44 -06:00
|
|
|
return TRUE;
|
2010-01-27 16:20:09 -08:00
|
|
|
}
|
|
|
|
|
|
2014-01-28 21:25:34 +01:00
|
|
|
gboolean
|
|
|
|
|
nm_device_dhcp6_renew (NMDevice *self, gboolean release)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
g_return_val_if_fail (priv->dhcp6.client != NULL, FALSE);
|
2014-01-28 21:25:34 +01:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DHCP6, "DHCPv6 lease renewal requested");
|
2014-01-28 21:25:34 +01:00
|
|
|
|
|
|
|
|
/* Terminate old DHCP instance and release the old lease */
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, release);
|
2014-01-28 21:25:34 +01:00
|
|
|
|
|
|
|
|
/* Start DHCP again on the interface */
|
2017-02-22 17:04:00 +01:00
|
|
|
return dhcp6_start (self, FALSE);
|
2014-01-28 21:25:34 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2016-11-03 12:05:12 +01:00
|
|
|
/*
|
|
|
|
|
* Called on the requesting interface when a subnet can't be obtained
|
|
|
|
|
* from known prefixes for a newly active shared connection.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_request_ip6_prefixes (NMDevice *self, int needed_prefixes)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->dhcp6.needed_prefixes = needed_prefixes;
|
|
|
|
|
|
|
|
|
|
if (priv->dhcp6.client) {
|
|
|
|
|
_LOGD (LOGD_IP6, "ipv6-pd: asking DHCPv6 for %d prefixes", needed_prefixes);
|
|
|
|
|
nm_device_dhcp6_renew (self, FALSE);
|
|
|
|
|
} else {
|
|
|
|
|
_LOGI (LOGD_IP6, "ipv6-pd: device doesn't use DHCPv6, can't request prefixes");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_needs_ip6_subnet (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->needs_ip6_subnet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Called on the ipv6.method=shared interface when a new subnet is allocated
|
|
|
|
|
* or the prefix from which it is allocated is renewed.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMPlatformIP6Address address = *subnet;
|
|
|
|
|
|
|
|
|
|
if (!priv->ac_ip6_config)
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->ac_ip6_config = _ip6_config_new (self);
|
2016-11-03 12:05:12 +01:00
|
|
|
|
|
|
|
|
/* Assign a ::1 address in the subnet for us. */
|
|
|
|
|
address.address.s6_addr32[3] |= htonl (1);
|
|
|
|
|
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_IP6, "ipv6-pd: using %s address (preferred for %u seconds)",
|
|
|
|
|
nm_utils_inet6_ntop (&address.address, NULL),
|
|
|
|
|
subnet->preferred);
|
|
|
|
|
|
|
|
|
|
/* This also updates the ndisc if there are actual changes. */
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2016-11-03 12:05:12 +01:00
|
|
|
_LOGW (LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Called whenever the policy picks a default IPv6 device.
|
|
|
|
|
* The ipv6.method=shared devices just reuse its DNS configuration.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMIP6Config *from_config = NULL;
|
2017-11-08 21:31:01 +01:00
|
|
|
guint i, len;
|
2016-11-03 12:05:12 +01:00
|
|
|
|
|
|
|
|
if (priv->ac_ip6_config) {
|
|
|
|
|
nm_ip6_config_reset_nameservers (priv->ac_ip6_config);
|
|
|
|
|
nm_ip6_config_reset_searches (priv->ac_ip6_config);
|
|
|
|
|
} else
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->ac_ip6_config = _ip6_config_new (self);
|
2016-11-03 12:05:12 +01:00
|
|
|
|
|
|
|
|
if (from_device)
|
|
|
|
|
from_config = nm_device_get_ip6_config (from_device);
|
|
|
|
|
if (!from_config)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-08 21:31:01 +01:00
|
|
|
len = nm_ip6_config_get_num_nameservers (from_config);
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-11-03 12:05:12 +01:00
|
|
|
nm_ip6_config_add_nameserver (priv->ac_ip6_config,
|
|
|
|
|
nm_ip6_config_get_nameserver (from_config, i));
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-08 21:31:01 +01:00
|
|
|
len = nm_ip6_config_get_num_searches (from_config);
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-11-03 12:05:12 +01:00
|
|
|
nm_ip6_config_add_search (priv->ac_ip6_config,
|
2017-11-08 21:31:01 +01:00
|
|
|
nm_ip6_config_get_search (from_config, i));
|
2016-11-03 12:05:12 +01:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2016-11-03 12:05:12 +01:00
|
|
|
_LOGW (LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2013-11-07 22:59:43 +01:00
|
|
|
static void
|
|
|
|
|
linklocal6_cleanup (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-01-04 09:46:22 +01:00
|
|
|
nm_clear_g_source (&priv->linklocal6_timeout_id);
|
2013-11-07 22:59:43 +01:00
|
|
|
}
|
|
|
|
|
|
2015-10-03 19:50:30 +02:00
|
|
|
static void
|
|
|
|
|
linklocal6_failed (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
linklocal6_cleanup (self);
|
|
|
|
|
nm_device_activate_schedule_ip6_config_timeout (self);
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 22:59:43 +01:00
|
|
|
static gboolean
|
|
|
|
|
linklocal6_timeout_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses failed due to timeout");
|
2015-10-03 19:50:30 +02:00
|
|
|
linklocal6_failed (self);
|
2013-11-07 22:59:43 +01:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
linklocal6_complete (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
const char *method;
|
|
|
|
|
|
|
|
|
|
g_assert (priv->linklocal6_timeout_id);
|
2017-05-06 10:56:21 +02:00
|
|
|
g_assert (priv->ext_ip6_config_captured);
|
|
|
|
|
g_assert (nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE));
|
2013-11-07 22:59:43 +01:00
|
|
|
|
|
|
|
|
linklocal6_cleanup (self);
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2013-11-07 22:59:43 +01:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
|
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses successful, continue with method %s", method);
|
2013-11-07 22:59:43 +01:00
|
|
|
|
2016-11-03 12:15:32 +01:00
|
|
|
if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
|
|
|
|
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
|
2014-07-22 16:24:07 -05:00
|
|
|
if (!addrconf6_start_with_link_ready (self)) {
|
|
|
|
|
/* Time out IPv6 instead of failing the entire activation */
|
|
|
|
|
nm_device_activate_schedule_ip6_config_timeout (self);
|
|
|
|
|
}
|
2014-11-14 16:04:44 -06:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
|
|
|
|
|
if (!dhcp6_start_with_link_ready (self, connection)) {
|
|
|
|
|
/* Time out IPv6 instead of failing the entire activation */
|
|
|
|
|
nm_device_activate_schedule_ip6_config_timeout (self);
|
|
|
|
|
}
|
2014-07-22 16:24:07 -05:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0)
|
2013-11-07 22:59:43 +01:00
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
|
|
|
|
else
|
|
|
|
|
g_return_if_fail (FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 17:14:30 -05:00
|
|
|
static void
|
|
|
|
|
check_and_add_ipv6ll_addr (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
int ip_ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
struct in6_addr lladdr;
|
2015-10-03 19:44:27 +02:00
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingIP6Config *s_ip6 = NULL;
|
|
|
|
|
GError *error = NULL;
|
2014-07-24 17:14:30 -05:00
|
|
|
|
|
|
|
|
if (priv->nm_ipv6ll == FALSE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (priv->ip6_config) {
|
2017-07-07 23:34:41 +02:00
|
|
|
NMDedupMultiIter ipconf_iter;
|
|
|
|
|
const NMPlatformIP6Address *addr;
|
2014-07-24 17:14:30 -05:00
|
|
|
|
2017-07-07 23:34:41 +02:00
|
|
|
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, priv->ip6_config, &addr) {
|
2015-10-03 19:50:30 +02:00
|
|
|
if ( IN6_IS_ADDR_LINKLOCAL (&addr->address)
|
2016-02-29 16:23:16 +01:00
|
|
|
&& !(addr->n_ifa_flags & IFA_F_DADFAILED)) {
|
2014-07-24 17:14:30 -05:00
|
|
|
/* Already have an LL address, nothing to do */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset (&lladdr, 0, sizeof (lladdr));
|
|
|
|
|
lladdr.s6_addr16[0] = htons (0xfe80);
|
2015-10-03 19:50:30 +02:00
|
|
|
|
2015-10-03 19:44:27 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (connection)
|
|
|
|
|
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
|
|
|
|
|
|
|
|
|
|
if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
|
2016-06-21 18:07:56 +02:00
|
|
|
NMUtilsStableType stable_type;
|
|
|
|
|
const char *stable_id;
|
|
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
stable_id = _get_stable_id (self, connection, &stable_type);
|
2016-06-21 18:07:56 +02:00
|
|
|
if ( !stable_id
|
|
|
|
|
|| !nm_utils_ipv6_addr_set_stable_privacy (stable_type,
|
|
|
|
|
&lladdr,
|
|
|
|
|
nm_device_get_iface (self),
|
|
|
|
|
stable_id,
|
|
|
|
|
priv->linklocal6_dad_counter++,
|
|
|
|
|
&error)) {
|
2015-10-03 19:44:27 +02:00
|
|
|
_LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
linklocal6_failed (self);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_LOGD (LOGD_IP6, "linklocal6: using IPv6 stable-privacy addressing");
|
|
|
|
|
} else {
|
|
|
|
|
NMUtilsIPv6IfaceId iid;
|
|
|
|
|
|
|
|
|
|
if (priv->linklocal6_timeout_id) {
|
|
|
|
|
/* We already started and attempt to add a LL address. For the EUI-64
|
|
|
|
|
* mode we can't pick a new one, we'll just fail. */
|
|
|
|
|
_LOGW (LOGD_IP6, "linklocal6: DAD failed for an EUI-64 address");
|
|
|
|
|
linklocal6_failed (self);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-11 12:19:28 +02:00
|
|
|
if (!nm_device_get_ip_iface_identifier (self, &iid, TRUE)) {
|
2015-10-03 19:44:27 +02:00
|
|
|
_LOGW (LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_LOGD (LOGD_IP6, "linklocal6: using EUI-64 identifier to generate IPv6LL address");
|
|
|
|
|
|
2016-05-27 18:19:55 +02:00
|
|
|
nm_utils_ipv6_addr_set_interface_identifier (&lladdr, iid);
|
2015-10-03 19:50:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL));
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_ip6_address_add (nm_device_get_platform (self),
|
platform: add self argument to platform functions
Most nm_platform_*() functions operate on the platform
singleton nm_platform_get(). That made sense because the
NMPlatform instance was mainly to hook fake platform for
testing.
While the implicit argument saved some typing, I think explicit is
better. Especially, because NMPlatform could become a more usable
object then just a hook for testing.
With this change, NMPlatform instances can be used individually, not
only as a singleton instance.
Before this change, the constructor of NMLinuxPlatform could not
call any nm_platform_*() functions because the singleton was not
yet initialized. We could only instantiate an incomplete instance,
register it via nm_platform_setup(), and then complete initialization
via singleton->setup().
With this change, we can create and fully initialize NMPlatform instances
before/without setting them up them as singleton.
Also, currently there is no clear distinction between functions
that operate on the NMPlatform instance, and functions that can
be used stand-alone (e.g. nm_platform_ip4_address_to_string()).
The latter can not be mocked for testing. With this change, the
distinction becomes obvious. That is also useful because it becomes
clearer which functions make use of the platform cache and which not.
Inside nm-linux-platform.c, continue the pattern that the
self instance is named @platform. That makes sense because
its type is NMPlatform, and not NMLinuxPlatform what we
would expect from a paramter named @self.
This is a major diff that causes some pain when rebasing. Try
to rebase to the parent commit of this commit as a first step.
Then rebase on top of this commit using merge-strategy "ours".
2015-04-18 12:36:09 +02:00
|
|
|
ip_ifindex,
|
2014-07-24 17:14:30 -05:00
|
|
|
lladdr,
|
|
|
|
|
64,
|
2015-10-10 19:58:59 +02:00
|
|
|
in6addr_any,
|
2014-07-24 17:14:30 -05:00
|
|
|
NM_PLATFORM_LIFETIME_PERMANENT,
|
|
|
|
|
NM_PLATFORM_LIFETIME_PERMANENT,
|
|
|
|
|
0)) {
|
|
|
|
|
_LOGW (LOGD_IP6, "failed to add IPv6 link-local address %s",
|
|
|
|
|
nm_utils_inet6_ntop (&lladdr, NULL));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 22:59:43 +01:00
|
|
|
static NMActStageReturn
|
|
|
|
|
linklocal6_start (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
const char *method;
|
|
|
|
|
|
|
|
|
|
linklocal6_cleanup (self);
|
|
|
|
|
|
2017-05-06 10:56:21 +02:00
|
|
|
if ( priv->ext_ip6_config_captured
|
|
|
|
|
&& nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE))
|
2016-08-29 15:33:33 +02:00
|
|
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
2013-11-07 22:59:43 +01:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2013-11-07 22:59:43 +01:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
|
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "linklocal6: starting IPv6 with method '%s', but the device has no link-local addresses configured. Wait.", method);
|
2013-11-07 22:59:43 +01:00
|
|
|
|
2014-07-24 17:14:30 -05:00
|
|
|
check_and_add_ipv6ll_addr (self);
|
|
|
|
|
|
2015-09-17 09:55:23 -05:00
|
|
|
/* Depending on the network and what the 'dad_transmits' and 'retrans_time_ms'
|
|
|
|
|
* sysctl values are, DAD for the IPv6LL address may take quite a while.
|
|
|
|
|
* FIXME: use dad/retrans sysctl values if they are higher than a minimum time.
|
|
|
|
|
* (rh #1101809)
|
|
|
|
|
*/
|
|
|
|
|
priv->linklocal6_timeout_id = g_timeout_add_seconds (15, linklocal6_timeout_cb, self);
|
2013-11-07 22:59:43 +01:00
|
|
|
|
|
|
|
|
return NM_ACT_STAGE_RETURN_POSTPONE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2013-11-07 22:59:43 +01:00
|
|
|
|
2017-01-17 13:11:07 +01:00
|
|
|
gint64
|
|
|
|
|
nm_device_get_configured_mtu_from_connection_default (NMDevice *self,
|
|
|
|
|
const char *property_name)
|
|
|
|
|
{
|
|
|
|
|
gs_free char *str = NULL;
|
|
|
|
|
|
|
|
|
|
str = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, property_name, self);
|
|
|
|
|
return _nm_utils_ascii_str_to_int64 (str, 10, 0, G_MAXUINT32, -1);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-14 17:04:17 +01:00
|
|
|
guint32
|
|
|
|
|
nm_device_get_configured_mtu_for_wired (NMDevice *self, gboolean *out_is_user_config)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingWired *setting;
|
2017-01-17 13:11:07 +01:00
|
|
|
gint64 mtu_default;
|
2017-01-14 17:04:17 +01:00
|
|
|
guint32 mtu;
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
|
|
|
|
nm_assert (out_is_user_config);
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (!connection)
|
|
|
|
|
g_return_val_if_reached (0);
|
|
|
|
|
|
|
|
|
|
setting = nm_connection_get_setting_wired (connection);
|
|
|
|
|
|
|
|
|
|
if (setting) {
|
|
|
|
|
mtu = nm_setting_wired_get_mtu (setting);
|
|
|
|
|
if (mtu) {
|
|
|
|
|
*out_is_user_config = TRUE;
|
|
|
|
|
return mtu;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-01-17 13:11:07 +01:00
|
|
|
|
|
|
|
|
mtu_default = nm_device_get_configured_mtu_from_connection_default (self, "ethernet.mtu");
|
|
|
|
|
if (mtu_default >= 0) {
|
|
|
|
|
*out_is_user_config = TRUE;
|
|
|
|
|
return (guint32) mtu_default;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-14 17:04:17 +01:00
|
|
|
*out_is_user_config = FALSE;
|
device: don't set MTU of device unless explicitly configured
Since commit 2b51d3967 "device: merge branch 'th/device-mtu-bgo777251'",
we always set the MTU for certain device types during activation. Even
if the MTU is neither specified via the connection nor other means, like
DHCP.
Revert that change. On activation, if nothing explicitly configures the
MTU, leave it unchanged. This is like what we do with ethernet's
cloned-mac-address, which has a default value "preserve".
So, as last resort the default value for MTU is now 0 (don't change),
instead of depending on the device type.
Note that you also can override the default value in global
configuration via NetworkManager.conf.
This behavior makes sense, because whenever NM actively resets the MTU,
it remembers the previous value and restores it when deactivating
the connection. That wasn't implemented before 2b51d3967, and the
MTU would depend on which connection was previously active. That
is no longer an issue as the MTU gets reset when deactivating.
https://bugzilla.redhat.com/show_bug.cgi?id=1460760
2017-06-13 12:26:51 +02:00
|
|
|
return 0;
|
2017-01-14 17:04:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-10-13 13:11:11 +02:00
|
|
|
static void
|
|
|
|
|
_set_mtu (NMDevice *self, guint32 mtu)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->mtu == mtu)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
priv->mtu = mtu;
|
|
|
|
|
_notify (self, PROP_MTU);
|
2017-10-18 19:01:50 +02:00
|
|
|
|
|
|
|
|
if (priv->master) {
|
|
|
|
|
/* changing the MTU of a slave, might require the master to reset
|
|
|
|
|
* it's MTU. Note that the master usually cannot set a MTU larger
|
|
|
|
|
* then the slave's. Hence, when the slave increases the MTU,
|
|
|
|
|
* master might want to retry setting the MTU. */
|
|
|
|
|
nm_device_commit_mtu (priv->master);
|
|
|
|
|
}
|
2017-10-13 13:11:11 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
static void
|
2017-01-15 13:38:33 +01:00
|
|
|
_commit_mtu (NMDevice *self, const NMIP4Config *config)
|
2016-10-19 15:55:01 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-01-15 13:38:33 +01:00
|
|
|
guint32 ip6_mtu, ip6_mtu_orig;
|
|
|
|
|
guint32 mtu_desired, mtu_desired_orig;
|
2017-01-13 18:40:50 +01:00
|
|
|
guint32 mtu_plat;
|
2017-01-16 10:20:26 +01:00
|
|
|
struct {
|
|
|
|
|
gboolean initialized;
|
|
|
|
|
guint32 value;
|
2017-01-17 16:16:46 +01:00
|
|
|
} ip6_mtu_sysctl = { 0, };
|
2017-01-13 18:40:50 +01:00
|
|
|
int ifindex;
|
2017-01-15 13:38:33 +01:00
|
|
|
char sbuf[64], sbuf1[64], sbuf2[64];
|
2016-10-19 15:55:01 +02:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
if (ifindex <= 0)
|
|
|
|
|
return;
|
2016-10-19 15:55:01 +02:00
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2017-10-12 19:36:09 +02:00
|
|
|
/* for assumed connections we don't tamper with the MTU. */
|
2017-01-15 13:38:33 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
gboolean mtu_is_user_config = FALSE;
|
|
|
|
|
guint32 mtu = 0;
|
|
|
|
|
|
2017-01-16 12:18:51 +01:00
|
|
|
/* preferably, get the MTU from explict user-configuration.
|
|
|
|
|
* Only if that fails, look at the current @config (which contains
|
|
|
|
|
* MTUs from DHCP/PPP) or maybe fallback to a device-specific MTU. */
|
2017-01-15 13:38:33 +01:00
|
|
|
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu)
|
|
|
|
|
mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &mtu_is_user_config);
|
|
|
|
|
|
2017-01-17 13:11:07 +01:00
|
|
|
if (mtu_is_user_config)
|
2017-01-15 13:38:33 +01:00
|
|
|
mtu_desired = mtu;
|
|
|
|
|
else {
|
|
|
|
|
if (config)
|
|
|
|
|
mtu_desired = nm_ip4_config_get_mtu (config);
|
|
|
|
|
else
|
|
|
|
|
mtu_desired = 0;
|
2017-01-16 12:18:51 +01:00
|
|
|
if (!mtu_desired && !priv->mtu_initialized) {
|
|
|
|
|
/* there is no MTU specified, and this is the first commit of the MTU.
|
|
|
|
|
* Reset a per-device MTU default, as returned from get_configured_mtu().
|
|
|
|
|
*
|
|
|
|
|
* The device might choose not to return a default MTU via get_configured_mtu()
|
|
|
|
|
* to suppress this behavior. */
|
|
|
|
|
mtu_desired = mtu;
|
|
|
|
|
}
|
2017-01-15 13:38:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-16 14:58:11 +01:00
|
|
|
if (mtu_desired && mtu_desired < 1280) {
|
|
|
|
|
NMSettingIPConfig *s_ip6;
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_device_get_applied_setting (self, NM_TYPE_SETTING_IP6_CONFIG);
|
2017-01-24 16:28:04 +01:00
|
|
|
if ( s_ip6
|
|
|
|
|
&& !NM_IN_STRSET (nm_setting_ip_config_get_method (s_ip6),
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
|
2017-01-16 14:58:11 +01:00
|
|
|
/* the interface has IPv6 enabled. The MTU with IPv6 cannot be smaller
|
|
|
|
|
* then 1280.
|
|
|
|
|
*
|
|
|
|
|
* For slave-devices (that don't have @s_ip6 we) don't do this fixup because
|
|
|
|
|
* it's anyway an unsolved problem when the slave configures a conflicting
|
|
|
|
|
* MTU. */
|
|
|
|
|
mtu_desired = 1280;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
ip6_mtu = priv->ip6_mtu;
|
2017-01-16 12:18:51 +01:00
|
|
|
if (!ip6_mtu && !priv->mtu_initialized) {
|
|
|
|
|
/* initially, if the IPv6 MTU is not specified, grow it as large as the
|
|
|
|
|
* link MTU @mtu_desired. Only exception is, if @mtu_desired is so small
|
|
|
|
|
* to disable IPv6. */
|
|
|
|
|
if (mtu_desired >= 1280)
|
|
|
|
|
ip6_mtu = mtu_desired;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv->mtu_initialized = TRUE;
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
if (!ip6_mtu && !mtu_desired)
|
|
|
|
|
return;
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2017-01-15 13:38:33 +01:00
|
|
|
mtu_desired_orig = mtu_desired;
|
|
|
|
|
ip6_mtu_orig = ip6_mtu;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
mtu_plat = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex);
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
if (ip6_mtu) {
|
|
|
|
|
ip6_mtu = NM_MAX (1280, ip6_mtu);
|
2015-02-25 15:21:48 +01:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
if (!mtu_desired)
|
|
|
|
|
mtu_desired = mtu_plat;
|
2015-02-25 14:49:34 +01:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
if (mtu_desired) {
|
|
|
|
|
mtu_desired = NM_MAX (1280, mtu_desired);
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
if (mtu_desired < ip6_mtu)
|
|
|
|
|
ip6_mtu = mtu_desired;
|
|
|
|
|
}
|
2015-02-25 15:35:26 +01:00
|
|
|
}
|
|
|
|
|
|
2017-01-16 10:20:26 +01:00
|
|
|
_LOGT (LOGD_DEVICE, "mtu: device-mtu: %u%s, ipv6-mtu: %u%s, ifindex: %d",
|
2017-01-15 13:38:33 +01:00
|
|
|
(guint) mtu_desired,
|
|
|
|
|
mtu_desired == mtu_desired_orig ? "" : nm_sprintf_buf (sbuf1, " (was %u)", (guint) mtu_desired_orig),
|
|
|
|
|
(guint) ip6_mtu,
|
2017-01-16 10:20:26 +01:00
|
|
|
ip6_mtu == ip6_mtu_orig ? "" : nm_sprintf_buf (sbuf2, " (was %u)", (guint) ip6_mtu_orig),
|
|
|
|
|
ifindex);
|
|
|
|
|
|
|
|
|
|
#define _IP6_MTU_SYS() \
|
|
|
|
|
({ \
|
|
|
|
|
if (!ip6_mtu_sysctl.initialized) { \
|
|
|
|
|
ip6_mtu_sysctl.value = nm_device_ipv6_sysctl_get_uint32 (self, "mtu", 0); \
|
|
|
|
|
ip6_mtu_sysctl.initialized = TRUE; \
|
|
|
|
|
} \
|
|
|
|
|
ip6_mtu_sysctl.value; \
|
|
|
|
|
})
|
|
|
|
|
if ( (mtu_desired && mtu_desired != mtu_plat)
|
|
|
|
|
|| (ip6_mtu && ip6_mtu != _IP6_MTU_SYS ())) {
|
2017-10-23 15:41:07 +02:00
|
|
|
gboolean anticipated_failure = FALSE;
|
2017-01-16 10:20:26 +01:00
|
|
|
|
|
|
|
|
if (!priv->mtu_initial && !priv->ip6_mtu_initial) {
|
|
|
|
|
/* before touching any of the MTU paramters, record the
|
|
|
|
|
* original setting to restore on deactivation. */
|
|
|
|
|
priv->mtu_initial = mtu_plat;
|
|
|
|
|
priv->ip6_mtu_initial = _IP6_MTU_SYS ();
|
|
|
|
|
}
|
2017-01-15 13:38:33 +01:00
|
|
|
|
2017-09-02 17:26:53 +02:00
|
|
|
if (mtu_desired && mtu_desired != mtu_plat) {
|
2017-10-23 15:41:07 +02:00
|
|
|
if (nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, mtu_desired) == NM_PLATFORM_ERROR_CANT_SET_MTU) {
|
|
|
|
|
anticipated_failure = TRUE;
|
|
|
|
|
_LOGW (LOGD_DEVICE, "mtu: failure to set MTU. %s",
|
|
|
|
|
NM_IS_DEVICE_VLAN (self)
|
|
|
|
|
? "Is the parent's MTU size large enough?"
|
|
|
|
|
: (!c_list_is_empty (&priv->slaves)
|
|
|
|
|
? "Are the MTU sizes of the slaves large enough?"
|
|
|
|
|
: "Did you configure the MTU correctly?"));
|
|
|
|
|
}
|
2017-09-02 17:26:53 +02:00
|
|
|
priv->carrier_wait_until_ms = nm_utils_get_monotonic_timestamp_ms () + CARRIER_WAIT_TIME_AFTER_MTU_MS;
|
|
|
|
|
}
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2017-01-16 10:20:26 +01:00
|
|
|
if (ip6_mtu && ip6_mtu != _IP6_MTU_SYS ()) {
|
2017-10-23 15:41:07 +02:00
|
|
|
if (!nm_device_ipv6_sysctl_set (self, "mtu",
|
|
|
|
|
nm_sprintf_buf (sbuf, "%u", (unsigned) ip6_mtu))) {
|
|
|
|
|
int errsv = errno;
|
|
|
|
|
|
|
|
|
|
_NMLOG (anticipated_failure && errsv == EINVAL ? LOGL_DEBUG : LOGL_WARN,
|
|
|
|
|
LOGD_DEVICE,
|
|
|
|
|
"mtu: failure to set IPv6 MTU%s",
|
|
|
|
|
anticipated_failure && errsv == EINVAL
|
|
|
|
|
? ": Is the underlying MTU value successfully set?"
|
|
|
|
|
: "");
|
|
|
|
|
}
|
2017-09-02 17:26:53 +02:00
|
|
|
priv->carrier_wait_until_ms = nm_utils_get_monotonic_timestamp_ms () + CARRIER_WAIT_TIME_AFTER_MTU_MS;
|
2017-01-13 18:40:50 +01:00
|
|
|
}
|
2015-02-25 15:35:26 +01:00
|
|
|
}
|
2017-01-16 10:20:26 +01:00
|
|
|
#undef _IP6_MTU_SYS
|
2017-01-13 18:40:50 +01:00
|
|
|
}
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2017-10-12 19:36:09 +02:00
|
|
|
void
|
|
|
|
|
nm_device_commit_mtu (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDeviceState state;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
state = nm_device_get_state (self);
|
|
|
|
|
if ( state >= NM_DEVICE_STATE_CONFIG
|
|
|
|
|
&& state < NM_DEVICE_STATE_DEACTIVATING) {
|
|
|
|
|
_LOGT (LOGD_DEVICE, "mtu: commit-mtu...");
|
|
|
|
|
_commit_mtu (self, NM_DEVICE_GET_PRIVATE (self)->ip4_config);
|
|
|
|
|
} else
|
|
|
|
|
_LOGT (LOGD_DEVICE, "mtu: commit-mtu... skip due to state %s", nm_device_state_to_str (state));
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-07 11:53:09 -05:00
|
|
|
static void
|
2016-10-13 11:06:25 +00:00
|
|
|
ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, NMDevice *self)
|
2011-10-07 11:53:09 -05:00
|
|
|
{
|
2016-10-13 11:06:25 +00:00
|
|
|
NMNDiscConfigMap changed = changed_int;
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-08-16 14:50:01 +02:00
|
|
|
guint i;
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2013-05-30 16:53:23 +02:00
|
|
|
g_return_if_fail (priv->act_request);
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2015-02-27 16:49:42 +01:00
|
|
|
if (!priv->ac_ip6_config)
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->ac_ip6_config = _ip6_config_new (self);
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
|
2017-08-16 14:50:01 +02:00
|
|
|
guint8 plen;
|
|
|
|
|
guint32 ifa_flags;
|
|
|
|
|
|
|
|
|
|
/* Check, whether kernel is recent enough to help user space handling RA.
|
|
|
|
|
* If it's not supported, we have no ipv6-privacy and must add autoconf
|
|
|
|
|
* addresses as /128. The reason for the /128 is to prevent the kernel
|
|
|
|
|
* from adding a prefix route for this address. */
|
|
|
|
|
ifa_flags = 0;
|
2017-10-10 18:20:05 +02:00
|
|
|
if (nm_platform_check_kernel_support (nm_device_get_platform (self),
|
|
|
|
|
NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)) {
|
2017-08-16 14:50:01 +02:00
|
|
|
ifa_flags |= IFA_F_NOPREFIXROUTE;
|
|
|
|
|
if (NM_IN_SET (priv->ndisc_use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
|
|
|
|
|
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
|
|
|
|
plen = 64;
|
|
|
|
|
} else
|
|
|
|
|
plen = 128;
|
|
|
|
|
|
2017-08-16 13:57:01 +02:00
|
|
|
nm_ip6_config_reset_addresses_ndisc (priv->ac_ip6_config,
|
|
|
|
|
rdata->addresses,
|
|
|
|
|
rdata->addresses_n,
|
2017-08-16 14:50:01 +02:00
|
|
|
plen,
|
2017-08-16 13:57:01 +02:00
|
|
|
ifa_flags);
|
2011-10-07 11:53:09 -05:00
|
|
|
}
|
|
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
if (NM_FLAGS_ANY (changed, NM_NDISC_CONFIG_ROUTES
|
|
|
|
|
| NM_NDISC_CONFIG_GATEWAYS)) {
|
2017-08-16 13:57:01 +02:00
|
|
|
nm_ip6_config_reset_routes_ndisc (priv->ac_ip6_config,
|
2017-10-04 15:21:21 +02:00
|
|
|
rdata->gateways,
|
|
|
|
|
rdata->gateways_n,
|
2017-08-16 13:57:01 +02:00
|
|
|
rdata->routes,
|
|
|
|
|
rdata->routes_n,
|
2017-09-28 18:48:39 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET6, TRUE),
|
core: use router preference for IPv6 routes
For routes and the default-route from NDisc, set the router preference
RTA_PREF.
Also, previously, we would only configure one IPv6 default-route. That by itself
was not really a problem, as long as NetworkManager would always make sure that
it configured the route to the ~best~ router.
Actually, NM should have done that already. It keeps the list of gateways
sorted, and prefers them according to their preference. But maybe
it didn't, so we have bug rh#1445417 (??).
Change that by configuring a default-route for all gateways, with
appropriate router prefrence. In case, kernel doesn't support RTA_PREF
yet, only configure all routes that share the same maxiumum preference.
https://bugzilla.redhat.com/show_bug.cgi?id=1445417
2017-10-09 10:58:47 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET6),
|
|
|
|
|
nm_platform_check_kernel_support (nm_device_get_platform (self),
|
|
|
|
|
NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF));
|
2011-10-07 11:53:09 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
|
|
|
|
|
/* Rebuild DNS server list from neighbor discovery cache. */
|
2013-05-30 16:53:23 +02:00
|
|
|
nm_ip6_config_reset_nameservers (priv->ac_ip6_config);
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2016-07-07 13:25:38 +02:00
|
|
|
for (i = 0; i < rdata->dns_servers_n; i++)
|
|
|
|
|
nm_ip6_config_add_nameserver (priv->ac_ip6_config, &rdata->dns_servers[i].address);
|
2011-10-07 11:53:09 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) {
|
|
|
|
|
/* Rebuild domain list from neighbor discovery cache. */
|
2016-11-01 13:33:32 +01:00
|
|
|
nm_ip6_config_reset_searches (priv->ac_ip6_config);
|
2013-12-19 10:58:46 -06:00
|
|
|
|
2016-07-07 13:25:38 +02:00
|
|
|
for (i = 0; i < rdata->dns_domains_n; i++)
|
2016-11-01 13:33:32 +01:00
|
|
|
nm_ip6_config_add_search (priv->ac_ip6_config, rdata->dns_domains[i].domain);
|
2013-05-30 16:53:23 +02:00
|
|
|
}
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
2015-06-30 16:13:03 +02:00
|
|
|
dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, TRUE);
|
2013-05-30 16:53:23 +02:00
|
|
|
|
2016-07-07 13:25:38 +02:00
|
|
|
priv->dhcp6.mode = rdata->dhcp_level;
|
2016-10-13 11:06:25 +00:00
|
|
|
if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE) {
|
2015-04-17 15:56:04 +02:00
|
|
|
_LOGD (LOGD_DEVICE | LOGD_DHCP6,
|
2014-02-12 23:54:26 +01:00
|
|
|
"Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6"
|
|
|
|
|
" as requested by IPv6 router...");
|
2017-02-22 17:04:00 +01:00
|
|
|
if (!dhcp6_start (self, FALSE)) {
|
2016-10-13 11:06:25 +00:00
|
|
|
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED,
|
|
|
|
|
NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
|
2016-01-14 20:42:01 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2013-05-30 16:53:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
2013-05-30 16:53:23 +02:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_sysctl_set_ip6_hop_limit_safe (nm_device_get_platform (self), nm_device_get_ip_iface (self), rdata->hop_limit);
|
2014-02-21 17:21:59 -05:00
|
|
|
|
2017-01-13 18:40:50 +01:00
|
|
|
if (changed & NM_NDISC_CONFIG_MTU) {
|
|
|
|
|
if (priv->ip6_mtu != rdata->mtu) {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "mtu: set IPv6 MTU to %u", (guint) rdata->mtu);
|
|
|
|
|
priv->ip6_mtu = rdata->mtu;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-10-09 12:06:53 +02:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
2011-10-07 11:53:09 -05:00
|
|
|
}
|
|
|
|
|
|
2014-08-13 09:40:08 -05:00
|
|
|
static void
|
2016-10-13 11:06:25 +00:00
|
|
|
ndisc_ra_timeout (NMNDisc *ndisc, NMDevice *self)
|
2014-08-13 09:40:08 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* We don't want to stop listening for router advertisements completely,
|
|
|
|
|
* but instead let device activation continue activating. If an RA
|
|
|
|
|
* shows up later, we'll use it as long as the device is not disconnected.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_IP6, "timed out waiting for IPv6 router advertisement");
|
2014-08-13 14:44:22 -05:00
|
|
|
if (priv->ip6_state == IP_CONF) {
|
|
|
|
|
/* If RA is our only source of addressing information and we don't
|
|
|
|
|
* ever receive one, then time out IPv6. But if there is other
|
|
|
|
|
* IPv6 configuration, like manual IPv6 addresses or external IPv6
|
|
|
|
|
* config, consider that sufficient for IPv6 success.
|
|
|
|
|
*/
|
2016-02-03 09:05:25 +01:00
|
|
|
if ( priv->ip6_config
|
|
|
|
|
&& nm_ip6_config_get_address_first_nontentative (priv->ip6_config, FALSE))
|
2014-08-13 14:44:22 -05:00
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
|
|
|
|
else
|
|
|
|
|
nm_device_activate_schedule_ip6_config_timeout (self);
|
|
|
|
|
}
|
2014-08-13 09:40:08 -05:00
|
|
|
}
|
|
|
|
|
|
2014-07-22 16:24:07 -05:00
|
|
|
static gboolean
|
2014-07-22 16:20:36 -05:00
|
|
|
addrconf6_start_with_link_ready (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMUtilsIPv6IfaceId iid;
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
g_assert (priv->ndisc);
|
2014-07-22 16:20:36 -05:00
|
|
|
|
2016-05-11 12:19:28 +02:00
|
|
|
if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) {
|
2015-10-03 19:44:27 +02:00
|
|
|
_LOGD (LOGD_IP6, "addrconf6: using the device EUI-64 identifier");
|
2016-10-13 11:06:25 +00:00
|
|
|
nm_ndisc_set_iid (priv->ndisc, iid);
|
2015-10-03 19:44:27 +02:00
|
|
|
} else {
|
2016-10-13 11:06:25 +00:00
|
|
|
/* Don't abort the addrconf at this point -- if ndisc needs the iid
|
2015-10-03 19:44:27 +02:00
|
|
|
* it will notice this itself. */
|
|
|
|
|
_LOGI (LOGD_IP6, "addrconf6: no interface identifier; IPv6 adddress creation may fail");
|
2014-07-22 16:24:07 -05:00
|
|
|
}
|
2014-07-22 16:20:36 -05:00
|
|
|
|
2014-08-13 14:29:25 -05:00
|
|
|
/* Apply any manual configuration before starting RA */
|
2017-09-25 14:28:16 +02:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE)) {
|
2014-08-13 14:29:25 -05:00
|
|
|
_LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration");
|
2017-09-25 14:28:16 +02:00
|
|
|
g_clear_object (&priv->con_ip6_config);
|
|
|
|
|
}
|
2014-08-13 14:29:25 -05:00
|
|
|
|
2016-11-03 12:15:32 +01:00
|
|
|
/* XXX: These sysctls would probably be better set by the lndp ndisc itself. */
|
|
|
|
|
switch (nm_ndisc_get_node_type (priv->ndisc)) {
|
|
|
|
|
case NM_NDISC_NODE_TYPE_HOST:
|
|
|
|
|
/* Accepting prefixes from discovered routers. */
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra", "1");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
|
|
|
|
|
break;
|
|
|
|
|
case NM_NDISC_NODE_TYPE_ROUTER:
|
|
|
|
|
/* We're the router. */
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "forwarding", "1");
|
|
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
2016-11-03 12:05:12 +01:00
|
|
|
priv->needs_ip6_subnet = TRUE;
|
|
|
|
|
g_signal_emit (self, signals[IP6_SUBNET_NEEDED], 0);
|
2016-11-03 12:15:32 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
2014-07-22 16:20:36 -05:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
priv->ndisc_changed_id = g_signal_connect (priv->ndisc,
|
2016-11-09 17:21:41 +01:00
|
|
|
NM_NDISC_CONFIG_RECEIVED,
|
2016-10-13 11:06:25 +00:00
|
|
|
G_CALLBACK (ndisc_config_changed),
|
2014-08-13 09:40:08 -05:00
|
|
|
self);
|
2016-10-13 11:06:25 +00:00
|
|
|
priv->ndisc_timeout_id = g_signal_connect (priv->ndisc,
|
|
|
|
|
NM_NDISC_RA_TIMEOUT,
|
|
|
|
|
G_CALLBACK (ndisc_ra_timeout),
|
2014-08-13 09:40:08 -05:00
|
|
|
self);
|
2014-09-27 09:04:46 +02:00
|
|
|
|
2016-11-03 12:15:32 +01:00
|
|
|
ndisc_set_router_config (priv->ndisc, self);
|
2016-10-13 11:06:25 +00:00
|
|
|
nm_ndisc_start (priv->ndisc);
|
2014-07-22 16:24:07 -05:00
|
|
|
return TRUE;
|
2014-07-22 16:20:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-11-03 12:15:32 +01:00
|
|
|
static NMNDiscNodeType
|
|
|
|
|
ndisc_node_type (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
g_assert (connection);
|
|
|
|
|
|
|
|
|
|
if (strcmp (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG),
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
|
|
|
|
|
return NM_NDISC_NODE_TYPE_ROUTER;
|
|
|
|
|
else
|
|
|
|
|
return NM_NDISC_NODE_TYPE_HOST;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-14 15:40:29 -06:00
|
|
|
static gboolean
|
2014-01-03 17:03:35 +01:00
|
|
|
addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
2011-10-07 11:53:09 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
2013-11-07 22:59:43 +01:00
|
|
|
NMActStageReturn ret;
|
2015-10-03 19:44:27 +02:00
|
|
|
NMSettingIP6Config *s_ip6 = NULL;
|
2015-12-17 15:49:03 +01:00
|
|
|
GError *error = NULL;
|
2016-06-21 18:07:56 +02:00
|
|
|
NMUtilsStableType stable_type;
|
|
|
|
|
const char *stable_id;
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2011-10-07 11:53:09 -05:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
2011-10-21 14:25:35 -05:00
|
|
|
g_warn_if_fail (priv->ac_ip6_config == NULL);
|
|
|
|
|
if (priv->ac_ip6_config) {
|
|
|
|
|
g_object_unref (priv->ac_ip6_config);
|
|
|
|
|
priv->ac_ip6_config = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-13 16:45:22 +02:00
|
|
|
g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref);
|
|
|
|
|
nm_clear_g_source (&priv->rt6_temporary_not_available_id);
|
|
|
|
|
|
2015-10-03 19:44:27 +02:00
|
|
|
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
|
|
|
|
|
g_assert (s_ip6);
|
|
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
stable_id = _get_stable_id (self, connection, &stable_type);
|
2017-05-08 14:42:40 +02:00
|
|
|
g_assert (stable_id);
|
|
|
|
|
priv->ndisc = nm_lndp_ndisc_new (nm_device_get_platform (self),
|
|
|
|
|
nm_device_get_ip_ifindex (self),
|
|
|
|
|
nm_device_get_ip_iface (self),
|
|
|
|
|
stable_type,
|
|
|
|
|
stable_id,
|
|
|
|
|
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
|
|
|
|
|
ndisc_node_type (self),
|
|
|
|
|
&error);
|
2016-10-13 11:06:25 +00:00
|
|
|
if (!priv->ndisc) {
|
|
|
|
|
_LOGE (LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message);
|
2015-12-17 15:49:03 +01:00
|
|
|
g_error_free (error);
|
2013-05-30 16:53:23 +02:00
|
|
|
return FALSE;
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
priv->ndisc_use_tempaddr = use_tempaddr;
|
2015-10-20 09:27:16 +02:00
|
|
|
|
|
|
|
|
if ( NM_IN_SET (use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
2017-10-10 18:20:05 +02:00
|
|
|
&& !nm_platform_check_kernel_support (nm_device_get_platform (self),
|
|
|
|
|
NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)) {
|
2015-10-20 09:27:16 +02:00
|
|
|
_LOGW (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for "
|
|
|
|
|
"IPv6 private addresses. This feature is not available");
|
|
|
|
|
}
|
2014-01-03 17:03:35 +01:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
if (!nm_setting_ip_config_get_may_fail (nm_connection_get_setting_ip6_config (connection)))
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_add_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, TRUE);
|
2014-04-14 17:57:56 +02:00
|
|
|
|
2013-11-07 22:59:43 +01:00
|
|
|
/* ensure link local is ready... */
|
|
|
|
|
ret = linklocal6_start (self);
|
2014-07-22 16:24:07 -05:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
|
|
|
|
|
/* success; wait for the LL address to show up */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2013-11-07 22:59:43 +01:00
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
/* success; already have the LL address; kick off neighbor discovery */
|
2016-08-29 15:33:33 +02:00
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
2014-07-22 16:24:07 -05:00
|
|
|
return addrconf6_start_with_link_ready (self);
|
2013-11-07 22:59:43 +01:00
|
|
|
}
|
|
|
|
|
|
2011-10-07 11:53:09 -05:00
|
|
|
static void
|
|
|
|
|
addrconf6_cleanup (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_changed_id);
|
|
|
|
|
nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_timeout_id);
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE);
|
2014-04-14 17:57:56 +02:00
|
|
|
|
2013-05-30 16:53:23 +02:00
|
|
|
g_clear_object (&priv->ac_ip6_config);
|
2017-09-13 16:45:22 +02:00
|
|
|
g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref);
|
|
|
|
|
nm_clear_g_source (&priv->rt6_temporary_not_available_id);
|
2016-10-13 11:06:25 +00:00
|
|
|
g_clear_object (&priv->ndisc);
|
2011-10-07 11:53:09 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2011-10-07 11:53:09 -05:00
|
|
|
|
2014-05-20 15:17:13 -05:00
|
|
|
static const char *ip6_properties_to_save[] = {
|
|
|
|
|
"accept_ra",
|
|
|
|
|
"accept_ra_defrtr",
|
|
|
|
|
"accept_ra_pinfo",
|
|
|
|
|
"accept_ra_rtr_pref",
|
2016-11-03 12:15:32 +01:00
|
|
|
"forwarding",
|
2014-05-20 15:17:13 -05:00
|
|
|
"disable_ipv6",
|
|
|
|
|
"hop_limit",
|
|
|
|
|
"use_tempaddr",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
save_ip6_properties (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
const char *ifname = nm_device_get_ip_iface (self);
|
|
|
|
|
char *value;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
g_hash_table_remove_all (priv->ip6_saved_properties);
|
|
|
|
|
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!nm_device_get_ip_ifindex (self))
|
|
|
|
|
return;
|
|
|
|
|
|
2014-05-20 15:17:13 -05:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (ip6_properties_to_save); i++) {
|
2017-10-23 13:55:54 +02:00
|
|
|
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
|
2017-10-23 13:55:54 +02:00
|
|
|
|
2017-10-23 13:55:54 +02:00
|
|
|
value = nm_platform_sysctl_get (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET6, buf, ifname, ip6_properties_to_save[i])));
|
2014-05-20 15:17:13 -05:00
|
|
|
if (value) {
|
|
|
|
|
g_hash_table_insert (priv->ip6_saved_properties,
|
|
|
|
|
(char *) ip6_properties_to_save[i],
|
|
|
|
|
value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
restore_ip6_properties (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
gpointer key, value;
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, priv->ip6_saved_properties);
|
2014-07-24 17:14:30 -05:00
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
|
|
|
/* Don't touch "disable_ipv6" if we're doing userland IPv6LL */
|
|
|
|
|
if (priv->nm_ipv6ll && strcmp (key, "disable_ipv6") == 0)
|
|
|
|
|
continue;
|
2014-05-20 15:17:13 -05:00
|
|
|
nm_device_ipv6_sysctl_set (self, key, value);
|
2014-07-24 17:14:30 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_disable_ipv6 (NMDevice *self, const char *value)
|
|
|
|
|
{
|
|
|
|
|
/* We only touch disable_ipv6 when NM is not managing the IPv6LL address */
|
|
|
|
|
if (NM_DEVICE_GET_PRIVATE (self)->nm_ipv6ll == FALSE)
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "disable_ipv6", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_nm_ipv6ll (NMDevice *self, gboolean enable)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
int ifindex = nm_device_get_ip_ifindex (self);
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
char *value;
|
2014-07-24 17:14:30 -05:00
|
|
|
|
2017-10-10 18:20:05 +02:00
|
|
|
if (!nm_platform_check_kernel_support (nm_device_get_platform (self),
|
|
|
|
|
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
|
2014-07-24 17:14:30 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
priv->nm_ipv6ll = enable;
|
|
|
|
|
if (ifindex > 0) {
|
device: tune down warning about failure to set userspace IPv6LL on non-existing device
When a device gets removed externally, we still try to clear userspace IPv6LL address handling.
That fails, due to non-existing device. Such a failure should not be logged as warning.
<debug> [1467723214.2078] device[0x558c59335ca0] (enp0s25): disposing
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): remove_pending_action (0): 'dhcp6' not pending (expected)
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): remove_pending_action (0): 'autoconf6' not pending (expected)
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): will disable userland IPv6LL
<debug> [1467723214.2079] platform-linux: link: change 20: user-ipv6ll: set IPv6 address generation mode to eui64
<trace> [1467723214.2080] platform-linux: delayed-action: schedule wait-for-nl-response (seq 92, timeout in 0.199998611)
<trace> [1467723214.2080] platform-linux: delayed-action: schedule refresh-link (ifindex 20)
<trace> [1467723214.2080] platform-linux: delayed-action: handle refresh-link (ifindex 20)
<debug> [1467723214.2080] platform-linux: do-request-link: 20
<trace> [1467723214.2080] platform-linux: netlink: recvmsg: new message type 2, seq 92
<debug> [1467723214.2080] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 92
<trace> [1467723214.2081] platform-linux: delayed-action: complete wait-for-nl-response (seq 92, timeout in 0.199895684, failure 19 (No such device))
<trace> [1467723214.2081] platform-linux: delayed-action: schedule wait-for-nl-response (seq 93, timeout in 0.199999306)
<trace> [1467723214.2081] platform-linux: delayed-action: handle wait-for-nl-response (any)
<trace> [1467723214.2081] platform-linux: netlink: recvmsg: new message type 2, seq 93
<debug> [1467723214.2081] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 93
<trace> [1467723214.2082] platform-linux: delayed-action: complete wait-for-nl-response (seq 93, timeout in 0.199921142, failure 19 (No such device))
<debug> [1467723214.2082] platform-linux: do-change-link[20]: failure changing link: failure 19 (No such device)
<warn> [1467723214.2082] device (enp0s25): failed to disable userspace IPv6LL address handling
https://bugzilla.redhat.com/show_bug.cgi?id=1323571
2016-07-05 15:04:37 +02:00
|
|
|
NMPlatformError plerr;
|
2014-07-24 17:14:30 -05:00
|
|
|
const char *detail = enable ? "enable" : "disable";
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_IP6, "will %s userland IPv6LL", detail);
|
2017-04-17 20:17:45 +02:00
|
|
|
plerr = nm_platform_link_set_user_ipv6ll_enabled (nm_device_get_platform (self), ifindex, enable);
|
device: tune down warning about failure to set userspace IPv6LL on non-existing device
When a device gets removed externally, we still try to clear userspace IPv6LL address handling.
That fails, due to non-existing device. Such a failure should not be logged as warning.
<debug> [1467723214.2078] device[0x558c59335ca0] (enp0s25): disposing
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): remove_pending_action (0): 'dhcp6' not pending (expected)
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): remove_pending_action (0): 'autoconf6' not pending (expected)
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): will disable userland IPv6LL
<debug> [1467723214.2079] platform-linux: link: change 20: user-ipv6ll: set IPv6 address generation mode to eui64
<trace> [1467723214.2080] platform-linux: delayed-action: schedule wait-for-nl-response (seq 92, timeout in 0.199998611)
<trace> [1467723214.2080] platform-linux: delayed-action: schedule refresh-link (ifindex 20)
<trace> [1467723214.2080] platform-linux: delayed-action: handle refresh-link (ifindex 20)
<debug> [1467723214.2080] platform-linux: do-request-link: 20
<trace> [1467723214.2080] platform-linux: netlink: recvmsg: new message type 2, seq 92
<debug> [1467723214.2080] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 92
<trace> [1467723214.2081] platform-linux: delayed-action: complete wait-for-nl-response (seq 92, timeout in 0.199895684, failure 19 (No such device))
<trace> [1467723214.2081] platform-linux: delayed-action: schedule wait-for-nl-response (seq 93, timeout in 0.199999306)
<trace> [1467723214.2081] platform-linux: delayed-action: handle wait-for-nl-response (any)
<trace> [1467723214.2081] platform-linux: netlink: recvmsg: new message type 2, seq 93
<debug> [1467723214.2081] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 93
<trace> [1467723214.2082] platform-linux: delayed-action: complete wait-for-nl-response (seq 93, timeout in 0.199921142, failure 19 (No such device))
<debug> [1467723214.2082] platform-linux: do-change-link[20]: failure changing link: failure 19 (No such device)
<warn> [1467723214.2082] device (enp0s25): failed to disable userspace IPv6LL address handling
https://bugzilla.redhat.com/show_bug.cgi?id=1323571
2016-07-05 15:04:37 +02:00
|
|
|
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
|
|
|
|
|
_NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN,
|
|
|
|
|
LOGD_IP6,
|
|
|
|
|
"failed to %s userspace IPv6LL address handling (%s)",
|
|
|
|
|
detail,
|
2017-08-21 19:18:45 +02:00
|
|
|
nm_platform_error_to_string_a (plerr));
|
device: tune down warning about failure to set userspace IPv6LL on non-existing device
When a device gets removed externally, we still try to clear userspace IPv6LL address handling.
That fails, due to non-existing device. Such a failure should not be logged as warning.
<debug> [1467723214.2078] device[0x558c59335ca0] (enp0s25): disposing
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): remove_pending_action (0): 'dhcp6' not pending (expected)
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): remove_pending_action (0): 'autoconf6' not pending (expected)
<debug> [1467723214.2079] device[0x558c59335ca0] (enp0s25): will disable userland IPv6LL
<debug> [1467723214.2079] platform-linux: link: change 20: user-ipv6ll: set IPv6 address generation mode to eui64
<trace> [1467723214.2080] platform-linux: delayed-action: schedule wait-for-nl-response (seq 92, timeout in 0.199998611)
<trace> [1467723214.2080] platform-linux: delayed-action: schedule refresh-link (ifindex 20)
<trace> [1467723214.2080] platform-linux: delayed-action: handle refresh-link (ifindex 20)
<debug> [1467723214.2080] platform-linux: do-request-link: 20
<trace> [1467723214.2080] platform-linux: netlink: recvmsg: new message type 2, seq 92
<debug> [1467723214.2080] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 92
<trace> [1467723214.2081] platform-linux: delayed-action: complete wait-for-nl-response (seq 92, timeout in 0.199895684, failure 19 (No such device))
<trace> [1467723214.2081] platform-linux: delayed-action: schedule wait-for-nl-response (seq 93, timeout in 0.199999306)
<trace> [1467723214.2081] platform-linux: delayed-action: handle wait-for-nl-response (any)
<trace> [1467723214.2081] platform-linux: netlink: recvmsg: new message type 2, seq 93
<debug> [1467723214.2081] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 93
<trace> [1467723214.2082] platform-linux: delayed-action: complete wait-for-nl-response (seq 93, timeout in 0.199921142, failure 19 (No such device))
<debug> [1467723214.2082] platform-linux: do-change-link[20]: failure changing link: failure 19 (No such device)
<warn> [1467723214.2082] device (enp0s25): failed to disable userspace IPv6LL address handling
https://bugzilla.redhat.com/show_bug.cgi?id=1323571
2016-07-05 15:04:37 +02:00
|
|
|
}
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
|
|
|
|
|
if (enable) {
|
2017-10-23 13:55:54 +02:00
|
|
|
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
|
2017-10-23 13:55:54 +02:00
|
|
|
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
/* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */
|
2017-04-17 20:17:45 +02:00
|
|
|
value = nm_platform_sysctl_get (nm_device_get_platform (self),
|
2017-10-23 13:55:54 +02:00
|
|
|
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET6, buf, nm_device_get_ip_iface (self), "disable_ipv6")));
|
2014-12-19 10:45:31 -06:00
|
|
|
if (g_strcmp0 (value, "0") == 0)
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1");
|
|
|
|
|
g_free (value);
|
2014-12-19 10:45:31 -06:00
|
|
|
|
|
|
|
|
/* Ensure IPv6 is enabled */
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "disable_ipv6", "0");
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
}
|
|
|
|
|
|
2014-07-24 17:14:30 -05:00
|
|
|
}
|
2014-05-20 15:17:13 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-04-16 16:38:00 +02:00
|
|
|
|
2014-01-03 17:03:35 +01:00
|
|
|
static NMSettingIP6ConfigPrivacy
|
2015-04-16 16:38:00 +02:00
|
|
|
_ip6_privacy_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
|
2014-01-03 17:03:35 +01:00
|
|
|
{
|
|
|
|
|
switch (use_tempaddr) {
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
|
|
|
|
|
return use_tempaddr;
|
|
|
|
|
default:
|
|
|
|
|
return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 16:38:00 +02:00
|
|
|
static NMSettingIP6ConfigPrivacy
|
|
|
|
|
_ip6_privacy_get (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMSettingIP6ConfigPrivacy ip6_privacy;
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
|
|
|
|
|
2015-06-02 17:38:07 +02:00
|
|
|
/* 1.) First look at the per-connection setting. If it is not -1 (unknown),
|
2015-04-16 16:38:00 +02:00
|
|
|
* use it. */
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2015-04-16 16:38:00 +02:00
|
|
|
if (connection) {
|
|
|
|
|
NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
|
|
|
|
|
if (s_ip6) {
|
|
|
|
|
ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6));
|
|
|
|
|
ip6_privacy = _ip6_privacy_clamp (ip6_privacy);
|
|
|
|
|
if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
|
|
|
|
|
return ip6_privacy;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-09 08:47:41 +02:00
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
2015-06-02 17:38:07 +02:00
|
|
|
"ipv6.ip6-privacy", self);
|
2015-04-16 16:38:00 +02:00
|
|
|
|
2015-06-02 17:38:07 +02:00
|
|
|
/* 2.) use the default value from the configuration. */
|
2015-04-16 16:38:00 +02:00
|
|
|
ip6_privacy = _nm_utils_ascii_str_to_int64 (value, 10,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
|
|
|
|
if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
|
|
|
|
|
return ip6_privacy;
|
|
|
|
|
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!nm_device_get_ip_ifindex (self))
|
|
|
|
|
return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;;
|
|
|
|
|
|
2015-06-02 17:38:07 +02:00
|
|
|
/* 3.) No valid default-value configured. Fallback to reading sysctl.
|
2015-04-16 16:38:00 +02:00
|
|
|
*
|
|
|
|
|
* Instead of reading static config files in /etc, just read the current sysctl value.
|
|
|
|
|
* This works as NM only writes to "/proc/sys/net/ipv6/conf/IFNAME/use_tempaddr", but leaves
|
|
|
|
|
* the "default" entry untouched. */
|
2017-04-17 20:17:45 +02:00
|
|
|
ip6_privacy = nm_platform_sysctl_get_int32 (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/default/use_tempaddr"), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
2015-04-16 16:38:00 +02:00
|
|
|
return _ip6_privacy_clamp (ip6_privacy);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-04-16 16:38:00 +02:00
|
|
|
|
2013-01-25 11:59:05 -06:00
|
|
|
static gboolean
|
|
|
|
|
ip6_requires_slaves (NMConnection *connection)
|
|
|
|
|
{
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
const char *method;
|
2013-01-25 11:59:05 -06:00
|
|
|
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
2013-01-25 11:59:05 -06:00
|
|
|
|
|
|
|
|
/* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
|
2016-11-05 18:37:53 +01:00
|
|
|
* to complete addressing. SLAAC and DHCP need a peer to provide a prefix.
|
2013-01-25 11:59:05 -06:00
|
|
|
*/
|
2013-09-26 17:34:23 -04:00
|
|
|
return strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
2016-11-05 18:37:53 +01:00
|
|
|
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0;
|
2013-01-25 11:59:05 -06:00
|
|
|
}
|
|
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
static NMActStageReturn
|
2012-09-27 12:12:15 -04:00
|
|
|
act_stage3_ip6_config_start (NMDevice *self,
|
|
|
|
|
NMIP6Config **out_config,
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason *out_failure_reason)
|
2009-07-29 12:12:41 -04:00
|
|
|
{
|
2009-07-30 13:50:42 -04:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2010-04-30 15:49:41 -07:00
|
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
2010-01-14 00:45:10 -08:00
|
|
|
NMConnection *connection;
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
const char *method;
|
2012-02-21 15:44:19 +01:00
|
|
|
NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
2016-08-31 19:11:25 +02:00
|
|
|
const char *ip6_privacy_str = "0";
|
2009-07-30 13:50:42 -04:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2017-02-22 17:04:00 +01:00
|
|
|
g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE);
|
2010-01-14 00:45:10 -08:00
|
|
|
|
2015-03-16 18:27:35 +01:00
|
|
|
if ( connection_ip6_method_requires_carrier (connection, NULL)
|
2017-06-01 23:08:30 +02:00
|
|
|
&& nm_device_is_master (self)
|
2014-02-25 18:00:34 -06:00
|
|
|
&& !priv->carrier) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_IP6 | LOGD_DEVICE,
|
|
|
|
|
"IPv6 config waiting until carrier is on");
|
2016-08-31 18:51:16 +02:00
|
|
|
return NM_ACT_STAGE_RETURN_IP_WAIT;
|
2013-06-07 15:11:23 -05:00
|
|
|
}
|
2010-01-14 00:45:10 -08:00
|
|
|
|
2017-06-01 23:08:30 +02:00
|
|
|
if (nm_device_is_master (self) && ip6_requires_slaves (connection)) {
|
2013-01-25 11:59:05 -06:00
|
|
|
/* If the master has no ready slaves, and depends on slaves for
|
|
|
|
|
* a successful IPv6 attempt, then postpone IPv6 addressing.
|
|
|
|
|
*/
|
2017-05-14 09:52:18 +02:00
|
|
|
if (!have_any_ready_slaves (self)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DEVICE | LOGD_IP6,
|
|
|
|
|
"IPv6 config waiting until slaves are ready");
|
2016-08-31 18:51:16 +02:00
|
|
|
return NM_ACT_STAGE_RETURN_IP_WAIT;
|
2013-01-25 11:59:05 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-13 11:06:25 +00:00
|
|
|
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
|
2016-04-07 15:09:54 +02:00
|
|
|
priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX;
|
2010-05-01 10:16:38 -07:00
|
|
|
|
2014-10-14 11:41:36 -05:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
|
2013-10-08 13:51:00 -04:00
|
|
|
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
|
2017-09-19 18:25:21 +02:00
|
|
|
if ( !priv->master
|
|
|
|
|
&& !nm_device_sys_iface_state_is_external (self)) {
|
2014-12-16 14:38:17 -06:00
|
|
|
gboolean old_nm_ipv6ll = priv->nm_ipv6ll;
|
|
|
|
|
|
2014-10-02 15:58:44 -05:00
|
|
|
/* When activating an IPv6 'ignore' connection we need to revert back
|
|
|
|
|
* to kernel IPv6LL, but the kernel won't actually assign an address
|
|
|
|
|
* to the interface until disable_ipv6 is bounced.
|
|
|
|
|
*/
|
|
|
|
|
set_nm_ipv6ll (self, FALSE);
|
2014-12-16 14:38:17 -06:00
|
|
|
if (old_nm_ipv6ll == TRUE)
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1");
|
2013-10-08 13:51:00 -04:00
|
|
|
restore_ip6_properties (self);
|
2014-10-02 15:58:44 -05:00
|
|
|
}
|
device: don't set ip4_state=IP_FAIL for ipv4.method=disabled
... and don't set ip6_state=IP_FAIL for ipv6.method=ignore.
The disabled state is like having an empty NMIP4Config object.
It should not result in %IP_FAIL state. Instead, we just want
to proceed and commit an empty NMIP4Config instance.
This was introduced by commit 0652d9c5961e4636eab87647af890aaf8c3e3269,
which I think was wrong.
Likewise, for ipv6.method=ignore we also don't want to mark the
IP state as failed. Instead, we want to proceed and set IP_DONE
right away -- without commiting anything, which is a difference
to the IPv4 case.
This is especially important, because an ip4_state/ip6_state of IP_FAIL
causes nm_device_can_assume_active_connection() to return FALSE, which
means we unmanage devices at shutdown. Ony might say that it doesn't
matter so much for a device without IP configuration, but imagine a
bond with VLANs on top that only has Layer 2 configuration. This will
bring down the entire stack.
With this change, devices with IP methods disabled/ignore stay up on
exit of NetworkManager (rh#1371126). Of course, that means on restart
software devices stay unamanged due to external-down (because since
commit e1edcda, devices without IP address are also external-down).
So, this really just fixes one scenario, breaking another one.
This should be fixed with bgo#746440 by not assuming connections.
https://bugzilla.redhat.com/show_bug.cgi?id=1371126
2016-08-29 15:37:55 +02:00
|
|
|
return NM_ACT_STAGE_RETURN_IP_DONE;
|
2013-10-08 13:51:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-02-25 15:35:26 +01:00
|
|
|
/* Ensure the MTU makes sense. If it was below 1280 the kernel would not
|
|
|
|
|
* expose any ipv6 sysctls or allow presence of any addresses on the interface,
|
|
|
|
|
* including LL, which * would make it impossible to autoconfigure MTU to a
|
|
|
|
|
* correct value. */
|
2017-01-15 13:38:33 +01:00
|
|
|
_commit_mtu (self, priv->ip4_config);
|
2015-02-25 15:35:26 +01:00
|
|
|
|
2014-10-02 15:58:44 -05:00
|
|
|
/* Any method past this point requires an IPv6LL address. Use NM-controlled
|
|
|
|
|
* IPv6LL if this is not an assumed connection, since assumed connections
|
|
|
|
|
* will already have IPv6 set up.
|
|
|
|
|
*/
|
2017-03-13 15:34:14 +01:00
|
|
|
if (!nm_device_sys_iface_state_is_external_or_assume (self))
|
2014-10-02 15:58:44 -05:00
|
|
|
set_nm_ipv6ll (self, TRUE);
|
|
|
|
|
|
2013-10-08 13:51:00 -04:00
|
|
|
/* Re-enable IPv6 on the interface */
|
2014-07-24 17:14:30 -05:00
|
|
|
set_disable_ipv6 (self, "0");
|
2013-10-08 13:51:00 -04:00
|
|
|
|
2017-05-06 10:56:21 +02:00
|
|
|
/* Synchronize external IPv6 configuration with kernel, since
|
|
|
|
|
* linklocal6_start() uses the information there to determine if we can
|
|
|
|
|
* proceed with the selected method (SLAAC, DHCP, link-local).
|
|
|
|
|
*/
|
|
|
|
|
nm_platform_process_events (nm_device_get_platform (self));
|
|
|
|
|
g_clear_object (&priv->ext_ip6_config_captured);
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self),
|
|
|
|
|
nm_device_get_platform (self),
|
2017-05-22 17:04:48 +02:00
|
|
|
nm_device_get_ip_ifindex (self),
|
2017-05-06 10:56:21 +02:00
|
|
|
FALSE,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
|
|
|
|
|
2015-04-16 16:38:00 +02:00
|
|
|
ip6_privacy = _ip6_privacy_get (self);
|
2014-01-03 17:03:35 +01:00
|
|
|
|
2016-11-03 12:15:32 +01:00
|
|
|
if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
|
|
|
|
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
|
2014-01-03 17:03:35 +01:00
|
|
|
if (!addrconf6_start (self, ip6_privacy)) {
|
2013-10-07 11:40:16 -05:00
|
|
|
/* IPv6 might be disabled; allow IPv4 to proceed */
|
2016-08-31 18:51:16 +02:00
|
|
|
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
|
2011-10-09 22:50:04 -05:00
|
|
|
} else
|
|
|
|
|
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
2013-11-07 20:38:08 +01:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
|
|
|
|
|
ret = linklocal6_start (self);
|
2013-05-07 13:08:33 -05:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
|
2016-10-13 11:06:25 +00:00
|
|
|
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED;
|
2017-02-22 17:04:00 +01:00
|
|
|
if (!dhcp6_start (self, TRUE)) {
|
2014-11-14 16:04:44 -06:00
|
|
|
/* IPv6 might be disabled; allow IPv4 to proceed */
|
2016-08-31 18:51:16 +02:00
|
|
|
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
|
2014-11-14 16:04:44 -06:00
|
|
|
} else
|
|
|
|
|
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
2013-05-07 13:08:33 -05:00
|
|
|
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) {
|
2010-04-30 15:49:41 -07:00
|
|
|
ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
2014-02-12 23:54:26 +01:00
|
|
|
} else
|
|
|
|
|
_LOGW (LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method);
|
2010-04-30 15:49:41 -07:00
|
|
|
|
2016-08-31 19:11:25 +02:00
|
|
|
if ( ret != NM_ACT_STAGE_RETURN_FAILURE
|
2017-03-13 15:34:14 +01:00
|
|
|
&& !nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2016-08-31 19:11:25 +02:00
|
|
|
switch (ip6_privacy) {
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
|
|
|
|
|
ip6_privacy_str = "0";
|
|
|
|
|
break;
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
|
|
|
|
|
ip6_privacy_str = "1";
|
|
|
|
|
break;
|
|
|
|
|
case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
|
|
|
|
|
ip6_privacy_str = "2";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "use_tempaddr", ip6_privacy_str);
|
2012-02-21 15:44:19 +01:00
|
|
|
}
|
|
|
|
|
|
2010-01-14 00:45:10 -08:00
|
|
|
return ret;
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
2012-11-15 17:52:24 -06:00
|
|
|
/**
|
|
|
|
|
* nm_device_activate_stage3_ip4_start:
|
|
|
|
|
* @self: the device
|
|
|
|
|
*
|
|
|
|
|
* Try starting IPv4 configuration.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_stage3_ip4_start (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMActStageReturn ret;
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
2012-11-15 17:52:24 -06:00
|
|
|
NMIP4Config *ip4_config = NULL;
|
|
|
|
|
|
|
|
|
|
g_assert (priv->ip4_state == IP_WAIT);
|
|
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_CONF);
|
2017-02-22 17:04:00 +01:00
|
|
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &failure_reason);
|
2012-11-15 17:52:24 -06:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
2016-08-31 20:01:12 +02:00
|
|
|
if (!ip4_config)
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
ip4_config = _ip4_config_new (self);
|
2016-08-31 20:01:12 +02:00
|
|
|
nm_device_activate_schedule_ip4_config_result (self, ip4_config);
|
|
|
|
|
g_object_unref (ip4_config);
|
|
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) {
|
|
|
|
|
_set_ip_state (self, AF_INET, IP_DONE);
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2012-11-15 17:52:24 -06:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
|
2012-11-15 17:52:24 -06:00
|
|
|
return FALSE;
|
2016-08-31 18:51:16 +02:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_IP_FAIL) {
|
2016-08-29 15:33:33 +02:00
|
|
|
/* Activation not wanted */
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_FAIL);
|
2016-08-31 18:51:16 +02:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_IP_WAIT) {
|
2012-11-15 17:52:24 -06:00
|
|
|
/* Wait for something to try IP config again */
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_WAIT);
|
2012-11-15 17:52:24 -06:00
|
|
|
} else
|
|
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_device_activate_stage3_ip6_start:
|
|
|
|
|
* @self: the device
|
|
|
|
|
*
|
|
|
|
|
* Try starting IPv6 configuration.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_stage3_ip6_start (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMActStageReturn ret;
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
2012-11-15 17:52:24 -06:00
|
|
|
NMIP6Config *ip6_config = NULL;
|
|
|
|
|
|
|
|
|
|
g_assert (priv->ip6_state == IP_WAIT);
|
|
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_CONF);
|
2017-02-22 17:04:00 +01:00
|
|
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &failure_reason);
|
2012-11-15 17:52:24 -06:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
|
2016-08-31 20:01:12 +02:00
|
|
|
if (!ip6_config)
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
ip6_config = _ip6_config_new (self);
|
2016-08-31 20:01:12 +02:00
|
|
|
/* Here we get a static IPv6 config, like for Shared where it's
|
|
|
|
|
* autogenerated or from modems where it comes from ModemManager.
|
|
|
|
|
*/
|
|
|
|
|
g_warn_if_fail (priv->ac_ip6_config == NULL);
|
|
|
|
|
priv->ac_ip6_config = ip6_config;
|
|
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
|
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) {
|
|
|
|
|
_set_ip_state (self, AF_INET6, IP_DONE);
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2012-11-15 17:52:24 -06:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
|
2012-11-15 17:52:24 -06:00
|
|
|
return FALSE;
|
2016-08-31 18:51:16 +02:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_IP_FAIL) {
|
2015-03-16 19:06:04 +01:00
|
|
|
/* Activation not wanted */
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_FAIL);
|
2016-08-31 18:51:16 +02:00
|
|
|
} else if (ret == NM_ACT_STAGE_RETURN_IP_WAIT) {
|
2012-11-15 17:52:24 -06:00
|
|
|
/* Wait for something to try IP config again */
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_WAIT);
|
2012-11-15 17:52:24 -06:00
|
|
|
} else
|
|
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2006-01-03 17:47:38 +00:00
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/*
|
2015-10-07 12:07:51 +02:00
|
|
|
* activate_stage3_ip_config_start
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
2009-07-29 12:12:41 -04:00
|
|
|
* Begin automatic/manual IP configuration
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
|
|
|
|
*/
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2015-10-07 12:07:51 +02:00
|
|
|
activate_stage3_ip_config_start (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_WAIT);
|
|
|
|
|
_set_ip_state (self, AF_INET6, IP_WAIT);
|
2013-10-21 12:50:58 -04:00
|
|
|
|
2017-09-26 14:08:27 +02:00
|
|
|
_active_connection_set_state_flags (self,
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_LAYER2_READY);
|
|
|
|
|
|
2008-07-11 10:28:53 +00:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
core: don't up devices during IP configuration stages
Assumed connections shouldn't require touching the device, and the
device should was already set IFF_UP during stage2 (which is
skipped for assumed connections). Instead, what the code was really
trying to do, was to ensure tha the IP interface the device was
going to use was up.
The only cases where the IP interface might *not* be up after stage2
is where the IP interface is different than the device's interface,
like for Bluetooth, ADSL, WWAN, and PPPoE. Move the call to
nm_platform_link_set_up() into nm_device_set_ip_iface() which all
those device types will call.
Thus, only the device types that really need to up their IP interface
will do so, but other devices (including when activating assumed
connections) that don't need to do this, won't do it.
2013-11-08 10:58:35 -06:00
|
|
|
/* Device should be up before we can do anything with it */
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_is_up (nm_device_get_platform (self), nm_device_get_ip_ifindex (self)))
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self));
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
/* IPv4 */
|
2015-11-09 11:44:09 +01:00
|
|
|
if ( nm_device_activate_ip4_state_in_wait (self)
|
|
|
|
|
&& !nm_device_activate_stage3_ip4_start (self))
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
/* IPv6 */
|
2015-11-09 11:44:09 +01:00
|
|
|
if ( nm_device_activate_ip6_state_in_wait (self)
|
|
|
|
|
&& !nm_device_activate_stage3_ip6_start (self))
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-08-16 05:55:58 +05:30
|
|
|
/* Proxy */
|
|
|
|
|
nm_device_set_proxy_config (self, NULL);
|
|
|
|
|
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, TRUE);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
static void
|
|
|
|
|
fw_change_zone_cb (NMFirewallManager *firewall_manager,
|
|
|
|
|
NMFirewallManagerCallId call_id,
|
|
|
|
|
GError *error,
|
|
|
|
|
gpointer user_data)
|
2015-10-06 17:26:27 +02:00
|
|
|
{
|
2017-05-03 18:34:17 +02:00
|
|
|
NMDevice *self = user_data;
|
2015-10-06 17:26:27 +02:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2015-10-06 17:26:27 +02:00
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
if (priv->fw_call != call_id)
|
|
|
|
|
g_return_if_reached ();
|
2015-10-06 17:26:27 +02:00
|
|
|
priv->fw_call = NULL;
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
if (nm_utils_error_is_cancelled (error, FALSE))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
switch (priv->fw_state) {
|
|
|
|
|
case FIREWALL_STATE_WAIT_STAGE_3:
|
|
|
|
|
priv->fw_state = FIREWALL_STATE_INITIALIZED;
|
|
|
|
|
nm_device_activate_schedule_stage3_ip_config_start (self);
|
|
|
|
|
break;
|
|
|
|
|
case FIREWALL_STATE_WAIT_IP_CONFIG:
|
|
|
|
|
priv->fw_state = FIREWALL_STATE_INITIALIZED;
|
|
|
|
|
if (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE)
|
|
|
|
|
nm_device_start_ip_check (self);
|
|
|
|
|
break;
|
|
|
|
|
case FIREWALL_STATE_INITIALIZED:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
}
|
2015-10-06 17:26:27 +02:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2012-03-21 15:03:23 -05:00
|
|
|
static void
|
2017-05-03 18:34:17 +02:00
|
|
|
fw_change_zone (NMDevice *self)
|
2012-03-21 15:03:23 -05:00
|
|
|
{
|
2017-05-03 18:34:17 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *applied_connection;
|
|
|
|
|
NMSettingConnection *s_con;
|
2014-11-12 14:31:56 +01:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
nm_assert (priv->fw_state >= FIREWALL_STATE_INITIALIZED);
|
2012-03-21 15:03:23 -05:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
applied_connection = nm_device_get_applied_connection (self);
|
|
|
|
|
nm_assert (applied_connection);
|
2012-03-21 15:03:23 -05:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
s_con = nm_connection_get_setting_connection (applied_connection);
|
|
|
|
|
nm_assert (s_con);
|
2015-09-23 17:18:44 +02:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
if (priv->fw_call) {
|
|
|
|
|
nm_firewall_manager_cancel_call (priv->fw_call);
|
|
|
|
|
nm_assert (!priv->fw_call);
|
|
|
|
|
}
|
2012-03-21 15:03:23 -05:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
if (G_UNLIKELY (!priv->fw_mgr))
|
|
|
|
|
priv->fw_mgr = g_object_ref (nm_firewall_manager_get ());
|
2016-10-14 19:57:34 +02:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
priv->fw_call = nm_firewall_manager_add_or_change_zone (priv->fw_mgr,
|
|
|
|
|
nm_device_get_ip_iface (self),
|
|
|
|
|
nm_setting_connection_get_zone (s_con),
|
|
|
|
|
FALSE, /* change zone */
|
|
|
|
|
fw_change_zone_cb,
|
|
|
|
|
self);
|
2012-03-21 15:03:23 -05:00
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/*
|
|
|
|
|
* nm_device_activate_schedule_stage3_ip_config_start
|
|
|
|
|
*
|
|
|
|
|
* Schedule IP configuration start
|
|
|
|
|
*/
|
2006-01-07 16:22:17 +00:00
|
|
|
void
|
2007-06-11 13:36:34 +00:00
|
|
|
nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2007-06-11 13:36:34 +00:00
|
|
|
NMDevicePrivate *priv;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
g_return_if_fail (priv->act_request);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2012-03-21 15:03:23 -05:00
|
|
|
/* Add the interface to the specified firewall zone */
|
2017-05-03 18:34:17 +02:00
|
|
|
if (priv->fw_state == FIREWALL_STATE_UNMANAGED) {
|
|
|
|
|
if (!nm_device_sys_iface_state_is_external (self)) {
|
|
|
|
|
priv->fw_state = FIREWALL_STATE_WAIT_STAGE_3;
|
|
|
|
|
fw_change_zone (self);
|
2015-10-06 17:26:27 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2017-05-03 18:34:17 +02:00
|
|
|
|
|
|
|
|
/* fake success. */
|
|
|
|
|
priv->fw_state = FIREWALL_STATE_INITIALIZED;
|
|
|
|
|
} else if (priv->fw_state == FIREWALL_STATE_WAIT_STAGE_3) {
|
|
|
|
|
/* a firewall call for stage3 is pending. Return and wait. */
|
|
|
|
|
return;
|
2014-11-13 14:55:47 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
nm_assert (priv->fw_state == FIREWALL_STATE_INITIALIZED);
|
|
|
|
|
|
2015-10-06 17:26:27 +02:00
|
|
|
activation_source_schedule (self, activate_stage3_ip_config_start, AF_INET);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-03 17:47:38 +00:00
|
|
|
static NMActStageReturn
|
2017-02-22 17:04:00 +01:00
|
|
|
act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *out_failure_reason)
|
2006-01-03 17:47:38 +00:00
|
|
|
{
|
2014-12-11 10:13:59 +01:00
|
|
|
if (!get_ip_config_may_fail (self, AF_INET)) {
|
2017-02-22 17:04:00 +01:00
|
|
|
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
2010-05-03 01:19:54 -07:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
2006-01-03 17:47:38 +00:00
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/*
|
2009-07-29 12:12:41 -04:00
|
|
|
* nm_device_activate_stage4_ip4_config_timeout
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
2009-07-29 12:12:41 -04:00
|
|
|
* Time out on retrieving the IPv4 config.
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
|
|
|
|
*/
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2015-10-07 12:07:51 +02:00
|
|
|
activate_stage4_ip4_config_timeout (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2007-01-04 12:06:26 +00:00
|
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &failure_reason);
|
2010-05-03 01:19:54 -07:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2010-05-03 01:19:54 -07:00
|
|
|
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
2015-10-06 14:27:03 +02:00
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_FAIL);
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-09 22:50:04 -05:00
|
|
|
* nm_device_activate_schedule_ip4_config_timeout
|
2009-07-29 12:12:41 -04:00
|
|
|
*
|
|
|
|
|
* Deal with a timeout of the IPv4 configuration
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
2011-10-09 22:50:04 -05:00
|
|
|
nm_device_activate_schedule_ip4_config_timeout (NMDevice *self)
|
2009-07-29 12:12:41 -04:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
g_return_if_fail (priv->act_request);
|
|
|
|
|
|
2015-10-07 12:07:51 +02:00
|
|
|
activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET);
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMActStageReturn
|
2017-02-22 17:04:00 +01:00
|
|
|
act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *out_failure_reason)
|
2009-07-29 12:12:41 -04:00
|
|
|
{
|
2014-12-11 10:13:59 +01:00
|
|
|
if (!get_ip_config_may_fail (self, AF_INET6)) {
|
2017-02-22 17:04:00 +01:00
|
|
|
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
2010-05-03 01:19:54 -07:00
|
|
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2015-10-07 12:07:51 +02:00
|
|
|
* activate_stage4_ip6_config_timeout
|
2009-07-29 12:12:41 -04:00
|
|
|
*
|
|
|
|
|
* Time out on retrieving the IPv6 config.
|
|
|
|
|
*
|
|
|
|
|
*/
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2015-10-07 12:07:51 +02:00
|
|
|
activate_stage4_ip6_config_timeout (NMDevice *self)
|
2009-07-29 12:12:41 -04:00
|
|
|
{
|
|
|
|
|
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
|
2017-02-22 17:04:00 +01:00
|
|
|
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
2009-07-29 12:12:41 -04:00
|
|
|
|
2017-02-22 17:04:00 +01:00
|
|
|
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &failure_reason);
|
2010-05-03 01:19:54 -07:00
|
|
|
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
|
|
|
|
if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
|
2017-02-22 17:04:00 +01:00
|
|
|
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
|
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_FAIL);
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2011-10-09 22:50:04 -05:00
|
|
|
* nm_device_activate_schedule_ip6_config_timeout
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
2009-07-29 12:12:41 -04:00
|
|
|
* Deal with a timeout of the IPv6 configuration
|
2005-12-31 08:21:24 +00:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
2011-10-09 22:50:04 -05:00
|
|
|
nm_device_activate_schedule_ip6_config_timeout (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2007-06-11 13:36:34 +00:00
|
|
|
NMDevicePrivate *priv;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-06-11 13:36:34 +00:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
g_return_if_fail (priv->act_request);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2015-10-07 12:07:51 +02:00
|
|
|
activation_source_schedule (self, activate_stage4_ip6_config_timeout, AF_INET6);
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2008-08-15 15:34:28 +00:00
|
|
|
static gboolean
|
2017-04-17 20:17:45 +02:00
|
|
|
share_init (NMDevice *self)
|
2008-08-15 15:34:28 +00:00
|
|
|
{
|
|
|
|
|
char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc",
|
|
|
|
|
"nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323",
|
|
|
|
|
NULL };
|
|
|
|
|
char **iter;
|
2014-02-12 23:54:26 +01:00
|
|
|
int errsv;
|
2008-08-15 15:34:28 +00:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv4/ip_forward"), "1")) {
|
2014-02-12 23:54:26 +01:00
|
|
|
errsv = errno;
|
2016-11-05 18:31:13 +01:00
|
|
|
nm_log_err (LOGD_SHARING, "share: error enabling IPv4 forwarding: (%d) %s",
|
2014-02-12 23:54:26 +01:00
|
|
|
errsv, strerror (errsv));
|
2009-07-29 12:12:41 -04:00
|
|
|
return FALSE;
|
2008-08-15 15:34:28 +00:00
|
|
|
}
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv4/ip_dynaddr"), "1")) {
|
2014-02-12 23:54:26 +01:00
|
|
|
errsv = errno;
|
2016-11-05 18:31:13 +01:00
|
|
|
nm_log_err (LOGD_SHARING, "share: error enabling dynamic addresses: (%d) %s",
|
2014-02-12 23:54:26 +01:00
|
|
|
errsv, strerror (errsv));
|
2008-08-15 15:34:28 +00:00
|
|
|
}
|
|
|
|
|
|
2015-01-09 11:49:25 +01:00
|
|
|
for (iter = modules; *iter; iter++)
|
2015-05-18 17:37:05 +02:00
|
|
|
nm_utils_modprobe (NULL, FALSE, *iter, NULL);
|
2008-08-15 15:34:28 +00:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-05 11:46:06 +02:00
|
|
|
#define add_share_rule(req, table, ...) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
char *_cmd = g_strdup_printf (__VA_ARGS__); \
|
|
|
|
|
nm_act_request_add_share_rule (req, table, _cmd); \
|
|
|
|
|
g_free (_cmd); \
|
|
|
|
|
} G_STMT_END
|
2008-08-15 15:34:28 +00:00
|
|
|
|
|
|
|
|
static gboolean
|
2011-10-09 23:48:13 -05:00
|
|
|
start_sharing (NMDevice *self, NMIP4Config *config)
|
2008-08-15 15:34:28 +00:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMActRequest *req;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
char str_addr[INET_ADDRSTRLEN + 1];
|
|
|
|
|
char str_mask[INET_ADDRSTRLEN + 1];
|
|
|
|
|
guint32 netmask, network;
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMPlatformIP4Address *ip4_addr = NULL;
|
2008-10-22 16:32:13 +00:00
|
|
|
const char *ip_iface;
|
2008-08-15 15:34:28 +00:00
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
g_return_val_if_fail (config != NULL, FALSE);
|
2008-08-15 15:34:28 +00:00
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
ip_iface = nm_device_get_ip_iface (self);
|
2017-10-31 18:22:37 +01:00
|
|
|
if (!ip_iface)
|
|
|
|
|
return FALSE;
|
2008-08-15 15:34:28 +00:00
|
|
|
|
2017-07-07 23:34:41 +02:00
|
|
|
ip4_addr = nm_ip4_config_get_first_address (config);
|
2017-07-25 14:45:08 +02:00
|
|
|
if (!ip4_addr || !ip4_addr->address)
|
2008-08-15 15:34:28 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2017-09-05 15:25:34 +02:00
|
|
|
netmask = _nm_utils_ip4_prefix_to_netmask (ip4_addr->plen);
|
2008-08-15 15:34:28 +00:00
|
|
|
if (!inet_ntop (AF_INET, &netmask, str_mask, sizeof (str_mask)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2013-06-29 13:33:36 +02:00
|
|
|
network = ip4_addr->address & netmask;
|
2008-08-15 15:34:28 +00:00
|
|
|
if (!inet_ntop (AF_INET, &network, str_addr, sizeof (str_addr)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!share_init (self))
|
2008-08-15 15:34:28 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
req = nm_device_get_act_request (self);
|
|
|
|
|
g_assert (req);
|
|
|
|
|
|
2011-09-06 18:31:40 -05:00
|
|
|
add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask);
|
2016-01-21 16:39:55 +01:00
|
|
|
add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface);
|
|
|
|
|
add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface);
|
2008-08-15 15:34:28 +00:00
|
|
|
|
|
|
|
|
nm_act_request_set_shared (req, TRUE);
|
|
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGE (LOGD_SHARING, "share: (%s) failed to start dnsmasq: %s",
|
2016-02-28 16:25:36 +01:00
|
|
|
ip_iface, error->message);
|
2008-08-15 15:34:28 +00:00
|
|
|
g_error_free (error);
|
|
|
|
|
nm_act_request_set_shared (req, FALSE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 19:45:34 +01:00
|
|
|
priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, NM_DNS_MASQ_MANAGER_STATE_CHANGED,
|
2008-08-15 15:34:28 +00:00
|
|
|
G_CALLBACK (dnsmasq_state_changed_cb),
|
|
|
|
|
self);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2014-03-19 12:39:38 -04:00
|
|
|
static void
|
|
|
|
|
arp_cleanup (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-12-23 14:15:05 +01:00
|
|
|
if (priv->arping.announcing) {
|
|
|
|
|
nm_arping_manager_destroy (priv->arping.announcing);
|
|
|
|
|
priv->arping.announcing = NULL;
|
|
|
|
|
}
|
2014-03-19 12:39:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
arp_announce (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4;
|
2015-12-23 14:15:05 +01:00
|
|
|
guint num, i;
|
|
|
|
|
const guint8 *hw_addr;
|
|
|
|
|
size_t hw_addr_len = 0;
|
2014-03-19 12:39:38 -04:00
|
|
|
|
|
|
|
|
arp_cleanup (self);
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
hw_addr = nm_platform_link_get_address (nm_device_get_platform (self),
|
2015-12-23 14:15:05 +01:00
|
|
|
nm_device_get_ip_ifindex (self),
|
|
|
|
|
&hw_addr_len);
|
|
|
|
|
|
|
|
|
|
if (!hw_addr_len || !hw_addr)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-03-19 12:39:38 -04:00
|
|
|
/* We only care about manually-configured addresses; DHCP- and autoip-configured
|
|
|
|
|
* ones should already have been seen on the network at this point.
|
|
|
|
|
*/
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2014-03-19 12:39:38 -04:00
|
|
|
if (!connection)
|
|
|
|
|
return;
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
if (!s_ip4)
|
|
|
|
|
return;
|
2014-10-19 17:30:10 -04:00
|
|
|
num = nm_setting_ip_config_get_num_addresses (s_ip4);
|
2014-03-19 12:39:38 -04:00
|
|
|
if (num == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-12-23 14:15:05 +01:00
|
|
|
priv->arping.announcing = nm_arping_manager_new (nm_device_get_ip_ifindex (self));
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
|
NMIPAddress *ip = nm_setting_ip_config_get_address (s_ip4, i);
|
|
|
|
|
in_addr_t addr;
|
|
|
|
|
|
|
|
|
|
if (inet_pton (AF_INET, nm_ip_address_get_address (ip), &addr) == 1)
|
|
|
|
|
nm_arping_manager_add_address (priv->arping.announcing, addr);
|
|
|
|
|
else
|
|
|
|
|
g_warn_if_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_arping_manager_announce_addresses (priv->arping.announcing);
|
2014-03-19 12:39:38 -04:00
|
|
|
}
|
|
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2017-06-01 21:50:40 +02:00
|
|
|
activate_stage5_ip4_config_result (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2009-08-05 18:03:09 -04:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2011-10-09 22:50:04 -05:00
|
|
|
NMActRequest *req;
|
2014-08-02 00:48:35 +02:00
|
|
|
const char *method;
|
2008-05-29 20:58:52 +00:00
|
|
|
NMConnection *connection;
|
2014-10-13 15:10:20 -05:00
|
|
|
int ip_ifindex;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2011-10-09 22:50:04 -05:00
|
|
|
req = nm_device_get_act_request (self);
|
|
|
|
|
g_assert (req);
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_act_request_get_applied_connection (req);
|
2011-10-09 22:50:04 -05:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
2014-10-13 15:10:20 -05:00
|
|
|
/* Interface must be IFF_UP before IP config can be applied */
|
|
|
|
|
ip_ifindex = nm_device_get_ip_ifindex (self);
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume (self)) {
|
|
|
|
|
nm_platform_link_set_up (nm_device_get_platform (self), ip_ifindex, NULL);
|
|
|
|
|
if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex))
|
2014-10-13 15:10:20 -05:00
|
|
|
_LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self));
|
|
|
|
|
}
|
2009-08-05 18:03:09 -04:00
|
|
|
|
2013-08-01 10:34:46 -05:00
|
|
|
/* NULL to use the existing priv->dev_ip4_config */
|
2017-09-28 14:22:07 +02:00
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE)) {
|
2015-04-17 15:56:04 +02:00
|
|
|
_LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed");
|
2017-02-22 20:20:22 +01:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2008-05-29 20:58:52 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2011-10-09 22:50:04 -05:00
|
|
|
/* Start IPv4 sharing if we need it */
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2013-09-26 17:34:23 -04:00
|
|
|
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
|
2013-08-01 10:34:46 -05:00
|
|
|
if (!start_sharing (self, priv->ip4_config)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_SHARING, "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed.");
|
2016-11-05 18:31:13 +01:00
|
|
|
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
|
2015-10-06 14:27:03 +02:00
|
|
|
return;
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
2014-04-29 16:42:57 -05:00
|
|
|
/* If IPv4 wasn't the first to complete, and DHCP was used, then ensure
|
|
|
|
|
* dispatcher scripts get the DHCP lease information.
|
|
|
|
|
*/
|
2016-04-07 14:34:31 +02:00
|
|
|
if ( priv->dhcp4.client
|
2014-04-29 16:42:57 -05:00
|
|
|
&& nm_device_activate_ip4_state_in_conf (self)
|
|
|
|
|
&& (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) {
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP4_CHANGE,
|
|
|
|
|
self,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL, NULL, NULL);
|
2014-04-29 16:42:57 -05:00
|
|
|
}
|
|
|
|
|
|
2014-03-19 12:39:38 -04:00
|
|
|
arp_announce (self);
|
|
|
|
|
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
|
2014-04-14 17:57:56 +02:00
|
|
|
|
2016-02-24 13:12:24 +01:00
|
|
|
/* Enter the IP_CHECK state if this is the first method to complete */
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_DONE);
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2013-08-01 10:34:46 -05:00
|
|
|
g_clear_object (&priv->dev_ip4_config);
|
2013-10-15 21:03:42 -05:00
|
|
|
if (config)
|
|
|
|
|
priv->dev_ip4_config = g_object_ref (config);
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2017-06-01 21:50:40 +02:00
|
|
|
activation_source_schedule (self, activate_stage5_ip4_config_result, AF_INET);
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
|
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_ip4_state_in_conf (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_CONF;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-28 13:34:44 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_ip4_state_in_wait (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_ip4_state_done (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_DONE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-14 18:37:57 +01:00
|
|
|
/*
|
|
|
|
|
* Returns a NMIP6Config containing NM-configured addresses which
|
|
|
|
|
* have the tentative flag, or NULL if none is present.
|
|
|
|
|
*/
|
|
|
|
|
static NMIP6Config *
|
|
|
|
|
dad6_get_pending_addresses (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMIP6Config *confs[] = { priv->ac_ip6_config,
|
|
|
|
|
priv->dhcp6.ip6_config,
|
|
|
|
|
priv->con_ip6_config,
|
|
|
|
|
priv->wwan_ip6_config };
|
|
|
|
|
const NMPlatformIP6Address *addr, *pl_addr;
|
|
|
|
|
NMIP6Config *dad6_config = NULL;
|
2017-07-07 23:34:41 +02:00
|
|
|
NMDedupMultiIter ipconf_iter;
|
|
|
|
|
guint i;
|
2016-03-14 18:37:57 +01:00
|
|
|
int ifindex;
|
|
|
|
|
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, NULL);
|
|
|
|
|
|
|
|
|
|
/* We are interested only in addresses that we have explicitly configured,
|
|
|
|
|
* not in externally added ones.
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (confs); i++) {
|
|
|
|
|
if (confs[i]) {
|
2017-07-07 23:34:41 +02:00
|
|
|
|
|
|
|
|
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) {
|
2017-04-17 20:17:45 +02:00
|
|
|
pl_addr = nm_platform_ip6_address_get (nm_device_get_platform (self),
|
2016-03-14 18:37:57 +01:00
|
|
|
ifindex,
|
2017-05-26 21:49:00 +02:00
|
|
|
addr->address);
|
2016-03-14 18:37:57 +01:00
|
|
|
if ( pl_addr
|
|
|
|
|
&& NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_TENTATIVE)
|
|
|
|
|
&& !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_DADFAILED)
|
|
|
|
|
&& !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
|
|
|
|
|
_LOGt (LOGD_DEVICE, "IPv6 DAD: pending address %s",
|
|
|
|
|
nm_platform_ip6_address_to_string (pl_addr, NULL, 0));
|
|
|
|
|
|
|
|
|
|
if (!dad6_config)
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
dad6_config = _ip6_config_new (self);
|
2016-03-14 18:37:57 +01:00
|
|
|
|
|
|
|
|
nm_ip6_config_add_address (dad6_config, pl_addr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dad6_config;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
static void
|
2015-10-07 12:07:51 +02:00
|
|
|
activate_stage5_ip6_config_commit (NMDevice *self)
|
2011-10-09 22:50:04 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMActRequest *req;
|
2016-11-05 18:31:20 +01:00
|
|
|
const char *method;
|
2011-10-09 22:50:04 -05:00
|
|
|
NMConnection *connection;
|
2014-10-13 15:10:20 -05:00
|
|
|
int ip_ifindex;
|
2016-11-05 18:31:20 +01:00
|
|
|
int errsv;
|
2011-10-09 22:50:04 -05:00
|
|
|
|
|
|
|
|
req = nm_device_get_act_request (self);
|
|
|
|
|
g_assert (req);
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_act_request_get_applied_connection (req);
|
2011-10-09 22:50:04 -05:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
2014-10-13 15:10:20 -05:00
|
|
|
/* Interface must be IFF_UP before IP config can be applied */
|
|
|
|
|
ip_ifindex = nm_device_get_ip_ifindex (self);
|
2017-10-31 18:22:37 +01:00
|
|
|
g_return_if_fail (ip_ifindex);
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume (self)) {
|
|
|
|
|
nm_platform_link_set_up (nm_device_get_platform (self), ip_ifindex, NULL);
|
|
|
|
|
if (!nm_platform_link_is_up (nm_device_get_platform (self), ip_ifindex))
|
2014-10-13 15:10:20 -05:00
|
|
|
_LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self));
|
|
|
|
|
}
|
2011-10-09 22:50:04 -05:00
|
|
|
|
2017-02-22 20:20:22 +01:00
|
|
|
if (ip6_config_merge_and_apply (self, TRUE)) {
|
2016-10-13 11:06:25 +00:00
|
|
|
if ( priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE
|
2016-01-14 20:39:33 +01:00
|
|
|
&& priv->ip6_state == IP_CONF) {
|
2016-04-07 14:45:57 +02:00
|
|
|
if (priv->dhcp6.ip6_config) {
|
2016-01-14 20:39:33 +01:00
|
|
|
/* If IPv6 wasn't the first IP to complete, and DHCP was used,
|
|
|
|
|
* then ensure dispatcher scripts get the DHCP lease information.
|
|
|
|
|
*/
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DHCP6_CHANGE,
|
|
|
|
|
self,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL, NULL, NULL);
|
2016-01-14 20:39:33 +01:00
|
|
|
} else {
|
|
|
|
|
/* still waiting for first dhcp6 lease. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-04-29 16:42:57 -05:00
|
|
|
}
|
2017-01-27 13:57:15 +01:00
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE);
|
|
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE);
|
2014-04-14 17:57:56 +02:00
|
|
|
|
2016-11-05 18:31:20 +01:00
|
|
|
/* Start IPv6 forwarding if we need it */
|
|
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
2016-11-09 17:58:11 +01:00
|
|
|
|
2016-11-05 18:31:20 +01:00
|
|
|
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/all/forwarding"), "1")) {
|
2016-11-05 18:31:20 +01:00
|
|
|
errsv = errno;
|
|
|
|
|
_LOGE (LOGD_SHARING, "share: error enabling IPv6 forwarding: (%d) %s", errsv, strerror (errsv));
|
|
|
|
|
nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-09 17:58:11 +01:00
|
|
|
|
2016-03-14 18:37:57 +01:00
|
|
|
/* Check if we have to wait for DAD */
|
|
|
|
|
if (priv->ip6_state == IP_CONF && !priv->dad6_ip6_config) {
|
2017-04-30 17:30:44 +02:00
|
|
|
if (!priv->carrier && priv->ignore_carrier && get_ip_config_may_fail (self, AF_INET6))
|
|
|
|
|
_LOGI (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: carrier missing and ignored, not delaying activation");
|
|
|
|
|
else
|
|
|
|
|
priv->dad6_ip6_config = dad6_get_pending_addresses (self);
|
|
|
|
|
|
2016-03-14 18:37:57 +01:00
|
|
|
if (priv->dad6_ip6_config) {
|
2017-04-30 17:30:44 +02:00
|
|
|
_LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination");
|
2016-03-14 18:37:57 +01:00
|
|
|
} else {
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_DONE);
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2016-03-14 18:37:57 +01:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-21 14:25:35 -05:00
|
|
|
} else {
|
2015-04-17 15:56:04 +02:00
|
|
|
_LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed");
|
2017-02-22 20:20:22 +01:00
|
|
|
nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-09 22:50:04 -05:00
|
|
|
void
|
2013-06-14 21:42:22 +02:00
|
|
|
nm_device_activate_schedule_ip6_config_result (NMDevice *self)
|
2011-10-09 22:50:04 -05:00
|
|
|
{
|
2014-01-23 13:02:16 -06:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2011-10-09 22:50:04 -05:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
2014-08-13 09:40:08 -05:00
|
|
|
/* If IP had previously failed, move it back to IP_CONF since we
|
|
|
|
|
* clearly now have configuration.
|
|
|
|
|
*/
|
|
|
|
|
if (priv->ip6_state == IP_FAIL)
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_CONF);
|
2014-08-13 09:40:08 -05:00
|
|
|
|
2015-10-07 12:07:51 +02:00
|
|
|
activation_source_schedule (self, activate_stage5_ip6_config_commit, AF_INET6);
|
2011-10-09 22:50:04 -05:00
|
|
|
}
|
|
|
|
|
|
2011-10-09 23:48:13 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_ip6_state_in_conf (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_CONF;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-28 13:34:44 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_ip6_state_in_wait (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 13:48:34 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_activate_ip6_state_done (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_DONE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2007-09-11 18:02:27 +00:00
|
|
|
static void
|
2017-01-24 19:43:52 +01:00
|
|
|
act_request_set_cb (NMActRequest *act_request,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
NMDevice *self)
|
2007-09-11 18:02:27 +00:00
|
|
|
{
|
2017-01-24 19:43:52 +01:00
|
|
|
_notify (self, PROP_ACTIVE_CONNECTION);
|
|
|
|
|
}
|
2007-09-11 18:02:27 +00:00
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
static void
|
|
|
|
|
act_request_set (NMDevice *self, NMActRequest *act_request)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
gs_unref_object NMActRequest *old_act_requst = NULL;
|
|
|
|
|
|
|
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
|
|
|
|
nm_assert (!act_request || NM_IS_ACT_REQUEST (act_request));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if ( !priv->act_request_public
|
|
|
|
|
&& priv->act_request == act_request)
|
2007-09-11 18:02:27 +00:00
|
|
|
return;
|
|
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
/* always clear the public flag. The few callers that set a new @act_request
|
|
|
|
|
* don't want that the property is public yet. */
|
|
|
|
|
priv->act_request_public = FALSE;
|
|
|
|
|
|
|
|
|
|
nm_clear_g_signal_handler (priv->act_request, &priv->act_request_id);
|
2008-06-10 02:01:13 +00:00
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
old_act_requst = priv->act_request;
|
|
|
|
|
priv->act_request = nm_g_object_ref (act_request);
|
2013-09-11 09:21:17 -05:00
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
if (act_request) {
|
|
|
|
|
priv->act_request_id = g_signal_connect (act_request,
|
|
|
|
|
"notify::"NM_EXPORTED_OBJECT_PATH,
|
|
|
|
|
G_CALLBACK (act_request_set_cb),
|
|
|
|
|
self);
|
2017-03-13 15:34:14 +01:00
|
|
|
|
|
|
|
|
switch (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request))) {
|
|
|
|
|
case NM_ACTIVATION_TYPE_EXTERNAL:
|
|
|
|
|
break;
|
|
|
|
|
case NM_ACTIVATION_TYPE_ASSUME:
|
|
|
|
|
if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_EXTERNAL)
|
|
|
|
|
nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_ASSUME);
|
|
|
|
|
break;
|
|
|
|
|
case NM_ACTIVATION_TYPE_MANAGED:
|
|
|
|
|
if (NM_IN_SET_TYPED (NMDeviceSysIfaceState,
|
|
|
|
|
priv->sys_iface_state,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_ASSUME))
|
|
|
|
|
nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-01-24 19:43:52 +01:00
|
|
|
}
|
2017-03-13 15:34:14 +01:00
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_ACTIVE_CONNECTION);
|
2007-09-11 18:02:27 +00:00
|
|
|
}
|
|
|
|
|
|
2010-01-13 17:59:54 -08:00
|
|
|
static void
|
2014-05-20 15:03:27 -05:00
|
|
|
dnsmasq_cleanup (NMDevice *self)
|
2010-01-14 00:45:10 -08:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!priv->dnsmasq_manager)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-01-04 10:35:11 +01:00
|
|
|
nm_clear_g_signal_handler (priv->dnsmasq_manager, &priv->dnsmasq_state_id);
|
2010-01-14 00:45:10 -08:00
|
|
|
|
|
|
|
|
nm_dnsmasq_manager_stop (priv->dnsmasq_manager);
|
|
|
|
|
g_object_unref (priv->dnsmasq_manager);
|
|
|
|
|
priv->dnsmasq_manager = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-17 22:39:34 -06:00
|
|
|
static void
|
|
|
|
|
_update_ip4_address (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMPlatformIP4Address *address;
|
2011-11-17 22:39:34 -06:00
|
|
|
|
2015-08-07 09:33:46 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2011-11-17 22:39:34 -06:00
|
|
|
|
device: avoid a crash during destruction
The ipv4_config might be gone already, _cleanup_generic_post() sets it to NULL.
NetworkManager[30564]: <info> caught SIGINT, shutting down normally.
(NetworkManager:30564): GLib-GObject-CRITICAL **: g_type_instance_get_private: assertion 'instance != NULL && instance->g_class != NULL' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x7ffff4d92f64 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd5e0) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff4a738c3 in g_logv (log_domain=0x7ffff4d92f64 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd5e0) at gmessages.c:1046
#1 0x00007ffff4a73a3f in g_log (log_domain=log_domain@entry=0x7ffff4d92f64 "GLib-GObject", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff4ae173d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff4a73a79 in g_return_if_fail_warning (log_domain=log_domain@entry=0x7ffff4d92f64 "GLib-GObject", pretty_function=pretty_function@entry=0x7ffff4d9aad0 <__FUNCTION__.13620> "g_type_instance_get_private", expression=expression@entry=0x7ffff4d99db8 "instance != NULL && instance->g_class != NULL") at gmessages.c:1088
#3 0x00007ffff4d8d2ba in g_type_instance_get_private (instance=instance@entry=0x0, private_type=<optimized out>) at gtype.c:4632
#4 0x00000000004bf774 in nm_ip4_config_get_num_addresses (config=0x0) at nm-ip4-config.c:1418
#5 0x0000000000458834 in _update_ip4_address (self=self@entry=0xa8a490 [NMDeviceBridge]) at devices/nm-device.c:6069
#6 0x000000000045e740 in nm_device_set_ip4_config (self=self@entry=0xa8a490 [NMDeviceBridge], new_config=new_config@entry=0x0, default_route_metric=default_route_metric@entry=0, commit=commit@entry=1, routes_full_sync=routes_full_sync@entry=1, reason=reason@entry=0x7fffffffd7cc) at devices/nm-device.c:6558
#7 0x0000000000466c56 in _cleanup_generic_post (self=self@entry=0xa8a490 [NMDeviceBridge], cleanup_type=cleanup_type@entry=CLEANUP_TYPE_KEEP) at devices/nm-device.c:8108
#8 0x00000000004671af in dispose (object=0xa8a490 [NMDeviceBridge]) at devices/nm-device.c:9128
#9 0x00007ffff4d6ea82 in g_object_unref (_object=0xa8a490) at gobject.c:3133
#10 0x00000000004d1a53 in remove_device (manager=manager@entry=0x8822b0 [NMManager], device=0xa8a490 [NMDeviceBridge], quitting=quitting@entry=1, allow_unmanage=allow_unmanage@entry=1) at nm-manager.c:780
#11 0x00000000004d7db1 in nm_manager_stop (self=self@entry=0x8822b0 [NMManager]) at nm-manager.c:4199
#12 0x0000000000445aa9 in main (argc=1, argv=0x7fffffffda88) at main.c:465
(gdb)
2015-08-12 16:03:12 +02:00
|
|
|
if ( priv->ip4_config
|
|
|
|
|
&& ip_config_valid (priv->state)
|
2017-07-07 23:34:41 +02:00
|
|
|
&& (address = nm_ip4_config_get_first_address (priv->ip4_config))) {
|
|
|
|
|
if (address->address != priv->ip4_address) {
|
|
|
|
|
priv->ip4_address = address->address;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP4_ADDRESS);
|
2015-08-07 09:33:46 +02:00
|
|
|
}
|
2011-11-17 22:39:34 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 16:39:57 -05:00
|
|
|
gboolean
|
2017-05-31 16:42:05 +02:00
|
|
|
nm_device_is_nm_owned (NMDevice *self)
|
2014-05-20 16:39:57 -05:00
|
|
|
{
|
2017-05-31 16:42:05 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->nm_owned;
|
2014-05-20 16:39:57 -05:00
|
|
|
}
|
|
|
|
|
|
2013-08-07 11:41:40 +02:00
|
|
|
/*
|
|
|
|
|
* delete_on_deactivate_link_delete
|
|
|
|
|
*
|
|
|
|
|
* Function will be queued with g_idle_add to call
|
|
|
|
|
* nm_platform_link_delete for the underlying resources
|
|
|
|
|
* of the device.
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
delete_on_deactivate_link_delete (gpointer user_data)
|
|
|
|
|
{
|
2014-03-05 22:20:14 +01:00
|
|
|
DeleteOnDeactivateData *data = user_data;
|
2014-02-12 23:54:26 +01:00
|
|
|
NMDevice *self = data->device;
|
2014-03-05 22:20:14 +01:00
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
_LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
|
|
|
|
|
data->ifindex, data->idle_add_id);
|
|
|
|
|
|
2014-03-05 22:20:14 +01:00
|
|
|
if (data->device) {
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (data->device);
|
2014-09-24 15:13:19 -05:00
|
|
|
gs_free_error GError *error = NULL;
|
2014-03-05 22:20:14 +01:00
|
|
|
|
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (data->device), (void **) &data->device);
|
|
|
|
|
priv->delete_on_deactivate_data = NULL;
|
2013-08-07 11:41:40 +02:00
|
|
|
|
2014-09-24 15:13:19 -05:00
|
|
|
if (!nm_device_unrealize (data->device, TRUE, &error))
|
|
|
|
|
_LOGD (LOGD_DEVICE, "delete_on_deactivate: unrealizing %d failed (%s)", data->ifindex, error->message);
|
2017-10-11 20:14:51 +02:00
|
|
|
} else if (data->ifindex > 0)
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_delete (nm_device_get_platform (self), data->ifindex);
|
2014-09-24 15:13:19 -05:00
|
|
|
|
2014-03-05 22:20:14 +01:00
|
|
|
g_free (data);
|
2013-08-07 11:41:40 +02:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-03-05 22:20:14 +01:00
|
|
|
delete_on_deactivate_unschedule (NMDevice *self)
|
2013-08-07 11:41:40 +02:00
|
|
|
{
|
2014-03-05 22:20:14 +01:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->delete_on_deactivate_data) {
|
|
|
|
|
DeleteOnDeactivateData *data = priv->delete_on_deactivate_data;
|
|
|
|
|
|
|
|
|
|
priv->delete_on_deactivate_data = NULL;
|
|
|
|
|
|
|
|
|
|
g_source_remove (data->idle_add_id);
|
|
|
|
|
g_object_remove_weak_pointer (G_OBJECT (self), (void **) &data->device);
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "delete_on_deactivate: cancel cleanup and delete virtual link #%d (id=%u)",
|
|
|
|
|
data->ifindex, data->idle_add_id);
|
2014-03-05 22:20:14 +01:00
|
|
|
g_free (data);
|
2013-08-07 11:41:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex)
|
|
|
|
|
{
|
2014-05-20 16:39:57 -05:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-03-05 22:20:14 +01:00
|
|
|
DeleteOnDeactivateData *data;
|
2013-08-07 11:41:40 +02:00
|
|
|
|
2017-05-31 16:42:05 +02:00
|
|
|
if (!priv->nm_owned)
|
2013-08-07 11:41:40 +02:00
|
|
|
return;
|
2014-11-04 09:41:42 +01:00
|
|
|
if (priv->queued_act_request)
|
|
|
|
|
return;
|
2014-09-05 08:50:02 -05:00
|
|
|
if (!nm_device_is_software (self) || !nm_device_is_real (self))
|
2013-08-07 11:41:40 +02:00
|
|
|
return;
|
|
|
|
|
if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)
|
|
|
|
|
return;
|
2013-12-03 09:37:58 +01:00
|
|
|
if (nm_device_get_state (self) == NM_DEVICE_STATE_UNAVAILABLE)
|
|
|
|
|
return;
|
2014-03-05 22:20:14 +01:00
|
|
|
delete_on_deactivate_unschedule (self); /* always cancel and reschedule */
|
|
|
|
|
|
|
|
|
|
data = g_new (DeleteOnDeactivateData, 1);
|
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (self), (void **) &data->device);
|
|
|
|
|
data->device = self;
|
|
|
|
|
data->ifindex = ifindex;
|
|
|
|
|
data->idle_add_id = g_idle_add (delete_on_deactivate_link_delete, data);
|
|
|
|
|
priv->delete_on_deactivate_data = data;
|
|
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "delete_on_deactivate: schedule cleanup and delete virtual link #%d (id=%u)",
|
|
|
|
|
ifindex, data->idle_add_id);
|
2013-08-07 11:41:40 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-21 12:28:09 +01:00
|
|
|
static void
|
|
|
|
|
_cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_NONE);
|
2016-05-05 10:58:10 +02:00
|
|
|
|
|
|
|
|
if (nm_clear_g_source (&priv->queued_ip4_config_id))
|
|
|
|
|
_LOGD (LOGD_DEVICE, "clearing queued IP4 config change");
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
priv->queued_ip4_config_pending = FALSE;
|
2015-11-21 12:28:09 +01:00
|
|
|
|
|
|
|
|
dhcp4_cleanup (self, cleanup_type, FALSE);
|
|
|
|
|
arp_cleanup (self);
|
|
|
|
|
dnsmasq_cleanup (self);
|
|
|
|
|
ipv4ll_cleanup (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_NONE);
|
2016-05-05 10:58:10 +02:00
|
|
|
|
|
|
|
|
if (nm_clear_g_source (&priv->queued_ip6_config_id))
|
|
|
|
|
_LOGD (LOGD_DEVICE, "clearing queued IP6 config change");
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
priv->queued_ip6_config_pending = FALSE;
|
2015-11-21 12:28:09 +01:00
|
|
|
|
2016-03-14 18:37:57 +01:00
|
|
|
g_clear_object (&priv->dad6_ip6_config);
|
2015-11-21 12:28:09 +01:00
|
|
|
dhcp6_cleanup (self, cleanup_type, FALSE);
|
|
|
|
|
linklocal6_cleanup (self);
|
|
|
|
|
addrconf6_cleanup (self);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-03 12:03:26 +01:00
|
|
|
gboolean
|
|
|
|
|
_nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name,
|
|
|
|
|
GError **error, const char **argv)
|
2016-01-05 15:52:36 +01:00
|
|
|
{
|
2016-01-07 11:55:44 +01:00
|
|
|
guint found_keys = 0;
|
2016-01-29 14:07:16 +01:00
|
|
|
guint i;
|
|
|
|
|
|
2017-03-03 12:06:58 +01:00
|
|
|
nm_assert (hash && g_hash_table_size (hash) > 0);
|
2016-01-29 14:07:16 +01:00
|
|
|
nm_assert (argv && argv[0]);
|
2016-01-05 15:52:36 +01:00
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
#if NM_MORE_ASSERTS > 10
|
|
|
|
|
/* Assert that the keys are unique. */
|
|
|
|
|
{
|
2017-10-13 16:12:35 +02:00
|
|
|
gs_unref_hashtable GHashTable *check_dups = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, NULL);
|
2016-01-05 15:52:36 +01:00
|
|
|
|
2016-01-29 14:07:16 +01:00
|
|
|
for (i = 0; argv[i]; i++) {
|
2017-01-18 13:24:42 +01:00
|
|
|
if (!nm_g_hash_table_add (check_dups, (char *) argv[i]))
|
2016-01-07 11:55:44 +01:00
|
|
|
nm_assert (FALSE);
|
2016-01-05 15:52:36 +01:00
|
|
|
}
|
2016-01-07 11:55:44 +01:00
|
|
|
nm_assert (g_hash_table_size (check_dups) > 0);
|
2016-01-05 15:52:36 +01:00
|
|
|
}
|
2016-01-07 11:55:44 +01:00
|
|
|
#endif
|
2016-01-05 15:52:36 +01:00
|
|
|
|
2016-01-29 14:07:16 +01:00
|
|
|
for (i = 0; argv[i]; i++) {
|
|
|
|
|
if (g_hash_table_contains (hash, argv[i]))
|
2016-01-07 11:55:44 +01:00
|
|
|
found_keys++;
|
2016-01-05 15:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
if (found_keys != g_hash_table_size (hash)) {
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
const char *k = NULL;
|
|
|
|
|
const char *first_invalid_key = NULL;
|
2016-01-05 15:54:00 +01:00
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
if (!error)
|
|
|
|
|
return FALSE;
|
2016-01-05 15:54:44 +01:00
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
g_hash_table_iter_init (&iter, hash);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) {
|
2017-02-04 17:53:17 +01:00
|
|
|
if (nm_utils_strv_find_first ((char **) argv, -1, k) < 0) {
|
2016-04-30 12:49:43 +02:00
|
|
|
first_invalid_key = k;
|
2016-01-07 11:55:44 +01:00
|
|
|
break;
|
2016-04-30 12:49:43 +02:00
|
|
|
}
|
2016-01-07 11:55:44 +01:00
|
|
|
}
|
2016-04-30 12:56:25 +02:00
|
|
|
if (setting_name) {
|
|
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
|
|
|
|
"Can't reapply changes to '%s.%s' setting",
|
|
|
|
|
setting_name,
|
|
|
|
|
first_invalid_key);
|
|
|
|
|
} else {
|
|
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
|
|
|
|
"Can't reapply any changes to '%s' setting",
|
|
|
|
|
first_invalid_key);
|
|
|
|
|
}
|
2016-01-07 11:55:44 +01:00
|
|
|
g_return_val_if_fail (first_invalid_key, FALSE);
|
2016-01-05 15:54:44 +01:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-11 09:59:25 +01:00
|
|
|
void
|
|
|
|
|
nm_device_reactivate_ip4_config (NMDevice *self,
|
|
|
|
|
NMSettingIPConfig *s_ip4_old,
|
2017-03-16 14:54:16 +01:00
|
|
|
NMSettingIPConfig *s_ip4_new,
|
|
|
|
|
gboolean force_restart)
|
2016-01-11 09:59:25 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2016-09-16 05:12:45 +02:00
|
|
|
const char *method_old, *method_new;
|
2016-01-11 09:59:25 +01:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->ip4_state != IP_NONE) {
|
|
|
|
|
g_clear_object (&priv->con_ip4_config);
|
2016-03-29 13:50:39 +02:00
|
|
|
g_clear_object (&priv->ext_ip4_config);
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->con_ip4_config = _ip4_config_new (self);
|
2016-01-11 09:59:25 +01:00
|
|
|
nm_ip4_config_merge_setting (priv->con_ip4_config,
|
|
|
|
|
s_ip4_new,
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET));
|
2016-01-11 09:59:25 +01:00
|
|
|
|
2017-03-16 14:54:16 +01:00
|
|
|
if (!force_restart) {
|
|
|
|
|
method_old = s_ip4_old
|
|
|
|
|
? nm_setting_ip_config_get_method (s_ip4_old)
|
|
|
|
|
: NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
|
|
|
method_new = s_ip4_new
|
|
|
|
|
? nm_setting_ip_config_get_method (s_ip4_new)
|
|
|
|
|
: NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
|
|
|
force_restart = !nm_streq0 (method_old, method_new);
|
|
|
|
|
}
|
2016-09-16 05:12:45 +02:00
|
|
|
|
2017-03-16 14:54:16 +01:00
|
|
|
if (force_restart) {
|
2016-01-11 09:59:25 +01:00
|
|
|
_cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE);
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET, IP_WAIT);
|
2016-01-11 09:59:25 +01:00
|
|
|
if (!nm_device_activate_stage3_ip4_start (self))
|
|
|
|
|
_LOGW (LOGD_IP4, "Failed to apply IPv4 configuration");
|
2016-02-12 14:19:46 +01:00
|
|
|
} else {
|
2017-09-28 14:22:07 +02:00
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE))
|
2016-02-12 14:19:46 +01:00
|
|
|
_LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration");
|
|
|
|
|
}
|
2016-01-11 09:59:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_reactivate_ip6_config (NMDevice *self,
|
|
|
|
|
NMSettingIPConfig *s_ip6_old,
|
2017-03-16 14:54:16 +01:00
|
|
|
NMSettingIPConfig *s_ip6_new,
|
|
|
|
|
gboolean force_restart)
|
2016-01-11 09:59:25 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2016-09-16 05:12:45 +02:00
|
|
|
const char *method_old, *method_new;
|
2016-01-11 09:59:25 +01:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->ip6_state != IP_NONE) {
|
|
|
|
|
g_clear_object (&priv->con_ip6_config);
|
2016-03-29 13:50:39 +02:00
|
|
|
g_clear_object (&priv->ext_ip6_config);
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
priv->con_ip6_config = _ip6_config_new (self);
|
2016-01-11 09:59:25 +01:00
|
|
|
nm_ip6_config_merge_setting (priv->con_ip6_config,
|
|
|
|
|
s_ip6_new,
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET6, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET6));
|
2016-01-11 09:59:25 +01:00
|
|
|
|
2017-03-16 14:54:16 +01:00
|
|
|
if (!force_restart) {
|
|
|
|
|
method_old = s_ip6_old
|
|
|
|
|
? nm_setting_ip_config_get_method (s_ip6_old)
|
|
|
|
|
: NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
|
|
|
method_new = s_ip6_new
|
|
|
|
|
? nm_setting_ip_config_get_method (s_ip6_new)
|
|
|
|
|
: NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
|
|
|
force_restart = !nm_streq0 (method_old, method_new);
|
|
|
|
|
}
|
2016-09-16 05:12:45 +02:00
|
|
|
|
2017-03-16 14:54:16 +01:00
|
|
|
if (force_restart) {
|
2016-01-11 09:59:25 +01:00
|
|
|
_cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE);
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_WAIT);
|
2016-01-11 09:59:25 +01:00
|
|
|
if (!nm_device_activate_stage3_ip6_start (self))
|
|
|
|
|
_LOGW (LOGD_IP6, "Failed to apply IPv6 configuration");
|
2016-02-12 14:19:46 +01:00
|
|
|
} else {
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2016-02-12 14:19:46 +01:00
|
|
|
_LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration");
|
|
|
|
|
}
|
2016-01-11 09:59:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-07 14:34:17 +01:00
|
|
|
static void
|
2017-04-21 15:46:56 +02:00
|
|
|
_pacrunner_manager_send (NMDevice *self)
|
2017-03-07 14:34:17 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-04-21 15:46:56 +02:00
|
|
|
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
|
|
|
|
|
&priv->pacrunner_call_id);
|
2017-04-07 10:23:22 +02:00
|
|
|
|
2017-04-21 15:46:56 +02:00
|
|
|
if (!priv->pacrunner_manager)
|
|
|
|
|
priv->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ());
|
|
|
|
|
|
|
|
|
|
priv->pacrunner_call_id = nm_pacrunner_manager_send (priv->pacrunner_manager,
|
|
|
|
|
nm_device_get_ip_iface (self),
|
|
|
|
|
priv->proxy_config,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
reactivate_proxy_config (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-03-07 14:34:17 +01:00
|
|
|
|
2017-04-21 15:46:56 +02:00
|
|
|
if (!priv->pacrunner_call_id)
|
|
|
|
|
return;
|
2017-03-07 14:34:17 +01:00
|
|
|
nm_device_set_proxy_config (self, priv->dhcp4.pac_url);
|
2017-04-21 15:46:56 +02:00
|
|
|
_pacrunner_manager_send (self);
|
2017-03-07 14:34:17 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-03 12:06:58 +01:00
|
|
|
static gboolean
|
|
|
|
|
can_reapply_change (NMDevice *self, const char *setting_name,
|
|
|
|
|
NMSetting *s_old, NMSetting *s_new,
|
|
|
|
|
GHashTable *diffs, GError **error)
|
|
|
|
|
{
|
2017-03-07 14:34:17 +01:00
|
|
|
if (nm_streq (setting_name, NM_SETTING_CONNECTION_SETTING_NAME)) {
|
|
|
|
|
/* Whitelist allowed properties from "connection" setting which are
|
|
|
|
|
* allowed to differ.
|
|
|
|
|
*
|
|
|
|
|
* This includes UUID, there is no principal problem with reapplying a
|
|
|
|
|
* connection and changing it's UUID. In fact, disallowing it makes it
|
|
|
|
|
* cumbersome for the user to reapply any connection but the original
|
|
|
|
|
* settings-connection. */
|
|
|
|
|
return nm_device_hash_check_invalid_keys (diffs,
|
|
|
|
|
NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
error,
|
|
|
|
|
NM_SETTING_CONNECTION_ID,
|
|
|
|
|
NM_SETTING_CONNECTION_UUID,
|
|
|
|
|
NM_SETTING_CONNECTION_STABLE_ID,
|
|
|
|
|
NM_SETTING_CONNECTION_AUTOCONNECT,
|
|
|
|
|
NM_SETTING_CONNECTION_ZONE,
|
|
|
|
|
NM_SETTING_CONNECTION_METERED,
|
|
|
|
|
NM_SETTING_CONNECTION_LLDP);
|
|
|
|
|
} else if (NM_IN_STRSET (setting_name,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME)) {
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
if (g_hash_table_contains (diffs, NM_SETTING_IP_CONFIG_ROUTE_TABLE)) {
|
|
|
|
|
/* changing the route-table setting is complicated, because it affects
|
|
|
|
|
* how we sync the routes. Don't support changing it without full
|
|
|
|
|
* re-activation.
|
|
|
|
|
*
|
|
|
|
|
* The problem is really that changing the setting also affects the sync
|
|
|
|
|
* mode. So, switching from NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN to
|
|
|
|
|
* NM_IP_ROUTE_TABLE_SYNC_MODE_FULL would somehow require us to get rid
|
|
|
|
|
* of additional routes, but we don't know which routes were added by NM
|
|
|
|
|
* and which should be removed.
|
|
|
|
|
*
|
|
|
|
|
* Note how nm_device_get_route_table() caches the value for the duration of the
|
|
|
|
|
* activation. */
|
|
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
|
|
|
|
"Can't reapply changes to '%s.%s' setting",
|
|
|
|
|
setting_name,
|
|
|
|
|
NM_SETTING_IP_CONFIG_ROUTE_TABLE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2017-03-07 14:34:17 +01:00
|
|
|
return TRUE;
|
|
|
|
|
} else {
|
2017-03-03 12:06:58 +01:00
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
|
|
|
|
|
"Can't reapply any changes to '%s' setting",
|
|
|
|
|
setting_name);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
reapply_connection (NMDevice *self, NMConnection *con_old, NMConnection *con_new)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check_and_reapply_connection:
|
2016-01-07 11:55:44 +01:00
|
|
|
* @connection: the new connection settings to be applied or %NULL to reapply
|
|
|
|
|
* the current settings connection
|
2016-02-11 09:04:58 +01:00
|
|
|
* @version_id: either zero, or the current version id for the applied
|
|
|
|
|
* connection.
|
2017-03-04 00:21:22 +01:00
|
|
|
* @audit_args: on return, a string representing the changes
|
2015-11-02 15:32:38 +01:00
|
|
|
* @error: the error if %FALSE is returned
|
|
|
|
|
*
|
|
|
|
|
* Change configuration of an already configured device if possible.
|
|
|
|
|
* Updates the device's applied connection upon success.
|
|
|
|
|
*
|
|
|
|
|
* Return: %FALSE if the new configuration can not be reapplied.
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
2017-03-03 12:06:58 +01:00
|
|
|
check_and_reapply_connection (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
guint64 version_id,
|
2017-03-04 00:21:22 +01:00
|
|
|
char **audit_args,
|
2017-03-03 12:06:58 +01:00
|
|
|
GError **error)
|
2015-11-02 15:32:38 +01:00
|
|
|
{
|
2017-03-03 12:06:58 +01:00
|
|
|
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
|
2016-01-07 11:55:44 +01:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-11-02 15:32:38 +01:00
|
|
|
NMConnection *applied = nm_device_get_applied_connection (self);
|
2016-01-07 11:55:44 +01:00
|
|
|
gs_unref_object NMConnection *applied_clone = NULL;
|
|
|
|
|
gs_unref_hashtable GHashTable *diffs = NULL;
|
|
|
|
|
NMConnection *con_old, *con_new;
|
|
|
|
|
NMSettingIPConfig *s_ip4_old, *s_ip4_new;
|
|
|
|
|
NMSettingIPConfig *s_ip6_old, *s_ip6_new;
|
2017-03-03 12:06:58 +01:00
|
|
|
GHashTableIter iter;
|
2015-11-02 15:32:38 +01:00
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
if (priv->state != NM_DEVICE_STATE_ACTIVATED) {
|
|
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
|
|
|
|
"Device is not activated");
|
2015-11-02 15:32:38 +01:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_connection_diff (connection,
|
|
|
|
|
applied,
|
|
|
|
|
NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP |
|
|
|
|
|
NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS,
|
|
|
|
|
&diffs);
|
|
|
|
|
|
2017-06-16 13:06:26 +02:00
|
|
|
if (audit_args) {
|
|
|
|
|
if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ()))
|
|
|
|
|
*audit_args = nm_utils_format_con_diff_for_audit (diffs);
|
|
|
|
|
else
|
|
|
|
|
*audit_args = NULL;
|
|
|
|
|
}
|
2017-03-04 00:21:22 +01:00
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
* check for unsupported changes and reject to reapply
|
|
|
|
|
*************************************************************************/
|
2017-03-03 12:06:58 +01:00
|
|
|
if (diffs) {
|
|
|
|
|
char *setting_name;
|
|
|
|
|
GHashTable *setting_diff;
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, diffs);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *) &setting_name, (gpointer *) &setting_diff)) {
|
|
|
|
|
if (!klass->can_reapply_change (self,
|
|
|
|
|
setting_name,
|
|
|
|
|
nm_connection_get_setting_by_name (applied, setting_name),
|
|
|
|
|
nm_connection_get_setting_by_name (connection, setting_name),
|
|
|
|
|
setting_diff,
|
|
|
|
|
error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-02 15:32:38 +01:00
|
|
|
|
2016-02-11 09:04:58 +01:00
|
|
|
if ( version_id != 0
|
|
|
|
|
&& version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) {
|
|
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_VERSION_ID_MISMATCH,
|
|
|
|
|
"Reapply failed because device changed in the meantime and the version-id mismatches");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
* Update applied connection
|
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
2016-02-11 08:36:39 +01:00
|
|
|
if (diffs)
|
|
|
|
|
nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request);
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)",
|
2017-03-14 11:15:05 +01:00
|
|
|
(unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)),
|
2016-02-11 08:36:39 +01:00
|
|
|
diffs ? "" : " (unmodified)");
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
if (diffs) {
|
2017-01-10 20:07:23 +01:00
|
|
|
NMConnection *connection_clean = connection;
|
|
|
|
|
gs_free NMConnection *connection_clean_free = NULL;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con_a, *s_con_n;
|
|
|
|
|
|
|
|
|
|
/* we allow re-applying a connection with differing ID, UUID, STABLE_ID and AUTOCONNECT.
|
2017-03-03 12:06:58 +01:00
|
|
|
* This is for convenience but these values are not actually changeable. So, check
|
2017-01-10 20:07:23 +01:00
|
|
|
* if they changed, and if the did revert to the original values. */
|
|
|
|
|
s_con_a = nm_connection_get_setting_connection (applied);
|
|
|
|
|
s_con_n = nm_connection_get_setting_connection (connection);
|
|
|
|
|
|
|
|
|
|
if ( !nm_streq (nm_setting_connection_get_id (s_con_a), nm_setting_connection_get_id (s_con_n))
|
|
|
|
|
|| !nm_streq (nm_setting_connection_get_uuid (s_con_a), nm_setting_connection_get_uuid (s_con_n))
|
|
|
|
|
|| nm_setting_connection_get_autoconnect (s_con_a) != nm_setting_connection_get_autoconnect (s_con_n)
|
|
|
|
|
|| !nm_streq0 (nm_setting_connection_get_stable_id (s_con_a), nm_setting_connection_get_stable_id (s_con_n))) {
|
|
|
|
|
connection_clean_free = nm_simple_connection_new_clone (connection);
|
|
|
|
|
connection_clean = connection_clean_free;
|
|
|
|
|
s_con_n = nm_connection_get_setting_connection (connection);
|
|
|
|
|
g_object_set (s_con_n,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, nm_setting_connection_get_id (s_con_a),
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, nm_setting_connection_get_uuid (s_con_a),
|
|
|
|
|
NM_SETTING_CONNECTION_AUTOCONNECT, nm_setting_connection_get_autoconnect (s_con_a),
|
|
|
|
|
NM_SETTING_CONNECTION_STABLE_ID, nm_setting_connection_get_stable_id (s_con_a),
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
con_old = applied_clone = nm_simple_connection_new_clone (applied);
|
|
|
|
|
con_new = applied;
|
2017-01-10 20:07:23 +01:00
|
|
|
nm_connection_replace_settings_from_connection (applied, connection_clean);
|
2016-04-30 12:34:17 +02:00
|
|
|
nm_connection_clear_secrets (applied);
|
2016-01-07 11:55:44 +01:00
|
|
|
} else
|
|
|
|
|
con_old = con_new = applied;
|
|
|
|
|
|
2017-03-16 14:37:54 +01:00
|
|
|
priv->v4_commit_first_time = TRUE;
|
|
|
|
|
priv->v6_commit_first_time = TRUE;
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
* Reapply changes
|
|
|
|
|
*************************************************************************/
|
2017-03-03 12:06:58 +01:00
|
|
|
klass->reapply_connection (self, con_old, con_new);
|
2016-01-07 11:55:44 +01:00
|
|
|
|
|
|
|
|
nm_device_update_firewall_zone (self);
|
|
|
|
|
nm_device_update_metered (self);
|
2017-03-06 17:48:01 +01:00
|
|
|
lldp_init (self, FALSE);
|
2016-01-07 11:55:44 +01:00
|
|
|
|
2017-03-03 12:06:58 +01:00
|
|
|
s_ip4_old = nm_connection_get_setting_ip4_config (con_old);
|
|
|
|
|
s_ip4_new = nm_connection_get_setting_ip4_config (con_new);
|
|
|
|
|
s_ip6_old = nm_connection_get_setting_ip6_config (con_old);
|
|
|
|
|
s_ip6_new = nm_connection_get_setting_ip6_config (con_new);
|
|
|
|
|
|
2017-03-16 14:54:16 +01:00
|
|
|
nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new, TRUE);
|
|
|
|
|
nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new, TRUE);
|
2015-11-02 15:32:38 +01:00
|
|
|
|
2017-03-07 14:34:17 +01:00
|
|
|
reactivate_proxy_config (self);
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
return TRUE;
|
2015-11-02 15:32:38 +01:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 13:06:26 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_reapply (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
return check_and_reapply_connection (self,
|
|
|
|
|
connection,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
error);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 09:04:58 +01:00
|
|
|
typedef struct {
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
guint64 version_id;
|
|
|
|
|
} ReapplyData;
|
|
|
|
|
|
2015-11-02 15:32:38 +01:00
|
|
|
static void
|
|
|
|
|
reapply_cb (NMDevice *self,
|
|
|
|
|
GDBusMethodInvocation *context,
|
|
|
|
|
NMAuthSubject *subject,
|
|
|
|
|
GError *error,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
2016-02-11 09:04:58 +01:00
|
|
|
ReapplyData *reapply_data = user_data;
|
|
|
|
|
guint64 version_id = 0;
|
|
|
|
|
gs_unref_object NMConnection *connection = NULL;
|
2015-11-02 15:32:38 +01:00
|
|
|
GError *local = NULL;
|
2017-03-04 00:21:22 +01:00
|
|
|
gs_free char *audit_args = NULL;
|
2015-11-02 15:32:38 +01:00
|
|
|
|
2016-02-11 09:04:58 +01:00
|
|
|
if (reapply_data) {
|
|
|
|
|
connection = reapply_data->connection;
|
|
|
|
|
version_id = reapply_data->version_id;
|
|
|
|
|
g_slice_free (ReapplyData, reapply_data);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-02 15:32:38 +01:00
|
|
|
if (error) {
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, subject, error->message);
|
2015-11-02 15:32:38 +01:00
|
|
|
g_dbus_method_invocation_return_gerror (context, error);
|
2016-01-07 11:55:44 +01:00
|
|
|
return;
|
2015-11-02 15:32:38 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-03 12:06:58 +01:00
|
|
|
if (!check_and_reapply_connection (self,
|
|
|
|
|
connection ? : (NMConnection *) nm_device_get_settings_connection (self),
|
|
|
|
|
version_id,
|
2017-03-04 00:21:22 +01:00
|
|
|
&audit_args,
|
2017-03-03 12:06:58 +01:00
|
|
|
&local)) {
|
2017-03-04 00:21:22 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, audit_args, subject, local->message);
|
2016-01-07 11:55:44 +01:00
|
|
|
g_dbus_method_invocation_take_error (context, local);
|
|
|
|
|
local = NULL;
|
|
|
|
|
} else {
|
2017-03-04 00:21:22 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, audit_args, subject, NULL);
|
2016-01-07 11:55:44 +01:00
|
|
|
g_dbus_method_invocation_return_value (context, NULL);
|
2015-11-02 15:32:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
impl_device_reapply (NMDevice *self,
|
|
|
|
|
GDBusMethodInvocation *context,
|
|
|
|
|
GVariant *settings,
|
2016-02-11 09:04:58 +01:00
|
|
|
guint64 version_id,
|
2016-02-12 14:02:53 +01:00
|
|
|
guint32 flags)
|
2015-11-02 15:32:38 +01:00
|
|
|
{
|
2016-01-07 11:55:44 +01:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-11-02 15:32:38 +01:00
|
|
|
NMSettingsConnection *settings_connection;
|
2016-01-07 11:55:44 +01:00
|
|
|
NMConnection *connection = NULL;
|
2015-11-02 15:32:38 +01:00
|
|
|
GError *error = NULL;
|
2016-02-11 09:04:58 +01:00
|
|
|
ReapplyData *reapply_data;
|
2015-11-02 15:32:38 +01:00
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
/* No flags supported as of now. */
|
|
|
|
|
if (flags != 0) {
|
2015-11-02 15:32:38 +01:00
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
2016-02-12 14:02:53 +01:00
|
|
|
NM_DEVICE_ERROR_FAILED,
|
2016-01-07 11:55:44 +01:00
|
|
|
"Invalid flags specified");
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message);
|
2016-01-07 11:55:44 +01:00
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (priv->state != NM_DEVICE_STATE_ACTIVATED) {
|
|
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
|
|
|
|
"Device is not activated");
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message);
|
2016-01-07 11:55:44 +01:00
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
2015-11-02 15:32:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings_connection = nm_device_get_settings_connection (self);
|
|
|
|
|
g_return_if_fail (settings_connection);
|
|
|
|
|
|
|
|
|
|
if (settings && g_variant_n_children (settings)) {
|
|
|
|
|
/* New settings specified inline. */
|
2016-03-23 15:50:20 +01:00
|
|
|
connection = _nm_simple_connection_new_from_dbus (settings,
|
|
|
|
|
NM_SETTING_PARSE_FLAGS_STRICT
|
|
|
|
|
| NM_SETTING_PARSE_FLAGS_NORMALIZE,
|
|
|
|
|
&error);
|
2015-11-02 15:32:38 +01:00
|
|
|
if (!connection) {
|
|
|
|
|
g_prefix_error (&error, "The settings specified are invalid: ");
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message);
|
2016-01-07 11:55:44 +01:00
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
2015-11-02 15:32:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
nm_connection_clear_secrets (connection);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 09:04:58 +01:00
|
|
|
if (connection || version_id) {
|
|
|
|
|
reapply_data = g_slice_new (ReapplyData);
|
|
|
|
|
reapply_data->connection = connection;
|
|
|
|
|
reapply_data->version_id = version_id;
|
|
|
|
|
} else
|
|
|
|
|
reapply_data = NULL;
|
|
|
|
|
|
2015-11-02 15:32:38 +01:00
|
|
|
/* Ask the manager to authenticate this request for us */
|
|
|
|
|
g_signal_emit (self, signals[AUTH_REQUEST], 0,
|
|
|
|
|
context,
|
|
|
|
|
nm_device_get_applied_connection (self),
|
|
|
|
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
|
|
|
|
TRUE,
|
|
|
|
|
reapply_cb,
|
2016-02-11 09:04:58 +01:00
|
|
|
reapply_data);
|
2015-11-02 15:32:38 +01:00
|
|
|
}
|
|
|
|
|
|
2016-02-11 09:18:35 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_applied_connection_cb (NMDevice *self,
|
|
|
|
|
GDBusMethodInvocation *context,
|
|
|
|
|
NMAuthSubject *subject,
|
|
|
|
|
GError *error,
|
|
|
|
|
gpointer user_data /* possibly dangling pointer */)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMConnection *applied_connection;
|
|
|
|
|
GVariant *settings;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
g_dbus_method_invocation_return_gerror (context, error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
applied_connection = nm_device_get_applied_connection (self);
|
|
|
|
|
|
|
|
|
|
if (!applied_connection) {
|
|
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
|
|
|
|
"Device is not activated");
|
|
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (applied_connection != user_data) {
|
|
|
|
|
/* The applied connection changed due to a race. Reauthenticate. */
|
|
|
|
|
g_signal_emit (self, signals[AUTH_REQUEST], 0,
|
|
|
|
|
context,
|
|
|
|
|
applied_connection,
|
|
|
|
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
|
|
|
|
TRUE,
|
|
|
|
|
get_applied_connection_cb,
|
|
|
|
|
applied_connection /* no need take a ref. We will not dereference this pointer. */);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
|
|
|
|
|
if (!settings)
|
|
|
|
|
settings = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
|
|
|
|
|
|
|
|
|
|
g_dbus_method_invocation_return_value (context,
|
|
|
|
|
g_variant_new ("(@a{sa{sv}}t)",
|
|
|
|
|
settings,
|
|
|
|
|
nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
impl_device_get_applied_connection (NMDevice *self,
|
|
|
|
|
GDBusMethodInvocation *context,
|
|
|
|
|
guint32 flags)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *applied_connection;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
/* No flags supported as of now. */
|
|
|
|
|
if (flags != 0) {
|
|
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"Invalid flags specified");
|
|
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applied_connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (!applied_connection) {
|
|
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
|
|
|
|
"Device is not activated");
|
|
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ask the manager to authenticate this request for us */
|
|
|
|
|
g_signal_emit (self, signals[AUTH_REQUEST], 0,
|
|
|
|
|
context,
|
|
|
|
|
applied_connection,
|
|
|
|
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
|
|
|
|
TRUE,
|
|
|
|
|
get_applied_connection_cb,
|
|
|
|
|
applied_connection /* no need take a ref. We will not dereference this pointer. */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-09-13 16:45:22 +02:00
|
|
|
typedef struct {
|
|
|
|
|
gint64 timestamp_ms;
|
|
|
|
|
bool dirty;
|
|
|
|
|
} IP6RoutesTemporaryNotAvailableData;
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_rt6_temporary_not_available_timeout (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->rt6_temporary_not_available_id = 0;
|
|
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
|
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_rt6_temporary_not_available_set (NMDevice *self,
|
|
|
|
|
GPtrArray *temporary_not_available)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
IP6RoutesTemporaryNotAvailableData *data;
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
gint64 now_ms, oldest_ms;
|
|
|
|
|
const gint64 MAX_AGE_MS = 20000;
|
|
|
|
|
guint i;
|
|
|
|
|
gboolean success = TRUE;
|
|
|
|
|
|
|
|
|
|
if ( !temporary_not_available
|
|
|
|
|
|| !temporary_not_available->len) {
|
|
|
|
|
/* nothing outstanding. Clear tracking the routes. */
|
|
|
|
|
g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref);
|
|
|
|
|
nm_clear_g_source (&priv->rt6_temporary_not_available_id);
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (priv->rt6_temporary_not_available) {
|
|
|
|
|
g_hash_table_iter_init (&iter, priv->rt6_temporary_not_available);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &data))
|
|
|
|
|
data->dirty = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
priv->rt6_temporary_not_available = g_hash_table_new_full ((GHashFunc) nmp_object_id_hash,
|
|
|
|
|
(GEqualFunc) nmp_object_id_equal,
|
|
|
|
|
(GDestroyNotify) nmp_object_unref,
|
|
|
|
|
nm_g_slice_free_fcn (IP6RoutesTemporaryNotAvailableData));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
now_ms = nm_utils_get_monotonic_timestamp_ms ();
|
|
|
|
|
oldest_ms = now_ms;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < temporary_not_available->len; i++) {
|
|
|
|
|
const NMPObject *o = temporary_not_available->pdata[i];
|
|
|
|
|
|
|
|
|
|
data = g_hash_table_lookup (priv->rt6_temporary_not_available, o);
|
|
|
|
|
if (data) {
|
|
|
|
|
if (!data->dirty)
|
|
|
|
|
continue;
|
|
|
|
|
data->dirty = FALSE;
|
|
|
|
|
nm_assert (data->timestamp_ms > 0 && data->timestamp_ms <= now_ms);
|
|
|
|
|
if (now_ms > data->timestamp_ms + MAX_AGE_MS) {
|
|
|
|
|
/* timeout. Could not add this address. */
|
|
|
|
|
_LOGW (LOGD_DEVICE, "failure to add IPv6 route: %s",
|
|
|
|
|
nmp_object_to_string (o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
|
|
|
|
success = FALSE;
|
|
|
|
|
} else
|
|
|
|
|
oldest_ms = MIN (data->timestamp_ms, oldest_ms);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = g_slice_new0 (IP6RoutesTemporaryNotAvailableData);
|
|
|
|
|
data->timestamp_ms = now_ms;
|
|
|
|
|
g_hash_table_insert (priv->rt6_temporary_not_available, (gpointer) nmp_object_ref (o), data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, priv->rt6_temporary_not_available);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &data)) {
|
|
|
|
|
if (data->dirty)
|
|
|
|
|
g_hash_table_iter_remove (&iter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_clear_g_source (&priv->rt6_temporary_not_available_id);
|
|
|
|
|
priv->rt6_temporary_not_available_id = g_timeout_add (oldest_ms + MAX_AGE_MS - now_ms,
|
|
|
|
|
_rt6_temporary_not_available_timeout,
|
|
|
|
|
self);
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2012-06-01 16:53:23 -05:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
disconnect_cb (NMDevice *self,
|
2015-04-15 14:53:30 -04:00
|
|
|
GDBusMethodInvocation *context,
|
2015-07-14 10:19:19 +02:00
|
|
|
NMAuthSubject *subject,
|
2012-06-01 16:53:23 -05:00
|
|
|
GError *error,
|
|
|
|
|
gpointer user_data)
|
2009-09-16 13:18:24 +02:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2012-06-01 16:53:23 -05:00
|
|
|
GError *local = NULL;
|
2011-11-17 23:44:17 -06:00
|
|
|
|
2014-01-17 11:18:23 -06:00
|
|
|
if (error) {
|
2015-04-15 14:53:30 -04:00
|
|
|
g_dbus_method_invocation_return_gerror (context, error);
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, NULL, subject, error->message);
|
2014-01-17 11:18:23 -06:00
|
|
|
return;
|
|
|
|
|
}
|
2013-10-18 12:32:01 +02:00
|
|
|
|
2014-01-17 11:18:23 -06:00
|
|
|
/* Authorized */
|
|
|
|
|
if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
local = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
|
|
|
|
"Device is not active");
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, NULL, subject, local->message);
|
2015-04-15 14:53:30 -04:00
|
|
|
g_dbus_method_invocation_take_error (context, local);
|
2014-01-17 11:18:23 -06:00
|
|
|
} else {
|
2017-11-07 12:36:17 +01:00
|
|
|
nm_device_autoconnect_blocked_set (self, NM_DEVICE_AUTOCONNECT_BLOCKED_MANUAL_DISCONNECT);
|
2013-10-18 12:32:01 +02:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_state_changed (self,
|
2014-01-03 13:58:05 -05:00
|
|
|
NM_DEVICE_STATE_DEACTIVATING,
|
2014-01-17 11:18:23 -06:00
|
|
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
2015-04-15 14:53:30 -04:00
|
|
|
g_dbus_method_invocation_return_value (context, NULL);
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, TRUE, NULL, subject, NULL);
|
2011-11-17 23:44:17 -06:00
|
|
|
}
|
2009-09-16 13:18:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-02-20 23:45:23 +01:00
|
|
|
static void
|
|
|
|
|
_clear_queued_act_request (NMDevicePrivate *priv)
|
|
|
|
|
{
|
|
|
|
|
if (priv->queued_act_request) {
|
2017-03-05 15:30:24 +01:00
|
|
|
nm_active_connection_set_state ((NMActiveConnection *) priv->queued_act_request,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
|
2015-02-20 23:45:23 +01:00
|
|
|
g_clear_object (&priv->queued_act_request);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-18 00:34:08 -06:00
|
|
|
static void
|
2015-04-15 14:53:30 -04:00
|
|
|
impl_device_disconnect (NMDevice *self, GDBusMethodInvocation *context)
|
2011-11-18 00:34:08 -06:00
|
|
|
{
|
2014-01-17 11:18:23 -06:00
|
|
|
NMConnection *connection;
|
2012-06-01 16:53:23 -05:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
if (NM_DEVICE_GET_PRIVATE (self)->act_request == NULL) {
|
2012-06-01 16:53:23 -05:00
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
|
|
|
|
"This device is not active");
|
2015-04-15 14:53:30 -04:00
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
2012-06-01 16:53:23 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2014-01-17 11:18:23 -06:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
2012-06-01 16:53:23 -05:00
|
|
|
/* Ask the manager to authenticate this request for us */
|
2014-07-15 13:36:24 +02:00
|
|
|
g_signal_emit (self, signals[AUTH_REQUEST], 0,
|
2012-06-01 16:53:23 -05:00
|
|
|
context,
|
2014-01-17 11:18:23 -06:00
|
|
|
connection,
|
2012-06-01 16:53:23 -05:00
|
|
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
|
|
|
|
TRUE,
|
|
|
|
|
disconnect_cb,
|
|
|
|
|
NULL);
|
2011-11-18 00:34:08 -06:00
|
|
|
}
|
|
|
|
|
|
2014-06-19 12:37:49 +02:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
delete_cb (NMDevice *self,
|
2015-04-15 14:53:30 -04:00
|
|
|
GDBusMethodInvocation *context,
|
2015-07-14 10:19:19 +02:00
|
|
|
NMAuthSubject *subject,
|
2014-06-19 12:37:49 +02:00
|
|
|
GError *error,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
2014-09-24 15:13:19 -05:00
|
|
|
GError *local = NULL;
|
|
|
|
|
|
2014-06-19 12:37:49 +02:00
|
|
|
if (error) {
|
2015-04-15 14:53:30 -04:00
|
|
|
g_dbus_method_invocation_return_gerror (context, error);
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, NULL, subject, error->message);
|
2014-06-19 12:37:49 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Authorized */
|
2017-03-04 00:06:59 +01:00
|
|
|
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, NULL, subject, NULL);
|
2014-09-24 15:13:19 -05:00
|
|
|
if (nm_device_unrealize (self, TRUE, &local))
|
|
|
|
|
g_dbus_method_invocation_return_value (context, NULL);
|
|
|
|
|
else
|
|
|
|
|
g_dbus_method_invocation_take_error (context, local);
|
2014-06-19 12:37:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-04-15 14:53:30 -04:00
|
|
|
impl_device_delete (NMDevice *self, GDBusMethodInvocation *context)
|
2014-06-19 12:37:49 +02:00
|
|
|
{
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
2014-09-05 08:50:02 -05:00
|
|
|
if (!nm_device_is_software (self) || !nm_device_is_real (self)) {
|
2014-06-19 12:37:49 +02:00
|
|
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_NOT_SOFTWARE,
|
2014-09-05 08:50:02 -05:00
|
|
|
"This device is not a software device or is not realized");
|
2015-04-15 14:53:30 -04:00
|
|
|
g_dbus_method_invocation_take_error (context, error);
|
2014-06-19 12:37:49 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ask the manager to authenticate this request for us */
|
2014-07-15 13:36:24 +02:00
|
|
|
g_signal_emit (self, signals[AUTH_REQUEST], 0,
|
2014-06-19 12:37:49 +02:00
|
|
|
context,
|
|
|
|
|
NULL,
|
|
|
|
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
|
|
|
|
TRUE,
|
|
|
|
|
delete_cb,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-16 15:01:16 -05:00
|
|
|
static gboolean
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
_device_activate (NMDevice *self, NMActRequest *req)
|
2007-09-14 19:51:04 +00:00
|
|
|
{
|
2011-11-17 23:50:13 -06:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
|
2014-10-16 15:01:16 -05:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
g_return_val_if_fail (nm_device_get_managed (self, FALSE), FALSE);
|
2014-10-16 15:01:16 -05:00
|
|
|
|
|
|
|
|
/* Ensure the activation request is still valid; the master may have
|
|
|
|
|
* already failed in which case activation of this device should not proceed.
|
|
|
|
|
*/
|
|
|
|
|
if (nm_active_connection_get_state (NM_ACTIVE_CONNECTION (req)) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
|
|
|
|
|
return FALSE;
|
2011-11-17 23:50:13 -06:00
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_act_request_get_applied_connection (req);
|
2011-11-17 23:50:13 -06:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
2015-04-17 15:46:17 +02:00
|
|
|
_LOGI (LOGD_DEVICE, "Activation: starting connection '%s' (%s)",
|
|
|
|
|
nm_connection_get_id (connection),
|
|
|
|
|
nm_connection_get_uuid (connection));
|
2007-09-14 19:51:04 +00:00
|
|
|
|
2014-03-05 22:20:14 +01:00
|
|
|
delete_on_deactivate_unschedule (self);
|
2014-03-05 22:07:19 +01:00
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
act_request_set (self, req);
|
2007-09-27 04:52:03 +00:00
|
|
|
|
2013-11-07 01:08:02 -06:00
|
|
|
nm_device_activate_schedule_stage1_device_prepare (self);
|
2014-10-16 15:01:16 -05:00
|
|
|
return TRUE;
|
2007-09-14 19:51:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-12-08 12:50:10 +01:00
|
|
|
static void
|
|
|
|
|
_carrier_wait_check_queued_act_request (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMActRequest *queued_req;
|
|
|
|
|
|
|
|
|
|
if ( !priv->queued_act_request
|
|
|
|
|
|| !priv->queued_act_request_is_waiting_for_carrier)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
priv->queued_act_request_is_waiting_for_carrier = FALSE;
|
|
|
|
|
if (!priv->carrier) {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "Cancel queued activation request as we have no carrier after timeout");
|
2015-10-19 15:16:20 +02:00
|
|
|
_clear_queued_act_request (priv);
|
2014-12-08 12:50:10 +01:00
|
|
|
} else {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "Activate queued activation request as we now have carrier");
|
|
|
|
|
queued_req = priv->queued_act_request;
|
|
|
|
|
priv->queued_act_request = NULL;
|
|
|
|
|
_device_activate (self, queued_req);
|
|
|
|
|
g_object_unref (queued_req);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
|
|
|
|
|
/* If we have carrier or if we are not waiting for it, the activation
|
|
|
|
|
* request is not blocked waiting for carrier. */
|
|
|
|
|
if (priv->carrier)
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (priv->carrier_wait_id == 0)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_act_request_get_applied_connection (req);
|
2015-10-19 14:44:38 +02:00
|
|
|
if (!connection_requires_carrier (connection))
|
|
|
|
|
return FALSE;
|
2014-12-08 12:50:10 +01:00
|
|
|
|
|
|
|
|
if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL, NULL)) {
|
|
|
|
|
/* We passed all @flags we have, and no @specific_object.
|
|
|
|
|
* This equals maximal availability, if a connection is not available
|
|
|
|
|
* in this case, it is not waiting for carrier.
|
|
|
|
|
*
|
|
|
|
|
* Actually, why are we even trying to activate it? Strange, but whatever
|
|
|
|
|
* the reason, don't wait for carrier.
|
|
|
|
|
*/
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER, NULL)) {
|
|
|
|
|
/* The connection was available with flags ALL, and it is still available
|
|
|
|
|
* if we pretend not to wait for carrier. That means that the
|
|
|
|
|
* connection is available now, and does not wait for carrier.
|
|
|
|
|
*
|
|
|
|
|
* Since the flags increase the availability of a connection, when checking
|
|
|
|
|
* ALL&~WAITING_CARRIER, it means that we certainly would wait for carrier. */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The activation request must wait for carrier. */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 16:15:37 +01:00
|
|
|
void
|
2015-07-14 16:53:24 +02:00
|
|
|
nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection)
|
2015-02-03 16:15:37 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-07-06 10:23:44 +02:00
|
|
|
_LOGI (LOGD_DEVICE, "disconnecting connection '%s' for new activation request",
|
2015-07-14 16:53:24 +02:00
|
|
|
nm_settings_connection_get_id (connection));
|
2015-02-03 16:15:37 +01:00
|
|
|
|
|
|
|
|
if ( priv->queued_act_request
|
2015-07-14 16:53:24 +02:00
|
|
|
&& connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request)))
|
2015-02-03 16:15:37 +01:00
|
|
|
_clear_queued_act_request (priv);
|
|
|
|
|
|
|
|
|
|
if ( priv->act_request
|
2015-07-14 16:53:24 +02:00
|
|
|
&& connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request))
|
2015-02-03 16:15:37 +01:00
|
|
|
&& priv->state < NM_DEVICE_STATE_DEACTIVATING)
|
|
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
NM_DEVICE_STATE_DEACTIVATING,
|
2015-06-18 15:40:42 -04:00
|
|
|
NM_DEVICE_STATE_REASON_NEW_ACTIVATION);
|
2015-02-03 16:15:37 +01:00
|
|
|
}
|
|
|
|
|
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
void
|
|
|
|
|
nm_device_queue_activation (NMDevice *self, NMActRequest *req)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-12-08 12:50:10 +01:00
|
|
|
gboolean must_queue;
|
|
|
|
|
|
|
|
|
|
must_queue = _carrier_wait_check_act_request_must_queue (self, req);
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
|
2016-03-23 14:51:53 +01:00
|
|
|
if (!priv->act_request && !must_queue && nm_device_is_real (self)) {
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
/* Just activate immediately */
|
2014-10-16 15:01:16 -05:00
|
|
|
if (!_device_activate (self, req))
|
|
|
|
|
g_assert_not_reached ();
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* supercede any already-queued request */
|
2015-02-20 23:45:23 +01:00
|
|
|
_clear_queued_act_request (priv);
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
priv->queued_act_request = g_object_ref (req);
|
2014-12-08 12:50:10 +01:00
|
|
|
priv->queued_act_request_is_waiting_for_carrier = must_queue;
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
|
2014-12-08 12:50:10 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect");
|
|
|
|
|
|
2015-02-03 16:15:37 +01:00
|
|
|
/* Deactivate existing activation request first */
|
2014-12-08 12:50:10 +01:00
|
|
|
if (priv->act_request) {
|
|
|
|
|
_LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
|
|
|
|
|
nm_device_state_changed (self,
|
|
|
|
|
NM_DEVICE_STATE_DEACTIVATING,
|
2015-02-17 10:40:18 +01:00
|
|
|
NM_DEVICE_STATE_REASON_NEW_ACTIVATION);
|
2014-12-08 12:50:10 +01:00
|
|
|
}
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
}
|
|
|
|
|
|
2005-12-31 08:21:24 +00:00
|
|
|
/*
|
|
|
|
|
* nm_device_is_activating
|
|
|
|
|
*
|
|
|
|
|
* Return whether or not the device is currently activating itself.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_is_activating (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2011-03-17 13:39:31 -05:00
|
|
|
NMDeviceState state;
|
2007-09-21 03:49:28 +00:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
state = nm_device_get_state (self);
|
2011-03-17 13:39:31 -05:00
|
|
|
if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
|
2007-02-05 12:14:09 +00:00
|
|
|
return TRUE;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-09-21 03:49:28 +00:00
|
|
|
/* There's a small race between the time when stage 1 is scheduled
|
|
|
|
|
* and when the device actually sets STATE_PREPARE when the activation
|
|
|
|
|
* handler is actually run. If there's an activation handler scheduled
|
|
|
|
|
* we're activating anyway.
|
|
|
|
|
*/
|
2015-10-06 11:05:14 +02:00
|
|
|
return priv->act_handle4.id ? TRUE : FALSE;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-16 05:55:58 +05:30
|
|
|
NMProxyConfig *
|
|
|
|
|
nm_device_get_proxy_config (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->proxy_config;
|
|
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-08-16 05:55:58 +05:30
|
|
|
static void
|
2017-03-07 14:34:17 +01:00
|
|
|
nm_device_set_proxy_config (NMDevice *self, const char *pac_url)
|
2016-08-16 05:55:58 +05:30
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingProxy *s_proxy = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_clear_object (&priv->proxy_config);
|
|
|
|
|
priv->proxy_config = nm_proxy_config_new ();
|
|
|
|
|
|
2017-03-07 14:34:17 +01:00
|
|
|
if (pac_url) {
|
|
|
|
|
nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
|
|
|
|
|
nm_proxy_config_set_pac_url (priv->proxy_config, pac_url);
|
|
|
|
|
_LOGD (LOGD_PROXY, "proxy: PAC url \"%s\"", pac_url);
|
|
|
|
|
} else
|
|
|
|
|
nm_proxy_config_set_method (priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
|
2016-08-16 05:55:58 +05:30
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
if (connection)
|
|
|
|
|
s_proxy = nm_connection_get_setting_proxy (connection);
|
|
|
|
|
|
|
|
|
|
if (s_proxy)
|
|
|
|
|
nm_proxy_config_merge_setting (priv->proxy_config, s_proxy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* IP Configuration stuff */
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMDhcp4Config *
|
2008-09-18 Dan Williams <dcbw@redhat.com>
Implement support for honoring configured and automatic hostnames, and for
setting the configured hostname.
* introspection/nm-ip4-config.xml
src/nm-ip4-config.c
src/nm-ip4-config.h
src/dhcp-manager/nm-dhcp-manager.c
- Remove useless hostname property; it's not really part of the IPv4
config
* introspection/nm-settings-system.xml
libnm-glib/nm-dbus-settings-system.c
libnm-glib/nm-dbus-settings-system.h
- Add SetHostname() call to system settings D-Bus interface
- Add Hostname property to system settings D-Bus interface
- (nm_dbus_settings_system_save_hostname,
nm_dbus_settings_system_get_hostname): implement
* src/nm-device.c
src/nm-device.h
- (nm_device_get_dhcp4_config): implement
* src/nm-manager.c
src/nm-manager.h
- Fetch and track system settings service hostname changes, and proxy
the changes via a GObject property of the manager
* system-settings/src/nm-system-config-interface.c
system-settings/src/nm-system-config-interface.h
- Replace nm_system_config_interface_supports_add() with a capabilities
bitfield
* system-settings/src/nm-system-config-error.c
system-settings/src/nm-system-config-error.h
- Add additional errors
* system-settings/src/dbus-settings.c
system-settings/src/dbus-settings.h
- (get_property, nm_sysconfig_settings_class_init): add hostname
property; first plugin returning a hostname wins
- (impl_settings_add_connection): use plugin capabilities instead of
nm_system_config_interface_supports_add()
- (impl_settings_save_hostname): implement hostname saving
* src/NetworkManagerPolicy.c
- (lookup_thread_run_cb, lookup_thread_worker, lookup_thread_new,
lookup_thread_die): implement an asynchronous hostname lookup thread
which given an IPv4 address tries to look up the hostname for that
address with reverse DNS
- (get_best_device): split out best device code from
update_routing_and_dns()
- (update_etc_hosts): update /etc/hosts with the machine's new hostname
to preserve the 127.0.0.1 reverse mapping that so many things require
- (set_system_hostname): set a given hostname
- (update_system_hostname): implement hostname policy; a configured
hostname (from the system settings service) is used if available,
otherwise an automatically determined hostname from DHCP, VPN, etc.
If there was no automatically determined hostname, reverse DNS of
the best device's IP address will be used, and as a last resort the
hostname 'localhost.localdomain' is set.
- (update_routing_and_dns): use get_best_device(); update the system
hostname when the network config changes
- (hostname_changed): update system hostname if the system settings
service signals a hostname change
- (nm_policy_new): list for system settings service hostname changes
- (nm_policy_destroy): ensure that an in-progress hostname lookup thread
gets told to die
* system-settings/plugins/keyfile/plugin.c
system-settings/plugins/ifcfg-suse/plugin.c
- (get_property, sc_plugin_ifcfg_class_init): implement hostname and
capabilities properties
* system-settings/plugins/ifcfg-fedora/shvar.c
- (svOpenFile): re-enable R/W access of ifcfg files since the plugin
writes out /etc/sysconfig/network now
* system-settings/plugins/ifcfg-fedora/plugin.c
- (plugin_get_hostname): get hostname from /etc/sysconfig/network
- (plugin_set_hostname): save hostname to /etc/sysconfig/network
- (sc_network_changed_cb): handle changes to /etc/sysconfig/network
- (sc_plugin_ifcfg_init): monitor /etc/sysconfig/network for changes
- (get_property, set_property, sc_plugin_ifcfg_class_init): implement
hostname get/set and capabilities get
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4077 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-09-18 15:16:44 +00:00
|
|
|
nm_device_get_dhcp4_config (NMDevice *self)
|
|
|
|
|
{
|
2010-01-14 00:45:10 -08:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
2008-09-18 Dan Williams <dcbw@redhat.com>
Implement support for honoring configured and automatic hostnames, and for
setting the configured hostname.
* introspection/nm-ip4-config.xml
src/nm-ip4-config.c
src/nm-ip4-config.h
src/dhcp-manager/nm-dhcp-manager.c
- Remove useless hostname property; it's not really part of the IPv4
config
* introspection/nm-settings-system.xml
libnm-glib/nm-dbus-settings-system.c
libnm-glib/nm-dbus-settings-system.h
- Add SetHostname() call to system settings D-Bus interface
- Add Hostname property to system settings D-Bus interface
- (nm_dbus_settings_system_save_hostname,
nm_dbus_settings_system_get_hostname): implement
* src/nm-device.c
src/nm-device.h
- (nm_device_get_dhcp4_config): implement
* src/nm-manager.c
src/nm-manager.h
- Fetch and track system settings service hostname changes, and proxy
the changes via a GObject property of the manager
* system-settings/src/nm-system-config-interface.c
system-settings/src/nm-system-config-interface.h
- Replace nm_system_config_interface_supports_add() with a capabilities
bitfield
* system-settings/src/nm-system-config-error.c
system-settings/src/nm-system-config-error.h
- Add additional errors
* system-settings/src/dbus-settings.c
system-settings/src/dbus-settings.h
- (get_property, nm_sysconfig_settings_class_init): add hostname
property; first plugin returning a hostname wins
- (impl_settings_add_connection): use plugin capabilities instead of
nm_system_config_interface_supports_add()
- (impl_settings_save_hostname): implement hostname saving
* src/NetworkManagerPolicy.c
- (lookup_thread_run_cb, lookup_thread_worker, lookup_thread_new,
lookup_thread_die): implement an asynchronous hostname lookup thread
which given an IPv4 address tries to look up the hostname for that
address with reverse DNS
- (get_best_device): split out best device code from
update_routing_and_dns()
- (update_etc_hosts): update /etc/hosts with the machine's new hostname
to preserve the 127.0.0.1 reverse mapping that so many things require
- (set_system_hostname): set a given hostname
- (update_system_hostname): implement hostname policy; a configured
hostname (from the system settings service) is used if available,
otherwise an automatically determined hostname from DHCP, VPN, etc.
If there was no automatically determined hostname, reverse DNS of
the best device's IP address will be used, and as a last resort the
hostname 'localhost.localdomain' is set.
- (update_routing_and_dns): use get_best_device(); update the system
hostname when the network config changes
- (hostname_changed): update system hostname if the system settings
service signals a hostname change
- (nm_policy_new): list for system settings service hostname changes
- (nm_policy_destroy): ensure that an in-progress hostname lookup thread
gets told to die
* system-settings/plugins/keyfile/plugin.c
system-settings/plugins/ifcfg-suse/plugin.c
- (get_property, sc_plugin_ifcfg_class_init): implement hostname and
capabilities properties
* system-settings/plugins/ifcfg-fedora/shvar.c
- (svOpenFile): re-enable R/W access of ifcfg files since the plugin
writes out /etc/sysconfig/network now
* system-settings/plugins/ifcfg-fedora/plugin.c
- (plugin_get_hostname): get hostname from /etc/sysconfig/network
- (plugin_set_hostname): save hostname to /etc/sysconfig/network
- (sc_network_changed_cb): handle changes to /etc/sysconfig/network
- (sc_plugin_ifcfg_init): monitor /etc/sysconfig/network for changes
- (get_property, set_property, sc_plugin_ifcfg_class_init): implement
hostname get/set and capabilities get
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4077 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-09-18 15:16:44 +00:00
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->dhcp4.config;
|
2008-09-18 Dan Williams <dcbw@redhat.com>
Implement support for honoring configured and automatic hostnames, and for
setting the configured hostname.
* introspection/nm-ip4-config.xml
src/nm-ip4-config.c
src/nm-ip4-config.h
src/dhcp-manager/nm-dhcp-manager.c
- Remove useless hostname property; it's not really part of the IPv4
config
* introspection/nm-settings-system.xml
libnm-glib/nm-dbus-settings-system.c
libnm-glib/nm-dbus-settings-system.h
- Add SetHostname() call to system settings D-Bus interface
- Add Hostname property to system settings D-Bus interface
- (nm_dbus_settings_system_save_hostname,
nm_dbus_settings_system_get_hostname): implement
* src/nm-device.c
src/nm-device.h
- (nm_device_get_dhcp4_config): implement
* src/nm-manager.c
src/nm-manager.h
- Fetch and track system settings service hostname changes, and proxy
the changes via a GObject property of the manager
* system-settings/src/nm-system-config-interface.c
system-settings/src/nm-system-config-interface.h
- Replace nm_system_config_interface_supports_add() with a capabilities
bitfield
* system-settings/src/nm-system-config-error.c
system-settings/src/nm-system-config-error.h
- Add additional errors
* system-settings/src/dbus-settings.c
system-settings/src/dbus-settings.h
- (get_property, nm_sysconfig_settings_class_init): add hostname
property; first plugin returning a hostname wins
- (impl_settings_add_connection): use plugin capabilities instead of
nm_system_config_interface_supports_add()
- (impl_settings_save_hostname): implement hostname saving
* src/NetworkManagerPolicy.c
- (lookup_thread_run_cb, lookup_thread_worker, lookup_thread_new,
lookup_thread_die): implement an asynchronous hostname lookup thread
which given an IPv4 address tries to look up the hostname for that
address with reverse DNS
- (get_best_device): split out best device code from
update_routing_and_dns()
- (update_etc_hosts): update /etc/hosts with the machine's new hostname
to preserve the 127.0.0.1 reverse mapping that so many things require
- (set_system_hostname): set a given hostname
- (update_system_hostname): implement hostname policy; a configured
hostname (from the system settings service) is used if available,
otherwise an automatically determined hostname from DHCP, VPN, etc.
If there was no automatically determined hostname, reverse DNS of
the best device's IP address will be used, and as a last resort the
hostname 'localhost.localdomain' is set.
- (update_routing_and_dns): use get_best_device(); update the system
hostname when the network config changes
- (hostname_changed): update system hostname if the system settings
service signals a hostname change
- (nm_policy_new): list for system settings service hostname changes
- (nm_policy_destroy): ensure that an in-progress hostname lookup thread
gets told to die
* system-settings/plugins/keyfile/plugin.c
system-settings/plugins/ifcfg-suse/plugin.c
- (get_property, sc_plugin_ifcfg_class_init): implement hostname and
capabilities properties
* system-settings/plugins/ifcfg-fedora/shvar.c
- (svOpenFile): re-enable R/W access of ifcfg files since the plugin
writes out /etc/sysconfig/network now
* system-settings/plugins/ifcfg-fedora/plugin.c
- (plugin_get_hostname): get hostname from /etc/sysconfig/network
- (plugin_set_hostname): save hostname to /etc/sysconfig/network
- (sc_network_changed_cb): handle changes to /etc/sysconfig/network
- (sc_plugin_ifcfg_init): monitor /etc/sysconfig/network for changes
- (get_property, set_property, sc_plugin_ifcfg_class_init): implement
hostname get/set and capabilities get
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4077 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-09-18 15:16:44 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
|
|
|
|
NMIP4Config *
|
|
|
|
|
nm_device_get_ip4_config (NMDevice *self)
|
|
|
|
|
{
|
2010-01-14 00:45:10 -08:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2008-03-11 22:26:46 +00:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip4_config;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-11-07 13:57:39 +00:00
|
|
|
static gboolean
|
|
|
|
|
nm_device_set_ip4_config (NMDevice *self,
|
|
|
|
|
NMIP4Config *new_config,
|
2017-09-12 13:45:53 +02:00
|
|
|
gboolean commit,
|
|
|
|
|
GPtrArray *ip4_dev_route_blacklist)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2007-12-06 14:51:43 +00:00
|
|
|
NMDevicePrivate *priv;
|
2008-11-07 13:57:39 +00:00
|
|
|
NMIP4Config *old_config = NULL;
|
2013-09-06 11:56:41 +02:00
|
|
|
gboolean has_changes = FALSE;
|
2008-11-07 13:57:39 +00:00
|
|
|
gboolean success = TRUE;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2007-12-06 14:51:43 +00:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
_LOGD (LOGD_IP4, "ip4-config: update (commit=%d, new-config=%p)",
|
|
|
|
|
commit, new_config);
|
2016-04-15 20:07:02 +02:00
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
nm_assert ( !new_config
|
|
|
|
|
|| ( new_config
|
2017-10-30 16:27:19 +01:00
|
|
|
&& ({
|
|
|
|
|
int ip_ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
|
|
|
|
|
( ip_ifindex > 0
|
|
|
|
|
&& ip_ifindex == nm_ip4_config_get_ifindex (new_config));
|
|
|
|
|
})));
|
2007-02-16 11:23:49 +00:00
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-02-20 16:31:10 -06:00
|
|
|
|
2008-11-07 13:57:39 +00:00
|
|
|
old_config = priv->ip4_config;
|
2008-03-11 02:46:35 +00:00
|
|
|
|
2013-07-02 22:22:57 +02:00
|
|
|
/* Always commit to nm-platform to update lifetimes */
|
2013-09-06 11:56:41 +02:00
|
|
|
if (commit && new_config) {
|
2017-01-15 13:38:33 +01:00
|
|
|
_commit_mtu (self, new_config);
|
2017-04-17 20:17:45 +02:00
|
|
|
success = nm_ip4_config_commit (new_config,
|
2017-09-13 17:42:41 +02:00
|
|
|
nm_device_get_platform (self),
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, FALSE)
|
|
|
|
|
? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL
|
|
|
|
|
: NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN);
|
2017-09-12 13:45:53 +02:00
|
|
|
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self),
|
|
|
|
|
nm_ip4_config_get_ifindex (new_config),
|
|
|
|
|
ip4_dev_route_blacklist);
|
2013-09-06 11:56:41 +02:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2008-11-07 13:57:39 +00:00
|
|
|
if (new_config) {
|
2013-09-06 11:56:41 +02:00
|
|
|
if (old_config) {
|
|
|
|
|
/* has_changes is set only on relevant changes, because when the configuration changes,
|
|
|
|
|
* this causes a re-read and reset. This should only happen for relevant changes */
|
|
|
|
|
nm_ip4_config_replace (old_config, new_config, &has_changes);
|
|
|
|
|
if (has_changes) {
|
2016-04-15 20:07:02 +02:00
|
|
|
_LOGD (LOGD_IP4, "ip4-config: update IP4Config instance (%s)",
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config)));
|
2013-09-06 11:56:41 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
has_changes = TRUE;
|
|
|
|
|
priv->ip4_config = g_object_ref (new_config);
|
2007-12-06 14:51:43 +00:00
|
|
|
|
2015-04-03 10:08:52 -04:00
|
|
|
if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config)))
|
|
|
|
|
nm_exported_object_export (NM_EXPORTED_OBJECT (new_config));
|
2014-03-17 20:36:48 +01:00
|
|
|
|
2016-04-15 20:07:02 +02:00
|
|
|
_LOGD (LOGD_IP4, "ip4-config: set IP4Config instance (%s)",
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config)));
|
2008-11-07 13:57:39 +00:00
|
|
|
}
|
2013-09-06 11:56:41 +02:00
|
|
|
} else if (old_config) {
|
|
|
|
|
has_changes = TRUE;
|
|
|
|
|
priv->ip4_config = NULL;
|
2016-04-15 20:07:02 +02:00
|
|
|
_LOGD (LOGD_IP4, "ip4-config: clear IP4Config instance (%s)",
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config)));
|
2013-08-01 10:34:46 -05:00
|
|
|
/* Device config is invalid if combined config is invalid */
|
|
|
|
|
g_clear_object (&priv->dev_ip4_config);
|
2008-11-07 13:57:39 +00:00
|
|
|
}
|
2007-12-06 14:51:43 +00:00
|
|
|
|
2017-03-20 13:36:00 +00:00
|
|
|
concheck_periodic_update (self);
|
|
|
|
|
|
2017-03-16 14:27:03 +00:00
|
|
|
if (!nm_device_sys_iface_state_is_external_or_assume (self))
|
|
|
|
|
ip4_rp_filter_update (self);
|
2014-08-29 00:03:47 +02:00
|
|
|
|
2013-09-06 11:56:41 +02:00
|
|
|
if (has_changes) {
|
2017-03-13 15:34:14 +01:00
|
|
|
NMSettingsConnection *settings_connection;
|
|
|
|
|
|
2013-09-06 11:56:41 +02:00
|
|
|
_update_ip4_address (self);
|
|
|
|
|
|
|
|
|
|
if (old_config != priv->ip4_config)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP4_CONFIG);
|
2013-09-06 11:56:41 +02:00
|
|
|
g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config);
|
|
|
|
|
|
2015-07-23 10:03:21 -05:00
|
|
|
if (old_config != priv->ip4_config)
|
|
|
|
|
nm_exported_object_clear_and_unexport (&old_config);
|
2014-05-27 16:42:19 -04:00
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if ( nm_device_sys_iface_state_is_external (self)
|
|
|
|
|
&& (settings_connection = nm_device_get_settings_connection (self))
|
|
|
|
|
&& nm_settings_connection_get_nm_generated (settings_connection)
|
|
|
|
|
&& nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) {
|
2014-05-27 16:42:19 -04:00
|
|
|
NMSetting *s_ip4;
|
|
|
|
|
|
2015-10-11 20:31:47 +02:00
|
|
|
g_object_freeze_notify (G_OBJECT (settings_connection));
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP4_CONFIG);
|
2015-10-11 20:31:47 +02:00
|
|
|
s_ip4 = nm_ip4_config_create_setting (priv->ip4_config);
|
2017-03-13 15:34:14 +01:00
|
|
|
nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip4);
|
2015-10-11 20:31:47 +02:00
|
|
|
|
|
|
|
|
g_object_thaw_notify (G_OBJECT (settings_connection));
|
2014-05-27 16:42:19 -04:00
|
|
|
}
|
2014-05-28 10:18:34 -04:00
|
|
|
|
|
|
|
|
nm_device_queue_recheck_assume (self);
|
2013-09-06 11:56:41 +02:00
|
|
|
}
|
2012-05-29 09:56:50 -05:00
|
|
|
|
2007-12-06 14:51:43 +00:00
|
|
|
return success;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-19 23:07:13 +02:00
|
|
|
static gboolean
|
|
|
|
|
_replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new)
|
|
|
|
|
{
|
|
|
|
|
GSList *old_link;
|
|
|
|
|
|
2016-03-07 18:14:30 +01:00
|
|
|
/* Below, assert that @new is not yet tracked, but still behave
|
|
|
|
|
* correctly in any case. Don't complain for missing @old since
|
|
|
|
|
* it could have been removed when the parent device became
|
|
|
|
|
* unmanaged. */
|
2015-08-19 23:07:13 +02:00
|
|
|
|
|
|
|
|
if ( old
|
|
|
|
|
&& (old_link = g_slist_find (*plist, old))) {
|
|
|
|
|
if (old != new) {
|
|
|
|
|
if (new)
|
|
|
|
|
old_link->data = g_object_ref (new);
|
|
|
|
|
else
|
2016-03-08 10:26:27 +01:00
|
|
|
*plist = g_slist_delete_link (*plist, old_link);
|
2015-08-19 23:07:13 +02:00
|
|
|
g_object_unref (old);
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (new) {
|
|
|
|
|
if (!g_slist_find (*plist, new))
|
|
|
|
|
*plist = g_slist_append (*plist, g_object_ref (new));
|
|
|
|
|
else
|
|
|
|
|
g_return_val_if_reached (TRUE);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-01 10:59:42 -05:00
|
|
|
void
|
2015-08-19 23:07:13 +02:00
|
|
|
nm_device_replace_vpn4_config (NMDevice *self, NMIP4Config *old, NMIP4Config *config)
|
2013-08-01 10:59:42 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-08-01 10:59:42 -05:00
|
|
|
|
2017-09-07 10:22:10 +02:00
|
|
|
nm_assert (!old || NM_IS_IP4_CONFIG (old));
|
|
|
|
|
nm_assert (!config || NM_IS_IP4_CONFIG (config));
|
|
|
|
|
nm_assert (!old || nm_ip4_config_get_ifindex (old) == nm_device_get_ip_ifindex (self));
|
|
|
|
|
nm_assert (!config || nm_ip4_config_get_ifindex (config) == nm_device_get_ip_ifindex (self));
|
|
|
|
|
|
2015-08-19 23:07:13 +02:00
|
|
|
if (!_replace_vpn_config_in_list (&priv->vpn4_configs, (GObject *) old, (GObject *) config))
|
2013-08-01 10:59:42 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* NULL to use existing configs */
|
2017-09-28 14:22:07 +02:00
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE))
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_IP4, "failed to set VPN routes for device");
|
2013-08-01 10:59:42 -05:00
|
|
|
}
|
|
|
|
|
|
2014-07-15 17:16:56 -05:00
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config)
|
2014-07-15 17:16:56 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-07-15 17:16:56 -05:00
|
|
|
|
|
|
|
|
if (priv->wwan_ip4_config == config)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_clear_object (&priv->wwan_ip4_config);
|
|
|
|
|
if (config)
|
|
|
|
|
priv->wwan_ip4_config = g_object_ref (config);
|
|
|
|
|
|
|
|
|
|
/* NULL to use existing configs */
|
2017-09-28 14:22:07 +02:00
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE))
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_IP4, "failed to set WWAN IPv4 configuration");
|
2014-07-15 17:16:56 -05:00
|
|
|
}
|
|
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
static gboolean
|
|
|
|
|
nm_device_set_ip6_config (NMDevice *self,
|
|
|
|
|
NMIP6Config *new_config,
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
gboolean commit)
|
2009-07-29 12:12:41 -04:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
NMIP6Config *old_config = NULL;
|
2013-09-06 11:56:41 +02:00
|
|
|
gboolean has_changes = FALSE;
|
2009-07-29 12:12:41 -04:00
|
|
|
gboolean success = TRUE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
_LOGD (LOGD_IP6, "ip6-config: update (commit=%d, new-config=%p)",
|
|
|
|
|
commit, new_config);
|
2016-04-15 20:07:02 +02:00
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
nm_assert ( !new_config
|
|
|
|
|
|| ( new_config
|
2017-10-30 16:27:19 +01:00
|
|
|
&& ({
|
|
|
|
|
int ip_ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
|
|
|
|
|
( ip_ifindex > 0
|
|
|
|
|
&& ip_ifindex == nm_ip6_config_get_ifindex (new_config));
|
|
|
|
|
})));
|
2009-07-29 12:12:41 -04:00
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-02-27 16:49:42 +01:00
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
old_config = priv->ip6_config;
|
|
|
|
|
|
2013-07-02 22:22:57 +02:00
|
|
|
/* Always commit to nm-platform to update lifetimes */
|
2013-09-06 11:56:41 +02:00
|
|
|
if (commit && new_config) {
|
2017-09-13 16:45:22 +02:00
|
|
|
gs_unref_ptrarray GPtrArray *temporary_not_available = NULL;
|
|
|
|
|
|
2017-01-15 13:38:33 +01:00
|
|
|
_commit_mtu (self, priv->ip4_config);
|
2017-09-13 16:45:22 +02:00
|
|
|
|
2015-07-13 19:20:08 +02:00
|
|
|
success = nm_ip6_config_commit (new_config,
|
2017-09-13 16:45:22 +02:00
|
|
|
nm_device_get_platform (self),
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET6, FALSE)
|
|
|
|
|
? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL
|
|
|
|
|
: NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
|
2017-09-13 16:45:22 +02:00
|
|
|
&temporary_not_available);
|
|
|
|
|
|
|
|
|
|
if (!_rt6_temporary_not_available_set (self, temporary_not_available))
|
|
|
|
|
success = FALSE;
|
2013-09-06 11:56:41 +02:00
|
|
|
}
|
2009-07-29 12:12:41 -04:00
|
|
|
|
|
|
|
|
if (new_config) {
|
2013-09-06 11:56:41 +02:00
|
|
|
if (old_config) {
|
|
|
|
|
/* has_changes is set only on relevant changes, because when the configuration changes,
|
|
|
|
|
* this causes a re-read and reset. This should only happen for relevant changes */
|
|
|
|
|
nm_ip6_config_replace (old_config, new_config, &has_changes);
|
|
|
|
|
if (has_changes) {
|
2016-04-15 20:07:02 +02:00
|
|
|
_LOGD (LOGD_IP6, "ip6-config: update IP6Config instance (%s)",
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config)));
|
2013-09-06 11:56:41 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
has_changes = TRUE;
|
|
|
|
|
priv->ip6_config = g_object_ref (new_config);
|
2009-07-29 12:12:41 -04:00
|
|
|
|
2015-04-03 10:08:52 -04:00
|
|
|
if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config)))
|
|
|
|
|
nm_exported_object_export (NM_EXPORTED_OBJECT (new_config));
|
2014-03-17 20:36:48 +01:00
|
|
|
|
2016-04-15 20:07:02 +02:00
|
|
|
_LOGD (LOGD_IP6, "ip6-config: set IP6Config instance (%s)",
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config)));
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
2013-09-06 11:56:41 +02:00
|
|
|
} else if (old_config) {
|
|
|
|
|
has_changes = TRUE;
|
|
|
|
|
priv->ip6_config = NULL;
|
2017-04-27 15:37:14 +02:00
|
|
|
priv->needs_ip6_subnet = FALSE;
|
2016-04-15 20:07:02 +02:00
|
|
|
_LOGD (LOGD_IP6, "ip6-config: clear IP6Config instance (%s)",
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config)));
|
2009-07-29 12:12:41 -04:00
|
|
|
}
|
|
|
|
|
|
2013-09-06 11:56:41 +02:00
|
|
|
if (has_changes) {
|
2017-03-13 15:34:14 +01:00
|
|
|
NMSettingsConnection *settings_connection;
|
|
|
|
|
|
2013-09-06 11:56:41 +02:00
|
|
|
if (old_config != priv->ip6_config)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP6_CONFIG);
|
2013-09-06 11:56:41 +02:00
|
|
|
g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config);
|
|
|
|
|
|
2015-07-23 10:03:21 -05:00
|
|
|
if (old_config != priv->ip6_config)
|
|
|
|
|
nm_exported_object_clear_and_unexport (&old_config);
|
2014-05-27 16:42:19 -04:00
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if ( nm_device_sys_iface_state_is_external (self)
|
|
|
|
|
&& (settings_connection = nm_device_get_settings_connection (self))
|
|
|
|
|
&& nm_settings_connection_get_nm_generated (settings_connection)
|
|
|
|
|
&& nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) {
|
2014-05-27 16:42:19 -04:00
|
|
|
NMSetting *s_ip6;
|
|
|
|
|
|
2015-10-11 20:31:47 +02:00
|
|
|
g_object_freeze_notify (G_OBJECT (settings_connection));
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP6_CONFIG);
|
2015-10-11 20:31:47 +02:00
|
|
|
s_ip6 = nm_ip6_config_create_setting (priv->ip6_config);
|
2017-03-13 15:34:14 +01:00
|
|
|
nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip6);
|
2015-10-11 20:31:47 +02:00
|
|
|
|
|
|
|
|
g_object_thaw_notify (G_OBJECT (settings_connection));
|
2014-05-27 16:42:19 -04:00
|
|
|
}
|
2014-05-28 10:18:34 -04:00
|
|
|
|
|
|
|
|
nm_device_queue_recheck_assume (self);
|
2016-11-03 12:15:32 +01:00
|
|
|
|
|
|
|
|
if (priv->ndisc)
|
|
|
|
|
ndisc_set_router_config (priv->ndisc, self);
|
2013-09-06 11:56:41 +02:00
|
|
|
}
|
2012-05-29 09:56:50 -05:00
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-01 10:59:42 -05:00
|
|
|
void
|
2015-08-19 23:07:13 +02:00
|
|
|
nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *config)
|
2013-08-01 10:59:42 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-08-01 10:59:42 -05:00
|
|
|
|
2017-09-07 10:22:10 +02:00
|
|
|
nm_assert (!old || NM_IS_IP6_CONFIG (old));
|
|
|
|
|
nm_assert (!config || NM_IS_IP6_CONFIG (config));
|
|
|
|
|
nm_assert (!old || nm_ip6_config_get_ifindex (old) == nm_device_get_ip_ifindex (self));
|
|
|
|
|
nm_assert (!config || nm_ip6_config_get_ifindex (config) == nm_device_get_ip_ifindex (self));
|
|
|
|
|
|
2015-08-19 23:07:13 +02:00
|
|
|
if (!_replace_vpn_config_in_list (&priv->vpn6_configs, (GObject *) old, (GObject *) config))
|
2013-08-01 10:59:42 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* NULL to use existing configs */
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_IP6, "failed to set VPN routes for device");
|
2013-08-01 10:59:42 -05:00
|
|
|
}
|
|
|
|
|
|
2013-10-15 21:03:42 -05:00
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_set_wwan_ip6_config (NMDevice *self, NMIP6Config *config)
|
2013-10-15 21:03:42 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-10-15 21:03:42 -05:00
|
|
|
|
|
|
|
|
if (priv->wwan_ip6_config == config)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_clear_object (&priv->wwan_ip6_config);
|
|
|
|
|
if (config)
|
|
|
|
|
priv->wwan_ip6_config = g_object_ref (config);
|
|
|
|
|
|
|
|
|
|
/* NULL to use existing configs */
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_IP6, "failed to set WWAN IPv6 configuration");
|
2013-10-15 21:03:42 -05:00
|
|
|
}
|
|
|
|
|
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMDhcp6Config *
|
2010-01-14 00:45:10 -08:00
|
|
|
nm_device_get_dhcp6_config (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
|
|
|
|
|
2016-04-07 14:45:57 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->dhcp6.config;
|
2010-01-14 00:45:10 -08:00
|
|
|
}
|
|
|
|
|
|
2009-07-29 12:12:41 -04:00
|
|
|
NMIP6Config *
|
|
|
|
|
nm_device_get_ip6_config (NMDevice *self)
|
|
|
|
|
{
|
2010-01-14 00:45:10 -08:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
2009-07-29 12:12:41 -04:00
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->ip6_config;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2014-06-12 14:04:42 +02:00
|
|
|
static void
|
|
|
|
|
dispatcher_cleanup (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2014-06-12 14:20:14 +02:00
|
|
|
if (priv->dispatcher.call_id) {
|
|
|
|
|
nm_dispatcher_call_cancel (priv->dispatcher.call_id);
|
|
|
|
|
priv->dispatcher.call_id = 0;
|
|
|
|
|
priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN;
|
|
|
|
|
priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE;
|
2014-06-12 14:04:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-21 12:49:23 -05:00
|
|
|
static void
|
2014-06-12 14:20:14 +02:00
|
|
|
dispatcher_complete_proceed_state (guint call_id, gpointer user_data)
|
2014-05-21 12:49:23 -05:00
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2014-06-12 14:20:14 +02:00
|
|
|
g_return_if_fail (call_id == priv->dispatcher.call_id);
|
2014-05-21 12:49:23 -05:00
|
|
|
|
2014-06-12 14:20:14 +02:00
|
|
|
priv->dispatcher.call_id = 0;
|
|
|
|
|
nm_device_queue_state (self, priv->dispatcher.post_state,
|
|
|
|
|
priv->dispatcher.post_state_reason);
|
|
|
|
|
priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN;
|
|
|
|
|
priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE;
|
2014-05-21 12:49:23 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-06-12 14:20:14 +02:00
|
|
|
|
2014-05-21 12:49:23 -05:00
|
|
|
static void
|
|
|
|
|
ip_check_pre_up (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2014-06-12 14:20:14 +02:00
|
|
|
if (priv->dispatcher.call_id != 0) {
|
|
|
|
|
g_warn_if_reached ();
|
|
|
|
|
dispatcher_cleanup (self);
|
|
|
|
|
}
|
2014-05-21 12:49:23 -05:00
|
|
|
|
2014-06-12 14:20:14 +02:00
|
|
|
priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES;
|
|
|
|
|
priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE;
|
2017-03-08 14:11:22 +01:00
|
|
|
if (!nm_dispatcher_call_device (NM_DISPATCHER_ACTION_PRE_UP,
|
|
|
|
|
self,
|
|
|
|
|
NULL,
|
|
|
|
|
dispatcher_complete_proceed_state,
|
|
|
|
|
self,
|
|
|
|
|
&priv->dispatcher.call_id)) {
|
2014-05-21 12:49:23 -05:00
|
|
|
/* Just proceed on errors */
|
2014-06-12 14:20:14 +02:00
|
|
|
dispatcher_complete_proceed_state (0, self);
|
2014-05-21 12:49:23 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-11 17:05:49 -05:00
|
|
|
static void
|
|
|
|
|
ip_check_gw_ping_cleanup (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-07-01 13:42:41 +02:00
|
|
|
nm_clear_g_source (&priv->gw_ping.watch);
|
|
|
|
|
nm_clear_g_source (&priv->gw_ping.timeout);
|
2013-06-11 17:05:49 -05:00
|
|
|
|
|
|
|
|
if (priv->gw_ping.pid) {
|
2014-02-14 11:58:06 +01:00
|
|
|
nm_utils_kill_child_async (priv->gw_ping.pid, SIGTERM, priv->gw_ping.log_domain, "ping", 1000, NULL, NULL);
|
2013-06-11 17:05:49 -05:00
|
|
|
priv->gw_ping.pid = 0;
|
|
|
|
|
}
|
2015-07-01 13:42:41 +02:00
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->gw_ping.binary, g_free);
|
|
|
|
|
g_clear_pointer (&priv->gw_ping.address, g_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
spawn_ping (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-07-01 16:35:52 +02:00
|
|
|
gs_free char *str_timeout = NULL;
|
|
|
|
|
gs_free char *tmp_str = NULL;
|
2015-07-01 13:42:41 +02:00
|
|
|
const char *args[] = { priv->gw_ping.binary, "-I", nm_device_get_ip_iface (self),
|
|
|
|
|
"-c", "1", "-w", NULL, priv->gw_ping.address, NULL };
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
|
|
|
|
|
args[6] = str_timeout = g_strdup_printf ("%u", priv->gw_ping.deadline);
|
|
|
|
|
tmp_str = g_strjoinv (" ", (gchar **) args);
|
|
|
|
|
_LOGD (priv->gw_ping.log_domain, "ping: running '%s'", tmp_str);
|
|
|
|
|
|
|
|
|
|
ret = g_spawn_async ("/",
|
|
|
|
|
(gchar **) args,
|
|
|
|
|
NULL,
|
|
|
|
|
G_SPAWN_DO_NOT_REAP_CHILD,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
&priv->gw_ping.pid,
|
|
|
|
|
&error);
|
|
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
|
_LOGW (priv->gw_ping.log_domain, "ping: could not spawn %s: %s",
|
|
|
|
|
priv->gw_ping.binary, error->message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
respawn_ping_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->gw_ping.watch = 0;
|
|
|
|
|
|
|
|
|
|
if (spawn_ping (self)) {
|
|
|
|
|
priv->gw_ping.watch = g_child_watch_add (priv->gw_ping.pid,
|
|
|
|
|
ip_check_ping_watch_cb, self);
|
|
|
|
|
} else {
|
|
|
|
|
ip_check_gw_ping_cleanup (self);
|
|
|
|
|
ip_check_pre_up (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-05-12 16:44:24 +02:00
|
|
|
NMLogDomain log_domain = priv->gw_ping.log_domain;
|
2015-07-01 13:42:41 +02:00
|
|
|
gboolean success = FALSE;
|
2013-06-11 17:05:49 -05:00
|
|
|
|
|
|
|
|
if (!priv->gw_ping.watch)
|
|
|
|
|
return;
|
|
|
|
|
priv->gw_ping.watch = 0;
|
|
|
|
|
priv->gw_ping.pid = 0;
|
|
|
|
|
|
|
|
|
|
if (WIFEXITED (status)) {
|
2015-07-01 13:42:41 +02:00
|
|
|
if (WEXITSTATUS (status) == 0) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (log_domain, "ping: gateway ping succeeded");
|
2015-07-01 13:42:41 +02:00
|
|
|
success = TRUE;
|
|
|
|
|
} else {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (log_domain, "ping: gateway ping failed with error code %d",
|
|
|
|
|
WEXITSTATUS (status));
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
} else
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (log_domain, "ping: stopped unexpectedly with status %d", status);
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2015-07-01 13:42:41 +02:00
|
|
|
if (success) {
|
|
|
|
|
/* We've got connectivity, proceed to pre_up */
|
|
|
|
|
ip_check_gw_ping_cleanup (self);
|
|
|
|
|
ip_check_pre_up (self);
|
|
|
|
|
} else {
|
|
|
|
|
/* If ping exited with an error it may have returned early,
|
|
|
|
|
* wait 1 second and restart it */
|
|
|
|
|
priv->gw_ping.watch = g_timeout_add_seconds (1, respawn_ping_cb, self);
|
|
|
|
|
}
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
ip_check_ping_timeout_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->gw_ping.timeout = 0;
|
|
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (priv->gw_ping.log_domain, "ping: gateway ping timed out");
|
2013-06-11 17:05:49 -05:00
|
|
|
|
|
|
|
|
ip_check_gw_ping_cleanup (self);
|
2014-05-21 12:49:23 -05:00
|
|
|
ip_check_pre_up (self);
|
2013-06-11 17:05:49 -05:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2015-07-01 13:42:41 +02:00
|
|
|
start_ping (NMDevice *self,
|
2015-05-12 16:44:24 +02:00
|
|
|
NMLogDomain log_domain,
|
2013-06-11 17:05:49 -05:00
|
|
|
const char *binary,
|
|
|
|
|
const char *address,
|
|
|
|
|
guint timeout)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (priv->gw_ping.watch == 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (priv->gw_ping.timeout == 0, FALSE);
|
|
|
|
|
|
2015-07-01 13:42:41 +02:00
|
|
|
priv->gw_ping.log_domain = log_domain;
|
|
|
|
|
priv->gw_ping.address = g_strdup (address);
|
|
|
|
|
priv->gw_ping.binary = g_strdup (binary);
|
|
|
|
|
priv->gw_ping.deadline = timeout + 10; /* the proper termination is enforced by a timer */
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2015-07-01 13:42:41 +02:00
|
|
|
if (spawn_ping (self)) {
|
2013-06-11 17:05:49 -05:00
|
|
|
priv->gw_ping.watch = g_child_watch_add (priv->gw_ping.pid, ip_check_ping_watch_cb, self);
|
2015-07-01 13:42:41 +02:00
|
|
|
priv->gw_ping.timeout = g_timeout_add_seconds (timeout, ip_check_ping_timeout_cb, self);
|
|
|
|
|
return TRUE;
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-01 13:42:41 +02:00
|
|
|
ip_check_gw_ping_cleanup (self);
|
|
|
|
|
return FALSE;
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_device_start_ip_check (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
guint timeout = 0;
|
|
|
|
|
const char *ping_binary = NULL;
|
2017-10-04 15:21:21 +02:00
|
|
|
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
2015-05-12 16:44:24 +02:00
|
|
|
NMLogDomain log_domain = LOGD_IP4;
|
2013-06-11 17:05:49 -05:00
|
|
|
|
|
|
|
|
/* Shouldn't be any active ping here, since IP_CHECK happens after the
|
|
|
|
|
* first IP method completes. Any subsequently completing IP method doesn't
|
|
|
|
|
* get checked.
|
|
|
|
|
*/
|
2016-11-09 13:06:11 +01:00
|
|
|
g_return_if_fail (!priv->gw_ping.watch);
|
|
|
|
|
g_return_if_fail (!priv->gw_ping.timeout);
|
|
|
|
|
g_return_if_fail (!priv->gw_ping.pid);
|
|
|
|
|
g_return_if_fail (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE);
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2013-06-11 17:05:49 -05:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
timeout = nm_setting_connection_get_gateway_ping_timeout (s_con);
|
|
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
buf[0] = '\0';
|
2013-06-11 17:05:49 -05:00
|
|
|
if (timeout) {
|
2017-10-04 15:21:21 +02:00
|
|
|
const NMPObject *gw;
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->ip4_config && priv->ip4_state == IP_DONE) {
|
|
|
|
|
gw = nm_ip4_config_best_default_route_get (priv->ip4_config);
|
|
|
|
|
if (gw) {
|
|
|
|
|
nm_utils_inet4_ntop (NMP_OBJECT_CAST_IP4_ROUTE (gw)->gateway, buf);
|
|
|
|
|
ping_binary = nm_utils_find_helper ("ping", "/usr/bin/ping", NULL);
|
|
|
|
|
log_domain = LOGD_IP4;
|
|
|
|
|
}
|
2013-06-11 17:05:49 -05:00
|
|
|
} else if (priv->ip6_config && priv->ip6_state == IP_DONE) {
|
2017-10-04 15:21:21 +02:00
|
|
|
gw = nm_ip6_config_best_default_route_get (priv->ip6_config);
|
|
|
|
|
if (gw) {
|
|
|
|
|
nm_utils_inet6_ntop (&NMP_OBJECT_CAST_IP6_ROUTE (gw)->gateway, buf);
|
|
|
|
|
ping_binary = nm_utils_find_helper ("ping6", "/usr/bin/ping6", NULL);
|
|
|
|
|
log_domain = LOGD_IP6;
|
|
|
|
|
}
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (buf[0])
|
2015-07-01 13:42:41 +02:00
|
|
|
start_ping (self, log_domain, ping_binary, buf, timeout);
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2014-05-21 12:49:23 -05:00
|
|
|
/* If no ping was started, just advance to pre_up */
|
2013-06-11 17:05:49 -05:00
|
|
|
if (!priv->gw_ping.pid)
|
2014-05-21 12:49:23 -05:00
|
|
|
ip_check_pre_up (self);
|
2013-06-11 17:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2013-12-09 16:32:36 -06:00
|
|
|
static gboolean
|
|
|
|
|
carrier_wait_timeout (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2013-12-09 16:32:36 -06:00
|
|
|
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
priv->carrier_wait_id = 0;
|
|
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
|
|
|
|
|
if (!priv->carrier)
|
|
|
|
|
_carrier_wait_check_queued_act_request (self);
|
2013-12-09 16:32:36 -06:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 16:09:22 -05:00
|
|
|
static gboolean
|
|
|
|
|
nm_device_is_up (NMDevice *self)
|
|
|
|
|
{
|
2016-09-12 12:01:56 +02:00
|
|
|
int ifindex;
|
2014-05-20 16:09:22 -05:00
|
|
|
|
2016-09-12 12:01:56 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2014-05-20 16:09:22 -05:00
|
|
|
|
2016-09-12 12:01:56 +02:00
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
2017-04-17 20:17:45 +02:00
|
|
|
return ifindex > 0 ? nm_platform_link_is_up (nm_device_get_platform (self), ifindex) : TRUE;
|
2014-05-20 16:09:22 -05:00
|
|
|
}
|
|
|
|
|
|
2008-05-14 01:55:49 +00:00
|
|
|
gboolean
|
2013-06-13 15:13:58 -05:00
|
|
|
nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2013-12-09 16:32:36 -06:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-02-11 14:00:20 +01:00
|
|
|
gboolean device_is_up = FALSE;
|
2016-05-09 18:32:29 +02:00
|
|
|
NMDeviceCapabilities capabilities;
|
2016-09-12 12:01:56 +02:00
|
|
|
int ifindex;
|
2007-03-12 04:49:29 +00:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-09-12 12:32:27 +02:00
|
|
|
NM_SET_OUT (no_firmware, FALSE);
|
|
|
|
|
|
2016-09-12 12:01:56 +02:00
|
|
|
if (!nm_device_get_enabled (self)) {
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGD (LOGD_PLATFORM, "bringing up device ignored due to disabled");
|
2016-09-12 12:32:27 +02:00
|
|
|
return FALSE;
|
2016-09-12 12:01:56 +02:00
|
|
|
}
|
2016-09-12 12:32:27 +02:00
|
|
|
|
2016-09-12 12:01:56 +02:00
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGD (LOGD_PLATFORM, "bringing up device %d", ifindex);
|
2016-09-12 12:01:56 +02:00
|
|
|
if (ifindex <= 0) {
|
|
|
|
|
/* assume success. */
|
|
|
|
|
} else {
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_set_up (nm_device_get_platform (self), ifindex, no_firmware))
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-09 18:30:06 +02:00
|
|
|
/* Store carrier immediately. */
|
2017-05-15 11:35:41 +02:00
|
|
|
nm_device_set_carrier_from_platform (self);
|
2016-05-09 18:30:06 +02:00
|
|
|
|
2014-02-11 14:00:20 +01:00
|
|
|
device_is_up = nm_device_is_up (self);
|
|
|
|
|
if (block && !device_is_up) {
|
|
|
|
|
gint64 wait_until = nm_utils_get_monotonic_timestamp_us () + 10000 /* microseconds */;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
g_usleep (200);
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_refresh (nm_device_get_platform (self), ifindex))
|
2014-02-11 14:00:20 +01:00
|
|
|
return FALSE;
|
|
|
|
|
device_is_up = nm_device_is_up (self);
|
|
|
|
|
} while (!device_is_up && nm_utils_get_monotonic_timestamp_us () < wait_until);
|
|
|
|
|
}
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
|
2014-02-11 14:00:20 +01:00
|
|
|
if (!device_is_up) {
|
|
|
|
|
if (block)
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGW (LOGD_PLATFORM, "device not up after timeout!");
|
2014-02-11 14:00:20 +01:00
|
|
|
else
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGD (LOGD_PLATFORM, "device not up immediately");
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-09 18:32:29 +02:00
|
|
|
/* some ethernet devices fail to report capabilities unless the device
|
|
|
|
|
* is up. Re-read the capabilities. */
|
|
|
|
|
capabilities = 0;
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
|
|
|
|
|
capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
|
|
|
|
|
_add_capabilities (self, capabilities);
|
|
|
|
|
|
2013-12-09 16:32:36 -06:00
|
|
|
/* Devices that support carrier detect must be IFF_UP to report carrier
|
|
|
|
|
* changes; so after setting the device IFF_UP we must suppress startup
|
|
|
|
|
* complete (via a pending action) until either the carrier turns on, or
|
|
|
|
|
* a timeout is reached.
|
|
|
|
|
*/
|
2015-04-17 15:19:48 +02:00
|
|
|
if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
|
2017-09-02 17:26:53 +02:00
|
|
|
gint64 now_ms, until_ms;
|
|
|
|
|
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
/* we start a grace period of 5 seconds during which we will schedule
|
|
|
|
|
* a pending action whenever we have no carrier.
|
|
|
|
|
*
|
|
|
|
|
* If during that time carrier goes away, we declare the interface
|
|
|
|
|
* as not ready. */
|
|
|
|
|
nm_clear_g_source (&priv->carrier_wait_id);
|
|
|
|
|
if (!priv->carrier)
|
|
|
|
|
nm_device_add_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
|
2017-09-02 17:26:53 +02:00
|
|
|
|
|
|
|
|
now_ms = nm_utils_get_monotonic_timestamp_ms ();
|
|
|
|
|
until_ms = NM_MAX (now_ms + CARRIER_WAIT_TIME_MS, priv->carrier_wait_until_ms);
|
|
|
|
|
priv->carrier_wait_id = g_timeout_add (until_ms - now_ms, carrier_wait_timeout, self);
|
2013-12-09 16:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
/* Can only get HW address of some devices when they are up */
|
2013-05-01 09:28:16 -04:00
|
|
|
nm_device_update_hw_address (self);
|
2007-03-02 Tambet Ingo <tambet@ximian.com>
* libnm-glib/nm-device-802-11-wireless.c: Cache networks (bssids) list.
We get signalled when it changes.
* libnm-glib/nm-client.c: Cache NMState and device list, we get signalled
when it changes.
* libnm-glib/nm-device.c: Cache the device state property.
* libnm-glib/nm-access-point.c: Cache the strength property.
* src/nm-device-802-11-wireless.c: Fix wireless device scanning scheduler.
The new algorithm is to start from SCAN_INTERVAL_MIN (currently defined as 0)
and add a SCAN_INTERVAL_STEP (currently 20 seconds) with each successful scan
until SCAN_INTERVAL_MAX (currently 120 seconds) is reached. Do not scan while
the device is down, activating, or activated (in case of A/B/G cards).
Remove some old dead ifdef'ed out code that used to configure wireless devices,
it's all done through supplicant now.
* src/supplicant-manager/nm-supplicant-interface.c: Fix the reference
counting issues with pending calls which caused leaks and crashes when
interface was removed (now that the interface actually gets removed).
* src/nm-call-store.c: Make a copy of data before running a foreach
with user callback on it - The most common usage pattern is to cancel
(and thus remove) all pending calls with foreach which would modify
the hash table we're iterating over.
* src/nm-manager.c: When a device is added, make sure it is "up". When
it's removed or disabled due to disabling wireless or networking, bring
it down.
* include/NetworkManager.h: Add new device state NM_DEVICE_STATE_DOWN.
* src/nm-device-802-11-wireless.c:
* src/nm-device-802-3-ethernet.c:
* src/nm-device.c:
- Remove "init" virtual function, all gobjects have a place for that
already (constructor).
- Replace "start" virtual function with "bring_up", devices can be
brought up and down more than just on startup now.
- Add "is_up" virtual function.
- Implement one way to bring a device down instead of previous 4 different
ways, each of witch did something different.
* src/NetworkManagerUtils.c (nm_dev_sock_open): This doesn't need an NMDevice,
all it needs is the device interface.
Get rid of NMData.dev_list (3 members to go).
Get rif of NMData in a lot of places.
* gnome/libnm_glib/libnm_glib.c: Make it compile again.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2395 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-03-02 09:30:48 +00:00
|
|
|
|
2011-11-17 22:39:34 -06:00
|
|
|
_update_ip4_address (self);
|
2016-05-29 17:54:36 +02:00
|
|
|
|
|
|
|
|
/* when the link comes up, we must restore IP configuration if necessary. */
|
|
|
|
|
if (priv->ip4_state == IP_DONE) {
|
2017-09-28 14:22:07 +02:00
|
|
|
if (!ip4_config_merge_and_apply (self, TRUE))
|
2016-05-29 17:54:36 +02:00
|
|
|
_LOGW (LOGD_IP4, "failed applying IP4 config after bringing link up");
|
|
|
|
|
}
|
|
|
|
|
if (priv->ip6_state == IP_DONE) {
|
2017-02-22 20:20:22 +01:00
|
|
|
if (!ip6_config_merge_and_apply (self, TRUE))
|
2016-05-29 17:54:36 +02:00
|
|
|
_LOGW (LOGD_IP6, "failed applying IP6 config after bringing link up");
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-14 01:55:49 +00:00
|
|
|
void
|
2013-06-13 15:13:58 -05:00
|
|
|
nm_device_take_down (NMDevice *self, gboolean block)
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
{
|
2016-09-12 12:01:56 +02:00
|
|
|
int ifindex;
|
2014-02-11 14:00:20 +01:00
|
|
|
gboolean device_is_up;
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
2016-09-12 12:01:56 +02:00
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGD (LOGD_PLATFORM, "taking down device %d", ifindex);
|
2016-09-12 12:01:56 +02:00
|
|
|
if (ifindex <= 0) {
|
|
|
|
|
/* devices without ifindex are always up. */
|
|
|
|
|
return;
|
2014-02-11 14:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_set_down (nm_device_get_platform (self), ifindex))
|
2016-09-12 12:01:56 +02:00
|
|
|
return;
|
|
|
|
|
|
2014-02-11 14:00:20 +01:00
|
|
|
device_is_up = nm_device_is_up (self);
|
|
|
|
|
if (block && device_is_up) {
|
|
|
|
|
gint64 wait_until = nm_utils_get_monotonic_timestamp_us () + 10000 /* microseconds */;
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
|
2014-02-11 14:00:20 +01:00
|
|
|
do {
|
|
|
|
|
g_usleep (200);
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_refresh (nm_device_get_platform (self), ifindex))
|
2014-02-11 14:00:20 +01:00
|
|
|
return;
|
|
|
|
|
device_is_up = nm_device_is_up (self);
|
|
|
|
|
} while (device_is_up && nm_utils_get_monotonic_timestamp_us () < wait_until);
|
|
|
|
|
}
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
|
2014-02-11 14:00:20 +01:00
|
|
|
if (device_is_up) {
|
|
|
|
|
if (block)
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGW (LOGD_PLATFORM, "device not down after timeout!");
|
2014-02-11 14:00:20 +01:00
|
|
|
else
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGD (LOGD_PLATFORM, "device not down immediately");
|
2014-02-11 14:00:20 +01:00
|
|
|
}
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
void
|
|
|
|
|
nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2014-05-20 15:03:27 -05:00
|
|
|
NMDevicePrivate *priv;
|
2008-04-17 23:04:34 +00:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2009-08-03 17:15:03 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
if (priv->firmware_missing != new_missing) {
|
|
|
|
|
priv->firmware_missing = new_missing;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_FIRMWARE_MISSING);
|
2009-08-03 17:15:03 -04:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2009-08-03 17:15:03 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_device_get_firmware_missing (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->firmware_missing;
|
|
|
|
|
}
|
2013-06-11 17:05:49 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static NMIP4Config *
|
2014-07-15 13:36:24 +02:00
|
|
|
find_ip4_lease_config (NMDevice *self,
|
2014-05-20 15:03:27 -05:00
|
|
|
NMConnection *connection,
|
|
|
|
|
NMIP4Config *ext_ip4_config)
|
|
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
const char *ip_iface = nm_device_get_ip_iface (self);
|
2015-02-20 16:31:10 -06:00
|
|
|
int ip_ifindex = nm_device_get_ip_ifindex (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
GSList *leases, *liter;
|
|
|
|
|
NMIP4Config *found = NULL;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
g_return_val_if_fail (NM_IS_IP4_CONFIG (ext_ip4_config), NULL);
|
|
|
|
|
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
2010-01-13 17:59:54 -08:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
leases = nm_dhcp_manager_get_lease_ip_configs (nm_dhcp_manager_get (),
|
core: pass NMDedupMultiIndex instance to NMIP4Config and other
NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
2017-06-12 08:16:47 +02:00
|
|
|
nm_device_get_multi_index (self),
|
2017-09-11 11:30:48 +02:00
|
|
|
AF_INET,
|
2014-05-20 15:03:27 -05:00
|
|
|
ip_iface,
|
2015-02-20 16:31:10 -06:00
|
|
|
ip_ifindex,
|
2014-05-20 15:03:27 -05:00
|
|
|
nm_connection_get_uuid (connection),
|
2017-09-28 14:40:12 +02:00
|
|
|
nm_device_get_route_table (self, AF_INET, TRUE),
|
2017-09-28 17:14:24 +02:00
|
|
|
nm_device_get_route_metric (self, AF_INET));
|
2014-05-20 15:03:27 -05:00
|
|
|
for (liter = leases; liter && !found; liter = liter->next) {
|
|
|
|
|
NMIP4Config *lease_config = liter->data;
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMPlatformIP4Address *address = nm_ip4_config_get_first_address (lease_config);
|
2017-10-04 15:21:21 +02:00
|
|
|
const NMPObject *gw1, *gw2;
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
g_assert (address);
|
|
|
|
|
if (!nm_ip4_config_address_exists (ext_ip4_config, address))
|
|
|
|
|
continue;
|
2017-10-04 15:21:21 +02:00
|
|
|
gw1 = nm_ip4_config_best_default_route_get (lease_config);
|
|
|
|
|
if (!gw1)
|
|
|
|
|
continue;
|
|
|
|
|
gw2 = nm_ip4_config_best_default_route_get (ext_ip4_config);
|
|
|
|
|
if (!gw2)
|
|
|
|
|
continue;
|
|
|
|
|
if (NMP_OBJECT_CAST_IP4_ROUTE (gw1)->gateway != NMP_OBJECT_CAST_IP4_ROUTE (gw2)->gateway)
|
2014-05-20 15:03:27 -05:00
|
|
|
continue;
|
|
|
|
|
found = g_object_ref (lease_config);
|
|
|
|
|
}
|
2008-07-11 10:28:53 +00:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
g_slist_free_full (leases, g_object_unref);
|
|
|
|
|
return found;
|
|
|
|
|
}
|
2013-06-12 10:48:03 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
capture_lease_config (NMDevice *self,
|
2014-05-20 15:03:27 -05:00
|
|
|
NMIP4Config *ext_ip4_config,
|
|
|
|
|
NMIP4Config **out_ip4_config,
|
|
|
|
|
NMIP6Config *ext_ip6_config,
|
|
|
|
|
NMIP6Config **out_ip6_config)
|
|
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-05-16 18:40:44 +02:00
|
|
|
NMSettingsConnection *const*connections;
|
2014-05-20 15:03:27 -05:00
|
|
|
guint i;
|
|
|
|
|
gboolean dhcp_used = FALSE;
|
2017-07-07 23:34:41 +02:00
|
|
|
NMDedupMultiIter ipconf_iter;
|
2013-10-24 13:55:06 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Ensure at least one address on the device has a non-infinite lifetime,
|
|
|
|
|
* otherwise DHCP cannot possibly be active on the device right now.
|
|
|
|
|
*/
|
|
|
|
|
if (ext_ip4_config && out_ip4_config) {
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMPlatformIP4Address *addr;
|
2013-10-24 13:55:06 -04:00
|
|
|
|
2017-07-07 23:34:41 +02:00
|
|
|
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ext_ip4_config, &addr) {
|
2014-05-20 15:03:27 -05:00
|
|
|
if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
|
|
|
|
|
dhcp_used = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (ext_ip6_config && out_ip6_config) {
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMPlatformIP6Address *addr;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-07-07 23:34:41 +02:00
|
|
|
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ext_ip6_config, &addr) {
|
2014-05-20 15:03:27 -05:00
|
|
|
if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
|
|
|
|
|
dhcp_used = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
g_return_if_fail ( (ext_ip6_config && out_ip6_config)
|
|
|
|
|
|| (ext_ip4_config && out_ip4_config));
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
if (!dhcp_used)
|
|
|
|
|
return;
|
2013-08-01 10:59:42 -05:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
connections = nm_settings_get_connections (priv->settings, NULL);
|
|
|
|
|
for (i = 0; connections[i]; i++) {
|
|
|
|
|
NMConnection *candidate = (NMConnection *) connections[i];
|
2014-05-20 15:03:27 -05:00
|
|
|
const char *method;
|
2012-02-21 15:44:19 +01:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
if (!nm_device_check_connection_compatible (self, candidate))
|
2014-05-20 15:03:27 -05:00
|
|
|
continue;
|
2014-05-28 10:18:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* IPv4 leases */
|
|
|
|
|
method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
if (out_ip4_config && strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) {
|
2014-07-15 13:36:24 +02:00
|
|
|
*out_ip4_config = find_ip4_lease_config (self, candidate, ext_ip4_config);
|
2014-05-20 15:03:27 -05:00
|
|
|
if (*out_ip4_config)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-05-07 10:23:44 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* IPv6 leases */
|
|
|
|
|
method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
if (out_ip6_config && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
|
|
|
|
/* FIXME: implement find_ip6_lease_config() */
|
|
|
|
|
}
|
2012-08-01 11:16:48 -06:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2017-09-22 10:56:38 +02:00
|
|
|
static gboolean
|
2017-09-22 12:11:32 +02:00
|
|
|
update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
int ifindex;
|
|
|
|
|
gboolean capture_resolv_conf;
|
2017-05-26 22:46:57 +02:00
|
|
|
GSList *iter;
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_assert_addr_family (addr_family);
|
2016-04-28 22:48:39 +02:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
if (!ifindex)
|
2017-09-22 10:56:38 +02:00
|
|
|
return FALSE;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-04-21 18:09:17 +02:00
|
|
|
capture_resolv_conf = initial
|
|
|
|
|
&& nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ());
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-09-22 10:56:38 +02:00
|
|
|
if (addr_family == AF_INET) {
|
|
|
|
|
|
|
|
|
|
g_clear_object (&priv->ext_ip4_config);
|
|
|
|
|
priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_multi_index (self),
|
|
|
|
|
nm_device_get_platform (self),
|
|
|
|
|
ifindex,
|
|
|
|
|
capture_resolv_conf);
|
|
|
|
|
if (priv->ext_ip4_config) {
|
|
|
|
|
if (initial) {
|
|
|
|
|
g_clear_object (&priv->dev_ip4_config);
|
|
|
|
|
capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-22 12:11:32 +02:00
|
|
|
if (intersect_configs) {
|
|
|
|
|
/* This function was called upon external changes. Remove the configuration
|
|
|
|
|
* (addresses,routes) that is no longer present externally from the internal
|
|
|
|
|
* config. This way, we don't re-add addresses that were manually removed
|
|
|
|
|
* by the user. */
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->con_ip4_config) {
|
|
|
|
|
nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
|
|
|
|
}
|
|
|
|
|
if (priv->dev_ip4_config) {
|
|
|
|
|
nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
|
|
|
|
}
|
|
|
|
|
if (priv->wwan_ip4_config) {
|
|
|
|
|
nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
|
|
|
|
}
|
2017-09-22 12:11:32 +02:00
|
|
|
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip4_config_intersect (iter->data, priv->ext_ip4_config, 0);
|
2017-09-22 12:11:32 +02:00
|
|
|
}
|
2017-09-22 10:56:38 +02:00
|
|
|
|
|
|
|
|
/* Remove parts from ext_ip4_config to only contain the information that
|
|
|
|
|
* was configured externally -- we already have the same configuration from
|
|
|
|
|
* internal origins. */
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->con_ip4_config) {
|
|
|
|
|
nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
|
|
|
|
}
|
|
|
|
|
if (priv->dev_ip4_config) {
|
|
|
|
|
nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
|
|
|
|
}
|
|
|
|
|
if (priv->wwan_ip4_config) {
|
|
|
|
|
nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET));
|
|
|
|
|
}
|
2017-09-22 10:56:38 +02:00
|
|
|
for (iter = priv->vpn4_configs; iter; iter = iter->next)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip4_config_subtract (priv->ext_ip4_config, iter->data, 0);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2014-11-21 13:13:48 +01:00
|
|
|
|
2017-09-22 10:56:38 +02:00
|
|
|
} else {
|
|
|
|
|
nm_assert (addr_family == AF_INET6);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-09-22 10:56:38 +02:00
|
|
|
g_clear_object (&priv->ext_ip6_config);
|
|
|
|
|
g_clear_object (&priv->ext_ip6_config_captured);
|
|
|
|
|
priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self),
|
|
|
|
|
nm_device_get_platform (self),
|
|
|
|
|
ifindex,
|
|
|
|
|
capture_resolv_conf,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
|
|
|
|
if (priv->ext_ip6_config_captured) {
|
|
|
|
|
|
|
|
|
|
priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured);
|
|
|
|
|
|
2017-09-22 12:11:32 +02:00
|
|
|
if (intersect_configs) {
|
|
|
|
|
/* This function was called upon external changes. Remove the configuration
|
|
|
|
|
* (addresses,routes) that is no longer present externally from the internal
|
|
|
|
|
* config. This way, we don't re-add addresses that were manually removed
|
|
|
|
|
* by the user. */
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->con_ip6_config) {
|
|
|
|
|
nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
|
|
|
|
if (priv->ac_ip6_config) {
|
|
|
|
|
nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
|
|
|
|
if (priv->dhcp6.ip6_config) {
|
|
|
|
|
nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
|
|
|
|
if (priv->wwan_ip6_config) {
|
|
|
|
|
nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
2017-09-22 12:11:32 +02:00
|
|
|
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip6_config_intersect (iter->data, priv->ext_ip6_config, 0);
|
2017-09-22 12:11:32 +02:00
|
|
|
}
|
2017-09-22 10:56:38 +02:00
|
|
|
|
|
|
|
|
/* Remove parts from ext_ip6_config to only contain the information that
|
|
|
|
|
* was configured externally -- we already have the same configuration from
|
|
|
|
|
* internal origins. */
|
2017-10-04 15:21:21 +02:00
|
|
|
if (priv->con_ip6_config) {
|
|
|
|
|
nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
|
|
|
|
if (priv->ac_ip6_config) {
|
|
|
|
|
nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
|
|
|
|
if (priv->dhcp6.ip6_config) {
|
|
|
|
|
nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
|
|
|
|
if (priv->wwan_ip6_config) {
|
|
|
|
|
nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config,
|
|
|
|
|
default_route_metric_penalty_get (self, AF_INET6));
|
|
|
|
|
}
|
2017-09-22 10:56:38 +02:00
|
|
|
for (iter = priv->vpn6_configs; iter; iter = iter->next)
|
2017-10-04 15:21:21 +02:00
|
|
|
nm_ip6_config_subtract (priv->ext_ip6_config, iter->data, 0);
|
2017-09-22 10:56:38 +02:00
|
|
|
}
|
2013-12-09 16:32:36 -06:00
|
|
|
}
|
2017-09-22 10:56:38 +02:00
|
|
|
|
|
|
|
|
return TRUE;
|
2015-06-24 08:59:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-09-22 10:56:38 +02:00
|
|
|
update_ip_config (NMDevice *self, int addr_family, gboolean initial)
|
2015-06-24 08:59:36 +00:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-10-02 13:55:27 +02:00
|
|
|
nm_assert_addr_family (addr_family);
|
2008-05-29 20:58:52 +00:00
|
|
|
|
2017-09-22 12:11:32 +02:00
|
|
|
if (update_ext_ip_config (self, addr_family, initial, TRUE)) {
|
2017-09-22 10:56:38 +02:00
|
|
|
if (addr_family == AF_INET) {
|
|
|
|
|
if (priv->ext_ip4_config)
|
2017-09-28 14:22:07 +02:00
|
|
|
ip4_config_merge_and_apply (self, FALSE);
|
2017-09-22 10:56:38 +02:00
|
|
|
} else {
|
|
|
|
|
if (priv->ext_ip6_config_captured)
|
|
|
|
|
ip6_config_merge_and_apply (self, FALSE);
|
|
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2013-04-04 10:20:24 -04:00
|
|
|
|
2017-09-22 10:56:38 +02:00
|
|
|
if ( addr_family == AF_INET6
|
|
|
|
|
&& priv->linklocal6_timeout_id
|
2016-01-30 21:37:22 +01:00
|
|
|
&& priv->ext_ip6_config_captured
|
2016-01-30 22:28:23 +01:00
|
|
|
&& nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) {
|
2014-05-20 15:03:27 -05:00
|
|
|
/* linklocal6 is ready now, do the state transition... we are also
|
|
|
|
|
* invoked as g_idle_add, so no problems with reentrance doing it now.
|
|
|
|
|
*/
|
|
|
|
|
linklocal6_complete (self);
|
|
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_capture_initial_config (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
2017-09-22 10:56:38 +02:00
|
|
|
update_ip_config (self, AF_INET, TRUE);
|
|
|
|
|
update_ip_config (self, AF_INET6, TRUE);
|
2015-06-24 08:59:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
queued_ip4_config_change (gpointer user_data)
|
|
|
|
|
{
|
2016-05-05 11:05:07 +02:00
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-06-24 08:59:36 +00:00
|
|
|
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
nm_assert (!priv->queued_ip4_config_pending);
|
|
|
|
|
|
2015-06-24 08:59:36 +00:00
|
|
|
/* Wait for any queued state changes */
|
|
|
|
|
if (priv->queued_state.id)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
priv->queued_ip4_config_id = 0;
|
2017-09-22 10:56:38 +02:00
|
|
|
|
|
|
|
|
/* If a commit is scheduled, this function would potentially interfere with
|
|
|
|
|
* it changing IP configurations before they are applied. Postpone the
|
|
|
|
|
* update in such case.
|
|
|
|
|
*/
|
|
|
|
|
if (activation_source_is_scheduled (self,
|
|
|
|
|
activate_stage5_ip4_config_result,
|
|
|
|
|
AF_INET)) {
|
|
|
|
|
priv->queued_ip4_config_pending = FALSE;
|
|
|
|
|
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
|
|
|
|
|
_LOGT (LOGD_DEVICE, "IP4 update was postponed");
|
|
|
|
|
} else
|
|
|
|
|
update_ip_config (self, AF_INET, FALSE);
|
2015-06-24 08:59:36 +00:00
|
|
|
|
2016-03-21 15:30:07 +01:00
|
|
|
set_unmanaged_external_down (self, TRUE);
|
|
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
|
|
|
|
|
priv->v4_has_shadowed_routes = _v4_has_shadowed_routes_detect (self);;
|
|
|
|
|
ip4_rp_filter_update (self);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-24 08:59:36 +00:00
|
|
|
return FALSE;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2015-06-24 08:59:36 +00:00
|
|
|
queued_ip6_config_change (gpointer user_data)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-05-05 11:05:07 +02:00
|
|
|
NMDevice *self = user_data;
|
|
|
|
|
NMDevicePrivate *priv;
|
2015-10-03 19:50:30 +02:00
|
|
|
GSList *iter;
|
|
|
|
|
gboolean need_ipv6ll = FALSE;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-05-05 11:05:07 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
nm_assert (!priv->queued_ip4_config_pending);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Wait for any queued state changes */
|
|
|
|
|
if (priv->queued_state.id)
|
|
|
|
|
return TRUE;
|
2011-10-07 15:58:08 +02:00
|
|
|
|
2015-06-24 08:59:36 +00:00
|
|
|
priv->queued_ip6_config_id = 0;
|
2017-09-22 10:56:38 +02:00
|
|
|
|
|
|
|
|
/* If a commit is scheduled, this function would potentially interfere with
|
|
|
|
|
* it changing IP configurations before they are applied. Postpone the
|
|
|
|
|
* update in such case.
|
|
|
|
|
*/
|
|
|
|
|
if (activation_source_is_scheduled (self,
|
|
|
|
|
activate_stage5_ip6_config_commit,
|
|
|
|
|
AF_INET6)) {
|
|
|
|
|
priv->queued_ip6_config_pending = FALSE;
|
|
|
|
|
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
|
|
|
|
|
_LOGT (LOGD_DEVICE, "IP6 update was postponed");
|
|
|
|
|
} else
|
|
|
|
|
update_ip_config (self, AF_INET6, FALSE);
|
2014-07-24 17:14:30 -05:00
|
|
|
|
2016-07-07 16:29:25 +02:00
|
|
|
if (priv->state < NM_DEVICE_STATE_DEACTIVATING
|
2017-04-17 20:17:45 +02:00
|
|
|
&& nm_platform_link_get (nm_device_get_platform (self), priv->ifindex)) {
|
2016-03-14 18:37:57 +01:00
|
|
|
/* Handle DAD failures */
|
2015-11-12 12:41:26 +01:00
|
|
|
for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
NMPlatformIP6Address *addr = iter->data;
|
2015-10-03 19:50:30 +02:00
|
|
|
|
2016-04-11 13:09:52 +02:00
|
|
|
if (addr->addr_source >= NM_IP_CONFIG_SOURCE_USER)
|
2015-11-12 12:41:26 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
_LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address",
|
|
|
|
|
nm_platform_ip6_address_to_string (addr, NULL, 0));
|
2015-10-03 19:50:30 +02:00
|
|
|
|
2015-11-12 12:41:26 +01:00
|
|
|
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
|
|
|
|
|
need_ipv6ll = TRUE;
|
2016-10-13 11:06:25 +00:00
|
|
|
else if (priv->ndisc)
|
|
|
|
|
nm_ndisc_dad_failed (priv->ndisc, &addr->address);
|
2015-11-12 12:41:26 +01:00
|
|
|
}
|
2015-10-03 19:50:30 +02:00
|
|
|
|
2015-11-12 12:41:26 +01:00
|
|
|
/* If no IPv6 link-local address exists but other addresses do then we
|
|
|
|
|
* must add the LL address to remain conformant with RFC 3513 chapter 2.1
|
|
|
|
|
* ("Addressing Model"): "All interfaces are required to have at least
|
|
|
|
|
* one link-local unicast address".
|
|
|
|
|
*/
|
|
|
|
|
if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config))
|
2015-10-03 19:50:30 +02:00
|
|
|
need_ipv6ll = TRUE;
|
2015-11-12 12:41:26 +01:00
|
|
|
|
|
|
|
|
if (need_ipv6ll)
|
|
|
|
|
check_and_add_ipv6ll_addr (self);
|
2015-10-03 19:50:30 +02:00
|
|
|
}
|
2015-11-12 12:41:26 +01:00
|
|
|
|
2015-10-03 19:50:30 +02:00
|
|
|
g_slist_free_full (priv->dad6_failed_addrs, g_free);
|
2015-11-05 16:39:19 +01:00
|
|
|
priv->dad6_failed_addrs = NULL;
|
2015-10-03 19:50:30 +02:00
|
|
|
|
2016-03-14 18:37:57 +01:00
|
|
|
/* Check if DAD is still pending */
|
|
|
|
|
if ( priv->ip6_state == IP_CONF
|
|
|
|
|
&& priv->dad6_ip6_config
|
|
|
|
|
&& priv->ext_ip6_config_captured) {
|
|
|
|
|
if (!nm_ip6_config_has_any_dad_pending (priv->ext_ip6_config_captured,
|
|
|
|
|
priv->dad6_ip6_config)) {
|
|
|
|
|
_LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated");
|
|
|
|
|
g_clear_object (&priv->dad6_ip6_config);
|
2016-08-29 14:27:46 +02:00
|
|
|
_set_ip_state (self, AF_INET6, IP_DONE);
|
2016-09-19 10:51:56 +02:00
|
|
|
check_ip_state (self, FALSE);
|
2017-09-13 16:45:22 +02:00
|
|
|
if (priv->rt6_temporary_not_available)
|
|
|
|
|
nm_device_activate_schedule_ip6_config_result (self);
|
2016-03-14 18:37:57 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-21 15:30:07 +01:00
|
|
|
set_unmanaged_external_down (self, TRUE);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
2013-12-09 12:55:04 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
2015-06-24 15:54:44 +02:00
|
|
|
device_ipx_changed (NMPlatform *platform,
|
2016-10-22 13:08:36 +02:00
|
|
|
int obj_type_i,
|
2015-06-24 08:59:36 +00:00
|
|
|
int ifindex,
|
|
|
|
|
gpointer platform_object,
|
2016-10-22 13:08:36 +02:00
|
|
|
int change_type_i,
|
2015-06-24 08:59:36 +00:00
|
|
|
NMDevice *self)
|
|
|
|
|
{
|
2016-10-22 13:08:36 +02:00
|
|
|
const NMPObjectType obj_type = obj_type_i;
|
|
|
|
|
const NMPlatformSignalChangeType change_type = change_type_i;
|
2015-06-24 15:54:44 +02:00
|
|
|
NMDevicePrivate *priv;
|
2015-10-03 19:50:30 +02:00
|
|
|
NMPlatformIP6Address *addr;
|
2015-06-24 15:54:44 +02:00
|
|
|
|
|
|
|
|
if (nm_device_get_ip_ifindex (self) != ifindex)
|
|
|
|
|
return;
|
2015-06-24 08:59:36 +00:00
|
|
|
|
2015-06-24 15:54:44 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-10-03 19:50:30 +02:00
|
|
|
|
2015-06-24 15:54:44 +02:00
|
|
|
switch (obj_type) {
|
|
|
|
|
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
|
|
|
|
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
|
|
|
|
|
priv->queued_ip4_config_pending = TRUE;
|
|
|
|
|
nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id));
|
|
|
|
|
} else if (!priv->queued_ip4_config_id) {
|
|
|
|
|
priv->queued_ip4_config_pending = FALSE;
|
2015-06-24 08:59:36 +00:00
|
|
|
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
|
|
|
|
|
_LOGD (LOGD_DEVICE, "queued IP4 config change");
|
|
|
|
|
}
|
2015-06-24 15:54:44 +02:00
|
|
|
break;
|
|
|
|
|
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
2015-10-03 19:50:30 +02:00
|
|
|
addr = platform_object;
|
|
|
|
|
|
2015-11-25 11:07:33 +01:00
|
|
|
if ( priv->state > NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
&& priv->state < NM_DEVICE_STATE_DEACTIVATING
|
2016-02-29 16:23:16 +01:00
|
|
|
&& ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED)
|
|
|
|
|
|| (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE))) {
|
2015-10-03 19:50:30 +02:00
|
|
|
priv->dad6_failed_addrs = g_slist_append (priv->dad6_failed_addrs,
|
|
|
|
|
g_memdup (addr, sizeof (NMPlatformIP6Address)));
|
|
|
|
|
}
|
2017-02-06 14:42:47 +01:00
|
|
|
/* fall through */
|
2015-06-24 15:54:44 +02:00
|
|
|
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
|
|
|
|
|
priv->queued_ip6_config_pending = TRUE;
|
|
|
|
|
nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id));
|
|
|
|
|
} else if (!priv->queued_ip6_config_id) {
|
|
|
|
|
priv->queued_ip6_config_pending = FALSE;
|
2015-06-24 08:59:36 +00:00
|
|
|
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
|
|
|
|
|
_LOGD (LOGD_DEVICE, "queued IP6 config change");
|
2015-06-17 19:13:08 +02:00
|
|
|
}
|
2015-06-24 15:54:44 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_return_if_reached ();
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
2007-02-05 12:14:09 +00:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
NM_UTILS_FLAGS2STR_DEFINE (nm_unmanaged_flags2str, NMUnmanagedFlags,
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_SLEEPING, "sleeping"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_QUITTING, "quitting"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_PARENT, "parent"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_LOOPBACK, "loopback"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_PLATFORM_INIT, "platform-init"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_EXPLICIT, "user-explicit"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_BY_DEFAULT, "by-default"),
|
2016-02-22 14:45:45 +01:00
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_SETTINGS, "user-settings"),
|
2017-09-26 16:28:49 +02:00
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_CONF, "user-conf"),
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_UDEV, "user-udev"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_EXTERNAL_DOWN, "external-down"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_UNMANAGED_IS_SLAVE, "is-slave"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
_unmanaged_flags2str (NMUnmanagedFlags flags, NMUnmanagedFlags mask, char *buf, gsize len)
|
|
|
|
|
{
|
|
|
|
|
char buf2[512];
|
|
|
|
|
char *b;
|
|
|
|
|
char *tmp, *tmp2;
|
|
|
|
|
gsize l;
|
|
|
|
|
|
|
|
|
|
nm_utils_to_string_buffer_init (&buf, &len);
|
|
|
|
|
if (!len)
|
|
|
|
|
return buf;
|
|
|
|
|
|
|
|
|
|
b = buf;
|
|
|
|
|
|
|
|
|
|
mask |= flags;
|
|
|
|
|
|
|
|
|
|
nm_unmanaged_flags2str (flags, b, len);
|
|
|
|
|
l = strlen (b);
|
|
|
|
|
b += l;
|
|
|
|
|
len -= l;
|
|
|
|
|
|
|
|
|
|
nm_unmanaged_flags2str (mask & ~flags, buf2, sizeof (buf2));
|
|
|
|
|
if (buf2[0]) {
|
|
|
|
|
gboolean add_separator = l > 0;
|
|
|
|
|
|
|
|
|
|
tmp = buf2;
|
|
|
|
|
while (TRUE) {
|
|
|
|
|
if (add_separator)
|
|
|
|
|
nm_utils_strbuf_append_c (&b, &len, ',');
|
|
|
|
|
add_separator = TRUE;
|
|
|
|
|
|
|
|
|
|
tmp2 = strchr (tmp, ',');
|
|
|
|
|
if (tmp2)
|
|
|
|
|
tmp2[0] = '\0';
|
|
|
|
|
|
|
|
|
|
nm_utils_strbuf_append_c (&b, &len, '!');
|
|
|
|
|
nm_utils_strbuf_append_str (&b, &len, tmp);
|
|
|
|
|
if (!tmp2)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
tmp = &tmp2[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_get_managed_by_flags(NMUnmanagedFlags flags, NMUnmanagedFlags mask, gboolean for_user_request)
|
|
|
|
|
{
|
|
|
|
|
/* Evaluate the managed state based on the unmanaged flags.
|
|
|
|
|
*
|
|
|
|
|
* Some flags are authoritative, meaning they always cause
|
|
|
|
|
* the device to be unmanaged (e.g. @NM_UNMANAGED_PLATFORM_INIT).
|
|
|
|
|
*
|
2016-06-22 14:04:25 +02:00
|
|
|
* OTOH, some flags can be overwritten. For example NM_UNMANAGED_USER_UDEV
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* is ignored once NM_UNMANAGED_USER_EXPLICIT is set. The idea is that
|
|
|
|
|
* the flag from the configuration has no effect once the user explicitly
|
|
|
|
|
* touches the unmanaged flags. */
|
|
|
|
|
|
|
|
|
|
if (for_user_request) {
|
|
|
|
|
|
|
|
|
|
/* @for_user_request can make the result only ~more~ managed.
|
|
|
|
|
* If the flags already indicate a managed state for a non-user-request,
|
|
|
|
|
* then it is also managed for an explict user-request.
|
|
|
|
|
*
|
|
|
|
|
* Effectively, this check is redundant, as the code below already
|
|
|
|
|
* already ensures that. Still, express this invariant explictly here. */
|
|
|
|
|
if (_get_managed_by_flags (flags, mask, FALSE))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
/* A for-user-request, is effectively the same as pretending
|
|
|
|
|
* that user-dbus flag is cleared. */
|
|
|
|
|
mask |= NM_UNMANAGED_USER_EXPLICIT;
|
|
|
|
|
flags &= ~NM_UNMANAGED_USER_EXPLICIT;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-22 14:45:45 +01:00
|
|
|
if ( NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_SETTINGS)
|
|
|
|
|
&& !NM_FLAGS_ANY (flags, NM_UNMANAGED_USER_SETTINGS)) {
|
|
|
|
|
/* NM_UNMANAGED_USER_SETTINGS can only explicitly unmanage a device. It cannot
|
|
|
|
|
* *manage* it. Having NM_UNMANAGED_USER_SETTINGS explicitly not set, is the
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* same as having it not set at all. */
|
2016-02-22 14:45:45 +01:00
|
|
|
mask &= ~NM_UNMANAGED_USER_SETTINGS;
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
}
|
|
|
|
|
|
2016-02-22 15:53:06 +01:00
|
|
|
if (NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_UDEV)) {
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
/* configuration from udev or nm-config overwrites the by-default flag
|
2017-09-26 16:28:49 +02:00
|
|
|
* which is based on the device type.
|
|
|
|
|
* configuration from udev overwrites external-down */
|
|
|
|
|
flags &= ~( NM_UNMANAGED_BY_DEFAULT
|
|
|
|
|
| NM_UNMANAGED_EXTERNAL_DOWN);
|
|
|
|
|
}
|
2016-04-08 11:36:13 +02:00
|
|
|
|
2017-09-26 16:28:49 +02:00
|
|
|
if (NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_CONF)) {
|
|
|
|
|
/* configuration from NetworkManager.conf overwrites the by-default flag
|
|
|
|
|
* which is based on the device type.
|
|
|
|
|
* It also overwrites the udev configuration and external-down */
|
|
|
|
|
flags &= ~( NM_UNMANAGED_BY_DEFAULT
|
2017-10-05 14:45:25 +02:00
|
|
|
| NM_UNMANAGED_USER_UDEV
|
|
|
|
|
| NM_UNMANAGED_EXTERNAL_DOWN);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( NM_FLAGS_HAS (mask, NM_UNMANAGED_IS_SLAVE)
|
|
|
|
|
&& !NM_FLAGS_HAS (flags, NM_UNMANAGED_IS_SLAVE)) {
|
|
|
|
|
/* for an enslaved device, by-default doesn't matter */
|
|
|
|
|
flags &= ~NM_UNMANAGED_BY_DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NM_FLAGS_HAS (mask, NM_UNMANAGED_USER_EXPLICIT)) {
|
|
|
|
|
/* if the device is managed by user-decision, certain other flags
|
|
|
|
|
* are ignored. */
|
|
|
|
|
flags &= ~( NM_UNMANAGED_BY_DEFAULT
|
|
|
|
|
| NM_UNMANAGED_USER_UDEV
|
2017-09-26 16:28:49 +02:00
|
|
|
| NM_UNMANAGED_USER_CONF
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
| NM_UNMANAGED_EXTERNAL_DOWN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return flags == NM_UNMANAGED_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* nm_device_get_managed:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* @for_user_request: whether to check the flags for an explict user-request
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* Whether the device is unmanaged according to the unmanaged flags.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the device is unmanaged because of the flags.
|
2014-05-20 15:03:27 -05:00
|
|
|
*/
|
|
|
|
|
gboolean
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
nm_device_get_managed (NMDevice *self, gboolean for_user_request)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2013-05-01 09:28:16 -04:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if (!nm_device_is_real (self)) {
|
|
|
|
|
/* a unrealized device is always considered unmanaged. */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
return _get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, for_user_request);
|
2007-02-05 12:14:09 +00:00
|
|
|
}
|
|
|
|
|
|
2016-03-23 09:39:22 +01:00
|
|
|
/**
|
|
|
|
|
* nm_device_get_unmanaged_mask:
|
|
|
|
|
* @self: the #NMDevice
|
|
|
|
|
* @flag: the unmanaged flags to check.
|
|
|
|
|
*
|
|
|
|
|
* Return the unmanaged flags mask set on this device.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the flags of the device ( & @flag)
|
|
|
|
|
*/
|
|
|
|
|
NMUnmanagedFlags
|
|
|
|
|
nm_device_get_unmanaged_mask (NMDevice *self, NMUnmanagedFlags flag)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_UNMANAGED_NONE);
|
|
|
|
|
g_return_val_if_fail (flag != NM_UNMANAGED_NONE, NM_UNMANAGED_NONE);
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->unmanaged_mask & flag;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* nm_device_get_unmanaged_flags:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* @flag: the unmanaged flags to check.
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* Return the unmanaged flags of the device.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the flags of the device ( & @flag)
|
2014-05-20 15:03:27 -05:00
|
|
|
*/
|
2015-11-05 02:41:42 +01:00
|
|
|
NMUnmanagedFlags
|
2015-11-05 02:32:53 +01:00
|
|
|
nm_device_get_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flag)
|
2011-03-17 13:39:31 -05:00
|
|
|
{
|
2016-03-23 09:39:22 +01:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_UNMANAGED_NONE);
|
|
|
|
|
g_return_val_if_fail (flag != NM_UNMANAGED_NONE, NM_UNMANAGED_NONE);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
2015-11-05 02:41:42 +01:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags & flag;
|
2011-03-17 13:39:31 -05:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* _set_unmanaged_flags:
|
|
|
|
|
* @self: the #NMDevice instance
|
|
|
|
|
* @flags: which #NMUnmanagedFlags to set.
|
|
|
|
|
* @set_op: whether to set/clear/forget the flags. You can also pass
|
|
|
|
|
* boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED
|
|
|
|
|
* and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively.
|
|
|
|
|
* @allow_state_transition: if %FALSE, setting flags never triggers a device
|
|
|
|
|
* state change. If %TRUE, the device can change state, if it is real and
|
|
|
|
|
* switches from managed to unmanaged (or vice versa).
|
2016-05-05 11:05:04 +02:00
|
|
|
* @now: whether the state change should be immediate or delayed
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* @reason: the device state reason passed to nm_device_state_changed() if
|
|
|
|
|
* the device becomes managed/unmanaged. This is only relevant if the
|
|
|
|
|
* device switches state and if @allow_state_transition is %TRUE.
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
* Set the unmanaged flags of the device.
|
|
|
|
|
**/
|
2015-06-29 18:06:12 +02:00
|
|
|
static void
|
|
|
|
|
_set_unmanaged_flags (NMDevice *self,
|
|
|
|
|
NMUnmanagedFlags flags,
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
NMUnmanFlagOp set_op,
|
|
|
|
|
gboolean allow_state_transition,
|
2016-05-05 11:05:04 +02:00
|
|
|
gboolean now,
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
NMDeviceStateReason reason)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
gboolean was_managed, transition_state;
|
|
|
|
|
NMUnmanagedFlags old_flags, old_mask;
|
2016-05-05 11:05:04 +02:00
|
|
|
NMDeviceState new_state;
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
const char *operation = NULL;
|
|
|
|
|
char str1[512];
|
|
|
|
|
char str2[512];
|
2017-03-13 18:45:36 +01:00
|
|
|
gboolean do_notify_has_pending_actions = FALSE;
|
|
|
|
|
gboolean had_pending_actions = FALSE;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
g_return_if_fail (flags);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if (!priv->real)
|
|
|
|
|
allow_state_transition = FALSE;
|
|
|
|
|
was_managed = allow_state_transition && nm_device_get_managed (self, FALSE);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-10-25 15:27:57 +02:00
|
|
|
if ( NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_PLATFORM_INIT)
|
|
|
|
|
&& NM_FLAGS_HAS (flags, NM_UNMANAGED_PLATFORM_INIT)
|
|
|
|
|
&& NM_IN_SET (set_op, NM_UNMAN_FLAG_OP_SET_MANAGED)) {
|
|
|
|
|
/* we are clearing the platform-init flags. This triggers additional actions. */
|
|
|
|
|
if (!NM_FLAGS_HAS (flags, NM_UNMANAGED_USER_SETTINGS)) {
|
|
|
|
|
gboolean unmanaged;
|
|
|
|
|
|
|
|
|
|
unmanaged = nm_device_spec_match_list (self,
|
|
|
|
|
nm_settings_get_unmanaged_specs (NM_DEVICE_GET_PRIVATE (self)->settings));
|
|
|
|
|
nm_device_set_unmanaged_flags (self,
|
|
|
|
|
NM_UNMANAGED_USER_SETTINGS,
|
|
|
|
|
!!unmanaged);
|
|
|
|
|
}
|
device: don't evaluate IP config changes until device is initialized
The unmanaged flags PLATFORM_INIT indicates whether UDEV is done
initializing the device. We should not handle IP config changes
before that pointer.
This avoids codepaths that require the permanent MAC address of the
device. We should not freeze the permanent MAC address before
UDEV initialized the device, for two reasons:
- getting the permanent MAC address using ethtool is racy as
UDEV might still rename the interface.
- freezing a fake permanent MAC address should only happen after
UDEV is done configuring the MAC address of software devices.
#0 0x000055555568bc7a in nm_device_update_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1) at src/devices/nm-device.c:11817
#1 0x000055555568c443 in nm_device_get_permanent_hw_address_full (self=self@entry=0x555555f0fb70 [NMDeviceVeth], force_freeze=force_freeze@entry=1, out_is_fake=out_is_fake@entry=0x0)
at src/devices/nm-device.c:12227
#2 0x000055555568cb06 in nm_device_get_permanent_hw_address (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:12237
#3 0x000055555568cb50 in spec_match_list (self=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12294
#4 0x00005555556a4ee6 in spec_match_list (device=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device-ethernet.c:1461
#5 0x00005555556978db in nm_device_spec_match_list (self=self@entry=0x555555f0fb70 [NMDeviceVeth], specs=0x555555a5c000 = {...}) at src/devices/nm-device.c:12277
#6 0x000055555558e187 in _match_section_infos_lookup (match_section_infos=0x555555a5d500, keyfile=0x555555a46f80, property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth], out_value=out_value@entry=0x7fffffffe018) at src/nm-config-data.c:1169
#7 0x00005555555922ca in nm_config_data_get_connection_default (self=0x555555a548c0 [NMConfigData], property=property@entry=0x555555793123 "ipv4.route-metric", device=device@entry=0x555555f0fb70 [NMDeviceVeth]) at src/nm-config-data.c:1234
#8 0x00005555556790cd in _get_ipx_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth], is_v4=is_v4@entry=1) at src/devices/nm-device.c:1142
#9 0x000055555567912e in nm_device_get_ip4_route_metric (self=self@entry=0x555555f0fb70 [NMDeviceVeth]) at src/devices/nm-device.c:1161
#10 0x000055555567da6c in ip4_config_merge_and_apply (self=self@entry=0x555555f0fb70 [NMDeviceVeth], config=config@entry=0x0, commit=commit@entry=0, out_reason=out_reason@entry=0x0)
at src/devices/nm-device.c:4787
#11 0x000055555567e0fb in update_ip4_config (self=self@entry=0x555555f0fb70 [NMDeviceVeth], initial=initial@entry=0) at src/devices/nm-device.c:9532
#12 0x0000555555693acd in queued_ip4_config_change (user_data=0x555555f0fb70) at src/devices/nm-device.c:9651
#13 0x00007ffff4c966ba in g_main_context_dispatch (context=0x555555a46af0) at gmain.c:3154
#14 0x00007ffff4c966ba in g_main_context_dispatch (context=context@entry=0x555555a46af0) at gmain.c:3769
#15 0x00007ffff4c96a70 in g_main_context_iterate (context=0x555555a46af0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#16 0x00007ffff4c96d92 in g_main_loop_run (loop=0x555555a47400) at gmain.c:4034
#17 0x000055555558372a in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:411
2016-10-26 13:43:49 +02:00
|
|
|
|
|
|
|
|
if (priv->queued_ip4_config_pending) {
|
|
|
|
|
priv->queued_ip4_config_pending = FALSE;
|
|
|
|
|
nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id));
|
|
|
|
|
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (priv->queued_ip6_config_pending) {
|
|
|
|
|
priv->queued_ip6_config_pending = FALSE;
|
|
|
|
|
nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id));
|
|
|
|
|
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
|
|
|
|
|
}
|
2017-03-13 18:45:36 +01:00
|
|
|
|
|
|
|
|
if (!priv->pending_actions) {
|
|
|
|
|
do_notify_has_pending_actions = TRUE;
|
|
|
|
|
had_pending_actions = nm_device_has_pending_action (self);
|
|
|
|
|
}
|
2016-10-25 15:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
old_flags = priv->unmanaged_flags;
|
|
|
|
|
old_mask = priv->unmanaged_mask;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
switch (set_op) {
|
|
|
|
|
case NM_UNMAN_FLAG_OP_FORGET:
|
|
|
|
|
priv->unmanaged_mask &= ~flags;
|
|
|
|
|
priv->unmanaged_flags &= ~flags;
|
|
|
|
|
operation = "forget";
|
|
|
|
|
break;
|
|
|
|
|
case NM_UNMAN_FLAG_OP_SET_UNMANAGED:
|
|
|
|
|
priv->unmanaged_mask |= flags;
|
|
|
|
|
priv->unmanaged_flags |= flags;
|
|
|
|
|
operation = "set-unmanaged";
|
|
|
|
|
break;
|
|
|
|
|
case NM_UNMAN_FLAG_OP_SET_MANAGED:
|
|
|
|
|
priv->unmanaged_mask |= flags;
|
|
|
|
|
priv->unmanaged_flags &= ~flags;
|
|
|
|
|
operation = "set-managed";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( old_flags == priv->unmanaged_flags
|
|
|
|
|
&& old_mask == priv->unmanaged_mask)
|
|
|
|
|
return;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
transition_state = allow_state_transition
|
|
|
|
|
&& was_managed != nm_device_get_managed (self, FALSE)
|
|
|
|
|
&& ( was_managed
|
|
|
|
|
|| ( !was_managed
|
|
|
|
|
&& nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED));
|
|
|
|
|
|
2017-03-15 10:28:48 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "unmanaged: flags set to [%s%s0x%0x/0x%x/%s%s], %s [%s=0x%0x]%s%s%s)",
|
|
|
|
|
_unmanaged_flags2str (priv->unmanaged_flags, priv->unmanaged_mask, str1, sizeof (str1)), \
|
|
|
|
|
(priv->unmanaged_flags | priv->unmanaged_mask) ? "=" : "", \
|
|
|
|
|
(guint) priv->unmanaged_flags, \
|
|
|
|
|
(guint) priv->unmanaged_mask, \
|
|
|
|
|
(_get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, FALSE) \
|
|
|
|
|
? "managed" \
|
|
|
|
|
: (_get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, TRUE) \
|
|
|
|
|
? "manageable" \
|
|
|
|
|
: "unmanaged")),
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
priv->real ? "" : "/unrealized",
|
|
|
|
|
operation,
|
|
|
|
|
nm_unmanaged_flags2str (flags, str2, sizeof (str2)),
|
|
|
|
|
flags,
|
|
|
|
|
NM_PRINT_FMT_QUOTED (allow_state_transition,
|
|
|
|
|
", reason ",
|
|
|
|
|
reason_to_string (reason),
|
|
|
|
|
transition_state ? ", transition-state" : "",
|
|
|
|
|
""));
|
|
|
|
|
|
2017-03-13 18:45:36 +01:00
|
|
|
if ( do_notify_has_pending_actions
|
|
|
|
|
&& had_pending_actions != nm_device_has_pending_action (self))
|
|
|
|
|
_notify (self, PROP_HAS_PENDING_ACTION);
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if (transition_state) {
|
2016-05-05 11:05:04 +02:00
|
|
|
new_state = was_managed ? NM_DEVICE_STATE_UNMANAGED : NM_DEVICE_STATE_UNAVAILABLE;
|
|
|
|
|
if (now)
|
|
|
|
|
nm_device_state_changed (self, new_state, reason);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
else
|
2016-05-05 11:05:04 +02:00
|
|
|
nm_device_queue_state (self, new_state, reason);
|
2007-02-05 12:14:09 +00:00
|
|
|
}
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
/**
|
|
|
|
|
* @self: the #NMDevice instance
|
|
|
|
|
* @flags: which #NMUnmanagedFlags to set.
|
|
|
|
|
* @set_op: whether to set/clear/forget the flags. You can also pass
|
|
|
|
|
* boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED
|
|
|
|
|
* and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively.
|
|
|
|
|
*
|
|
|
|
|
* Set the unmanaged flags of the device (does not trigger a state change).
|
|
|
|
|
**/
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_unmanaged_flags (NMDevice *self,
|
|
|
|
|
NMUnmanagedFlags flags,
|
|
|
|
|
NMUnmanFlagOp set_op)
|
|
|
|
|
{
|
2016-05-05 11:05:04 +02:00
|
|
|
_set_unmanaged_flags (self, flags, set_op, FALSE, FALSE, NM_DEVICE_STATE_REASON_NONE);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_device_set_unmanaged_by_flags:
|
|
|
|
|
* @self: the #NMDevice instance
|
|
|
|
|
* @flags: which #NMUnmanagedFlags to set.
|
|
|
|
|
* @set_op: whether to set/clear/forget the flags. You can also pass
|
|
|
|
|
* boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED
|
|
|
|
|
* and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively.
|
|
|
|
|
* @reason: the device state reason passed to nm_device_state_changed() if
|
|
|
|
|
* the device becomes managed/unmanaged.
|
|
|
|
|
*
|
|
|
|
|
* Set the unmanaged flags of the device and possibly trigger a state change.
|
|
|
|
|
**/
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_unmanaged_by_flags (NMDevice *self,
|
|
|
|
|
NMUnmanagedFlags flags,
|
|
|
|
|
NMUnmanFlagOp set_op,
|
|
|
|
|
NMDeviceStateReason reason)
|
|
|
|
|
{
|
2016-05-05 11:05:04 +02:00
|
|
|
_set_unmanaged_flags (self, flags, set_op, TRUE, TRUE, reason);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_set_unmanaged_by_flags_queue (NMDevice *self,
|
|
|
|
|
NMUnmanagedFlags flags,
|
|
|
|
|
NMUnmanFlagOp set_op,
|
|
|
|
|
NMDeviceStateReason reason)
|
|
|
|
|
{
|
|
|
|
|
_set_unmanaged_flags (self, flags, set_op, TRUE, FALSE, reason);
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-15 23:53:46 +02:00
|
|
|
void
|
2016-10-25 15:27:57 +02:00
|
|
|
nm_device_set_unmanaged_by_user_settings (NMDevice *self)
|
2015-09-15 23:53:46 +02:00
|
|
|
{
|
|
|
|
|
gboolean unmanaged;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
2016-10-25 15:27:57 +02:00
|
|
|
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
|
|
|
|
|
/* the device is already unmanaged due to platform-init.
|
|
|
|
|
*
|
|
|
|
|
* We want to delay evaluating the device spec, because it will freeze
|
|
|
|
|
* the permanent MAC address. That should not be done, before the platform
|
|
|
|
|
* link is fully initialized (via UDEV).
|
|
|
|
|
*
|
|
|
|
|
* Note that when clearing NM_UNMANAGED_PLATFORM_INIT, we will re-evaluate
|
|
|
|
|
* whether the device is unmanaged by user-settings. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-09-15 23:53:46 +02:00
|
|
|
|
2016-10-25 15:27:57 +02:00
|
|
|
unmanaged = nm_device_spec_match_list (self,
|
|
|
|
|
nm_settings_get_unmanaged_specs (NM_DEVICE_GET_PRIVATE (self)->settings));
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
2016-01-13 12:03:47 +01:00
|
|
|
nm_device_set_unmanaged_by_flags (self,
|
2016-02-22 14:45:45 +01:00
|
|
|
NM_UNMANAGED_USER_SETTINGS,
|
2016-10-25 15:27:57 +02:00
|
|
|
!!unmanaged,
|
2016-01-13 12:03:47 +01:00
|
|
|
unmanaged
|
|
|
|
|
? NM_DEVICE_STATE_REASON_NOW_UNMANAGED
|
|
|
|
|
: NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
2015-09-15 23:53:46 +02:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
void
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
nm_device_set_unmanaged_by_user_udev (NMDevice *self)
|
2005-12-31 08:21:24 +00:00
|
|
|
{
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
int ifindex;
|
|
|
|
|
gboolean platform_unmanaged = FALSE;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
2016-09-05 16:55:07 +02:00
|
|
|
ifindex = self->_priv->ifindex;
|
2007-02-05 12:14:09 +00:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if ( ifindex <= 0
|
2017-04-17 20:17:45 +02:00
|
|
|
|| !nm_platform_link_get_unmanaged (nm_device_get_platform (self), ifindex, &platform_unmanaged))
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
return;
|
2005-12-31 08:21:24 +00:00
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
nm_device_set_unmanaged_by_flags (self,
|
|
|
|
|
NM_UNMANAGED_USER_UDEV,
|
|
|
|
|
platform_unmanaged,
|
|
|
|
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2013-07-27 10:41:44 +02:00
|
|
|
|
2017-09-26 16:28:49 +02:00
|
|
|
void
|
|
|
|
|
nm_device_set_unmanaged_by_user_conf (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
gboolean value;
|
|
|
|
|
NMUnmanFlagOp set_op;
|
|
|
|
|
|
|
|
|
|
value = nm_config_data_get_device_config_boolean (NM_CONFIG_GET_DATA,
|
|
|
|
|
NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED,
|
|
|
|
|
self,
|
|
|
|
|
-1,
|
|
|
|
|
TRUE);
|
|
|
|
|
switch (value) {
|
|
|
|
|
case TRUE:
|
|
|
|
|
set_op = NM_UNMAN_FLAG_OP_SET_MANAGED;
|
|
|
|
|
break;
|
|
|
|
|
case FALSE:
|
|
|
|
|
set_op = NM_UNMAN_FLAG_OP_SET_UNMANAGED;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
set_op = NM_UNMAN_FLAG_OP_FORGET;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_device_set_unmanaged_by_flags (self,
|
|
|
|
|
NM_UNMANAGED_USER_CONF,
|
|
|
|
|
set_op,
|
|
|
|
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 02:28:34 +01:00
|
|
|
void
|
2016-01-13 12:03:47 +01:00
|
|
|
nm_device_set_unmanaged_by_quitting (NMDevice *self)
|
2015-11-05 02:28:34 +01:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-01-14 17:45:54 +01:00
|
|
|
gboolean need_deactivate = nm_device_is_activating (self) ||
|
|
|
|
|
priv->state == NM_DEVICE_STATE_ACTIVATED;
|
2015-11-05 02:28:34 +01:00
|
|
|
|
|
|
|
|
/* It's OK to block here because we're quitting */
|
2016-01-14 17:45:54 +01:00
|
|
|
if (need_deactivate)
|
2015-11-05 02:28:34 +01:00
|
|
|
_set_state_full (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_NOW_UNMANAGED, TRUE);
|
|
|
|
|
|
2016-01-13 12:03:47 +01:00
|
|
|
nm_device_set_unmanaged_by_flags (self,
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
NM_UNMANAGED_QUITTING,
|
2016-01-13 12:03:47 +01:00
|
|
|
TRUE,
|
|
|
|
|
need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED
|
|
|
|
|
: NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
|
2015-11-05 02:28:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
void
|
2014-07-30 10:57:45 -04:00
|
|
|
nm_device_set_dhcp_anycast_address (NMDevice *self, const char *addr)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2013-05-29 12:57:13 -03:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2014-07-30 10:57:45 -04:00
|
|
|
g_return_if_fail (!addr || nm_utils_hwaddr_valid (addr, ETH_ALEN));
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2014-07-30 10:57:45 -04:00
|
|
|
g_free (priv->dhcp_anycast_address);
|
|
|
|
|
priv->dhcp_anycast_address = g_strdup (addr);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
void
|
|
|
|
|
nm_device_reapply_settings_immediately (NMDevice *self)
|
|
|
|
|
{
|
2016-01-07 11:55:44 +01:00
|
|
|
NMConnection *applied_connection;
|
2015-07-14 16:53:24 +02:00
|
|
|
NMSettingsConnection *settings_connection;
|
|
|
|
|
NMDeviceState state;
|
2016-01-07 11:55:44 +01:00
|
|
|
NMSettingConnection *s_con_settings;
|
|
|
|
|
NMSettingConnection *s_con_applied;
|
|
|
|
|
const char *zone;
|
|
|
|
|
NMMetered metered;
|
2016-02-11 08:36:39 +01:00
|
|
|
guint64 version_id;
|
2015-07-14 16:53:24 +02:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
state = nm_device_get_state (self);
|
|
|
|
|
if ( state <= NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
|| state > NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
applied_connection = nm_device_get_applied_connection (self);
|
|
|
|
|
settings_connection = nm_device_get_settings_connection (self);
|
|
|
|
|
|
|
|
|
|
if (!nm_settings_connection_has_unmodified_applied_connection (settings_connection,
|
|
|
|
|
applied_connection,
|
|
|
|
|
NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY))
|
|
|
|
|
return;
|
|
|
|
|
|
2016-01-07 11:55:44 +01:00
|
|
|
s_con_settings = nm_connection_get_setting_connection ((NMConnection *) settings_connection);
|
|
|
|
|
s_con_applied = nm_connection_get_setting_connection (applied_connection);
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)),
|
|
|
|
|
nm_setting_connection_get_zone (s_con_applied)) != 0) {
|
|
|
|
|
|
2016-09-05 16:55:07 +02:00
|
|
|
version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request);
|
2017-03-14 11:15:05 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (unsigned long long) version_id);
|
2016-01-07 11:55:44 +01:00
|
|
|
|
|
|
|
|
g_object_set (G_OBJECT (s_con_applied),
|
|
|
|
|
NM_SETTING_CONNECTION_ZONE, zone,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_device_update_firewall_zone (self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) {
|
|
|
|
|
|
2016-09-05 16:55:07 +02:00
|
|
|
version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request);
|
2017-03-14 11:15:05 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (unsigned long long) version_id);
|
2016-01-07 11:55:44 +01:00
|
|
|
|
|
|
|
|
g_object_set (G_OBJECT (s_con_applied),
|
|
|
|
|
NM_SETTING_CONNECTION_METERED, metered,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_device_update_metered (self);
|
|
|
|
|
}
|
2015-07-14 16:53:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_update_firewall_zone (NMDevice *self)
|
|
|
|
|
{
|
2017-05-03 18:34:17 +02:00
|
|
|
NMDevicePrivate *priv;
|
2015-07-14 16:53:24 +02:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-07-14 16:53:24 +02:00
|
|
|
|
2017-05-03 18:34:17 +02:00
|
|
|
if ( priv->fw_state >= FIREWALL_STATE_INITIALIZED
|
|
|
|
|
&& !nm_device_sys_iface_state_is_external (self))
|
|
|
|
|
fw_change_zone (self);
|
2015-07-14 16:53:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-07 12:06:27 +02:00
|
|
|
void
|
2015-04-30 14:18:14 +02:00
|
|
|
nm_device_update_metered (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
#define NM_METERED_INVALID ((NMMetered) -1)
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMSettingConnection *setting;
|
|
|
|
|
NMMetered conn_value, value = NM_METERED_INVALID;
|
|
|
|
|
NMConnection *connection = NULL;
|
|
|
|
|
NMDeviceState state;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
state = nm_device_get_state (self);
|
|
|
|
|
if ( state <= NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
|| state > NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
value = NM_METERED_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
if (value == NM_METERED_INVALID) {
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2015-04-30 14:18:14 +02:00
|
|
|
if (connection) {
|
|
|
|
|
setting = nm_connection_get_setting_connection (connection);
|
|
|
|
|
if (setting) {
|
|
|
|
|
conn_value = nm_setting_connection_get_metered (setting);
|
|
|
|
|
if (conn_value != NM_METERED_UNKNOWN)
|
|
|
|
|
value = conn_value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Try to guess a value using the metered flag in IP configuration */
|
|
|
|
|
if (value == NM_METERED_INVALID) {
|
|
|
|
|
if ( priv->ip4_config
|
|
|
|
|
&& priv->ip4_state == IP_DONE
|
|
|
|
|
&& nm_ip4_config_get_metered (priv->ip4_config))
|
|
|
|
|
value = NM_METERED_GUESS_YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Otherwise look at connection type */
|
|
|
|
|
if (value == NM_METERED_INVALID) {
|
|
|
|
|
if ( nm_connection_is_type (connection, NM_SETTING_GSM_SETTING_NAME)
|
|
|
|
|
|| nm_connection_is_type (connection, NM_SETTING_CDMA_SETTING_NAME))
|
|
|
|
|
value = NM_METERED_GUESS_YES;
|
|
|
|
|
else
|
|
|
|
|
value = NM_METERED_GUESS_NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value != priv->metered) {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "set metered value %d", value);
|
|
|
|
|
priv->metered = value;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_METERED);
|
2015-04-30 14:18:14 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-05 13:42:24 +02:00
|
|
|
static gboolean
|
|
|
|
|
_nm_device_check_connection_available (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
NMDeviceCheckConAvailableFlags flags,
|
|
|
|
|
const char *specific_object)
|
|
|
|
|
{
|
|
|
|
|
NMDeviceState state;
|
|
|
|
|
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
/* an unrealized software device is always available, hardware devices never. */
|
|
|
|
|
if (!nm_device_is_real (self)) {
|
|
|
|
|
if (nm_device_is_software (self))
|
|
|
|
|
return nm_device_check_connection_compatible (self, connection);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-05 13:42:24 +02:00
|
|
|
state = nm_device_get_state (self);
|
|
|
|
|
if (state < NM_DEVICE_STATE_UNMANAGED)
|
|
|
|
|
return FALSE;
|
|
|
|
|
if ( state < NM_DEVICE_STATE_UNAVAILABLE
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
&& ( ( !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
|
|
|
|
|
&& !nm_device_get_managed (self, FALSE))
|
|
|
|
|
|| ( NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
|
|
|
|
|
&& !nm_device_get_managed (self, TRUE))))
|
2015-10-05 13:42:24 +02:00
|
|
|
return FALSE;
|
|
|
|
|
if ( state < NM_DEVICE_STATE_DISCONNECTED
|
2014-09-24 16:58:07 -05:00
|
|
|
&& !nm_device_is_software (self)
|
2015-12-09 12:08:40 +01:00
|
|
|
&& ( ( !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
|
2015-10-05 13:42:24 +02:00
|
|
|
&& !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
|
2015-12-09 12:08:40 +01:00
|
|
|
|| ( NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST)
|
|
|
|
|
&& !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST))))
|
2015-10-05 13:42:24 +02:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!nm_device_check_connection_compatible (self, connection))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
2015-01-16 16:43:48 +01:00
|
|
|
* nm_device_check_connection_available():
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice
|
2014-05-20 15:03:27 -05:00
|
|
|
* @connection: the #NMConnection to check for availability
|
2015-01-16 16:43:48 +01:00
|
|
|
* @flags: flags to affect the decision making of whether a connection
|
|
|
|
|
* is available. Adding a flag can only make a connection more available,
|
|
|
|
|
* not less.
|
|
|
|
|
* @specific_object: a device type dependent argument to further
|
|
|
|
|
* filter the result. Passing a non %NULL specific object can only reduce
|
|
|
|
|
* the availability of a connection.
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
2015-01-16 16:43:48 +01:00
|
|
|
* Check if @connection is available to be activated on @self.
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Returns: %TRUE if @connection can be activated on @self
|
2014-05-20 15:03:27 -05:00
|
|
|
*/
|
|
|
|
|
gboolean
|
2015-01-16 16:43:48 +01:00
|
|
|
nm_device_check_connection_available (NMDevice *self,
|
|
|
|
|
NMConnection *connection,
|
|
|
|
|
NMDeviceCheckConAvailableFlags flags,
|
|
|
|
|
const char *specific_object)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2015-10-05 13:42:24 +02:00
|
|
|
gboolean available;
|
2014-12-08 12:15:02 +01:00
|
|
|
|
2015-10-05 13:42:24 +02:00
|
|
|
available = _nm_device_check_connection_available (self, connection, flags, specific_object);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2015-10-05 13:42:24 +02:00
|
|
|
#if NM_MORE_ASSERTS >= 2
|
|
|
|
|
{
|
|
|
|
|
/* The meaning of the flags is so that *adding* a flag relaxes a condition, thus making
|
|
|
|
|
* the device *more* available. Assert against that requirement by testing all the flags. */
|
|
|
|
|
NMDeviceCheckConAvailableFlags i, j, k;
|
|
|
|
|
gboolean available_all[NM_DEVICE_CHECK_CON_AVAILABLE_ALL + 1] = { FALSE };
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; i++)
|
|
|
|
|
available_all[i] = _nm_device_check_connection_available (self, connection, i, specific_object);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; i++) {
|
|
|
|
|
for (j = 1; j <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; j <<= 1) {
|
|
|
|
|
if (NM_FLAGS_HAS (i, j)) {
|
|
|
|
|
k = i & ~j;
|
|
|
|
|
nm_assert ( available_all[i] == available_all[k]
|
|
|
|
|
|| available_all[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2015-10-05 13:42:24 +02:00
|
|
|
return available;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
2016-01-20 17:44:50 +01:00
|
|
|
static gboolean
|
|
|
|
|
available_connections_del_all (NMDevice *self)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-09-05 16:55:07 +02:00
|
|
|
if (g_hash_table_size (self->_priv->available_connections) == 0)
|
2016-01-20 17:44:50 +01:00
|
|
|
return FALSE;
|
2016-09-05 16:55:07 +02:00
|
|
|
g_hash_table_remove_all (self->_priv->available_connections);
|
2016-01-20 17:44:50 +01:00
|
|
|
return TRUE;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2016-01-20 17:44:50 +01:00
|
|
|
available_connections_add (NMDevice *self, NMConnection *connection)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-09-05 16:55:07 +02:00
|
|
|
return nm_g_hash_table_add (self->_priv->available_connections, g_object_ref (connection));
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static gboolean
|
2016-01-20 17:44:50 +01:00
|
|
|
available_connections_del (NMDevice *self, NMConnection *connection)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-09-05 16:55:07 +02:00
|
|
|
return g_hash_table_remove (self->_priv->available_connections, connection);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
check_connection_available (NMDevice *self,
|
2014-05-20 15:03:27 -05:00
|
|
|
NMConnection *connection,
|
2015-01-16 14:54:11 +01:00
|
|
|
NMDeviceCheckConAvailableFlags flags,
|
2014-05-20 15:03:27 -05:00
|
|
|
const char *specific_object)
|
|
|
|
|
{
|
2014-12-08 12:50:10 +01:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Connections which require a network connection are not available when
|
|
|
|
|
* the device has no carrier, even with ignore-carrer=TRUE.
|
|
|
|
|
*/
|
2014-12-08 12:50:10 +01:00
|
|
|
if ( priv->carrier
|
|
|
|
|
|| !connection_requires_carrier (connection))
|
|
|
|
|
return TRUE;
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-12-08 12:50:10 +01:00
|
|
|
if ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
|
|
|
|
|
&& priv->carrier_wait_id != 0) {
|
|
|
|
|
/* The device has no carrier though the connection requires it.
|
|
|
|
|
*
|
|
|
|
|
* If we are still waiting for carrier, the connection is available
|
|
|
|
|
* for an explicit user-request. */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-02 00:01:26 +02:00
|
|
|
/* master types are always available even without carrier.
|
|
|
|
|
* Making connection non-available would un-enslave slaves which
|
|
|
|
|
* is not desired. */
|
|
|
|
|
if (nm_device_is_master (self))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2014-12-08 12:50:10 +01:00
|
|
|
return FALSE;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_recheck_available_connections (NMDevice *self)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2016-05-16 18:40:44 +02:00
|
|
|
NMSettingsConnection *const*connections;
|
2016-01-20 17:44:50 +01:00
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
GHashTableIter h_iter;
|
|
|
|
|
NMConnection *connection;
|
2016-05-16 18:40:44 +02:00
|
|
|
guint i;
|
|
|
|
|
gs_unref_hashtable GHashTable *prune_list = NULL;
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE(self);
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
if (g_hash_table_size (priv->available_connections) > 0) {
|
|
|
|
|
prune_list = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
|
g_hash_table_iter_init (&h_iter, priv->available_connections);
|
|
|
|
|
while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL))
|
|
|
|
|
g_hash_table_add (prune_list, connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connections = nm_settings_get_connections (priv->settings, NULL);
|
|
|
|
|
for (i = 0; connections[i]; i++) {
|
|
|
|
|
connection = (NMConnection *) connections[i];
|
|
|
|
|
|
|
|
|
|
if (nm_device_check_connection_available (self,
|
|
|
|
|
connection,
|
|
|
|
|
NM_DEVICE_CHECK_CON_AVAILABLE_NONE,
|
|
|
|
|
NULL)) {
|
|
|
|
|
if (available_connections_add (self, connection))
|
|
|
|
|
changed = TRUE;
|
|
|
|
|
if (prune_list)
|
|
|
|
|
g_hash_table_remove (prune_list, connection);
|
2016-01-20 17:44:50 +01:00
|
|
|
}
|
2016-05-16 18:40:44 +02:00
|
|
|
}
|
2016-01-20 17:44:50 +01:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
if (prune_list) {
|
|
|
|
|
g_hash_table_iter_init (&h_iter, prune_list);
|
|
|
|
|
while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) {
|
|
|
|
|
if (available_connections_del (self, connection))
|
|
|
|
|
changed = TRUE;
|
2016-01-20 17:44:50 +01:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2016-01-19 11:33:33 +01:00
|
|
|
|
2016-02-15 21:14:22 +01:00
|
|
|
if (changed)
|
2016-04-13 14:59:43 +02:00
|
|
|
_notify (self, PROP_AVAILABLE_CONNECTIONS);
|
2016-02-15 21:14:22 +01:00
|
|
|
available_connections_check_delete_unrealized (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2012-05-14 15:32:54 +02:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
2016-03-23 10:35:55 +01:00
|
|
|
* nm_device_get_best_connection:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice
|
2014-05-20 15:03:27 -05:00
|
|
|
* @specific_object: a specific object path if any
|
2016-03-23 10:35:55 +01:00
|
|
|
* @error: reason why no connection was returned
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
2016-03-23 10:35:55 +01:00
|
|
|
* Returns a connection that's most suitable for user-initiated activation
|
|
|
|
|
* of a device, optionally with a given specific object.
|
2014-05-20 15:03:27 -05:00
|
|
|
*
|
2016-03-23 10:35:55 +01:00
|
|
|
* Returns: the #NMSettingsConnection or %NULL (setting an @error)
|
2014-05-20 15:03:27 -05:00
|
|
|
*/
|
2016-03-23 10:35:55 +01:00
|
|
|
NMSettingsConnection *
|
|
|
|
|
nm_device_get_best_connection (NMDevice *self,
|
|
|
|
|
const char *specific_object,
|
|
|
|
|
GError **error)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-03-23 10:35:55 +01:00
|
|
|
NMSettingsConnection *connection = NULL;
|
|
|
|
|
NMSettingsConnection *candidate;
|
|
|
|
|
guint64 best_timestamp = 0;
|
2014-05-20 15:03:27 -05:00
|
|
|
GHashTableIter iter;
|
2016-03-23 10:35:55 +01:00
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, priv->available_connections);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer) &candidate, NULL)) {
|
|
|
|
|
guint64 candidate_timestamp = 0;
|
|
|
|
|
|
|
|
|
|
/* If a specific object is given, only include connections that are
|
|
|
|
|
* compatible with it.
|
|
|
|
|
*/
|
|
|
|
|
if ( specific_object /* << Optimization: we know that the connection is available without @specific_object. */
|
|
|
|
|
&& !nm_device_check_connection_available (self,
|
|
|
|
|
NM_CONNECTION (candidate),
|
|
|
|
|
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
|
|
|
|
|
specific_object))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
nm_settings_connection_get_timestamp (candidate, &candidate_timestamp);
|
|
|
|
|
if (!connection || (candidate_timestamp > best_timestamp)) {
|
|
|
|
|
connection = candidate;
|
|
|
|
|
best_timestamp = candidate_timestamp;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-23 10:35:55 +01:00
|
|
|
|
|
|
|
|
if (!connection) {
|
|
|
|
|
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
|
|
|
|
"The device '%s' has no connections available for activation.",
|
|
|
|
|
nm_device_get_iface (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return connection;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
2016-05-16 18:40:44 +02:00
|
|
|
cp_connection_added_or_updated (NMDevice *self, NMConnection *connection)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-01-20 17:44:50 +01:00
|
|
|
gboolean changed;
|
2016-01-14 18:18:25 +01:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2016-01-20 17:44:50 +01:00
|
|
|
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
|
2016-01-14 18:18:25 +01:00
|
|
|
|
2016-01-20 17:44:50 +01:00
|
|
|
if (nm_device_check_connection_available (self,
|
|
|
|
|
connection,
|
2016-01-20 17:59:26 +01:00
|
|
|
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST,
|
2016-01-20 17:44:50 +01:00
|
|
|
NULL))
|
|
|
|
|
changed = available_connections_add (self, connection);
|
|
|
|
|
else
|
|
|
|
|
changed = available_connections_del (self, connection);
|
2016-01-14 18:18:25 +01:00
|
|
|
|
2016-01-20 17:44:50 +01:00
|
|
|
if (changed) {
|
2016-04-13 14:59:43 +02:00
|
|
|
_notify (self, PROP_AVAILABLE_CONNECTIONS);
|
2016-01-20 18:02:34 +01:00
|
|
|
available_connections_check_delete_unrealized (self);
|
2016-01-14 18:04:42 +01:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
static void
|
|
|
|
|
cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
cp_connection_added_or_updated (user_data, connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gboolean by_user, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
cp_connection_added_or_updated (user_data, connection);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
2016-01-20 17:44:50 +01:00
|
|
|
cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-01-14 18:18:25 +01:00
|
|
|
NMDevice *self = user_data;
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2016-01-14 18:18:25 +01:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
2016-01-20 17:44:50 +01:00
|
|
|
if (available_connections_del (self, connection)) {
|
2016-04-13 14:59:43 +02:00
|
|
|
_notify (self, PROP_AVAILABLE_CONNECTIONS);
|
2016-01-20 18:02:34 +01:00
|
|
|
available_connections_check_delete_unrealized (self);
|
2016-01-14 18:04:42 +01:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2013-01-24 17:47:59 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_supports_vlans (NMDevice *self)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2017-04-17 20:17:45 +02:00
|
|
|
return nm_platform_link_supports_vlans (nm_device_get_platform (self), nm_device_get_ifindex (self));
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2014-01-02 14:46:02 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_add_pending_action():
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice to add the pending action to
|
2017-01-27 15:41:25 +01:00
|
|
|
* @action: a static string that identifies the action. The string instance must
|
|
|
|
|
* stay valid until the pending action is removed (that is, the string is
|
|
|
|
|
* not cloned, but ownership stays with the caller).
|
2014-05-20 15:03:27 -05:00
|
|
|
* @assert_not_yet_pending: if %TRUE, assert that the @action is currently not yet pending.
|
|
|
|
|
* Otherwise, ignore duplicate scheduling of the same action silently.
|
|
|
|
|
*
|
|
|
|
|
* Adds a pending action to the device.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the action was added (and not already added before). %FALSE
|
|
|
|
|
* if the same action is already scheduled. In the latter case, the action was not scheduled
|
|
|
|
|
* a second time.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_add_pending_action (NMDevice *self, const char *action, gboolean assert_not_yet_pending)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
GSList *iter;
|
|
|
|
|
guint count = 0;
|
2013-05-01 09:28:16 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
g_return_val_if_fail (action, FALSE);
|
2013-08-13 17:45:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Check if the action is already pending. Cannot add duplicate actions */
|
|
|
|
|
for (iter = priv->pending_actions; iter; iter = iter->next) {
|
|
|
|
|
if (!strcmp (action, iter->data)) {
|
|
|
|
|
if (assert_not_yet_pending) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DEVICE, "add_pending_action (%d): '%s' already pending",
|
|
|
|
|
count + g_slist_length (iter), action);
|
2014-05-20 15:03:27 -05:00
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
} else {
|
2017-05-12 16:48:57 +02:00
|
|
|
_LOGT (LOGD_DEVICE, "add_pending_action (%d): '%s' already pending (expected)",
|
2014-02-12 23:54:26 +01:00
|
|
|
count + g_slist_length (iter), action);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
count++;
|
|
|
|
|
}
|
2011-11-18 00:09:37 -06:00
|
|
|
|
2017-02-02 12:09:48 +01:00
|
|
|
priv->pending_actions = g_slist_prepend (priv->pending_actions, (char *) action);
|
2014-05-20 15:03:27 -05:00
|
|
|
count++;
|
2011-11-18 00:05:37 -06:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "add_pending_action (%d): '%s'", count, action);
|
2012-06-01 15:27:39 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
if (count == 1)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_HAS_PENDING_ACTION);
|
2012-05-29 09:56:50 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2012-05-29 09:56:50 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/**
|
|
|
|
|
* nm_device_remove_pending_action():
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: the #NMDevice to remove the pending action from
|
2017-01-27 15:41:25 +01:00
|
|
|
* @action: a string that identifies the action.
|
2014-05-20 15:03:27 -05:00
|
|
|
* @assert_is_pending: if %TRUE, assert that the @action is pending.
|
|
|
|
|
* If %FALSE, don't do anything if the current action is not pending and
|
|
|
|
|
* return %FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Removes a pending action previously added by nm_device_add_pending_action().
|
|
|
|
|
*
|
|
|
|
|
* Returns: whether the @action was pending and is now removed.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean assert_is_pending)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2016-03-04 08:46:51 +01:00
|
|
|
NMDevicePrivate *priv;
|
2015-11-05 16:19:01 +01:00
|
|
|
GSList *iter, *next;
|
2014-05-20 15:03:27 -05:00
|
|
|
guint count = 0;
|
2014-02-10 08:49:47 -06:00
|
|
|
|
2016-03-04 08:46:51 +01:00
|
|
|
g_return_val_if_fail (self, FALSE);
|
2014-05-20 15:03:27 -05:00
|
|
|
g_return_val_if_fail (action, FALSE);
|
2014-02-24 18:10:18 -06:00
|
|
|
|
2016-03-04 08:46:51 +01:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-11-05 16:19:01 +01:00
|
|
|
for (iter = priv->pending_actions; iter; iter = next) {
|
|
|
|
|
next = iter->next;
|
2014-05-20 15:03:27 -05:00
|
|
|
if (!strcmp (action, iter->data)) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "remove_pending_action (%d): '%s'",
|
|
|
|
|
count + g_slist_length (iter->next), /* length excluding 'iter' */
|
|
|
|
|
action);
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter);
|
|
|
|
|
if (priv->pending_actions == NULL)
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_HAS_PENDING_ACTION);
|
2014-05-20 15:03:27 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
count++;
|
|
|
|
|
}
|
2014-05-28 10:18:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
if (assert_is_pending) {
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending", count, action);
|
2014-05-20 15:03:27 -05:00
|
|
|
g_return_val_if_reached (FALSE);
|
2014-02-12 23:54:26 +01:00
|
|
|
} else
|
2017-05-12 16:48:57 +02:00
|
|
|
_LOGT (LOGD_DEVICE, "remove_pending_action (%d): '%s' not pending (expected)", count, action);
|
2014-02-12 23:54:26 +01:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
2011-11-18 00:34:08 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_has_pending_action (NMDevice *self)
|
2014-05-20 15:03:27 -05:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-03-13 18:45:36 +01:00
|
|
|
if (priv->pending_actions)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2017-09-29 17:08:55 +02:00
|
|
|
if ( nm_device_is_real (self)
|
|
|
|
|
&& nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
|
2017-03-13 18:45:36 +01:00
|
|
|
/* as long as the platform link is not yet initialized, we have a pending
|
|
|
|
|
* action. */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2014-05-22 14:51:55 -05:00
|
|
|
static void
|
2015-02-03 16:15:37 +01:00
|
|
|
_cancel_activation (NMDevice *self)
|
2014-05-22 14:51:55 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2014-07-02 15:19:58 +02:00
|
|
|
if (priv->fw_call) {
|
2015-09-23 17:18:44 +02:00
|
|
|
nm_firewall_manager_cancel_call (priv->fw_call);
|
2017-05-03 18:34:17 +02:00
|
|
|
nm_assert (!priv->fw_call);
|
2014-07-02 15:19:58 +02:00
|
|
|
priv->fw_call = NULL;
|
2017-05-03 18:34:17 +02:00
|
|
|
priv->fw_state = FIREWALL_STATE_INITIALIZED;
|
2014-07-02 15:19:58 +02:00
|
|
|
}
|
2014-05-22 14:51:55 -05:00
|
|
|
|
2015-02-03 16:15:37 +01:00
|
|
|
ip_check_gw_ping_cleanup (self);
|
|
|
|
|
|
|
|
|
|
/* Break the activation chain */
|
2015-10-06 11:05:14 +02:00
|
|
|
activation_source_clear (self, AF_INET);
|
|
|
|
|
activation_source_clear (self, AF_INET6);
|
2015-02-03 16:15:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-06-30 16:13:03 +02:00
|
|
|
_cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type)
|
2015-02-03 16:15:37 +01:00
|
|
|
{
|
2017-05-03 18:34:17 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-02-03 16:15:37 +01:00
|
|
|
|
|
|
|
|
_cancel_activation (self);
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE
|
2017-05-03 18:34:17 +02:00
|
|
|
&& priv->fw_state >= FIREWALL_STATE_INITIALIZED
|
|
|
|
|
&& priv->fw_mgr
|
2017-03-13 15:34:14 +01:00
|
|
|
&& !nm_device_sys_iface_state_is_external (self)) {
|
2017-05-03 18:34:17 +02:00
|
|
|
nm_firewall_manager_remove_from_zone (priv->fw_mgr,
|
2014-07-02 15:19:58 +02:00
|
|
|
nm_device_get_ip_iface (self),
|
2015-09-23 17:18:44 +02:00
|
|
|
NULL,
|
|
|
|
|
NULL,
|
2014-07-02 15:19:58 +02:00
|
|
|
NULL);
|
2014-05-22 14:51:55 -05:00
|
|
|
}
|
2017-05-03 18:34:17 +02:00
|
|
|
priv->fw_state = FIREWALL_STATE_UNMANAGED;
|
|
|
|
|
g_clear_object (&priv->fw_mgr);
|
2014-05-22 14:51:55 -05:00
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
queued_state_clear (self);
|
2014-05-22 14:51:55 -05:00
|
|
|
|
2015-11-21 12:28:09 +01:00
|
|
|
_cleanup_ip4_pre (self, cleanup_type);
|
|
|
|
|
_cleanup_ip6_pre (self, cleanup_type);
|
2014-05-22 14:51:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-06-30 16:13:03 +02:00
|
|
|
_cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
2014-05-22 14:51:55 -05:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-07-22 11:40:35 +02:00
|
|
|
priv->v4_commit_first_time = TRUE;
|
|
|
|
|
priv->v6_commit_first_time = TRUE;
|
2014-08-29 00:03:47 +02:00
|
|
|
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
priv->v4_route_table_initalized = FALSE;
|
|
|
|
|
priv->v6_route_table_initalized = FALSE;
|
|
|
|
|
|
2017-10-04 15:21:21 +02:00
|
|
|
priv->default_route_metric_penalty_ip4_has = FALSE;
|
|
|
|
|
priv->default_route_metric_penalty_ip6_has = FALSE;
|
|
|
|
|
|
2015-10-03 19:44:27 +02:00
|
|
|
priv->linklocal6_dad_counter = 0;
|
|
|
|
|
|
2016-04-04 12:52:56 +02:00
|
|
|
/* Clean up IP configs; this does not actually deconfigure the
|
|
|
|
|
* interface; the caller must flush routes and addresses explicitly.
|
|
|
|
|
*/
|
2017-09-12 13:45:53 +02:00
|
|
|
nm_device_set_ip4_config (self, NULL, TRUE, NULL);
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
nm_device_set_ip6_config (self, NULL, TRUE);
|
2016-08-16 05:55:58 +05:30
|
|
|
g_clear_object (&priv->proxy_config);
|
2014-11-21 13:13:48 +01:00
|
|
|
g_clear_object (&priv->con_ip4_config);
|
2014-05-22 14:51:55 -05:00
|
|
|
g_clear_object (&priv->dev_ip4_config);
|
|
|
|
|
g_clear_object (&priv->ext_ip4_config);
|
2014-07-15 17:16:56 -05:00
|
|
|
g_clear_object (&priv->wwan_ip4_config);
|
2014-05-22 14:51:55 -05:00
|
|
|
g_clear_object (&priv->ip4_config);
|
2014-11-21 13:13:48 +01:00
|
|
|
g_clear_object (&priv->con_ip6_config);
|
2014-05-22 14:51:55 -05:00
|
|
|
g_clear_object (&priv->ac_ip6_config);
|
|
|
|
|
g_clear_object (&priv->ext_ip6_config);
|
2016-01-30 21:37:22 +01:00
|
|
|
g_clear_object (&priv->ext_ip6_config_captured);
|
2013-10-15 21:03:42 -05:00
|
|
|
g_clear_object (&priv->wwan_ip6_config);
|
2014-05-22 14:51:55 -05:00
|
|
|
g_clear_object (&priv->ip6_config);
|
2016-03-14 18:37:57 +01:00
|
|
|
g_clear_object (&priv->dad6_ip6_config);
|
2014-05-22 14:51:55 -05:00
|
|
|
|
2017-09-13 16:45:22 +02:00
|
|
|
g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref);
|
|
|
|
|
nm_clear_g_source (&priv->rt6_temporary_not_available_id);
|
|
|
|
|
|
2015-08-19 23:07:13 +02:00
|
|
|
g_slist_free_full (priv->vpn4_configs, g_object_unref);
|
|
|
|
|
priv->vpn4_configs = NULL;
|
|
|
|
|
g_slist_free_full (priv->vpn6_configs, g_object_unref);
|
|
|
|
|
priv->vpn6_configs = NULL;
|
|
|
|
|
|
2017-04-27 15:37:14 +02:00
|
|
|
/* We no longer accept the delegations. nm_device_set_ip6_config(NULL)
|
|
|
|
|
* above disables them. */
|
|
|
|
|
nm_assert (priv->needs_ip6_subnet == FALSE);
|
2016-11-03 12:05:12 +01:00
|
|
|
|
2017-01-24 19:43:52 +01:00
|
|
|
if (priv->act_request) {
|
|
|
|
|
nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
|
|
|
|
|
|
|
|
|
|
priv->master_ready_handled = FALSE;
|
|
|
|
|
nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
|
|
|
|
|
|
|
|
|
|
act_request_set (self, NULL);
|
|
|
|
|
}
|
2014-05-22 14:51:55 -05:00
|
|
|
|
|
|
|
|
/* Clear legacy IPv4 address property */
|
|
|
|
|
if (priv->ip4_address) {
|
|
|
|
|
priv->ip4_address = 0;
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP4_ADDRESS);
|
2014-05-22 14:51:55 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
2014-05-22 14:51:55 -05:00
|
|
|
/* Check if the device was deactivated, and if so, delete_link.
|
|
|
|
|
* Don't call delete_link synchronously because we are currently
|
|
|
|
|
* handling a state change -- which is not reentrant. */
|
|
|
|
|
delete_on_deactivate_check_and_schedule (self, nm_device_get_ip_ifindex (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ip_iface should be cleared after flushing all routes and addreses, since
|
|
|
|
|
* those are identified by ip_iface, not by iface (which might be a tty
|
|
|
|
|
* or ATM device).
|
|
|
|
|
*/
|
|
|
|
|
nm_device_set_ip_iface (self, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/*
|
|
|
|
|
* nm_device_cleanup
|
|
|
|
|
*
|
|
|
|
|
* Remove a device's routing table entries and IP addresses.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2015-06-30 16:13:03 +02:00
|
|
|
nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType cleanup_type)
|
2010-05-25 10:52:25 -07:00
|
|
|
{
|
2010-07-01 10:32:11 -07:00
|
|
|
NMDevicePrivate *priv;
|
2014-05-20 15:03:27 -05:00
|
|
|
int ifindex;
|
2010-07-01 10:32:11 -07:00
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
2010-05-25 10:52:25 -07:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
if (reason == NM_DEVICE_STATE_REASON_NOW_MANAGED)
|
2015-04-17 13:47:10 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "preparing device");
|
2014-02-12 23:54:26 +01:00
|
|
|
else
|
2015-04-17 13:47:10 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "deactivating device (reason '%s') [%d]", reason_to_string (reason), reason);
|
2010-05-25 10:52:25 -07:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Save whether or not we tried IPv6 for later */
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2010-07-01 10:32:11 -07:00
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
_cleanup_generic_pre (self, cleanup_type);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
|
|
|
|
/* Turn off kernel IPv6 */
|
2015-06-30 16:13:03 +02:00
|
|
|
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
2015-03-16 18:19:05 +01:00
|
|
|
set_disable_ipv6 (self, "1");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra", "0");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0");
|
|
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
|
|
|
|
|
/* Call device type-specific deactivation */
|
|
|
|
|
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
|
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
|
2017-04-18 14:46:27 +02:00
|
|
|
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
2016-08-09 15:34:34 +02:00
|
|
|
/* master: release slaves */
|
|
|
|
|
nm_device_master_release_slaves (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-08-09 15:34:34 +02:00
|
|
|
/* Take out any entries in the routing table and any IP address the device had. */
|
|
|
|
|
if (ifindex > 0) {
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
NMPlatform *platform = nm_device_get_platform (self);
|
|
|
|
|
|
|
|
|
|
nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex);
|
|
|
|
|
nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex);
|
2016-08-09 15:34:34 +02:00
|
|
|
}
|
2011-05-03 11:57:26 -05:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
|
platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags
NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`.
Using that form of RTM_NEWROUTE message, we could only add a certain
route with a certain network/plen,metric triple once. That was already
hugely inconvenient, because
- when configuring routes, multiple (managed) interfaces may get
conflicting routes (multihoming). Only one of the routes can be actually
configured using `ip route replace`, so we need to track routes that are
currently shadowed.
- when configuring routes, we might replace externally configured
routes on unmanaged interfaces. We should not interfere with such
routes.
That was worked around by having NMRouteManager (and NMDefaultRouteManager).
NMRouteManager would keep a list of the routes which NetworkManager would like
to configure, even if momentarily being unable to do so due to conflicting routes.
This worked mostly well but was complicated. It involved bumping metrics to
avoid conflicts for device routes, as we might require them for gateway routes.
Drop that now. Instead, use the corresponding of `ip route append` to configure
routes. This allows NetworkManager to confiure (almost) all routes that we care.
Especially, it can configure all routes on a managed interface, without
replacing/interfering with routes on other interfaces. Hence, NMRouteManager
becomes obsolete.
It practice it is a bit more complicated because:
- when adding an IPv4 address, kernel will automatically create a device route
for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for
IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4
addresses yet (and we don't require such a kernel yet), we still need functionality
similar to nm_route_manager_ip4_route_register_device_route_purge_list().
This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set().
- trying to configure an IPv6 route with a source address will be rejected
by kernel as long as the address is tentative (see related bug rh#1457196).
Preferably, NMDevice would keep the list of routes which should be configured,
while kernel would have the list of what actually is configured. There is a
feed-back loop where both affect each other (for example, when externally deleting
a route, NMDevice must forget about it too). Previously, NMRouteManager would have
the task of remembering all routes which we currently want to configure, but cannot
due to conflicting routes.
We get rid of that, because now we configure non-exclusive routes. We however still
will need to remember IPv6 routes with a source address, that currently cannot be
configured yet. Hence, we will need to keep track of routes that
currently cannot be configured, but later may be.
That is still not done yet, as NMRouteManager didn't handle this
correctly either.
2017-08-14 14:18:53 +02:00
|
|
|
if (ifindex > 0)
|
|
|
|
|
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), ifindex, NULL);
|
|
|
|
|
|
2017-05-08 21:22:00 +02:00
|
|
|
/* slave: mark no longer enslaved */
|
|
|
|
|
if ( priv->master
|
|
|
|
|
&& nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0)
|
|
|
|
|
nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
|
|
|
|
|
2015-10-07 11:48:38 +02:00
|
|
|
if (priv->lldp_listener)
|
|
|
|
|
nm_lldp_listener_stop (priv->lldp_listener);
|
|
|
|
|
|
2015-04-30 14:18:14 +02:00
|
|
|
nm_device_update_metered (self);
|
2016-06-30 11:42:28 +02:00
|
|
|
|
|
|
|
|
/* during device cleanup, we want to reset the MAC address of the device
|
|
|
|
|
* to the initial state.
|
|
|
|
|
*
|
|
|
|
|
* We certainly want to do that when reaching the UNMANAGED state... */
|
|
|
|
|
if (nm_device_get_state (self) <= NM_DEVICE_STATE_UNMANAGED)
|
|
|
|
|
nm_device_hw_addr_reset (self, "unmanage");
|
|
|
|
|
else {
|
|
|
|
|
/* for other device states (UNAVAILABLE, DISCONNECTED), allow the
|
|
|
|
|
* device to overwrite the reset behavior, so that Wi-Fi can set
|
|
|
|
|
* a randomized MAC address used during scanning. */
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->deactivate_reset_hw_addr (self);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-16 12:18:51 +01:00
|
|
|
priv->mtu_initialized = FALSE;
|
2017-01-16 10:20:26 +01:00
|
|
|
if (priv->mtu_initial || priv->ip6_mtu_initial) {
|
|
|
|
|
ifindex = nm_device_get_ip_ifindex (self);
|
|
|
|
|
|
|
|
|
|
if ( ifindex > 0
|
|
|
|
|
&& cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
|
|
|
|
_LOGT (LOGD_DEVICE, "mtu: reset device-mtu: %u, ipv6-mtu: %u, ifindex: %d",
|
|
|
|
|
(guint) priv->mtu_initial, (guint) priv->ip6_mtu_initial, ifindex);
|
2017-09-02 17:26:53 +02:00
|
|
|
if (priv->mtu_initial) {
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_set_mtu (nm_device_get_platform (self), ifindex, priv->mtu_initial);
|
2017-09-02 17:26:53 +02:00
|
|
|
priv->carrier_wait_until_ms = nm_utils_get_monotonic_timestamp_ms () + CARRIER_WAIT_TIME_AFTER_MTU_MS;
|
|
|
|
|
}
|
2017-01-16 10:20:26 +01:00
|
|
|
if (priv->ip6_mtu_initial) {
|
|
|
|
|
char sbuf[64];
|
|
|
|
|
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "mtu",
|
|
|
|
|
nm_sprintf_buf (sbuf, "%u", (unsigned) priv->ip6_mtu_initial));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
priv->mtu_initial = 0;
|
|
|
|
|
priv->ip6_mtu_initial = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
_cleanup_generic_post (self, cleanup_type);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
2016-06-30 11:42:28 +02:00
|
|
|
static void
|
|
|
|
|
deactivate_reset_hw_addr (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
nm_device_hw_addr_reset (self, "deactivate");
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-29 09:12:18 -05:00
|
|
|
static char *
|
|
|
|
|
find_dhcp4_address (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-07-07 23:34:41 +02:00
|
|
|
const NMPlatformIP4Address *a;
|
|
|
|
|
NMDedupMultiIter ipconf_iter;
|
2014-10-29 09:12:18 -05:00
|
|
|
|
|
|
|
|
if (!priv->ip4_config)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2017-07-07 23:34:41 +02:00
|
|
|
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip4_config, &a) {
|
2016-04-11 13:09:52 +02:00
|
|
|
if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP)
|
2014-10-29 09:12:18 -05:00
|
|
|
return g_strdup (nm_utils_inet4_ntop (a->address, NULL));
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_spawn_iface_helper (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-11-26 21:20:23 +01:00
|
|
|
gboolean configured = FALSE;
|
2014-10-29 09:12:18 -05:00
|
|
|
NMConnection *connection;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
const char *method;
|
|
|
|
|
GPtrArray *argv;
|
|
|
|
|
gs_free char *dhcp4_address = NULL;
|
2015-07-08 19:34:34 +02:00
|
|
|
char *logging_backend;
|
2016-06-21 18:07:56 +02:00
|
|
|
NMUtilsStableType stable_type;
|
|
|
|
|
const char *stable_id;
|
2014-10-29 09:12:18 -05:00
|
|
|
|
|
|
|
|
if (priv->state != NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
return;
|
|
|
|
|
if (!nm_device_can_assume_connections (self))
|
|
|
|
|
return;
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_applied_connection (self);
|
2014-10-29 09:12:18 -05:00
|
|
|
g_assert (connection);
|
|
|
|
|
|
|
|
|
|
argv = g_ptr_array_sized_new (10);
|
|
|
|
|
g_ptr_array_set_free_func (argv, g_free);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (argv, g_strdup (LIBEXECDIR "/nm-iface-helper"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--ifname"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup (nm_device_get_ip_iface (self)));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--uuid"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup (nm_connection_get_uuid (connection)));
|
|
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
stable_id = _get_stable_id (self, connection, &stable_type);
|
2016-06-21 18:07:56 +02:00
|
|
|
if (stable_id && stable_type != NM_UTILS_STABLE_TYPE_UUID) {
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--stable-id"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup_printf ("%d %s", (int) stable_type, stable_id));
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-08 19:34:34 +02:00
|
|
|
logging_backend = nm_config_get_is_debug (nm_config_get ())
|
|
|
|
|
? g_strdup ("debug")
|
|
|
|
|
: nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG,
|
|
|
|
|
NM_CONFIG_KEYFILE_GROUP_LOGGING,
|
|
|
|
|
NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND,
|
|
|
|
|
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
|
|
|
|
|
if (logging_backend) {
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--logging-backend"));
|
|
|
|
|
g_ptr_array_add (argv, logging_backend);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-05 15:40:12 +02:00
|
|
|
g_ptr_array_add (argv, g_strdup ("--log-level"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup (nm_logging_level_to_string ()));
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--log-domains"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup (nm_logging_domains_to_string ()));
|
|
|
|
|
|
2014-10-29 09:12:18 -05:00
|
|
|
dhcp4_address = find_dhcp4_address (self);
|
|
|
|
|
|
|
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
2015-09-11 17:07:23 +02:00
|
|
|
if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) {
|
2014-10-29 09:12:18 -05:00
|
|
|
NMSettingIPConfig *s_ip4;
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
g_assert (s_ip4);
|
|
|
|
|
|
2014-11-26 21:20:23 +01:00
|
|
|
g_ptr_array_add (argv, g_strdup ("--priority4"));
|
2017-09-28 17:14:24 +02:00
|
|
|
g_ptr_array_add (argv, g_strdup_printf ("%u", nm_device_get_route_metric (self, AF_INET)));
|
2014-10-29 09:12:18 -05:00
|
|
|
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--dhcp4"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup (dhcp4_address));
|
|
|
|
|
if (nm_setting_ip_config_get_may_fail (s_ip4) == FALSE)
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--dhcp4-required"));
|
|
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
if (priv->dhcp4.client) {
|
2017-04-26 11:49:30 +02:00
|
|
|
const char *hostname;
|
2015-09-11 17:07:23 +02:00
|
|
|
GBytes *client_id;
|
2014-10-29 09:12:18 -05:00
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
client_id = nm_dhcp_client_get_client_id (priv->dhcp4.client);
|
2015-09-11 17:07:23 +02:00
|
|
|
if (client_id) {
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--dhcp4-clientid"));
|
2016-07-10 13:42:13 +02:00
|
|
|
g_ptr_array_add (argv,
|
|
|
|
|
_nm_utils_bin2str (g_bytes_get_data (client_id, NULL),
|
|
|
|
|
g_bytes_get_size (client_id),
|
|
|
|
|
FALSE));
|
2015-09-11 17:07:23 +02:00
|
|
|
}
|
|
|
|
|
|
2016-04-07 14:34:31 +02:00
|
|
|
hostname = nm_dhcp_client_get_hostname (priv->dhcp4.client);
|
2015-09-11 17:07:23 +02:00
|
|
|
if (hostname) {
|
2017-04-26 11:49:30 +02:00
|
|
|
if (nm_dhcp_client_get_use_fqdn (priv->dhcp4.client))
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn"));
|
|
|
|
|
else
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname"));
|
2015-09-11 17:07:23 +02:00
|
|
|
g_ptr_array_add (argv, g_strdup (hostname));
|
|
|
|
|
}
|
2014-10-29 09:12:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configured = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
2015-09-11 17:07:23 +02:00
|
|
|
if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
2014-10-29 09:12:18 -05:00
|
|
|
NMSettingIPConfig *s_ip6;
|
|
|
|
|
NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
|
|
|
|
|
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
g_assert (s_ip6);
|
|
|
|
|
|
2014-11-26 21:20:23 +01:00
|
|
|
g_ptr_array_add (argv, g_strdup ("--priority6"));
|
2017-09-28 17:14:24 +02:00
|
|
|
g_ptr_array_add (argv, g_strdup_printf ("%u", nm_device_get_route_metric (self, AF_INET6)));
|
2014-11-26 21:20:23 +01:00
|
|
|
|
2014-10-29 09:12:18 -05:00
|
|
|
g_ptr_array_add (argv, g_strdup ("--slaac"));
|
|
|
|
|
|
|
|
|
|
if (nm_setting_ip_config_get_may_fail (s_ip6) == FALSE)
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--slaac-required"));
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (argv, g_strdup ("--slaac-tempaddr"));
|
2016-10-13 11:06:25 +00:00
|
|
|
g_ptr_array_add (argv, g_strdup_printf ("%d", priv->ndisc_use_tempaddr));
|
2014-10-29 09:12:18 -05:00
|
|
|
|
2016-05-11 12:19:28 +02:00
|
|
|
if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) {
|
2014-10-29 09:12:18 -05:00
|
|
|
g_ptr_array_add (argv, g_strdup ("--iid"));
|
2016-07-10 13:42:13 +02:00
|
|
|
g_ptr_array_add (argv,
|
|
|
|
|
_nm_utils_bin2str (iid.id_u8,
|
|
|
|
|
sizeof (NMUtilsIPv6IfaceId),
|
|
|
|
|
FALSE));
|
2014-10-29 09:12:18 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-03 19:44:27 +02:00
|
|
|
g_ptr_array_add (argv, g_strdup ("--addr-gen-mode"));
|
|
|
|
|
g_ptr_array_add (argv, g_strdup_printf ("%d", nm_setting_ip6_config_get_addr_gen_mode (NM_SETTING_IP6_CONFIG (s_ip6))));
|
|
|
|
|
|
2014-10-29 09:12:18 -05:00
|
|
|
configured = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (configured) {
|
|
|
|
|
GPid pid;
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (argv, NULL);
|
|
|
|
|
|
|
|
|
|
if (nm_logging_enabled (LOGL_DEBUG, LOGD_DEVICE)) {
|
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
|
|
tmp = g_strjoinv (" ", (char **) argv->pdata);
|
|
|
|
|
_LOGD (LOGD_DEVICE, "running '%s'", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (g_spawn_async (NULL, (char **) argv->pdata, NULL,
|
|
|
|
|
G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &error)) {
|
|
|
|
|
_LOGI (LOGD_DEVICE, "spawned helper PID %u", (guint) pid);
|
|
|
|
|
} else {
|
|
|
|
|
_LOGW (LOGD_DEVICE, "failed to spawn helper: %s", error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_ptr_array_unref (argv);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-05-20 15:03:27 -05:00
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
ip_config_valid (NMDeviceState state)
|
|
|
|
|
{
|
|
|
|
|
return (state == NM_DEVICE_STATE_UNMANAGED) ||
|
|
|
|
|
(state >= NM_DEVICE_STATE_IP_CHECK &&
|
|
|
|
|
state <= NM_DEVICE_STATE_DEACTIVATING);
|
2011-05-03 11:57:26 -05:00
|
|
|
}
|
|
|
|
|
|
2013-10-09 13:55:05 -05:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
notify_ip_properties (NMDevice *self)
|
2013-10-09 13:55:05 -05:00
|
|
|
{
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_IP_IFACE);
|
|
|
|
|
_notify (self, PROP_IP4_CONFIG);
|
|
|
|
|
_notify (self, PROP_DHCP4_CONFIG);
|
|
|
|
|
_notify (self, PROP_IP6_CONFIG);
|
|
|
|
|
_notify (self, PROP_DHCP6_CONFIG);
|
2013-10-09 13:55:05 -05:00
|
|
|
}
|
|
|
|
|
|
2014-12-03 12:47:30 -06:00
|
|
|
static void
|
|
|
|
|
ip6_managed_setup (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
set_nm_ipv6ll (self, TRUE);
|
|
|
|
|
set_disable_ipv6 (self, "1");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
|
|
|
|
|
nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0");
|
2016-11-03 12:15:32 +01:00
|
|
|
nm_device_ipv6_sysctl_set (self, "forwarding", "0");
|
2014-12-03 12:47:30 -06:00
|
|
|
}
|
|
|
|
|
|
2014-08-05 20:08:34 +02:00
|
|
|
static void
|
|
|
|
|
deactivate_async_ready (NMDevice *self,
|
|
|
|
|
GAsyncResult *res,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMDeviceStateReason reason = GPOINTER_TO_UINT (user_data);
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->deactivate_async_finish (self, res, &error);
|
|
|
|
|
|
|
|
|
|
/* If operation cancelled, just return */
|
|
|
|
|
if ( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
|
|
|
|
|
|| (priv->deactivating_cancellable && g_cancellable_is_cancelled (priv->deactivating_cancellable))) {
|
2015-10-05 13:05:05 +02:00
|
|
|
_LOGW (LOGD_DEVICE, "Deactivation cancelled");
|
2017-03-13 11:51:33 +01:00
|
|
|
} else {
|
|
|
|
|
/* In every other case, transition to the DISCONNECTED state */
|
2015-10-05 13:05:05 +02:00
|
|
|
if (error) {
|
|
|
|
|
_LOGW (LOGD_DEVICE, "Deactivation failed: %s",
|
|
|
|
|
error->message);
|
|
|
|
|
}
|
2014-08-05 20:08:34 +02:00
|
|
|
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_clear_object (&priv->deactivating_cancellable);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
deactivate_dispatcher_complete (guint call_id, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMDeviceStateReason reason;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (call_id == priv->dispatcher.call_id);
|
|
|
|
|
g_return_if_fail (priv->dispatcher.post_state == NM_DEVICE_STATE_DISCONNECTED);
|
|
|
|
|
|
|
|
|
|
reason = priv->dispatcher.post_state_reason;
|
|
|
|
|
|
|
|
|
|
priv->dispatcher.call_id = 0;
|
|
|
|
|
priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN;
|
|
|
|
|
priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE;
|
|
|
|
|
|
2017-03-13 11:51:33 +01:00
|
|
|
if (nm_clear_g_cancellable (&priv->deactivating_cancellable))
|
2014-08-05 20:08:34 +02:00
|
|
|
g_warn_if_reached ();
|
|
|
|
|
|
|
|
|
|
if ( NM_DEVICE_GET_CLASS (self)->deactivate_async
|
|
|
|
|
&& NM_DEVICE_GET_CLASS (self)->deactivate_async_finish) {
|
|
|
|
|
priv->deactivating_cancellable = g_cancellable_new ();
|
|
|
|
|
NM_DEVICE_GET_CLASS (self)->deactivate_async (self,
|
|
|
|
|
priv->deactivating_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) deactivate_async_ready,
|
|
|
|
|
GUINT_TO_POINTER (reason));
|
|
|
|
|
} else
|
|
|
|
|
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-23 18:25:05 -05:00
|
|
|
static void
|
2014-07-15 13:36:24 +02:00
|
|
|
_set_state_full (NMDevice *self,
|
2014-05-23 18:25:05 -05:00
|
|
|
NMDeviceState state,
|
|
|
|
|
NMDeviceStateReason reason,
|
|
|
|
|
gboolean quitting)
|
2007-02-05 12:14:09 +00:00
|
|
|
{
|
2015-09-21 16:48:50 +02:00
|
|
|
NMDevicePrivate *priv;
|
2007-03-02 Tambet Ingo <tambet@ximian.com>
* libnm-glib/nm-device-802-11-wireless.c: Cache networks (bssids) list.
We get signalled when it changes.
* libnm-glib/nm-client.c: Cache NMState and device list, we get signalled
when it changes.
* libnm-glib/nm-device.c: Cache the device state property.
* libnm-glib/nm-access-point.c: Cache the strength property.
* src/nm-device-802-11-wireless.c: Fix wireless device scanning scheduler.
The new algorithm is to start from SCAN_INTERVAL_MIN (currently defined as 0)
and add a SCAN_INTERVAL_STEP (currently 20 seconds) with each successful scan
until SCAN_INTERVAL_MAX (currently 120 seconds) is reached. Do not scan while
the device is down, activating, or activated (in case of A/B/G cards).
Remove some old dead ifdef'ed out code that used to configure wireless devices,
it's all done through supplicant now.
* src/supplicant-manager/nm-supplicant-interface.c: Fix the reference
counting issues with pending calls which caused leaks and crashes when
interface was removed (now that the interface actually gets removed).
* src/nm-call-store.c: Make a copy of data before running a foreach
with user callback on it - The most common usage pattern is to cancel
(and thus remove) all pending calls with foreach which would modify
the hash table we're iterating over.
* src/nm-manager.c: When a device is added, make sure it is "up". When
it's removed or disabled due to disabling wireless or networking, bring
it down.
* include/NetworkManager.h: Add new device state NM_DEVICE_STATE_DOWN.
* src/nm-device-802-11-wireless.c:
* src/nm-device-802-3-ethernet.c:
* src/nm-device.c:
- Remove "init" virtual function, all gobjects have a place for that
already (constructor).
- Replace "start" virtual function with "bring_up", devices can be
brought up and down more than just on startup now.
- Add "is_up" virtual function.
- Implement one way to bring a device down instead of previous 4 different
ways, each of witch did something different.
* src/NetworkManagerUtils.c (nm_dev_sock_open): This doesn't need an NMDevice,
all it needs is the device interface.
Get rid of NMData.dev_list (3 members to go).
Get rif of NMData in a lot of places.
* gnome/libnm_glib/libnm_glib.c: Make it compile again.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2395 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-03-02 09:30:48 +00:00
|
|
|
NMDeviceState old_state;
|
2008-04-27 14:30:06 +00:00
|
|
|
NMActRequest *req;
|
2008-08-18 18:29:47 +00:00
|
|
|
gboolean no_firmware = FALSE;
|
2015-07-14 16:53:24 +02:00
|
|
|
NMSettingsConnection *connection;
|
2007-03-02 Tambet Ingo <tambet@ximian.com>
* libnm-glib/nm-device-802-11-wireless.c: Cache networks (bssids) list.
We get signalled when it changes.
* libnm-glib/nm-client.c: Cache NMState and device list, we get signalled
when it changes.
* libnm-glib/nm-device.c: Cache the device state property.
* libnm-glib/nm-access-point.c: Cache the strength property.
* src/nm-device-802-11-wireless.c: Fix wireless device scanning scheduler.
The new algorithm is to start from SCAN_INTERVAL_MIN (currently defined as 0)
and add a SCAN_INTERVAL_STEP (currently 20 seconds) with each successful scan
until SCAN_INTERVAL_MAX (currently 120 seconds) is reached. Do not scan while
the device is down, activating, or activated (in case of A/B/G cards).
Remove some old dead ifdef'ed out code that used to configure wireless devices,
it's all done through supplicant now.
* src/supplicant-manager/nm-supplicant-interface.c: Fix the reference
counting issues with pending calls which caused leaks and crashes when
interface was removed (now that the interface actually gets removed).
* src/nm-call-store.c: Make a copy of data before running a foreach
with user callback on it - The most common usage pattern is to cancel
(and thus remove) all pending calls with foreach which would modify
the hash table we're iterating over.
* src/nm-manager.c: When a device is added, make sure it is "up". When
it's removed or disabled due to disabling wireless or networking, bring
it down.
* include/NetworkManager.h: Add new device state NM_DEVICE_STATE_DOWN.
* src/nm-device-802-11-wireless.c:
* src/nm-device-802-3-ethernet.c:
* src/nm-device.c:
- Remove "init" virtual function, all gobjects have a place for that
already (constructor).
- Replace "start" virtual function with "bring_up", devices can be
brought up and down more than just on startup now.
- Add "is_up" virtual function.
- Implement one way to bring a device down instead of previous 4 different
ways, each of witch did something different.
* src/NetworkManagerUtils.c (nm_dev_sock_open): This doesn't need an NMDevice,
all it needs is the device interface.
Get rid of NMData.dev_list (3 members to go).
Get rif of NMData in a lot of places.
* gnome/libnm_glib/libnm_glib.c: Make it compile again.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2395 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-03-02 09:30:48 +00:00
|
|
|
|
2015-09-21 16:48:50 +02:00
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2012-10-06 12:37:34 -05:00
|
|
|
/* Track re-entry */
|
2013-05-20 16:15:37 -03:00
|
|
|
g_warn_if_fail (priv->in_state_changed == FALSE);
|
2012-10-06 12:37:34 -05:00
|
|
|
|
2015-09-21 16:48:50 +02:00
|
|
|
old_state = priv->state;
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2010-07-01 10:32:11 -07:00
|
|
|
/* Do nothing if state isn't changing, but as a special case allow
|
|
|
|
|
* re-setting UNAVAILABLE if the device is missing firmware so that we
|
|
|
|
|
* can retry device initialization.
|
|
|
|
|
*/
|
|
|
|
|
if ( (priv->state == state)
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
&& ( state != NM_DEVICE_STATE_UNAVAILABLE
|
|
|
|
|
|| !priv->firmware_missing)) {
|
2017-10-06 11:45:38 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "state change: %s -> %s (reason '%s', sys-iface-state: '%s'%s)",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (old_state),
|
|
|
|
|
nm_device_state_to_str (state),
|
2015-09-21 16:48:50 +02:00
|
|
|
reason_to_string (reason),
|
2017-05-19 15:35:29 +02:00
|
|
|
_sys_iface_state_to_str (priv->sys_iface_state),
|
|
|
|
|
priv->firmware_missing ? ", missing firmware" : "");
|
2008-03-24 02:56:25 +00:00
|
|
|
return;
|
2012-10-10 17:30:46 +02:00
|
|
|
}
|
2008-03-24 02:56:25 +00:00
|
|
|
|
2017-10-06 11:45:38 +02:00
|
|
|
_LOGI (LOGD_DEVICE, "state change: %s -> %s (reason '%s', sys-iface-state: '%s')",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (old_state),
|
|
|
|
|
nm_device_state_to_str (state),
|
2014-02-12 23:54:26 +01:00
|
|
|
reason_to_string (reason),
|
2017-05-19 15:35:29 +02:00
|
|
|
_sys_iface_state_to_str (priv->sys_iface_state));
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2015-09-21 16:48:50 +02:00
|
|
|
priv->in_state_changed = TRUE;
|
|
|
|
|
|
|
|
|
|
priv->state = state;
|
|
|
|
|
priv->state_reason = reason;
|
|
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
queued_state_clear (self);
|
2007-06-13 11:58:25 +00:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
dispatcher_cleanup (self);
|
2014-08-05 20:08:34 +02:00
|
|
|
if (priv->deactivating_cancellable)
|
|
|
|
|
g_cancellable_cancel (priv->deactivating_cancellable);
|
2014-05-20 17:10:42 -05:00
|
|
|
|
2008-04-27 14:30:06 +00:00
|
|
|
/* Cache the activation request for the dispatcher */
|
2017-01-24 19:43:52 +01:00
|
|
|
req = nm_g_object_ref (priv->act_request);
|
2008-04-27 14:30:06 +00:00
|
|
|
|
2017-04-18 14:46:27 +02:00
|
|
|
if ( state > NM_DEVICE_STATE_UNMANAGED
|
|
|
|
|
&& state <= NM_DEVICE_STATE_ACTIVATED
|
2017-03-13 15:34:14 +01:00
|
|
|
&& nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_NOW_MANAGED
|
|
|
|
|
&& NM_IN_SET_TYPED (NMDeviceSysIfaceState,
|
|
|
|
|
priv->sys_iface_state,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_ASSUME))
|
|
|
|
|
nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_MANAGED);
|
|
|
|
|
|
2017-11-02 10:56:30 +01:00
|
|
|
if ( state <= NM_DEVICE_STATE_DISCONNECTED
|
|
|
|
|
|| state >= NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
priv->auth_retries = NM_DEVICE_AUTH_RETRIES_UNSET;
|
|
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
if (state > NM_DEVICE_STATE_DISCONNECTED)
|
|
|
|
|
nm_device_assume_state_reset (self);
|
|
|
|
|
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
|
2016-01-20 17:44:50 +01:00
|
|
|
if (available_connections_del_all (self))
|
2016-04-13 14:59:43 +02:00
|
|
|
_notify (self, PROP_AVAILABLE_CONNECTIONS);
|
2016-03-23 14:51:34 +01:00
|
|
|
if (old_state > NM_DEVICE_STATE_UNAVAILABLE)
|
|
|
|
|
_clear_queued_act_request (priv);
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
}
|
2012-08-01 11:16:48 -06:00
|
|
|
|
|
|
|
|
/* Update the available connections list when a device first becomes available */
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
if (state >= NM_DEVICE_STATE_DISCONNECTED && old_state < NM_DEVICE_STATE_DISCONNECTED)
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_recheck_available_connections (self);
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
if (state <= NM_DEVICE_STATE_DISCONNECTED || state > NM_DEVICE_STATE_DEACTIVATING) {
|
|
|
|
|
if (nm_clear_g_free (&priv->current_stable_id))
|
|
|
|
|
_LOGT (LOGD_DEVICE, "stable-id: clear");
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-17 23:04:34 +00:00
|
|
|
/* Handle the new state here; but anything that could trigger
|
|
|
|
|
* another state change should be done below.
|
|
|
|
|
*/
|
2007-02-05 12:14:09 +00:00
|
|
|
switch (state) {
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
case NM_DEVICE_STATE_UNMANAGED:
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_set_firmware_missing (self, FALSE);
|
2013-06-12 10:48:03 -05:00
|
|
|
if (old_state > NM_DEVICE_STATE_UNMANAGED) {
|
2017-03-13 15:34:14 +01:00
|
|
|
if (priv->sys_iface_state != NM_DEVICE_SYS_IFACE_STATE_MANAGED) {
|
|
|
|
|
nm_device_cleanup (self, reason,
|
|
|
|
|
priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_REMOVED
|
|
|
|
|
? CLEANUP_TYPE_REMOVED
|
|
|
|
|
: CLEANUP_TYPE_KEEP);
|
|
|
|
|
} else {
|
2015-03-16 18:19:05 +01:00
|
|
|
/* Clean up if the device is now unmanaged but was activated */
|
|
|
|
|
if (nm_device_get_act_request (self))
|
2015-06-30 16:13:03 +02:00
|
|
|
nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE);
|
2015-03-16 18:19:05 +01:00
|
|
|
nm_device_take_down (self, TRUE);
|
2016-06-21 11:22:07 +02:00
|
|
|
nm_device_hw_addr_reset (self, "unmanage");
|
2015-03-16 18:19:05 +01:00
|
|
|
set_nm_ipv6ll (self, FALSE);
|
|
|
|
|
restore_ip6_properties (self);
|
2017-02-23 15:19:03 +01:00
|
|
|
break;
|
2015-03-16 18:19:05 +01:00
|
|
|
}
|
2013-06-12 10:48:03 -05:00
|
|
|
}
|
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a
conglomeration of hardware state (IFF_UP) and any device-specific things
(supplicant, periodic timers, etc) that the device used to indicate
readiness. Unfortunately, if the hardware was already IFF_UP for some
reason, then the device specific stuff wouldn't get run, and the device
would be stuck.
* src/nm-device.c
src/nm-device.h
- Create hw_is_up, hw_bring_up, and hw_take_down
- Rename bring_down -> take_down
- (real_hw_is_up): check interface flags for IFF_UP
- (nm_device_hw_is_up): let subclasses figure out their own HW state
- (nm_device_is_up): make static; only used locally
- (nm_device_hw_bring_up): update the hardware and IPv4 addresses even
if the device is already up; if the device isn't up, bring it up
- (nm_device_hw_take_down): just take down hardware
- (nm_device_bring_up): bring up HW first, then device specific stuff
- (nm_device_take_down): always deactivate device when called; always
try to take hardware down too
- (nm_device_state_changed): take device down when entering unmanaged
state from a higher state
* src/nm-device-802-11-wireless.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
- (real_take_down, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler,
supplicant_mgr_state_cb_handler): fix some messages
* src/nm-device-802-3-ethernet.c
- (real_hw_is_up, real_hw_bring_up, real_hw_take_down): implement; just
check IFF_UP really
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3618 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-29 15:36:29 +00:00
|
|
|
break;
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
case NM_DEVICE_STATE_UNAVAILABLE:
|
2013-10-24 13:55:06 -04:00
|
|
|
if (old_state == NM_DEVICE_STATE_UNMANAGED) {
|
2014-07-15 13:36:24 +02:00
|
|
|
save_ip6_properties (self);
|
2017-03-13 15:34:14 +01:00
|
|
|
if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED)
|
2014-12-03 12:47:30 -06:00
|
|
|
ip6_managed_setup (self);
|
2013-10-24 13:55:06 -04:00
|
|
|
}
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) {
|
2014-12-05 14:13:28 -06:00
|
|
|
if (old_state == NM_DEVICE_STATE_UNMANAGED || priv->firmware_missing) {
|
|
|
|
|
if (!nm_device_bring_up (self, TRUE, &no_firmware) && no_firmware)
|
2016-10-06 21:28:40 +02:00
|
|
|
_LOGW (LOGD_PLATFORM, "firmware may be missing.");
|
2014-12-05 14:13:28 -06:00
|
|
|
nm_device_set_firmware_missing (self, no_firmware ? TRUE : FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ensure the device gets deactivated in response to stuff like
|
|
|
|
|
* carrier changes or rfkill. But don't deactivate devices that are
|
|
|
|
|
* about to assume a connection since that defeats the purpose of
|
|
|
|
|
* assuming the device's existing connection.
|
|
|
|
|
*
|
|
|
|
|
* Note that we "deactivate" the device even when coming from
|
|
|
|
|
* UNMANAGED, to ensure that it's in a clean state.
|
|
|
|
|
*/
|
2015-06-30 16:13:03 +02:00
|
|
|
nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE);
|
2014-12-05 14:13:28 -06:00
|
|
|
}
|
2009-08-05 18:03:09 -04:00
|
|
|
break;
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
case NM_DEVICE_STATE_DISCONNECTED:
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
if (old_state > NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
/* Ensure devices that previously assumed a connection now have
|
|
|
|
|
* userspace IPv6LL enabled.
|
|
|
|
|
*/
|
2014-07-24 17:14:30 -05:00
|
|
|
set_nm_ipv6ll (self, TRUE);
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE);
|
2014-12-03 12:47:30 -06:00
|
|
|
} else if (old_state < NM_DEVICE_STATE_DISCONNECTED) {
|
2017-03-13 15:34:14 +01:00
|
|
|
if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) {
|
2014-12-03 12:47:30 -06:00
|
|
|
/* Ensure IPv6 is set up as it may not have been done when
|
|
|
|
|
* entering the UNAVAILABLE state depending on the reason.
|
|
|
|
|
*/
|
|
|
|
|
ip6_managed_setup (self);
|
|
|
|
|
}
|
core: bounce disable_ipv6 when setting userspace IPv6 link-local (bgo #740096)
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
2014-11-13 19:52:21 -06:00
|
|
|
}
|
2007-03-02 Tambet Ingo <tambet@ximian.com>
* libnm-glib/nm-device-802-11-wireless.c: Cache networks (bssids) list.
We get signalled when it changes.
* libnm-glib/nm-client.c: Cache NMState and device list, we get signalled
when it changes.
* libnm-glib/nm-device.c: Cache the device state property.
* libnm-glib/nm-access-point.c: Cache the strength property.
* src/nm-device-802-11-wireless.c: Fix wireless device scanning scheduler.
The new algorithm is to start from SCAN_INTERVAL_MIN (currently defined as 0)
and add a SCAN_INTERVAL_STEP (currently 20 seconds) with each successful scan
until SCAN_INTERVAL_MAX (currently 120 seconds) is reached. Do not scan while
the device is down, activating, or activated (in case of A/B/G cards).
Remove some old dead ifdef'ed out code that used to configure wireless devices,
it's all done through supplicant now.
* src/supplicant-manager/nm-supplicant-interface.c: Fix the reference
counting issues with pending calls which caused leaks and crashes when
interface was removed (now that the interface actually gets removed).
* src/nm-call-store.c: Make a copy of data before running a foreach
with user callback on it - The most common usage pattern is to cancel
(and thus remove) all pending calls with foreach which would modify
the hash table we're iterating over.
* src/nm-manager.c: When a device is added, make sure it is "up". When
it's removed or disabled due to disabling wireless or networking, bring
it down.
* include/NetworkManager.h: Add new device state NM_DEVICE_STATE_DOWN.
* src/nm-device-802-11-wireless.c:
* src/nm-device-802-3-ethernet.c:
* src/nm-device.c:
- Remove "init" virtual function, all gobjects have a place for that
already (constructor).
- Replace "start" virtual function with "bring_up", devices can be
brought up and down more than just on startup now.
- Add "is_up" virtual function.
- Implement one way to bring a device down instead of previous 4 different
ways, each of witch did something different.
* src/NetworkManagerUtils.c (nm_dev_sock_open): This doesn't need an NMDevice,
all it needs is the device interface.
Get rid of NMData.dev_list (3 members to go).
Get rif of NMData in a lot of places.
* gnome/libnm_glib/libnm_glib.c: Make it compile again.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2395 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-03-02 09:30:48 +00:00
|
|
|
break;
|
device: re-read initial hw-address before activating connection
Previously, we would only once read the initial hardware address during
device realization.
When a device activates, NetworkManager always sets the MAC address as configured
in the cloned-mac-address setting -- or, if unspecified -- it falls back
to use the permanent hardware-address instead.
Later, when deactivating the device, the MAC address is reset to the
"inital MAC address".
This patch changes, that the "initial MAC address" is re-read every time
before activating the device, contrary to reading it once in the
beginning.
This allows for a user to first start NetworkManager and later change the
MAC address of the device. When activating the device, NM will reset the
MAC address for the time the device is active. But when disconnecting,
it resets to the user-changed value, not the value when NM was started.
https://bugzilla.gnome.org/show_bug.cgi?id=708820
2016-05-20 18:10:51 +02:00
|
|
|
case NM_DEVICE_STATE_PREPARE:
|
|
|
|
|
nm_device_update_initial_hw_address (self);
|
|
|
|
|
break;
|
2014-12-10 10:23:40 -06:00
|
|
|
case NM_DEVICE_STATE_NEED_AUTH:
|
|
|
|
|
if (old_state > NM_DEVICE_STATE_NEED_AUTH) {
|
|
|
|
|
/* Clean up any half-done IP operations if the device's layer2
|
|
|
|
|
* finds out it needs authentication during IP config.
|
|
|
|
|
*/
|
2015-11-21 12:28:09 +01:00
|
|
|
_cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE);
|
|
|
|
|
_cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE);
|
2014-12-10 10:23:40 -06:00
|
|
|
}
|
|
|
|
|
break;
|
2008-04-17 23:04:34 +00:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-07 12:36:17 +01:00
|
|
|
/* Reset intern autoconnect flags when the device is activating or connected. */
|
2014-03-13 14:37:26 +01:00
|
|
|
if ( state >= NM_DEVICE_STATE_PREPARE
|
|
|
|
|
&& state <= NM_DEVICE_STATE_ACTIVATED)
|
2017-11-07 12:36:17 +01:00
|
|
|
nm_device_autoconnect_blocked_unset (self, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERNAL);
|
2014-03-13 14:37:26 +01:00
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_STATE);
|
|
|
|
|
_notify (self, PROP_STATE_REASON);
|
2017-03-06 12:23:23 +01:00
|
|
|
g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) state, (guint) old_state, (guint) reason);
|
2008-04-17 23:04:34 +00:00
|
|
|
|
2008-04-27 14:30:06 +00:00
|
|
|
/* Post-process the event after internal notification */
|
|
|
|
|
|
2008-04-17 23:04:34 +00:00
|
|
|
switch (state) {
|
2009-09-14 13:24:29 -07:00
|
|
|
case NM_DEVICE_STATE_UNAVAILABLE:
|
|
|
|
|
/* If the device can activate now (ie, it's got a carrier, the supplicant
|
|
|
|
|
* is active, or whatever) schedule a delayed transition to DISCONNECTED
|
2010-09-25 00:34:10 -05:00
|
|
|
* to get things rolling. The device can't transition immediately because
|
2009-09-14 13:24:29 -07:00
|
|
|
* we can't change states again from the state handler for a variety of
|
|
|
|
|
* reasons.
|
|
|
|
|
*/
|
2015-01-20 20:25:25 +01:00
|
|
|
if (nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
|
2015-04-13 17:16:55 -05:00
|
|
|
nm_device_queue_recheck_available (self,
|
|
|
|
|
NM_DEVICE_STATE_REASON_NONE,
|
|
|
|
|
NM_DEVICE_STATE_REASON_NONE);
|
2010-04-08 15:51:54 -07:00
|
|
|
} else {
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "device not yet available for transition to DISCONNECTED");
|
2010-04-07 16:41:44 -07:00
|
|
|
}
|
2009-09-14 13:24:29 -07:00
|
|
|
break;
|
2014-01-03 13:58:05 -05:00
|
|
|
case NM_DEVICE_STATE_DEACTIVATING:
|
2015-02-03 16:15:37 +01:00
|
|
|
_cancel_activation (self);
|
|
|
|
|
|
2016-05-11 16:53:16 +02:00
|
|
|
/* We cache the ignore_carrier state to not react on config-reloads while the connection
|
|
|
|
|
* is active. But on deactivating, reset the ignore-carrier flag to the current state. */
|
|
|
|
|
priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self);
|
2015-04-17 14:12:10 +02:00
|
|
|
|
2014-05-23 18:25:05 -05:00
|
|
|
if (quitting) {
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device_sync (NM_DISPATCHER_ACTION_PRE_DOWN,
|
|
|
|
|
self, req);
|
2014-05-23 18:25:05 -05:00
|
|
|
} else {
|
2014-06-12 14:20:14 +02:00
|
|
|
priv->dispatcher.post_state = NM_DEVICE_STATE_DISCONNECTED;
|
|
|
|
|
priv->dispatcher.post_state_reason = reason;
|
2017-03-08 14:11:22 +01:00
|
|
|
if (!nm_dispatcher_call_device (NM_DISPATCHER_ACTION_PRE_DOWN,
|
|
|
|
|
self,
|
|
|
|
|
req,
|
|
|
|
|
deactivate_dispatcher_complete,
|
|
|
|
|
self,
|
|
|
|
|
&priv->dispatcher.call_id)) {
|
2014-05-23 18:25:05 -05:00
|
|
|
/* Just proceed on errors */
|
2014-08-05 20:08:34 +02:00
|
|
|
deactivate_dispatcher_complete (0, self);
|
2014-05-23 18:25:05 -05:00
|
|
|
}
|
2014-05-20 17:10:42 -05:00
|
|
|
}
|
2016-08-16 05:55:58 +05:30
|
|
|
|
2017-04-21 15:46:56 +02:00
|
|
|
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
|
|
|
|
|
&priv->pacrunner_call_id);
|
2014-01-03 13:58:05 -05:00
|
|
|
break;
|
2013-04-24 10:40:58 -04:00
|
|
|
case NM_DEVICE_STATE_DISCONNECTED:
|
2014-12-08 12:50:10 +01:00
|
|
|
if ( priv->queued_act_request
|
|
|
|
|
&& !priv->queued_act_request_is_waiting_for_carrier) {
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
NMActRequest *queued_req;
|
|
|
|
|
|
|
|
|
|
queued_req = priv->queued_act_request;
|
|
|
|
|
priv->queued_act_request = NULL;
|
2017-05-17 11:34:54 +02:00
|
|
|
_device_activate (self, queued_req);
|
core: queue re-activations to allow DEACTIVATING state
If a device is already activated, queue the new activation to allow
the transition through the DEACTIVATING state.
---
Also remove the "HACK" bits in nm_device_deactivate(). This hack was
added on 2007-09-25 in commit 9c2848d. At the time, with user settings
services, if a client created a connection and requested that NM
activate it, NM may not have read the connection from the client over
D-Bus yet. So NM created a "deferred" activation request which waited
until the connection was read from the client, and then began activation.
The Policy watched for device state changes and other events (like
it does now) and activated a new device if the old one was no longer
valid. It specifically checked for deferred activations and then
did nothing. However, when the client's connection was read, then
nm-device.c cleared the deferred activation bit, leading to a short
period of time where the device was in DISCONNECTED state but there
was no deferred activation, because the device only changes state to
PREPARE from the idle handler for stage1. If other events happened
during this time, the policy would tear down the device that was
about to be activated. This early state transition to PREPARE
worked around that.
We need to remove it now though, because (a) the reason for its
existence is no longer valid, and (b) _device_activate() may now
be called from inside nm_device_state_changed() and thus it cannot
change to a new state inside the function.
2014-02-17 17:16:08 -06:00
|
|
|
g_object_unref (queued_req);
|
2014-10-16 15:01:16 -05:00
|
|
|
}
|
2013-04-24 10:40:58 -04:00
|
|
|
break;
|
2007-02-05 12:14:09 +00:00
|
|
|
case NM_DEVICE_STATE_ACTIVATED:
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGI (LOGD_DEVICE, "Activation: successful, device activated.");
|
2015-04-30 14:18:14 +02:00
|
|
|
nm_device_update_metered (self);
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device (NM_DISPATCHER_ACTION_UP,
|
|
|
|
|
self,
|
|
|
|
|
req,
|
|
|
|
|
NULL, NULL, NULL);
|
2016-08-16 05:55:58 +05:30
|
|
|
|
2017-04-21 15:46:56 +02:00
|
|
|
if (priv->proxy_config)
|
|
|
|
|
_pacrunner_manager_send (self);
|
2007-02-05 12:14:09 +00:00
|
|
|
break;
|
|
|
|
|
case NM_DEVICE_STATE_FAILED:
|
2015-11-03 22:38:55 +01:00
|
|
|
/* Usually upon failure the activation chain is interrupted in
|
|
|
|
|
* one of the stages; but in some cases the device fails for
|
|
|
|
|
* external events (as a failure of master connection) while
|
|
|
|
|
* the activation sequence is running and so we need to ensure
|
|
|
|
|
* that the chain is terminated here.
|
|
|
|
|
*/
|
|
|
|
|
_cancel_activation (self);
|
|
|
|
|
|
2017-03-13 15:34:14 +01:00
|
|
|
if (nm_device_sys_iface_state_is_external_or_assume (self)) {
|
2014-12-03 14:47:44 +01:00
|
|
|
/* Avoid tearing down assumed connection, assume it's connected */
|
|
|
|
|
nm_device_queue_state (self,
|
|
|
|
|
NM_DEVICE_STATE_ACTIVATED,
|
|
|
|
|
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
connection = nm_device_get_settings_connection (self);
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGW (LOGD_DEVICE | LOGD_WIFI,
|
|
|
|
|
"Activation: failed for connection '%s'",
|
2015-07-14 16:53:24 +02:00
|
|
|
connection ? nm_settings_connection_get_id (connection) : "<unknown>");
|
2012-09-12 22:44:31 -05:00
|
|
|
|
2012-11-14 14:05:30 -06:00
|
|
|
/* Notify any slaves of the unexpected failure */
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_master_release_slaves (self);
|
2012-11-14 14:05:30 -06:00
|
|
|
|
2012-09-12 22:44:31 -05:00
|
|
|
/* If the connection doesn't yet have a timestamp, set it to zero so that
|
|
|
|
|
* we can distinguish between connections we've tried to activate and have
|
|
|
|
|
* failed (zero timestamp), connections that succeeded (non-zero timestamp),
|
|
|
|
|
* and those we haven't tried yet (no timestamp).
|
|
|
|
|
*/
|
2015-07-14 16:53:24 +02:00
|
|
|
if (connection && !nm_settings_connection_get_timestamp (connection, NULL))
|
|
|
|
|
nm_settings_connection_update_timestamp (connection, (guint64) 0, TRUE);
|
2012-09-12 22:44:31 -05:00
|
|
|
|
2009-09-14 13:24:29 -07:00
|
|
|
/* Schedule the transition to DISCONNECTED. The device can't transition
|
2010-09-25 00:34:10 -05:00
|
|
|
* immediately because we can't change states again from the state
|
2009-09-14 13:24:29 -07:00
|
|
|
* handler for a variety of reasons.
|
|
|
|
|
*/
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
|
2007-02-05 12:14:09 +00:00
|
|
|
break;
|
2013-06-11 17:05:49 -05:00
|
|
|
case NM_DEVICE_STATE_IP_CHECK:
|
2017-05-03 18:34:17 +02:00
|
|
|
if ( priv->fw_state >= FIREWALL_STATE_INITIALIZED
|
2017-05-04 15:04:10 +02:00
|
|
|
&& priv->ip_iface
|
2017-03-13 15:34:14 +01:00
|
|
|
&& !nm_device_sys_iface_state_is_external (self)) {
|
2017-05-03 18:34:17 +02:00
|
|
|
priv->fw_state = FIREWALL_STATE_WAIT_IP_CONFIG;
|
|
|
|
|
fw_change_zone (self);
|
2015-09-17 13:41:34 +02:00
|
|
|
} else
|
|
|
|
|
nm_device_start_ip_check (self);
|
2013-10-09 13:55:05 -05:00
|
|
|
|
|
|
|
|
/* IP-related properties are only valid when the device has IP configuration;
|
|
|
|
|
* now that it does, ensure their change notifications are emitted.
|
|
|
|
|
*/
|
2014-07-15 13:36:24 +02:00
|
|
|
notify_ip_properties (self);
|
2013-06-11 17:05:49 -05:00
|
|
|
break;
|
2012-08-21 17:49:41 +02:00
|
|
|
case NM_DEVICE_STATE_SECONDARIES:
|
2014-07-15 13:36:24 +02:00
|
|
|
ip_check_gw_ping_cleanup (self);
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "device entered SECONDARIES state");
|
2012-08-21 17:49:41 +02:00
|
|
|
break;
|
2007-02-05 12:14:09 +00:00
|
|
|
default:
|
|
|
|
|
break;
|
2005-12-31 08:21:24 +00:00
|
|
|
}
|
2008-04-27 14:30:06 +00:00
|
|
|
|
2013-08-07 11:41:40 +02:00
|
|
|
if (state > NM_DEVICE_STATE_DISCONNECTED)
|
2014-07-15 13:36:24 +02:00
|
|
|
delete_on_deactivate_unschedule (self);
|
2013-08-07 11:41:40 +02:00
|
|
|
|
2014-05-20 17:10:42 -05:00
|
|
|
if ( (old_state == NM_DEVICE_STATE_ACTIVATED || old_state == NM_DEVICE_STATE_DEACTIVATING)
|
2014-05-23 18:25:05 -05:00
|
|
|
&& (state != NM_DEVICE_STATE_DEACTIVATING)) {
|
2015-07-14 16:53:24 +02:00
|
|
|
if (quitting) {
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device_sync (NM_DISPATCHER_ACTION_DOWN,
|
|
|
|
|
self, req);
|
2015-07-14 16:53:24 +02:00
|
|
|
} else {
|
2017-03-08 14:11:22 +01:00
|
|
|
nm_dispatcher_call_device (NM_DISPATCHER_ACTION_DOWN,
|
|
|
|
|
self,
|
|
|
|
|
req,
|
|
|
|
|
NULL, NULL, NULL);
|
2015-07-14 16:53:24 +02:00
|
|
|
}
|
2014-05-23 18:25:05 -05:00
|
|
|
}
|
2008-04-27 14:30:06 +00:00
|
|
|
|
2013-10-09 13:55:05 -05:00
|
|
|
/* IP-related properties are only valid when the device has IP configuration.
|
|
|
|
|
* If it no longer does, ensure their change notifications are emitted.
|
|
|
|
|
*/
|
|
|
|
|
if (ip_config_valid (old_state) && !ip_config_valid (state))
|
2014-07-15 13:36:24 +02:00
|
|
|
notify_ip_properties (self);
|
2013-10-09 13:55:05 -05:00
|
|
|
|
2017-03-20 13:36:00 +00:00
|
|
|
concheck_periodic_update (self);
|
|
|
|
|
|
2008-04-27 14:30:06 +00:00
|
|
|
/* Dispose of the cached activation request */
|
|
|
|
|
if (req)
|
|
|
|
|
g_object_unref (req);
|
2012-10-06 12:37:34 -05:00
|
|
|
|
2013-05-20 16:15:37 -03:00
|
|
|
priv->in_state_changed = FALSE;
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
|
|
|
|
if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED))
|
2016-02-29 16:27:27 +05:30
|
|
|
_notify (self, PROP_MANAGED);
|
2007-02-05 12:14:09 +00:00
|
|
|
}
|
|
|
|
|
|
2014-05-23 18:25:05 -05:00
|
|
|
void
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_state_changed (NMDevice *self,
|
2014-05-23 18:25:05 -05:00
|
|
|
NMDeviceState state,
|
|
|
|
|
NMDeviceStateReason reason)
|
|
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
_set_state_full (self, state, reason, FALSE);
|
2014-05-23 18:25:05 -05:00
|
|
|
}
|
|
|
|
|
|
2011-12-08 11:46:58 -06:00
|
|
|
static gboolean
|
2017-02-02 12:39:07 +01:00
|
|
|
queued_state_set (gpointer user_data)
|
2011-12-08 11:46:58 -06:00
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (user_data);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2012-11-14 18:00:22 -06:00
|
|
|
NMDeviceState new_state;
|
|
|
|
|
NMDeviceStateReason new_reason;
|
2011-12-08 11:46:58 -06:00
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
nm_assert (priv->queued_state.id);
|
2012-11-14 18:00:22 -06:00
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (priv->queued_state.state),
|
2017-02-02 12:39:07 +01:00
|
|
|
reason_to_string (priv->queued_state.reason),
|
|
|
|
|
priv->queued_state.id,
|
|
|
|
|
"change state");
|
2012-11-14 18:00:22 -06:00
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
/* Clear queued state struct before triggering state change, since
|
|
|
|
|
* the state change may queue another state.
|
|
|
|
|
*/
|
|
|
|
|
priv->queued_state.id = 0;
|
|
|
|
|
new_state = priv->queued_state.state;
|
|
|
|
|
new_reason = priv->queued_state.reason;
|
|
|
|
|
|
|
|
|
|
nm_device_state_changed (self, new_state, new_reason);
|
|
|
|
|
nm_device_remove_pending_action (self, queued_state_to_string (new_state), TRUE);
|
|
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
2011-12-08 11:46:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_device_queue_state (NMDevice *self,
|
|
|
|
|
NMDeviceState state,
|
|
|
|
|
NMDeviceStateReason reason)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_DEVICE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
if (priv->queued_state.id && priv->queued_state.state == state) {
|
|
|
|
|
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s%s%s%s",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (priv->queued_state.state),
|
2017-02-02 12:39:07 +01:00
|
|
|
reason_to_string (priv->queued_state.reason),
|
|
|
|
|
priv->queued_state.id,
|
|
|
|
|
"ignore queuing same state change",
|
|
|
|
|
NM_PRINT_FMT_QUOTED (priv->queued_state.reason != reason,
|
|
|
|
|
" (reason differs: ", reason_to_string (reason), ")", ""));
|
2014-05-20 15:03:27 -05:00
|
|
|
return;
|
2017-02-02 12:39:07 +01:00
|
|
|
}
|
2013-04-04 10:20:24 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Add pending action for the new state before clearing the queued states, so
|
|
|
|
|
* that we don't accidently pop all pending states and reach 'startup complete' */
|
|
|
|
|
nm_device_add_pending_action (self, queued_state_to_string (state), TRUE);
|
2013-11-02 10:38:23 -05:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* We should only ever have one delayed state transition at a time */
|
|
|
|
|
if (priv->queued_state.id) {
|
2017-02-02 12:39:07 +01:00
|
|
|
_LOGW (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (priv->queued_state.state),
|
2017-02-02 12:39:07 +01:00
|
|
|
reason_to_string (priv->queued_state.reason),
|
|
|
|
|
priv->queued_state.id,
|
|
|
|
|
"replace previously queued state change");
|
|
|
|
|
nm_clear_g_source (&priv->queued_state.id);
|
|
|
|
|
nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE);
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2013-04-04 10:20:24 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->queued_state.state = state;
|
|
|
|
|
priv->queued_state.reason = reason;
|
2017-02-02 12:39:07 +01:00
|
|
|
priv->queued_state.id = g_idle_add (queued_state_set, self);
|
2013-04-04 10:20:24 -04:00
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (state),
|
2017-02-02 12:39:07 +01:00
|
|
|
reason_to_string (reason),
|
|
|
|
|
priv->queued_state.id,
|
|
|
|
|
"queue state change");
|
2013-04-04 10:20:24 -04:00
|
|
|
}
|
|
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
static void
|
|
|
|
|
queued_state_clear (NMDevice *self)
|
2013-04-04 10:20:24 -04:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-02-02 12:39:07 +01:00
|
|
|
if (!priv->queued_state.id)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
|
2017-06-07 17:22:16 +02:00
|
|
|
nm_device_state_to_str (priv->queued_state.state),
|
2017-02-02 12:39:07 +01:00
|
|
|
reason_to_string (priv->queued_state.reason),
|
|
|
|
|
priv->queued_state.id,
|
|
|
|
|
"clear queued state change");
|
|
|
|
|
nm_clear_g_source (&priv->queued_state.id);
|
|
|
|
|
nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE);
|
2013-04-04 10:20:24 -04:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
NMDeviceState
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_get_state (NMDevice *self)
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
{
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_STATE_UNKNOWN);
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->state;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-05-20 15:03:27 -05:00
|
|
|
/* NMConfigDevice interface related stuff */
|
2014-03-31 21:45:54 -05:00
|
|
|
|
2014-06-21 12:44:56 -04:00
|
|
|
const char *
|
|
|
|
|
nm_device_get_hw_address (NMDevice *self)
|
2013-04-24 10:40:58 -04:00
|
|
|
{
|
2014-05-20 15:03:27 -05:00
|
|
|
NMDevicePrivate *priv;
|
2016-10-26 12:20:12 +02:00
|
|
|
char buf[NM_UTILS_HWADDR_LEN_MAX];
|
|
|
|
|
gsize l;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
2016-10-26 12:20:12 +02:00
|
|
|
|
2014-07-15 13:36:24 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-10-26 12:20:12 +02:00
|
|
|
nm_assert ( (!priv->hw_addr && priv->hw_addr_len == 0)
|
|
|
|
|
|| ( priv->hw_addr
|
|
|
|
|
&& _nm_utils_hwaddr_aton (priv->hw_addr, buf, sizeof (buf), &l)
|
|
|
|
|
&& l == priv->hw_addr_len));
|
2016-05-20 12:34:13 +02:00
|
|
|
|
|
|
|
|
return priv->hw_addr;
|
2014-03-31 21:45:54 -05:00
|
|
|
}
|
2008-04-22 19:07:00 +00:00
|
|
|
|
2016-09-07 23:47:14 +02:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_update_hw_address (NMDevice *self)
|
2014-03-31 21:45:54 -05:00
|
|
|
{
|
2016-05-20 12:34:13 +02:00
|
|
|
NMDevicePrivate *priv;
|
2014-07-14 17:59:45 -05:00
|
|
|
const guint8 *hwaddr;
|
|
|
|
|
gsize hwaddrlen = 0;
|
2008-04-07 Dan Williams <dcbw@redhat.com>
* include/NetworkManager.h
- Remove the DOWN and CANCELLED device states
- Add UNMANAGED and UNAVAILABLE device states
- Document the device states
* introspection/nm-device.xml
src/nm-device-interface.c
src/nm-device-interface.h
- Add the 'managed' property
* test/nm-tool.c
- (detail_device): print out device state
* src/NetworkManagerSystem.h
src/backends/NetworkManagerArch.c
src/backends/NetworkManagerDebian.c
src/backends/NetworkManagerFrugalware.c
src/backends/NetworkManagerGentoo.c
src/backends/NetworkManagerMandriva.c
src/backends/NetworkManagerPaldo.c
src/backends/NetworkManagerRedHat.c
src/backends/NetworkManagerSlackware.c
src/backends/NetworkManagerSuSE.c
- (nm_system_device_get_system_config, nm_system_device_get_disabled
nm_system_device_free_system_config): remove; they were unused and
their functionality should be re-implemented in each distro's
system settings service plugin
* src/nm-gsm-device.c
src/nm-gsm-device.h
src/nm-cdma-device.c
src/nm-cdma-device.h
- (*_new): take the 'managed' argument
* src/nm-device.c
- (nm_device_set_address): remove, fold into nm_device_bring_up()
- (nm_device_init): start in unmanaged state, not disconnected
- (constructor): don't start device until the system settings service
has had a chance to figure out if the device is managed or not
- (nm_device_deactivate, nm_device_bring_up, nm_device_bring_down):
don't set device state here, let callers handle that as appropriate
- (nm_device_dispose): don't touch the device if it's not managed
- (set_property, get_property, nm_device_class_init): implement the
'managed' property
- (nm_device_state_changed): bring the device up if its now managed,
and deactivate it if it used to be active
- (nm_device_get_managed, nm_device_set_managed): do the right thing
with the managed state
* src/nm-hal-manager.c
- (wired_device_creator, wireless_device_creator, modem_device_creator):
take initial managed state and pass it along to device constructors
- (create_device_and_add_to_list): get managed state and pass to
type creators
* src/nm-device-802-11-wireless.c
- (real_can_activate): fold in most of
nm_device_802_11_wireless_can_activate()
- (can_scan): can't scan in UNAVAILABLE or UNMANAGED
- (link_timeout_cb): instead of deactivating, change device state and
let the device state handler to it
- (real_update_hw_address): clean up
- (state_changed_cb): when entering UNAVAILABLE state, schedule an idle
handler to transition to DISCONNECTED if the device isn't rfkilled
* src/nm-device-802-3-ethernet.c
- (set_carrier): move above callers and get rid of prototype
- (device_state_changed): when entering UNAVAILABLE state, schedule an
idle handler to transition to DISCONNECTED if the device has a
carrier
- (real_update_hw_address): clean up
- (link_timeout_cb, ppp_state_changed): change state instead of calling
deactivation directly as deactivation doesn't change state anymore
* src/NetworkManagerPolicy.c
- (schedule_activate_check): yay, remove wireless_enabled hack since
the NMManager and wireless devices work that out themselves now
- (device_state_changed): change to a switch and update for new device
states
- (device_carrier_changed): remove; device handles this now through
state changes
- (device_added): don't care about carrier any more; the initial
activation check will happen when the device transitions to
DISCONNECTED
* src/nm-manager.c
- (dispose): clear unmanaged devices
- (handle_unmanaged_devices): update unmanaged device list and toggle
the managed property on each device when needed
- (system_settings_properties_changed_cb): handle signals from the
system settings service
- (system_settings_get_unmanaged_devices_cb): handle callback from
getting the unmanaged device list method call
- (query_unmanaged_devices): ask the system settings service for its
list of unmanaged devices
- (nm_manager_name_owner_changed, initial_get_connections): get unmanaged
devices
- (manager_set_wireless_enabled): push rfkill state down to wireless
devices directly and let them handle the necessary state transitions
- (manager_device_state_changed): update for new device states
- (nm_manager_add_device): set initial rfkill state on wireless devices
- (nm_manager_remove_device): don't touch the device if it's unmanaged
- (nm_manager_activate_connection): return error if the device is
unmanaged
- (nm_manager_sleep): handle new device states correctly; don't change
the state of unavailable/unmanaged devices
* libnm-glib/nm-device-802-11-wireless.c
- (state_changed_cb): update for new device states
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3540 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 02:58:02 +00:00
|
|
|
|
2016-05-20 12:34:13 +02:00
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-05-20 13:47:23 +02:00
|
|
|
if (priv->ifindex <= 0)
|
2016-09-07 23:47:14 +02:00
|
|
|
return FALSE;
|
2016-05-20 12:34:13 +02:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
hwaddr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &hwaddrlen);
|
2014-10-04 15:59:37 +02:00
|
|
|
|
2015-12-13 22:09:59 +01:00
|
|
|
if ( priv->type == NM_DEVICE_TYPE_ETHERNET
|
2016-05-20 12:34:13 +02:00
|
|
|
&& hwaddr
|
2016-05-24 11:28:44 +02:00
|
|
|
&& nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth)))
|
2015-12-13 22:09:59 +01:00
|
|
|
hwaddrlen = 0;
|
|
|
|
|
|
2016-10-28 17:06:13 +02:00
|
|
|
if (!hwaddrlen)
|
|
|
|
|
return FALSE;
|
2016-10-26 12:20:12 +02:00
|
|
|
|
2016-10-28 17:06:13 +02:00
|
|
|
if ( priv->hw_addr_len
|
|
|
|
|
&& priv->hw_addr_len != hwaddrlen) {
|
|
|
|
|
char s_buf[NM_UTILS_HWADDR_LEN_MAX_STR];
|
2016-10-26 12:20:12 +02:00
|
|
|
|
2016-10-28 17:06:13 +02:00
|
|
|
/* we cannot change the address length of a device once it is set (except
|
|
|
|
|
* unrealizing the device).
|
|
|
|
|
*
|
|
|
|
|
* The reason is that the permanent and initial MAC addresses also must have the
|
|
|
|
|
* same address length, so it's unclear what it would mean that the length changes. */
|
|
|
|
|
_LOGD (LOGD_PLATFORM | LOGD_DEVICE,
|
|
|
|
|
"hw-addr: read a MAC address with differing length (%s vs. %s)",
|
|
|
|
|
priv->hw_addr,
|
|
|
|
|
nm_utils_hwaddr_ntoa_buf (hwaddr, hwaddrlen, TRUE, s_buf, sizeof (s_buf)));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2014-03-31 21:45:54 -05:00
|
|
|
|
2016-10-28 17:06:13 +02:00
|
|
|
if ( priv->hw_addr
|
|
|
|
|
&& nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen))
|
|
|
|
|
return FALSE;
|
2016-05-24 13:45:58 +02:00
|
|
|
|
2016-10-28 17:06:13 +02:00
|
|
|
g_free (priv->hw_addr);
|
|
|
|
|
priv->hw_addr_len_ = hwaddrlen;
|
|
|
|
|
priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen);
|
|
|
|
|
|
|
|
|
|
_LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr);
|
|
|
|
|
_notify (self, PROP_HW_ADDRESS);
|
|
|
|
|
|
|
|
|
|
if ( !priv->hw_addr_initial
|
|
|
|
|
|| ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET
|
|
|
|
|
&& priv->state < NM_DEVICE_STATE_PREPARE
|
|
|
|
|
&& !nm_device_is_activating (self))) {
|
|
|
|
|
/* when we get a hw_addr the first time or while the device
|
|
|
|
|
* is not activated (with no explict hw address set), always
|
|
|
|
|
* update our inital hw-address as well. */
|
|
|
|
|
nm_device_update_initial_hw_address (self);
|
2014-03-31 21:45:54 -05:00
|
|
|
}
|
2016-10-28 17:06:13 +02:00
|
|
|
return TRUE;
|
2013-04-24 10:40:58 -04:00
|
|
|
}
|
|
|
|
|
|
2015-12-13 22:09:59 +01:00
|
|
|
void
|
2015-12-14 08:46:29 +01:00
|
|
|
nm_device_update_initial_hw_address (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-05-20 13:36:09 +02:00
|
|
|
if ( priv->hw_addr
|
2016-06-03 13:37:08 +02:00
|
|
|
&& !nm_streq0 (priv->hw_addr_initial, priv->hw_addr)) {
|
2016-06-20 12:28:04 +02:00
|
|
|
if ( priv->hw_addr_initial
|
|
|
|
|
&& priv->hw_addr_type != HW_ADDR_TYPE_UNSET) {
|
|
|
|
|
/* once we have the initial hw address set, we only allow
|
|
|
|
|
* update if the currenty type is "unset". */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-06-03 13:37:08 +02:00
|
|
|
g_free (priv->hw_addr_initial);
|
|
|
|
|
priv->hw_addr_initial = g_strdup (priv->hw_addr);
|
2016-05-20 13:36:09 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "hw-addr: update initial MAC address %s",
|
2016-06-03 13:37:08 +02:00
|
|
|
priv->hw_addr_initial);
|
2016-05-20 13:33:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-14 08:46:29 +01:00
|
|
|
|
2016-05-20 13:33:28 +02:00
|
|
|
void
|
2016-10-24 12:50:17 +02:00
|
|
|
nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
|
2016-05-20 13:33:28 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-05-20 13:47:23 +02:00
|
|
|
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
|
|
|
|
|
size_t len = 0;
|
|
|
|
|
gboolean success_read;
|
2016-10-24 12:50:17 +02:00
|
|
|
int ifindex;
|
|
|
|
|
const NMPlatformLink *pllink;
|
2016-05-20 13:33:28 +02:00
|
|
|
|
2016-05-20 13:47:23 +02:00
|
|
|
if (priv->hw_addr_perm) {
|
|
|
|
|
/* the permanent hardware address is only read once and not
|
|
|
|
|
* re-read later.
|
|
|
|
|
*
|
|
|
|
|
* Except during unrealize/realize cycles, where we clear the permanent
|
|
|
|
|
* hardware address during unrealization. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-12-14 08:46:29 +01:00
|
|
|
|
2016-10-24 12:50:17 +02:00
|
|
|
ifindex = priv->ifindex;
|
|
|
|
|
if (ifindex <= 0)
|
2016-05-20 13:47:23 +02:00
|
|
|
return;
|
2016-05-20 10:09:39 +02:00
|
|
|
|
2016-10-24 12:50:17 +02:00
|
|
|
/* the user is advised to configure stable MAC addresses for software devices via
|
|
|
|
|
* UDEV. Thus, check whether the link is fully initialized. */
|
2017-04-17 20:17:45 +02:00
|
|
|
pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex);
|
2016-10-24 12:50:17 +02:00
|
|
|
if ( !pllink
|
|
|
|
|
|| !pllink->initialized) {
|
|
|
|
|
if (!force_freeze) {
|
|
|
|
|
/* we can afford to wait. Back off and leave the permanent MAC address
|
|
|
|
|
* undecided for now. */
|
2016-05-20 13:47:23 +02:00
|
|
|
return;
|
2016-10-24 12:50:17 +02:00
|
|
|
}
|
|
|
|
|
/* try to refresh the link just to give UDEV a bit more time... */
|
2017-04-17 20:17:45 +02:00
|
|
|
nm_platform_link_refresh (nm_device_get_platform (self), ifindex);
|
2016-10-24 12:50:17 +02:00
|
|
|
/* maybe the MAC address changed... */
|
|
|
|
|
nm_device_update_hw_address (self);
|
|
|
|
|
} else if (!priv->hw_addr_len)
|
|
|
|
|
nm_device_update_hw_address (self);
|
|
|
|
|
|
|
|
|
|
if (!priv->hw_addr_len) {
|
|
|
|
|
/* we need the current MAC address because we require the permanent MAC address
|
|
|
|
|
* to have the same length as the current address.
|
|
|
|
|
*
|
|
|
|
|
* Abort if there is no current MAC address. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
success_read = nm_platform_link_get_permanent_address (nm_device_get_platform (self), ifindex, buf, &len);
|
2016-10-24 12:50:17 +02:00
|
|
|
if (success_read && priv->hw_addr_len == len) {
|
|
|
|
|
priv->hw_addr_perm_fake = FALSE;
|
|
|
|
|
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len);
|
|
|
|
|
_LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'",
|
|
|
|
|
priv->hw_addr_perm);
|
|
|
|
|
goto notify_and_out;
|
2016-05-20 13:47:23 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-24 12:50:17 +02:00
|
|
|
/* we failed to read a permanent MAC address, thus we use a fake address,
|
|
|
|
|
* that is the current MAC address of the device.
|
|
|
|
|
*
|
|
|
|
|
* Note that the permanet MAC address of a NMDevice instance does not change
|
|
|
|
|
* after being set once. Thus, we use now a fake address and stick to that
|
|
|
|
|
* (until we unrealize the device). */
|
|
|
|
|
priv->hw_addr_perm_fake = TRUE;
|
|
|
|
|
|
|
|
|
|
/* We also persist our choice of the fake address to the device state
|
|
|
|
|
* file to use the same address on restart of NetworkManager.
|
|
|
|
|
* First, try to reload the address from the state file. */
|
|
|
|
|
{
|
2016-10-13 15:56:13 +02:00
|
|
|
gs_free NMConfigDeviceStateData *dev_state = NULL;
|
|
|
|
|
|
2017-04-19 15:45:31 +02:00
|
|
|
dev_state = nm_config_device_state_load (ifindex);
|
2016-10-13 15:56:13 +02:00
|
|
|
if ( dev_state
|
|
|
|
|
&& dev_state->perm_hw_addr_fake
|
|
|
|
|
&& nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len)
|
|
|
|
|
&& !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) {
|
|
|
|
|
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)",
|
|
|
|
|
success_read
|
|
|
|
|
? "read HW addr length of permanent MAC address differs"
|
|
|
|
|
: "unable to read permanent MAC address",
|
|
|
|
|
dev_state->perm_hw_addr_fake,
|
|
|
|
|
priv->hw_addr);
|
|
|
|
|
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
|
2016-10-24 12:50:17 +02:00
|
|
|
goto notify_and_out;
|
2016-10-13 15:56:13 +02:00
|
|
|
}
|
2015-12-14 08:46:29 +01:00
|
|
|
}
|
2016-10-13 15:56:13 +02:00
|
|
|
|
2016-10-24 12:50:17 +02:00
|
|
|
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)",
|
|
|
|
|
success_read
|
|
|
|
|
? "read HW addr length of permanent MAC address differs"
|
|
|
|
|
: "unable to read permanent MAC address",
|
|
|
|
|
priv->hw_addr);
|
|
|
|
|
priv->hw_addr_perm = g_strdup (priv->hw_addr);
|
2016-10-13 15:56:13 +02:00
|
|
|
|
2016-10-24 12:50:17 +02:00
|
|
|
notify_and_out:
|
2016-06-17 18:53:45 +02:00
|
|
|
_notify (self, PROP_PERM_HW_ADDRESS);
|
2015-12-14 08:46:29 +01:00
|
|
|
}
|
|
|
|
|
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
static const char *
|
|
|
|
|
_get_cloned_mac_address_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_addr)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
const char *addr = NULL;
|
|
|
|
|
|
|
|
|
|
nm_assert (out_addr && !*out_addr);
|
|
|
|
|
|
|
|
|
|
setting = nm_connection_get_setting (connection,
|
|
|
|
|
is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
|
|
|
|
|
if (setting) {
|
|
|
|
|
addr = is_wifi
|
|
|
|
|
? nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) setting)
|
|
|
|
|
: nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) setting);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!addr) {
|
|
|
|
|
gs_free char *a = NULL;
|
|
|
|
|
|
|
|
|
|
a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
is_wifi ? "wifi.cloned-mac-address" : "ethernet.cloned-mac-address",
|
|
|
|
|
self);
|
2016-09-01 16:18:34 +02:00
|
|
|
|
|
|
|
|
addr = NM_CLONED_MAC_PRESERVE;
|
2016-06-20 12:28:04 +02:00
|
|
|
|
|
|
|
|
if (!a) {
|
|
|
|
|
if (is_wifi) {
|
|
|
|
|
NMSettingMacRandomization v;
|
|
|
|
|
|
|
|
|
|
/* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */
|
|
|
|
|
a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION,
|
|
|
|
|
self);
|
|
|
|
|
v = _nm_utils_ascii_str_to_int64 (a, 10,
|
|
|
|
|
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
|
|
|
|
|
NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
|
|
|
|
|
NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
|
|
|
|
|
if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
|
|
|
|
|
addr = NM_CLONED_MAC_RANDOM;
|
|
|
|
|
}
|
|
|
|
|
} else if ( NM_CLONED_MAC_IS_SPECIAL (a)
|
|
|
|
|
|| nm_utils_hwaddr_valid (a, ETH_ALEN))
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
addr = *out_addr = g_steal_pointer (&a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|
|
all: make MAC address randomization algorithm configurable
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"
2016-06-22 20:31:39 +02:00
|
|
|
static const char *
|
|
|
|
|
_get_generate_mac_address_mask_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_value)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
const char *value = NULL;
|
|
|
|
|
char *a;
|
|
|
|
|
|
|
|
|
|
nm_assert (out_value && !*out_value);
|
|
|
|
|
|
|
|
|
|
setting = nm_connection_get_setting (connection,
|
|
|
|
|
is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
|
|
|
|
|
if (setting) {
|
|
|
|
|
value = is_wifi
|
|
|
|
|
? nm_setting_wireless_get_generate_mac_address_mask ((NMSettingWireless *) setting)
|
|
|
|
|
: nm_setting_wired_get_generate_mac_address_mask ((NMSettingWired *) setting);
|
|
|
|
|
if (value)
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
is_wifi ? "wifi.generate-mac-address-mask" : "ethernet.generate-mac-mac-address-mask",
|
|
|
|
|
self);
|
|
|
|
|
if (!a)
|
|
|
|
|
return NULL;
|
|
|
|
|
*out_value = a;
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_device_hw_addr_is_explict (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2017-02-02 12:34:30 +01:00
|
|
|
return !NM_IN_SET ((HwAddrType) priv->hw_addr_type,
|
|
|
|
|
HW_ADDR_TYPE_PERMANENT,
|
|
|
|
|
HW_ADDR_TYPE_UNSET);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-07 23:47:14 +02:00
|
|
|
static gboolean
|
2016-10-13 17:51:07 +02:00
|
|
|
_hw_addr_matches (NMDevice *self, const guint8 *addr, gsize addr_len)
|
2016-09-07 23:47:14 +02:00
|
|
|
{
|
|
|
|
|
const char *cur_addr;
|
|
|
|
|
|
|
|
|
|
cur_addr = nm_device_get_hw_address (self);
|
2016-10-13 17:51:07 +02:00
|
|
|
return cur_addr && nm_utils_hwaddr_matches (addr, addr_len, cur_addr, -1);
|
2016-09-07 23:47:14 +02:00
|
|
|
}
|
|
|
|
|
|
2016-05-20 09:41:40 +02:00
|
|
|
static gboolean
|
|
|
|
|
_hw_addr_set (NMDevice *self,
|
2016-10-13 17:51:07 +02:00
|
|
|
const char *const addr,
|
|
|
|
|
const char *const operation,
|
|
|
|
|
const char *const detail)
|
2013-04-24 10:40:58 -04:00
|
|
|
{
|
2016-05-20 09:41:40 +02:00
|
|
|
NMDevicePrivate *priv;
|
2014-05-20 15:03:27 -05:00
|
|
|
gboolean success = FALSE;
|
2016-07-05 10:41:18 +02:00
|
|
|
NMPlatformError plerr;
|
2014-07-30 10:57:45 -04:00
|
|
|
guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
|
2016-10-13 17:51:07 +02:00
|
|
|
gsize addr_len;
|
2016-06-20 12:28:04 +02:00
|
|
|
gboolean was_up;
|
2013-04-24 10:40:58 -04:00
|
|
|
|
2016-05-20 09:41:40 +02:00
|
|
|
nm_assert (NM_IS_DEVICE (self));
|
|
|
|
|
nm_assert (addr);
|
2016-06-21 11:22:07 +02:00
|
|
|
nm_assert (operation);
|
2016-05-20 09:41:40 +02:00
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-10-13 17:51:07 +02:00
|
|
|
if (!_nm_utils_hwaddr_aton (addr, addr_bytes, sizeof (addr_bytes), &addr_len))
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Do nothing if current MAC is same */
|
2016-10-13 17:51:07 +02:00
|
|
|
if (_hw_addr_matches (self, addr_bytes, addr_len)) {
|
2016-09-07 23:47:14 +02:00
|
|
|
_LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", addr);
|
2014-05-20 15:03:27 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2016-05-20 09:41:40 +02:00
|
|
|
|
2016-10-26 12:20:12 +02:00
|
|
|
if ( priv->hw_addr_len
|
|
|
|
|
&& priv->hw_addr_len != addr_len)
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-06-21 11:22:07 +02:00
|
|
|
_LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s' (%s, %s)...", addr, operation, detail);
|
2016-05-20 13:36:09 +02:00
|
|
|
|
2016-06-20 12:28:04 +02:00
|
|
|
was_up = nm_device_is_up (self);
|
|
|
|
|
if (was_up) {
|
|
|
|
|
/* Can't change MAC address while device is up */
|
|
|
|
|
nm_device_take_down (self, FALSE);
|
|
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
plerr = nm_platform_link_set_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), addr_bytes, addr_len);
|
2016-07-05 10:41:18 +02:00
|
|
|
success = (plerr == NM_PLATFORM_ERROR_SUCCESS);
|
2014-05-20 15:03:27 -05:00
|
|
|
if (success) {
|
|
|
|
|
/* MAC address succesfully changed; update the current MAC to match */
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_update_hw_address (self);
|
2016-10-13 17:51:07 +02:00
|
|
|
if (_hw_addr_matches (self, addr_bytes, addr_len)) {
|
2016-06-21 11:22:07 +02:00
|
|
|
_LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
|
|
|
|
|
operation, addr, detail);
|
2014-05-20 15:03:27 -05:00
|
|
|
} else {
|
2016-09-13 11:16:11 +02:00
|
|
|
gint64 poll_end, now;
|
|
|
|
|
|
2016-08-29 18:28:34 +02:00
|
|
|
_LOGD (LOGD_DEVICE,
|
|
|
|
|
"set-hw-addr: new MAC address %s not successfully %s (%s) (refresh link)",
|
2016-06-21 11:22:07 +02:00
|
|
|
addr, operation, detail);
|
2016-09-07 23:47:14 +02:00
|
|
|
|
|
|
|
|
/* The platform call indicated success, however the address is not
|
|
|
|
|
* as expected. That is either due to a driver issue (brcmfmac, bgo#770456,
|
|
|
|
|
* rh#1374023) or a race where externally the MAC address was reset.
|
|
|
|
|
* The race is rather unlikely.
|
|
|
|
|
*
|
|
|
|
|
* The alternative would be to postpone the activation in case the
|
|
|
|
|
* MAC address is not yet ready and poll without blocking. However,
|
|
|
|
|
* that is rather complicated and it is not expected that this case
|
|
|
|
|
* happens for regular drivers.
|
|
|
|
|
* Note that brcmfmac can block NetworkManager for 500 msec while
|
|
|
|
|
* taking down the device. Let's add annother 100 msec to that.
|
|
|
|
|
*
|
|
|
|
|
* wait/poll up to 100 msec until it changes. */
|
|
|
|
|
|
|
|
|
|
poll_end = nm_utils_get_monotonic_timestamp_us () + (100 * 1000);
|
|
|
|
|
for (;;) {
|
2017-04-17 20:17:45 +02:00
|
|
|
if (!nm_platform_link_refresh (nm_device_get_platform (self), nm_device_get_ip_ifindex (self)))
|
2016-09-07 23:47:14 +02:00
|
|
|
goto handle_fail;
|
|
|
|
|
if (!nm_device_update_hw_address (self))
|
|
|
|
|
goto handle_wait;
|
2016-10-13 17:51:07 +02:00
|
|
|
if (!_hw_addr_matches (self, addr_bytes, addr_len))
|
2016-09-07 23:47:14 +02:00
|
|
|
goto handle_fail;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
handle_wait:
|
|
|
|
|
now = nm_utils_get_monotonic_timestamp_us ();
|
|
|
|
|
if (now < poll_end) {
|
|
|
|
|
g_usleep (NM_MIN (poll_end - now, 500));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
handle_fail:
|
2016-09-11 09:48:56 +02:00
|
|
|
success = FALSE;
|
|
|
|
|
break;
|
2016-09-07 23:47:14 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-13 11:16:11 +02:00
|
|
|
if (success) {
|
|
|
|
|
_LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
|
|
|
|
|
operation, addr, detail);
|
|
|
|
|
} else {
|
|
|
|
|
_LOGW (LOGD_DEVICE,
|
|
|
|
|
"set-hw-addr: new MAC address %s not successfully %s (%s)",
|
|
|
|
|
addr, operation, detail);
|
|
|
|
|
}
|
2016-09-11 09:48:56 +02:00
|
|
|
}
|
2016-09-13 11:16:11 +02:00
|
|
|
} else {
|
|
|
|
|
_NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN,
|
|
|
|
|
LOGD_DEVICE, "set-hw-addr: failed to %s MAC address to %s (%s) (%s)",
|
|
|
|
|
operation, addr, detail,
|
2017-08-21 19:18:45 +02:00
|
|
|
nm_platform_error_to_string_a (plerr));
|
2016-09-11 09:48:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (was_up) {
|
|
|
|
|
if (!nm_device_bring_up (self, TRUE, NULL))
|
|
|
|
|
return FALSE;
|
2016-08-29 18:28:34 +02:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
return success;
|
2013-04-24 10:40:58 -04:00
|
|
|
}
|
|
|
|
|
|
2016-05-20 09:41:40 +02:00
|
|
|
gboolean
|
2016-10-25 16:41:42 +02:00
|
|
|
nm_device_hw_addr_set (NMDevice *self,
|
|
|
|
|
const char *addr,
|
|
|
|
|
const char *detail,
|
|
|
|
|
gboolean set_permanent)
|
2016-05-20 09:41:40 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
if (!addr)
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
|
2016-10-25 16:41:42 +02:00
|
|
|
if (set_permanent) {
|
|
|
|
|
/* The type is set to PERMANENT by NMDeviceVlan when taking the MAC
|
|
|
|
|
* address from the parent and by NMDeviceWifi when setting a random MAC
|
|
|
|
|
* address during scanning.
|
|
|
|
|
*/
|
|
|
|
|
priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT;
|
|
|
|
|
}
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
2016-06-21 11:22:07 +02:00
|
|
|
return _hw_addr_set (self, addr, "set", detail);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-21 15:54:01 +01:00
|
|
|
/*
|
|
|
|
|
* _hw_addr_get_cloned:
|
|
|
|
|
* @self: a #NMDevice
|
|
|
|
|
* @connection: a #NMConnection
|
|
|
|
|
* @is_wifi: whether the device is Wi-Fi
|
|
|
|
|
* @preserve: (out): whether the address must be reset to initial one
|
|
|
|
|
* @hwaddr: (out): the cloned MAC address to set on interface
|
|
|
|
|
* @hwaddr_type: (out): the type of address to set
|
|
|
|
|
* @hwaddr_detail: (out): the detail (origin) of address to set
|
|
|
|
|
* @error: (out): on return, an error or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Computes the MAC to be set on a interface. On success, one of the
|
|
|
|
|
* following exclusive conditions are verified:
|
|
|
|
|
*
|
|
|
|
|
* - @preserve is %TRUE: the address must be reset to the initial one
|
|
|
|
|
* - @hwaddr is not %NULL: the given address must be set on the device
|
|
|
|
|
* - @hwaddr is %NULL and @preserve is %FALSE: no action needed
|
|
|
|
|
*
|
|
|
|
|
* Returns: %FALSE in case of error in determining the cloned MAC address,
|
|
|
|
|
* %TRUE otherwise
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
|
|
|
|
_hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi,
|
|
|
|
|
gboolean *preserve, char **hwaddr, HwAddrType *hwaddr_type,
|
|
|
|
|
char **hwaddr_detail, GError **error)
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
2017-02-21 15:54:01 +01:00
|
|
|
gs_free char *addr_setting_free = NULL;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
gs_free char *hw_addr_generated = NULL;
|
all: make MAC address randomization algorithm configurable
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"
2016-06-22 20:31:39 +02:00
|
|
|
gs_free char *generate_mac_address_mask_tmp = NULL;
|
2016-06-21 11:22:07 +02:00
|
|
|
const char *addr, *addr_setting;
|
2017-02-21 15:54:01 +01:00
|
|
|
char *addr_out;
|
|
|
|
|
HwAddrType type_out;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2017-02-21 15:54:01 +01:00
|
|
|
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
|
|
|
|
|
g_return_val_if_fail (!error || !*error, FALSE);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!connection)
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
|
2017-02-21 15:54:01 +01:00
|
|
|
addr = addr_setting = _get_cloned_mac_address_setting (self, connection, is_wifi, &addr_setting_free);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
2016-06-20 12:28:04 +02:00
|
|
|
if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) {
|
|
|
|
|
/* "preserve" means to reset the initial MAC address. */
|
2017-02-21 15:54:01 +01:00
|
|
|
NM_SET_OUT (preserve, TRUE);
|
|
|
|
|
NM_SET_OUT (hwaddr, NULL);
|
|
|
|
|
NM_SET_OUT (hwaddr_type, HW_ADDR_TYPE_UNSET);
|
|
|
|
|
NM_SET_OUT (hwaddr_detail, g_steal_pointer (&addr_setting_free) ?: g_strdup (addr_setting));
|
|
|
|
|
return TRUE;
|
2016-06-20 12:28:04 +02:00
|
|
|
}
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) {
|
2017-07-25 10:37:14 +02:00
|
|
|
gboolean is_fake;
|
|
|
|
|
|
|
|
|
|
addr = nm_device_get_permanent_hw_address_full (self, TRUE, &is_fake);
|
|
|
|
|
if (is_fake) {
|
|
|
|
|
/* Preserve the current address if the permanent address if fake */
|
|
|
|
|
NM_SET_OUT (preserve, TRUE);
|
|
|
|
|
NM_SET_OUT (hwaddr, NULL);
|
|
|
|
|
NM_SET_OUT (hwaddr_type, HW_ADDR_TYPE_UNSET);
|
|
|
|
|
NM_SET_OUT (hwaddr_detail, g_steal_pointer (&addr_setting_free) ?: g_strdup (addr_setting));
|
|
|
|
|
return TRUE;
|
|
|
|
|
} else if (!addr) {
|
2017-02-21 15:54:01 +01:00
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"failed to retrieve permanent address");
|
2016-05-20 09:41:40 +02:00
|
|
|
return FALSE;
|
2017-02-21 15:54:01 +01:00
|
|
|
}
|
|
|
|
|
addr_out = g_strdup (addr);
|
|
|
|
|
type_out = HW_ADDR_TYPE_PERMANENT;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
} else if (NM_IN_STRSET (addr, NM_CLONED_MAC_RANDOM)) {
|
2016-06-23 16:01:10 +02:00
|
|
|
if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) {
|
|
|
|
|
/* hm, we already use a generate MAC address. Most certainly, that is from the same
|
|
|
|
|
* activation request, so we should not create a new random address, instead keep
|
|
|
|
|
* the current. */
|
2017-02-21 15:54:01 +01:00
|
|
|
goto out_no_action;
|
2016-06-23 16:01:10 +02:00
|
|
|
}
|
all: make MAC address randomization algorithm configurable
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"
2016-06-22 20:31:39 +02:00
|
|
|
hw_addr_generated = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (self),
|
2017-02-21 15:54:01 +01:00
|
|
|
_get_generate_mac_address_mask_setting (self, connection,
|
|
|
|
|
is_wifi,
|
|
|
|
|
&generate_mac_address_mask_tmp));
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
if (!hw_addr_generated) {
|
2017-02-21 15:54:01 +01:00
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"failed to generate %s MAC address", "random");
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
2017-02-21 15:54:01 +01:00
|
|
|
|
|
|
|
|
addr_out = g_steal_pointer (&hw_addr_generated);
|
|
|
|
|
type_out = HW_ADDR_TYPE_GENERATED;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
} else if (NM_IN_STRSET (addr, NM_CLONED_MAC_STABLE)) {
|
|
|
|
|
NMUtilsStableType stable_type;
|
|
|
|
|
const char *stable_id;
|
|
|
|
|
|
2016-06-23 16:01:10 +02:00
|
|
|
if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) {
|
|
|
|
|
/* hm, we already use a generate MAC address. Most certainly, that is from the same
|
|
|
|
|
* activation request, so let's skip creating the stable address anew. */
|
2017-02-21 15:54:01 +01:00
|
|
|
goto out_no_action;
|
2016-06-23 16:01:10 +02:00
|
|
|
}
|
|
|
|
|
|
2016-12-18 13:54:26 +01:00
|
|
|
stable_id = _get_stable_id (self, connection, &stable_type);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
if (stable_id) {
|
|
|
|
|
hw_addr_generated = nm_utils_hw_addr_gen_stable_eth (stable_type, stable_id,
|
all: make MAC address randomization algorithm configurable
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"
2016-06-22 20:31:39 +02:00
|
|
|
nm_device_get_ip_iface (self),
|
|
|
|
|
nm_device_get_initial_hw_address (self),
|
|
|
|
|
_get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp));
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
}
|
|
|
|
|
if (!hw_addr_generated) {
|
2017-02-21 15:54:01 +01:00
|
|
|
g_set_error (error,
|
|
|
|
|
NM_DEVICE_ERROR,
|
|
|
|
|
NM_DEVICE_ERROR_FAILED,
|
|
|
|
|
"failed to generate %s MAC address", "stable");
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
2017-02-21 15:54:01 +01:00
|
|
|
|
|
|
|
|
addr_out = g_steal_pointer (&hw_addr_generated);
|
|
|
|
|
type_out = HW_ADDR_TYPE_GENERATED;
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
} else {
|
|
|
|
|
/* this must be a valid address. Otherwise, we shouldn't come here. */
|
2016-10-13 17:51:07 +02:00
|
|
|
if (!nm_utils_hwaddr_valid (addr, -1))
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
g_return_val_if_reached (FALSE);
|
2017-02-21 15:54:01 +01:00
|
|
|
|
|
|
|
|
addr_out = g_strdup (addr);
|
|
|
|
|
type_out = HW_ADDR_TYPE_EXPLICIT;
|
2016-05-20 09:41:40 +02:00
|
|
|
}
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
2017-02-21 15:54:01 +01:00
|
|
|
NM_SET_OUT (preserve, FALSE);
|
|
|
|
|
NM_SET_OUT (hwaddr, addr_out);
|
|
|
|
|
NM_SET_OUT (hwaddr_type, type_out);
|
|
|
|
|
NM_SET_OUT (hwaddr_detail, g_steal_pointer (&addr_setting_free) ?: g_strdup (addr_setting));
|
|
|
|
|
return TRUE;
|
|
|
|
|
out_no_action:
|
|
|
|
|
NM_SET_OUT (preserve, FALSE);
|
|
|
|
|
NM_SET_OUT (hwaddr, NULL);
|
|
|
|
|
NM_SET_OUT (hwaddr_type, HW_ADDR_TYPE_UNSET);
|
|
|
|
|
NM_SET_OUT (hwaddr_detail, NULL);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi,
|
|
|
|
|
char **hwaddr, gboolean *preserve, GError **error)
|
|
|
|
|
{
|
|
|
|
|
if (!_hw_addr_get_cloned (self, connection, is_wifi, preserve, hwaddr, NULL, NULL, error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi)
|
|
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
gboolean preserve = FALSE;
|
|
|
|
|
gs_free char *hwaddr = NULL;
|
|
|
|
|
gs_free char *detail = NULL;
|
|
|
|
|
HwAddrType type = HW_ADDR_TYPE_UNSET;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!_hw_addr_get_cloned (self, connection, is_wifi, &preserve, &hwaddr, &type, &detail, &error)) {
|
|
|
|
|
_LOGW (LOGD_DEVICE, "set-hw-addr: %s", error->message);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (preserve)
|
|
|
|
|
return nm_device_hw_addr_reset (self, detail);
|
|
|
|
|
|
2017-03-30 09:54:20 +02:00
|
|
|
if (hwaddr) {
|
|
|
|
|
priv->hw_addr_type = type;
|
2017-02-21 15:54:01 +01:00
|
|
|
return _hw_addr_set (self, hwaddr, "set-cloned", detail);
|
2017-03-30 09:54:20 +02:00
|
|
|
}
|
2017-02-21 15:54:01 +01:00
|
|
|
|
|
|
|
|
return TRUE;
|
2016-05-20 09:41:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2016-06-21 11:22:07 +02:00
|
|
|
nm_device_hw_addr_reset (NMDevice *self, const char *detail)
|
2016-05-20 09:41:40 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
const char *addr;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
if (priv->hw_addr_type == HW_ADDR_TYPE_UNSET)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
priv->hw_addr_type = HW_ADDR_TYPE_UNSET;
|
2016-05-20 13:47:23 +02:00
|
|
|
addr = nm_device_get_initial_hw_address (self);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
if (!addr) {
|
|
|
|
|
/* as hw_addr_type is not UNSET, we expect that we can get an
|
|
|
|
|
* initial address to which to reset. */
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-21 11:22:07 +02:00
|
|
|
return _hw_addr_set (self, addr, "reset", detail);
|
2016-05-20 09:41:40 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-13 15:56:13 +02:00
|
|
|
const char *
|
2016-10-24 12:50:17 +02:00
|
|
|
nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean force_freeze, gboolean *out_is_fake)
|
2016-10-13 15:56:13 +02:00
|
|
|
{
|
|
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2016-10-24 12:50:17 +02:00
|
|
|
|
|
|
|
|
if ( !priv->hw_addr_perm
|
|
|
|
|
&& force_freeze) {
|
|
|
|
|
/* somebody requests a permanent MAC address, but we don't have it set
|
|
|
|
|
* yet. We cannot delay it any longer and try to get it without waiting
|
|
|
|
|
* for UDEV. */
|
|
|
|
|
nm_device_update_permanent_hw_address (self, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-13 15:56:13 +02:00
|
|
|
NM_SET_OUT (out_is_fake, priv->hw_addr_perm && priv->hw_addr_perm_fake);
|
|
|
|
|
return priv->hw_addr_perm;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-03 17:37:26 -05:00
|
|
|
const char *
|
2016-10-13 18:52:12 +02:00
|
|
|
nm_device_get_permanent_hw_address (NMDevice *self)
|
2014-10-03 17:37:26 -05:00
|
|
|
{
|
2016-10-24 12:50:17 +02:00
|
|
|
return nm_device_get_permanent_hw_address_full (self, TRUE, NULL);
|
2014-10-03 17:37:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
nm_device_get_initial_hw_address (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
|
|
|
|
|
2016-06-03 13:37:08 +02:00
|
|
|
return NM_DEVICE_GET_PRIVATE (self)->hw_addr_initial;
|
2014-10-03 17:37:26 -05:00
|
|
|
}
|
|
|
|
|
|
2013-03-13 13:52:55 -04:00
|
|
|
/**
|
|
|
|
|
* nm_device_spec_match_list:
|
2014-07-15 13:36:24 +02:00
|
|
|
* @self: an #NMDevice
|
2013-03-13 13:52:55 -04:00
|
|
|
* @specs: (element-type utf8): a list of device specs
|
|
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Checks if @self matches any of the specifications in @specs. The
|
2013-03-13 13:52:55 -04:00
|
|
|
* currently-supported spec types are:
|
|
|
|
|
*
|
|
|
|
|
* "mac:00:11:22:33:44:55" - matches a device with the given
|
|
|
|
|
* hardware address
|
|
|
|
|
*
|
|
|
|
|
* "interface-name:foo0" - matches a device with the given
|
|
|
|
|
* interface name
|
|
|
|
|
*
|
|
|
|
|
* "s390-subchannels:00.11.22" - matches a device with the given
|
|
|
|
|
* z/VM / s390 subchannels.
|
|
|
|
|
*
|
2013-03-20 09:48:24 -04:00
|
|
|
* "*" - matches any device
|
|
|
|
|
*
|
2014-07-15 13:36:24 +02:00
|
|
|
* Returns: #TRUE if @self matches one of the specs in @specs
|
2013-03-13 13:52:55 -04:00
|
|
|
*/
|
2011-11-17 23:16:50 -06:00
|
|
|
gboolean
|
2014-07-15 13:36:24 +02:00
|
|
|
nm_device_spec_match_list (NMDevice *self, const GSList *specs)
|
2017-06-01 22:32:12 +02:00
|
|
|
{
|
|
|
|
|
return nm_device_spec_match_list_full (self, specs, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nm_device_spec_match_list_full (NMDevice *self, const GSList *specs, int no_match_value)
|
2009-06-11 00:39:12 -04:00
|
|
|
{
|
core: refactor evaluation of device's match-spec
Previously, we would have different functions like
- nm_match_spec_device_type()
- nm_match_spec_hwaddr()
- nm_match_spec_s390_subchannels()
- nm_match_spec_interface_name()
which all would handle one type of match-spec.
So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.
Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.
The upside is:
- the logic how to evaluate the match-spec is all at one place
(match_device_eval()) instead of spread over multiple
functions.
- It requires iterating the list at most twice. Twice, because
we do a fast pre-search for "*".
One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.
(cherry picked from commit b957403efd53ff7d826ac7a4f80487032c03824b)
2017-01-20 19:50:25 +01:00
|
|
|
NMDeviceClass *klass;
|
|
|
|
|
NMMatchSpecMatchType m;
|
2009-06-11 00:39:12 -04:00
|
|
|
|
core: refactor evaluation of device's match-spec
Previously, we would have different functions like
- nm_match_spec_device_type()
- nm_match_spec_hwaddr()
- nm_match_spec_s390_subchannels()
- nm_match_spec_interface_name()
which all would handle one type of match-spec.
So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.
Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.
The upside is:
- the logic how to evaluate the match-spec is all at one place
(match_device_eval()) instead of spread over multiple
functions.
- It requires iterating the list at most twice. Twice, because
we do a fast pre-search for "*".
One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.
(cherry picked from commit b957403efd53ff7d826ac7a4f80487032c03824b)
2017-01-20 19:50:25 +01:00
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
2013-02-12 17:59:37 -05:00
|
|
|
|
core: refactor evaluation of device's match-spec
Previously, we would have different functions like
- nm_match_spec_device_type()
- nm_match_spec_hwaddr()
- nm_match_spec_s390_subchannels()
- nm_match_spec_interface_name()
which all would handle one type of match-spec.
So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.
Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.
The upside is:
- the logic how to evaluate the match-spec is all at one place
(match_device_eval()) instead of spread over multiple
functions.
- It requires iterating the list at most twice. Twice, because
we do a fast pre-search for "*".
One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.
(cherry picked from commit b957403efd53ff7d826ac7a4f80487032c03824b)
2017-01-20 19:50:25 +01:00
|
|
|
klass = NM_DEVICE_GET_CLASS (self);
|
2016-06-15 11:25:29 +02:00
|
|
|
|
core: refactor evaluation of device's match-spec
Previously, we would have different functions like
- nm_match_spec_device_type()
- nm_match_spec_hwaddr()
- nm_match_spec_s390_subchannels()
- nm_match_spec_interface_name()
which all would handle one type of match-spec.
So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.
Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.
The upside is:
- the logic how to evaluate the match-spec is all at one place
(match_device_eval()) instead of spread over multiple
functions.
- It requires iterating the list at most twice. Twice, because
we do a fast pre-search for "*".
One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.
(cherry picked from commit b957403efd53ff7d826ac7a4f80487032c03824b)
2017-01-20 19:50:25 +01:00
|
|
|
m = nm_match_spec_device (specs,
|
|
|
|
|
nm_device_get_iface (self),
|
|
|
|
|
nm_device_get_type_description (self),
|
2017-03-17 16:18:48 +01:00
|
|
|
nm_device_get_driver (self),
|
|
|
|
|
nm_device_get_driver_version (self),
|
core: refactor evaluation of device's match-spec
Previously, we would have different functions like
- nm_match_spec_device_type()
- nm_match_spec_hwaddr()
- nm_match_spec_s390_subchannels()
- nm_match_spec_interface_name()
which all would handle one type of match-spec.
So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.
Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.
The upside is:
- the logic how to evaluate the match-spec is all at one place
(match_device_eval()) instead of spread over multiple
functions.
- It requires iterating the list at most twice. Twice, because
we do a fast pre-search for "*".
One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.
(cherry picked from commit b957403efd53ff7d826ac7a4f80487032c03824b)
2017-01-20 19:50:25 +01:00
|
|
|
nm_device_get_permanent_hw_address (self),
|
|
|
|
|
klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL);
|
2017-06-01 22:32:12 +02:00
|
|
|
|
|
|
|
|
switch (m) {
|
|
|
|
|
case NM_MATCH_SPEC_MATCH:
|
|
|
|
|
return TRUE;
|
|
|
|
|
case NM_MATCH_SPEC_NEG_MATCH:
|
|
|
|
|
return FALSE;
|
|
|
|
|
case NM_MATCH_SPEC_NO_MATCH:
|
|
|
|
|
return no_match_value;
|
|
|
|
|
}
|
|
|
|
|
nm_assert_not_reached ();
|
|
|
|
|
return no_match_value;
|
2013-02-12 17:59:37 -05:00
|
|
|
}
|
|
|
|
|
|
2017-01-19 17:25:29 +01:00
|
|
|
guint
|
|
|
|
|
nm_device_get_supplicant_timeout (NMDevice *self)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSetting8021x *s_8021x;
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
gint timeout;
|
|
|
|
|
#define SUPPLICANT_DEFAULT_TIMEOUT 25
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), SUPPLICANT_DEFAULT_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
connection = nm_device_get_applied_connection (self);
|
|
|
|
|
g_return_val_if_fail (connection, SUPPLICANT_DEFAULT_TIMEOUT);
|
|
|
|
|
s_8021x = nm_connection_get_setting_802_1x (connection);
|
device: avoid assertion in nm_device_get_supplicant_timeout() for Wi-Fi connection
... without 802-1x setting.
NetworkManager[27913]: <trace> [1487689965.7156] device[0x555555bc0060] (wlp3s0): powersave is set to 3
NetworkManager[27913]: <info> [1487689965.7156] Config: added 'ssid' value 'xxx'
NetworkManager[27913]: <info> [1487689965.7156] Config: added 'scan_ssid' value '1'
NetworkManager[27913]: <info> [1487689965.7156] Config: added 'bssid' value 'xxx'
NetworkManager[27913]: <info> [1487689965.7157] Config: added 'key_mgmt' value 'WPA-PSK'
NetworkManager[27913]: <info> [1487689965.7157] Config: added 'psk' value '<hidden>'
NetworkManager[27913]: <debug> [1487689965.7157] sup-iface[0x555555be0010,wlp3s0]: assoc[0x555555ebd800]: starting association...
NetworkManager[27913]: nm_device_get_supplicant_timeout: assertion 's_8021x' failed
(gdb) bt
...
#3 0x00007ffff4c70419 in g_return_if_fail_warning (log_domain=log_domain@entry=0x55555577610e "NetworkManager", pretty_function=pretty_function@entry=0x5555557725e0 <__func__.44436> "nm_device_get_supplicant_timeout", expression=expression@entry=0x5555557725bb "s_8021x") at gmessages.c:2536
#4 0x000055555568af3a in nm_device_get_supplicant_timeout (self=0x555555bc0060 [NMDeviceWifi]) at src/devices/nm-device.c:12963
#5 0x00007fffe88d7f1e in act_stage2_config (device=<optimized out>, reason=0x7fffffffe000) at src/devices/wifi/nm-device-wifi.c:2651
#6 0x00005555556879f1 in activate_stage2_device_config (self=0x555555bc0060 [NMDeviceWifi]) at src/devices/nm-device.c:4320
#7 0x000055555566876b in activation_source_handle_cb (self=self@entry=0x555555bc0060 [NMDeviceWifi], family=family@entry=2) at src/devices/nm-device.c:4060
#8 0x000055555566882e in activation_source_handle_cb4 (user_data=user_data@entry=0x555555bc0060) at src/devices/nm-device.c:3997
#9 0x00007ffff4c658e7 in g_idle_dispatch (source=0x555555e228c0, callback=0x555555668820 <activation_source_handle_cb4>, user_data=0x555555bc0060) at gmain.c:5545
#10 0x00007ffff4c68e52 in g_main_dispatch (context=0x555555a214d0) at gmain.c:3203
#11 0x00007ffff4c68e52 in g_main_context_dispatch (context=context@entry=0x555555a214d0) at gmain.c:3856
#12 0x00007ffff4c691d0 in g_main_context_iterate (context=0x555555a214d0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3929
#13 0x00007ffff4c694f2 in g_main_loop_run (loop=0x555555a1a750) at gmain.c:4125
#14 0x00005555555821fe in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:423
Fixes: 07570e245ac97054027acd928ed09ae2b83e62b0
2017-02-21 16:12:58 +01:00
|
|
|
if (s_8021x) {
|
|
|
|
|
timeout = nm_setting_802_1x_get_auth_timeout (s_8021x);
|
|
|
|
|
if (timeout > 0)
|
|
|
|
|
return timeout;
|
|
|
|
|
}
|
2017-01-19 17:25:29 +01:00
|
|
|
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
|
|
|
|
"802-1x.auth-timeout",
|
|
|
|
|
self);
|
|
|
|
|
return _nm_utils_ascii_str_to_int64 (value, 10, 1, G_MAXINT32,
|
|
|
|
|
SUPPLICANT_DEFAULT_TIMEOUT);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-24 11:11:18 +02:00
|
|
|
gboolean
|
2017-11-02 10:56:30 +01:00
|
|
|
nm_device_auth_retries_try_next (NMDevice *self)
|
2017-10-24 11:11:18 +02:00
|
|
|
{
|
2017-11-02 10:56:30 +01:00
|
|
|
NMDevicePrivate *priv;
|
2017-11-02 09:25:40 +01:00
|
|
|
NMSettingConnection *s_con;
|
2017-11-02 10:56:30 +01:00
|
|
|
int auth_retries;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
auth_retries = priv->auth_retries;
|
2017-10-24 11:11:18 +02:00
|
|
|
|
2017-11-02 09:25:40 +01:00
|
|
|
if (G_UNLIKELY (auth_retries == NM_DEVICE_AUTH_RETRIES_UNSET)) {
|
2017-10-24 11:11:18 +02:00
|
|
|
auth_retries = -1;
|
|
|
|
|
|
2017-11-02 09:25:40 +01:00
|
|
|
s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (self, NM_TYPE_SETTING_CONNECTION));
|
|
|
|
|
if (s_con)
|
|
|
|
|
auth_retries = nm_setting_connection_get_auth_retries (s_con);
|
2017-10-24 11:11:18 +02:00
|
|
|
|
|
|
|
|
if (auth_retries == -1) {
|
|
|
|
|
gs_free char *value = NULL;
|
|
|
|
|
|
|
|
|
|
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
|
2017-11-02 09:25:40 +01:00
|
|
|
"connection.auth-retries",
|
2017-10-24 11:11:18 +02:00
|
|
|
self);
|
|
|
|
|
auth_retries = _nm_utils_ascii_str_to_int64 (value, 10, -1, G_MAXINT32, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (auth_retries == 0)
|
2017-11-02 09:25:40 +01:00
|
|
|
auth_retries = NM_DEVICE_AUTH_RETRIES_INFINITY;
|
2017-10-24 11:11:18 +02:00
|
|
|
else if (auth_retries == -1)
|
2017-11-02 09:25:40 +01:00
|
|
|
auth_retries = NM_DEVICE_AUTH_RETRIES_DEFAULT;
|
2017-10-24 11:11:18 +02:00
|
|
|
else
|
|
|
|
|
nm_assert (auth_retries > 0);
|
|
|
|
|
|
2017-11-02 10:56:30 +01:00
|
|
|
priv->auth_retries = auth_retries;
|
2017-10-24 11:11:18 +02:00
|
|
|
}
|
|
|
|
|
|
2017-11-02 09:25:40 +01:00
|
|
|
if (auth_retries == NM_DEVICE_AUTH_RETRIES_INFINITY)
|
2017-10-24 11:11:18 +02:00
|
|
|
return TRUE;
|
|
|
|
|
if (auth_retries <= 0) {
|
|
|
|
|
nm_assert (auth_retries == 0);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2017-11-02 10:56:30 +01:00
|
|
|
priv->auth_retries--;
|
2017-10-24 11:11:18 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2015-10-06 11:05:14 +02:00
|
|
|
static const char *
|
|
|
|
|
_activation_func_to_string (ActivationHandleFunc func)
|
|
|
|
|
{
|
|
|
|
|
#define FUNC_TO_STRING_CHECK_AND_RETURN(func, f) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
if ((func) == (f)) \
|
|
|
|
|
return #f; \
|
|
|
|
|
} G_STMT_END
|
2015-10-07 12:07:51 +02:00
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage1_device_prepare);
|
|
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage2_device_config);
|
|
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage3_ip_config_start);
|
|
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage4_ip4_config_timeout);
|
|
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage4_ip6_config_timeout);
|
2017-06-01 21:50:40 +02:00
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage5_ip4_config_result);
|
2015-10-07 12:07:51 +02:00
|
|
|
FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage5_ip6_config_commit);
|
2015-10-06 11:05:14 +02:00
|
|
|
g_return_val_if_reached ("unknown");
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-10-06 11:05:14 +02:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
|
|
|
|
nm_device_init (NMDevice *self)
|
|
|
|
|
{
|
2015-12-07 17:05:12 +01:00
|
|
|
NMDevicePrivate *priv;
|
|
|
|
|
|
|
|
|
|
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DEVICE, NMDevicePrivate);
|
|
|
|
|
|
2016-09-05 16:55:07 +02:00
|
|
|
self->_priv = priv;
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
c_list_init (&priv->slaves);
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
priv->netns = g_object_ref (NM_NETNS_GET);
|
|
|
|
|
|
2017-11-07 12:36:17 +01:00
|
|
|
priv->autoconnect_blocked_flags = DEFAULT_AUTOCONNECT
|
|
|
|
|
? NM_DEVICE_AUTOCONNECT_BLOCKED_NONE
|
|
|
|
|
: NM_DEVICE_AUTOCONNECT_BLOCKED_USER;
|
|
|
|
|
|
2017-11-02 10:56:30 +01:00
|
|
|
priv->auth_retries = NM_DEVICE_AUTH_RETRIES_UNSET;
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->type = NM_DEVICE_TYPE_UNKNOWN;
|
|
|
|
|
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
|
|
|
|
|
priv->state = NM_DEVICE_STATE_UNMANAGED;
|
|
|
|
|
priv->state_reason = NM_DEVICE_STATE_REASON_NONE;
|
|
|
|
|
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT;
|
|
|
|
|
priv->unmanaged_mask = priv->unmanaged_flags;
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
|
2017-10-13 16:12:35 +02:00
|
|
|
priv->ip6_saved_properties = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_free);
|
2017-03-13 15:34:14 +01:00
|
|
|
priv->sys_iface_state = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL;
|
2014-11-18 16:29:05 +01:00
|
|
|
|
2015-07-22 11:40:35 +02:00
|
|
|
priv->v4_commit_first_time = TRUE;
|
|
|
|
|
priv->v6_commit_first_time = TRUE;
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
2015-12-09 10:29:15 +01:00
|
|
|
static GObject*
|
|
|
|
|
constructor (GType type,
|
|
|
|
|
guint n_construct_params,
|
|
|
|
|
GObjectConstructParam *construct_params)
|
|
|
|
|
{
|
|
|
|
|
GObject *object;
|
|
|
|
|
GObjectClass *klass;
|
|
|
|
|
NMDevice *self;
|
|
|
|
|
NMDevicePrivate *priv;
|
2015-12-08 14:49:50 +01:00
|
|
|
const NMPlatformLink *pllink;
|
|
|
|
|
|
2015-12-09 10:29:15 +01:00
|
|
|
klass = G_OBJECT_CLASS (nm_device_parent_class);
|
|
|
|
|
object = klass->constructor (type, n_construct_params, construct_params);
|
|
|
|
|
if (!object)
|
|
|
|
|
return NULL;
|
2015-12-08 14:49:50 +01:00
|
|
|
|
2015-12-09 10:29:15 +01:00
|
|
|
self = NM_DEVICE (object);
|
|
|
|
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-12-08 14:49:50 +01:00
|
|
|
|
2016-05-20 12:34:13 +02:00
|
|
|
if ( priv->iface
|
|
|
|
|
&& G_LIKELY (!nm_utils_get_testing ())) {
|
2017-04-17 20:17:45 +02:00
|
|
|
pllink = nm_platform_link_get_by_ifname (nm_device_get_platform (self), priv->iface);
|
2015-12-08 14:49:50 +01:00
|
|
|
|
|
|
|
|
if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) {
|
|
|
|
|
priv->ifindex = pllink->ifindex;
|
2016-02-29 15:52:27 +01:00
|
|
|
priv->up = NM_FLAGS_HAS (pllink->n_ifi_flags, IFF_UP);
|
2015-12-08 14:49:50 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-06-15 11:25:29 +02:00
|
|
|
if (priv->hw_addr_perm) {
|
2016-10-13 17:51:07 +02:00
|
|
|
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
|
|
|
|
|
gsize l;
|
|
|
|
|
|
|
|
|
|
if (!_nm_utils_hwaddr_aton (priv->hw_addr_perm, buf, sizeof (buf), &l)) {
|
2016-06-15 11:25:29 +02:00
|
|
|
g_clear_pointer (&priv->hw_addr_perm, g_free);
|
|
|
|
|
g_return_val_if_reached (object);
|
2016-05-20 12:34:13 +02:00
|
|
|
}
|
2016-06-15 11:25:29 +02:00
|
|
|
|
2016-10-26 12:20:12 +02:00
|
|
|
priv->hw_addr_len_ = l;
|
2016-10-13 17:51:07 +02:00
|
|
|
priv->hw_addr = nm_utils_hwaddr_ntoa (buf, l);
|
2016-06-15 11:25:29 +02:00
|
|
|
_LOGT (LOGD_DEVICE, "hw-addr: has permanent hw-address '%s'", priv->hw_addr_perm);
|
2016-05-20 12:34:13 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-09 10:29:15 +01:00
|
|
|
return object;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
constructed (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (object);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMPlatform *platform;
|
|
|
|
|
|
2014-09-24 17:46:15 -05:00
|
|
|
if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
|
|
|
|
|
priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
/* Watch for external IP config changes */
|
2017-04-17 20:17:45 +02:00
|
|
|
platform = nm_device_get_platform (self);
|
2015-06-24 15:54:44 +02:00
|
|
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self);
|
|
|
|
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self);
|
|
|
|
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self);
|
|
|
|
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self);
|
2014-07-15 13:36:24 +02:00
|
|
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
priv->settings = g_object_ref (NM_SETTINGS_GET);
|
|
|
|
|
g_assert (priv->settings);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
g_signal_connect (priv->settings,
|
|
|
|
|
NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
|
|
|
|
|
G_CALLBACK (cp_connection_added),
|
2014-07-15 13:36:24 +02:00
|
|
|
self);
|
2016-05-16 18:40:44 +02:00
|
|
|
g_signal_connect (priv->settings,
|
|
|
|
|
NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
|
|
|
|
|
G_CALLBACK (cp_connection_updated),
|
|
|
|
|
self);
|
|
|
|
|
g_signal_connect (priv->settings,
|
|
|
|
|
NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
|
|
|
|
|
G_CALLBACK (cp_connection_removed),
|
2014-07-15 13:36:24 +02:00
|
|
|
self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
|
2015-08-11 13:35:02 +02:00
|
|
|
|
|
|
|
|
_LOGD (LOGD_DEVICE, "constructed (%s)", G_OBJECT_TYPE_NAME (self));
|
2014-05-20 15:03:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dispose (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *self = NM_DEVICE (object);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
NMPlatform *platform;
|
|
|
|
|
|
2015-08-11 13:35:02 +02:00
|
|
|
_LOGD (LOGD_DEVICE, "disposing");
|
2014-12-18 10:23:06 -06:00
|
|
|
|
2017-03-13 12:02:09 +01:00
|
|
|
nm_clear_g_cancellable (&priv->deactivating_cancellable);
|
|
|
|
|
|
manager: fix preserving assume state during activation
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
2017-06-07 17:34:47 +02:00
|
|
|
nm_device_assume_state_reset (self);
|
|
|
|
|
|
2016-12-26 11:12:39 +01:00
|
|
|
_parent_set_ifindex (self, 0, FALSE);
|
|
|
|
|
|
2017-04-17 20:17:45 +02:00
|
|
|
platform = nm_device_get_platform (self);
|
2016-05-05 12:19:20 +02:00
|
|
|
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
|
|
|
|
|
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
|
2017-03-16 14:27:03 +00:00
|
|
|
|
2015-12-23 14:15:05 +01:00
|
|
|
g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy);
|
|
|
|
|
priv->arping.dad_list = NULL;
|
|
|
|
|
|
|
|
|
|
arp_cleanup (self);
|
|
|
|
|
|
2017-04-14 17:46:20 +02:00
|
|
|
nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id);
|
2015-04-17 14:12:10 +02:00
|
|
|
|
2014-05-20 17:10:42 -05:00
|
|
|
dispatcher_cleanup (self);
|
|
|
|
|
|
2017-04-21 15:46:56 +02:00
|
|
|
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
|
|
|
|
|
&priv->pacrunner_call_id);
|
2016-08-16 05:55:58 +05:30
|
|
|
g_clear_object (&priv->pacrunner_manager);
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
_cleanup_generic_pre (self, CLEANUP_TYPE_KEEP);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
g_warn_if_fail (c_list_is_empty (&priv->slaves));
|
2014-05-20 15:03:27 -05:00
|
|
|
g_assert (priv->master_ready_id == 0);
|
|
|
|
|
|
2014-07-24 17:14:30 -05:00
|
|
|
/* Let the kernel manage IPv6LL again */
|
|
|
|
|
set_nm_ipv6ll (self, FALSE);
|
|
|
|
|
|
2015-06-30 16:13:03 +02:00
|
|
|
_cleanup_generic_post (self, CLEANUP_TYPE_KEEP);
|
2009-07-15 13:53:49 -04:00
|
|
|
|
2015-02-08 10:07:11 +01:00
|
|
|
g_hash_table_remove_all (priv->ip6_saved_properties);
|
2009-07-15 13:53:49 -04:00
|
|
|
|
2016-01-04 09:46:22 +01:00
|
|
|
nm_clear_g_source (&priv->recheck_assume_id);
|
|
|
|
|
nm_clear_g_source (&priv->recheck_available.call_id);
|
2015-04-13 17:16:55 -05:00
|
|
|
|
2016-01-19 11:33:33 +01:00
|
|
|
nm_clear_g_source (&priv->check_delete_unrealized_id);
|
|
|
|
|
|
2016-08-16 12:10:23 +02:00
|
|
|
nm_clear_g_source (&priv->stats.timeout_id);
|
|
|
|
|
|
2017-05-12 16:21:55 +02:00
|
|
|
carrier_disconnected_action_cancel (self);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2016-12-26 11:12:39 +01:00
|
|
|
if (priv->ifindex > 0) {
|
|
|
|
|
priv->ifindex = 0;
|
|
|
|
|
_notify (self, PROP_IFINDEX);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-16 18:40:44 +02:00
|
|
|
if (priv->settings) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self);
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self);
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self);
|
2009-07-15 13:53:49 -04:00
|
|
|
}
|
|
|
|
|
|
2016-01-20 17:44:50 +01:00
|
|
|
available_connections_del_all (self);
|
2012-05-14 15:32:54 +02:00
|
|
|
|
device: fix delaying startup complete waiting for carrier
platform: signal: link changed: 2: eth0 <DOWN;broadcast,multicast> mtu ...
...
device[0x7f90c29c64d0] (eth0): bringing up device
...
platform: signal: link changed: 2: eth0 <UP,LOWER_UP;broadcast,multicast,up,running,lowerup> mtu ...
...
device (eth0): link connected
...
device[0x7f90c29c64d0] (eth0): add_pending_action (2): 'carrier wait'
Note how we schedule the pending action 'carrier-wait', although the device
already has carrier. That means, the pending action will not be removed
until timeout, 5 seconds later.
Avoid scheduling 'carrier-wait' if we already have carrier.
However, don't just add the pending action 'carrier-wait' only during
nm_device_bring_up(). Instead, always schedule the carrier_wait timeout.
This gives a grace period during which we keep setting 'carrier-wait' whenever
we have no carrier. This should prevent two cases:
- during nm_device_bring_up() the platform state might not yet have
caught up. If we don't add the pending action there, we will add
it a moment later when carrier goes away.
- bringing the interface up might cause carrier to get lost for a
moment (flapping). If that happens within the timeout, also add the
pending action.
2017-05-12 16:32:15 +02:00
|
|
|
if (nm_clear_g_source (&priv->carrier_wait_id))
|
|
|
|
|
nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
|
2009-09-16 13:18:24 +02:00
|
|
|
|
2015-02-20 23:45:23 +01:00
|
|
|
_clear_queued_act_request (priv);
|
2014-03-05 10:16:39 -06:00
|
|
|
|
2015-06-17 19:13:08 +02:00
|
|
|
nm_clear_g_source (&priv->device_link_changed_id);
|
|
|
|
|
nm_clear_g_source (&priv->device_ip_link_changed_id);
|
|
|
|
|
|
2015-10-07 11:48:38 +02:00
|
|
|
if (priv->lldp_listener) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->lldp_listener,
|
|
|
|
|
G_CALLBACK (lldp_neighbors_changed),
|
|
|
|
|
self);
|
|
|
|
|
nm_lldp_listener_stop (priv->lldp_listener);
|
|
|
|
|
g_clear_object (&priv->lldp_listener);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
|
2016-01-19 12:53:34 +01:00
|
|
|
|
|
|
|
|
if (nm_clear_g_source (&priv->queued_state.id)) {
|
|
|
|
|
/* FIXME: we'd expect the queud_state to be alredy cleared and this statement
|
|
|
|
|
* not being necessary. Add this check here to hopefully investigate crash
|
|
|
|
|
* rh#1270247. */
|
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
}
|
2012-08-01 11:16:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-05-20 15:03:27 -05:00
|
|
|
finalize (GObject *object)
|
2012-08-01 11:16:48 -06:00
|
|
|
{
|
2014-05-20 15:03:27 -05:00
|
|
|
NMDevice *self = NM_DEVICE (object);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2014-02-12 23:54:26 +01:00
|
|
|
_LOGD (LOGD_DEVICE, "finalize(): %s", G_OBJECT_TYPE_NAME (self));
|
|
|
|
|
|
2014-06-21 12:44:56 -04:00
|
|
|
g_free (priv->hw_addr);
|
2016-06-03 13:37:08 +02:00
|
|
|
g_free (priv->hw_addr_perm);
|
|
|
|
|
g_free (priv->hw_addr_initial);
|
2017-01-27 15:41:25 +01:00
|
|
|
g_slist_free (priv->pending_actions);
|
2015-10-03 19:50:30 +02:00
|
|
|
g_slist_free_full (priv->dad6_failed_addrs, g_free);
|
2014-05-22 14:04:01 -05:00
|
|
|
g_clear_pointer (&priv->physical_port_id, g_free);
|
2014-05-20 15:03:27 -05:00
|
|
|
g_free (priv->udi);
|
|
|
|
|
g_free (priv->iface);
|
|
|
|
|
g_free (priv->ip_iface);
|
|
|
|
|
g_free (priv->driver);
|
|
|
|
|
g_free (priv->driver_version);
|
|
|
|
|
g_free (priv->firmware_version);
|
|
|
|
|
g_free (priv->type_desc);
|
2015-05-15 15:00:07 +02:00
|
|
|
g_free (priv->type_description);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_free (priv->dhcp_anycast_address);
|
2016-12-18 13:54:26 +01:00
|
|
|
g_free (priv->current_stable_id);
|
2014-05-20 15:03:27 -05:00
|
|
|
|
2015-02-08 10:07:11 +01:00
|
|
|
g_hash_table_unref (priv->ip6_saved_properties);
|
|
|
|
|
g_hash_table_unref (priv->available_connections);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
|
2016-05-16 18:40:44 +02:00
|
|
|
|
|
|
|
|
/* for testing, NMDeviceTest does not invoke NMDevice::constructed,
|
|
|
|
|
* and thus @settings might be unset. */
|
|
|
|
|
if (priv->settings)
|
|
|
|
|
g_object_unref (priv->settings);
|
2017-04-17 20:17:45 +02:00
|
|
|
|
|
|
|
|
g_object_unref (priv->netns);
|
2012-08-01 11:16:48 -06:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
|
|
|
|
set_property (GObject *object, guint prop_id,
|
|
|
|
|
const GValue *value, GParamSpec *pspec)
|
2013-11-04 19:51:28 -06:00
|
|
|
{
|
2016-05-20 12:34:13 +02:00
|
|
|
NMDevice *self = (NMDevice *) object;
|
2014-07-15 13:36:24 +02:00
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
2015-05-15 15:00:07 +02:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_UDI:
|
2017-05-17 15:01:10 +02:00
|
|
|
/* construct-only */
|
|
|
|
|
priv->udi = g_value_dup_string (value);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_IFACE:
|
2016-09-26 13:26:15 +02:00
|
|
|
/* construct-only */
|
2015-12-08 14:49:50 +01:00
|
|
|
priv->iface = g_value_dup_string (value);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DRIVER:
|
2017-01-20 17:33:44 +01:00
|
|
|
/* construct-only */
|
|
|
|
|
priv->driver = g_value_dup_string (value);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DRIVER_VERSION:
|
2017-01-20 17:33:44 +01:00
|
|
|
/* construct-only */
|
2016-05-30 16:11:28 +02:00
|
|
|
priv->driver_version = g_value_dup_string (value);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_FIRMWARE_VERSION:
|
2017-01-20 17:33:44 +01:00
|
|
|
/* construct-only */
|
2016-05-30 16:11:28 +02:00
|
|
|
priv->firmware_version = g_value_dup_string (value);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_IP4_ADDRESS:
|
|
|
|
|
priv->ip4_address = g_value_get_uint (value);
|
|
|
|
|
break;
|
2016-08-30 14:58:52 +02:00
|
|
|
case PROP_MANAGED:
|
|
|
|
|
if (nm_device_is_real (self)) {
|
|
|
|
|
gboolean managed;
|
|
|
|
|
NMDeviceStateReason reason;
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
|
2016-08-30 14:58:52 +02:00
|
|
|
managed = g_value_get_boolean (value);
|
2017-05-19 17:34:23 +02:00
|
|
|
if (managed) {
|
2016-08-30 14:58:52 +02:00
|
|
|
reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED;
|
2017-05-19 17:34:23 +02:00
|
|
|
if (NM_IN_SET_TYPED (NMDeviceSysIfaceState,
|
|
|
|
|
priv->sys_iface_state,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_REMOVED))
|
|
|
|
|
nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_ASSUME);
|
|
|
|
|
} else {
|
2016-08-30 14:58:52 +02:00
|
|
|
reason = NM_DEVICE_STATE_REASON_REMOVED;
|
2017-04-18 14:46:27 +02:00
|
|
|
nm_device_sys_iface_state_set (self, NM_DEVICE_SYS_IFACE_STATE_REMOVED);
|
|
|
|
|
}
|
2016-08-30 14:58:52 +02:00
|
|
|
nm_device_set_unmanaged_by_flags (self,
|
|
|
|
|
NM_UNMANAGED_USER_EXPLICIT,
|
|
|
|
|
!managed,
|
|
|
|
|
reason);
|
|
|
|
|
}
|
2015-09-15 14:27:31 +02:00
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_AUTOCONNECT:
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
if (g_value_get_boolean (value))
|
|
|
|
|
nm_device_autoconnect_blocked_unset (self, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL);
|
|
|
|
|
else
|
|
|
|
|
nm_device_autoconnect_blocked_set (self, NM_DEVICE_AUTOCONNECT_BLOCKED_USER);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_FIRMWARE_MISSING:
|
2016-09-26 13:26:15 +02:00
|
|
|
/* construct-only */
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->firmware_missing = g_value_get_boolean (value);
|
|
|
|
|
break;
|
2015-04-14 14:16:04 +02:00
|
|
|
case PROP_NM_PLUGIN_MISSING:
|
2016-09-26 13:26:15 +02:00
|
|
|
/* construct-only */
|
2015-04-14 14:16:04 +02:00
|
|
|
priv->nm_plugin_missing = g_value_get_boolean (value);
|
|
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_DEVICE_TYPE:
|
2017-01-20 17:33:44 +01:00
|
|
|
/* construct-only */
|
|
|
|
|
nm_assert (priv->type == NM_DEVICE_TYPE_UNKNOWN);
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->type = g_value_get_uint (value);
|
|
|
|
|
break;
|
2015-12-08 14:49:50 +01:00
|
|
|
case PROP_LINK_TYPE:
|
2016-09-26 13:26:15 +02:00
|
|
|
/* construct-only */
|
2017-01-20 17:33:44 +01:00
|
|
|
nm_assert (priv->link_type == NM_LINK_TYPE_NONE);
|
2015-12-08 14:49:50 +01:00
|
|
|
priv->link_type = g_value_get_uint (value);
|
|
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_TYPE_DESC:
|
2017-01-20 17:33:44 +01:00
|
|
|
/* construct-only */
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->type_desc = g_value_dup_string (value);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_RFKILL_TYPE:
|
2017-01-20 17:33:44 +01:00
|
|
|
/* construct-only */
|
2014-05-20 15:03:27 -05:00
|
|
|
priv->rfkill_type = g_value_get_uint (value);
|
|
|
|
|
break;
|
2016-06-15 11:25:29 +02:00
|
|
|
case PROP_PERM_HW_ADDRESS:
|
2016-09-26 13:26:15 +02:00
|
|
|
/* construct-only */
|
2016-06-15 11:25:29 +02:00
|
|
|
priv->hw_addr_perm = g_value_dup_string (value);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
2016-08-16 12:10:23 +02:00
|
|
|
case PROP_REFRESH_RATE_MS:
|
|
|
|
|
_stats_set_refresh_rate (self, g_value_get_uint (value));
|
2016-08-10 11:54:31 +02:00
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
2013-11-04 19:51:28 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
|
|
|
|
get_property (GObject *object, guint prop_id,
|
2015-12-02 10:53:16 +01:00
|
|
|
GValue *value, GParamSpec *pspec)
|
2012-08-01 11:16:48 -06:00
|
|
|
{
|
2014-05-20 15:03:27 -05:00
|
|
|
NMDevice *self = NM_DEVICE (object);
|
|
|
|
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
|
|
|
GPtrArray *array;
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
NMConnection *connection;
|
2015-10-07 11:48:38 +02:00
|
|
|
GVariantBuilder array_builder;
|
2013-11-04 19:51:28 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_UDI:
|
2017-05-16 14:11:07 +02:00
|
|
|
/* UDI is (depending on the device type) a path to sysfs and can contain
|
|
|
|
|
* non-UTF-8.
|
|
|
|
|
* ip link add name $'d\xccf\\c' type dummy */
|
|
|
|
|
g_value_take_string (value,
|
|
|
|
|
nm_utils_str_utf8safe_escape_cp (priv->udi,
|
|
|
|
|
NM_UTILS_STR_UTF8_SAFE_FLAG_NONE));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_IFACE:
|
2017-05-16 14:11:07 +02:00
|
|
|
g_value_take_string (value,
|
|
|
|
|
nm_utils_str_utf8safe_escape_cp (priv->iface,
|
|
|
|
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_IP_IFACE:
|
2017-05-16 14:11:07 +02:00
|
|
|
if (ip_config_valid (priv->state)) {
|
|
|
|
|
g_value_take_string (value,
|
|
|
|
|
nm_utils_str_utf8safe_escape_cp (nm_device_get_ip_iface (self),
|
|
|
|
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
|
|
|
|
} else
|
2014-05-20 15:03:27 -05:00
|
|
|
g_value_set_string (value, NULL);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_IFINDEX:
|
|
|
|
|
g_value_set_int (value, priv->ifindex);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_DRIVER:
|
2017-05-16 14:11:07 +02:00
|
|
|
g_value_take_string (value,
|
|
|
|
|
nm_utils_str_utf8safe_escape_cp (priv->driver,
|
|
|
|
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DRIVER_VERSION:
|
2017-05-16 14:11:07 +02:00
|
|
|
g_value_take_string (value,
|
|
|
|
|
nm_utils_str_utf8safe_escape_cp (priv->driver_version,
|
|
|
|
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_FIRMWARE_VERSION:
|
2017-05-16 14:11:07 +02:00
|
|
|
g_value_take_string (value,
|
|
|
|
|
nm_utils_str_utf8safe_escape_cp (priv->firmware_version,
|
|
|
|
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_CAPABILITIES:
|
|
|
|
|
g_value_set_uint (value, (priv->capabilities & ~NM_DEVICE_CAP_INTERNAL_MASK));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_IP4_ADDRESS:
|
|
|
|
|
g_value_set_uint (value, priv->ip4_address);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_CARRIER:
|
|
|
|
|
g_value_set_boolean (value, priv->carrier);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MTU:
|
|
|
|
|
g_value_set_uint (value, priv->mtu);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_IP4_CONFIG:
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip4_config : NULL);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DHCP4_CONFIG:
|
2016-04-07 14:34:31 +02:00
|
|
|
nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4.config : NULL);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_IP6_CONFIG:
|
2015-04-03 10:08:52 -04:00
|
|
|
nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip6_config : NULL);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DHCP6_CONFIG:
|
2016-04-07 14:45:57 +02:00
|
|
|
nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6.config : NULL);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_STATE:
|
|
|
|
|
g_value_set_uint (value, priv->state);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_STATE_REASON:
|
2015-04-15 14:53:30 -04:00
|
|
|
g_value_take_variant (value,
|
|
|
|
|
g_variant_new ("(uu)", priv->state, priv->state_reason));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_ACTIVE_CONNECTION:
|
2017-01-24 19:43:52 +01:00
|
|
|
nm_utils_g_value_set_object_path (value, priv->act_request_public ? priv->act_request : NULL);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DEVICE_TYPE:
|
|
|
|
|
g_value_set_uint (value, priv->type);
|
|
|
|
|
break;
|
2015-12-08 14:49:50 +01:00
|
|
|
case PROP_LINK_TYPE:
|
|
|
|
|
g_value_set_uint (value, priv->link_type);
|
|
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_MANAGED:
|
device: remove default-unmanaged and refactor unmanaged flags
Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.
Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.
Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.
Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).
Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.
Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.
https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
|
|
|
/* The managed state exposed on D-Bus only depends on the current device state alone. */
|
|
|
|
|
g_value_set_boolean (value, nm_device_get_state (self) > NM_DEVICE_STATE_UNMANAGED);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_AUTOCONNECT:
|
device: refactor autoconnect blocking by introducing NMDeviceAutoconnectBlockedFlags enum
The flags allow for more then two reasons. Currently the only reasons
for allowing or disallowing autoconnect are "user" and "intern".
It's a bit odd, that NMDeviceAutoconnectBlockedFlags has a negative
meaning. So
nm_device_set_autoconnect_intern (device, FALSE);
gets replaced by
nm_device_set_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_INTERN);
and so on.
However, it's chosen this way, because autoconnect shall be allowed,
unless any blocked-reason is set. That is, to check whether autoconnect
is allowed, we do
if (!nm_device_get_autoconnect_blocked (device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL))
The alternative check would be
if (nm_device_get_autoconnect_allowed (device, NM_DEVICE_AUTOCONNECT_ALLOWED_ALL) == NM_DEVICE_AUTOCONNECT_ALLOWED_ALL)
which seems odd too.
So, add the inverse flags to block autoconnect.
Beside refactoring and inverting the meaning of the autoconnect
settings, there is no change in behavior.
2017-11-07 10:48:55 +01:00
|
|
|
g_value_set_boolean (value,
|
|
|
|
|
nm_device_autoconnect_blocked_get (self, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL)
|
|
|
|
|
? FALSE
|
|
|
|
|
: TRUE);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_FIRMWARE_MISSING:
|
|
|
|
|
g_value_set_boolean (value, priv->firmware_missing);
|
|
|
|
|
break;
|
2015-04-14 14:16:04 +02:00
|
|
|
case PROP_NM_PLUGIN_MISSING:
|
|
|
|
|
g_value_set_boolean (value, priv->nm_plugin_missing);
|
|
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_TYPE_DESC:
|
|
|
|
|
g_value_set_string (value, priv->type_desc);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_RFKILL_TYPE:
|
|
|
|
|
g_value_set_uint (value, priv->rfkill_type);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_AVAILABLE_CONNECTIONS:
|
|
|
|
|
array = g_ptr_array_sized_new (g_hash_table_size (priv->available_connections));
|
|
|
|
|
g_hash_table_iter_init (&iter, priv->available_connections);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL))
|
|
|
|
|
g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection)));
|
2015-04-15 14:53:30 -04:00
|
|
|
g_ptr_array_add (array, NULL);
|
|
|
|
|
g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_PHYSICAL_PORT_ID:
|
|
|
|
|
g_value_set_string (value, priv->physical_port_id);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MASTER:
|
2015-08-06 13:23:56 +02:00
|
|
|
g_value_set_object (value, nm_device_get_master (self));
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
2016-12-26 11:12:39 +01:00
|
|
|
case PROP_PARENT:
|
|
|
|
|
nm_utils_g_value_set_object_path (value, priv->parent_device);
|
|
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_HW_ADDRESS:
|
2014-06-21 12:44:56 -04:00
|
|
|
g_value_set_string (value, priv->hw_addr);
|
2014-05-20 15:03:27 -05:00
|
|
|
break;
|
2016-10-13 18:52:12 +02:00
|
|
|
case PROP_PERM_HW_ADDRESS: {
|
|
|
|
|
const char *perm_hw_addr;
|
|
|
|
|
gboolean perm_hw_addr_is_fake;
|
|
|
|
|
|
2016-10-24 12:50:17 +02:00
|
|
|
perm_hw_addr = nm_device_get_permanent_hw_address_full (self, FALSE, &perm_hw_addr_is_fake);
|
2016-06-17 18:53:45 +02:00
|
|
|
/* this property is exposed on D-Bus for NMDeviceEthernet and NMDeviceWifi. */
|
2016-10-13 18:52:12 +02:00
|
|
|
g_value_set_string (value, perm_hw_addr && !perm_hw_addr_is_fake ? perm_hw_addr : NULL);
|
2016-06-17 18:53:45 +02:00
|
|
|
break;
|
2016-10-13 18:52:12 +02:00
|
|
|
}
|
2014-05-20 15:03:27 -05:00
|
|
|
case PROP_HAS_PENDING_ACTION:
|
|
|
|
|
g_value_set_boolean (value, nm_device_has_pending_action (self));
|
|
|
|
|
break;
|
2015-04-29 16:34:38 +02:00
|
|
|
case PROP_METERED:
|
|
|
|
|
g_value_set_uint (value, priv->metered);
|
|
|
|
|
break;
|
2015-10-07 11:48:38 +02:00
|
|
|
case PROP_LLDP_NEIGHBORS:
|
|
|
|
|
if (priv->lldp_listener)
|
|
|
|
|
g_value_set_variant (value, nm_lldp_listener_get_neighbors (priv->lldp_listener));
|
|
|
|
|
else {
|
|
|
|
|
g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
|
|
|
|
|
g_value_take_variant (value, g_variant_builder_end (&array_builder));
|
|
|
|
|
}
|
|
|
|
|
break;
|
2014-09-05 08:50:02 -05:00
|
|
|
case PROP_REAL:
|
2016-01-12 10:38:16 +01:00
|
|
|
g_value_set_boolean (value, nm_device_is_real (self));
|
2014-09-05 08:50:02 -05:00
|
|
|
break;
|
2015-12-02 10:33:19 +01:00
|
|
|
case PROP_SLAVES: {
|
2017-05-13 21:57:51 +02:00
|
|
|
CList *slave_iter;
|
2015-12-02 10:33:19 +01:00
|
|
|
char **slave_list;
|
2017-05-13 21:57:51 +02:00
|
|
|
gsize i, n;
|
2015-12-02 10:33:19 +01:00
|
|
|
|
2017-05-13 21:57:51 +02:00
|
|
|
n = c_list_length (&priv->slaves);
|
|
|
|
|
slave_list = g_new (char *, n + 1);
|
|
|
|
|
i = 0;
|
|
|
|
|
c_list_for_each (slave_iter, &priv->slaves) {
|
|
|
|
|
SlaveInfo *info = c_list_entry (slave_iter, SlaveInfo, lst_slave);
|
2015-12-02 10:33:19 +01:00
|
|
|
const char *path;
|
|
|
|
|
|
2015-12-02 10:53:16 +01:00
|
|
|
if (!NM_DEVICE_GET_PRIVATE (info->slave)->is_enslaved)
|
|
|
|
|
continue;
|
2015-12-02 10:33:19 +01:00
|
|
|
path = nm_exported_object_get_path ((NMExportedObject *) info->slave);
|
|
|
|
|
if (path)
|
|
|
|
|
slave_list[i++] = g_strdup (path);
|
|
|
|
|
}
|
2017-05-13 21:57:51 +02:00
|
|
|
nm_assert (i <= n);
|
2015-12-02 10:33:19 +01:00
|
|
|
slave_list[i] = NULL;
|
|
|
|
|
g_value_take_boxed (value, slave_list);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-08-10 11:54:31 +02:00
|
|
|
case PROP_REFRESH_RATE_MS:
|
2016-08-16 11:35:23 +02:00
|
|
|
g_value_set_uint (value, priv->stats.refresh_rate_ms);
|
2016-08-10 11:54:31 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_TX_BYTES:
|
2016-08-16 11:35:23 +02:00
|
|
|
g_value_set_uint64 (value, priv->stats.tx_bytes);
|
2016-08-10 11:54:31 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_RX_BYTES:
|
2016-08-16 11:35:23 +02:00
|
|
|
g_value_set_uint64 (value, priv->stats.rx_bytes);
|
2016-08-10 11:54:31 +02:00
|
|
|
break;
|
2017-03-20 13:36:00 +00:00
|
|
|
case PROP_CONNECTIVITY:
|
|
|
|
|
g_value_set_uint (value, priv->connectivity_state);
|
|
|
|
|
break;
|
2014-05-20 15:03:27 -05:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-01 11:16:48 -06:00
|
|
|
}
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
static void
|
|
|
|
|
nm_device_class_init (NMDeviceClass *klass)
|
2012-08-01 11:16:48 -06:00
|
|
|
{
|
2014-05-20 15:03:27 -05:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2015-04-03 10:08:52 -04:00
|
|
|
NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (klass);
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
g_type_class_add_private (object_class, sizeof (NMDevicePrivate));
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2017-01-03 15:27:23 +01:00
|
|
|
exported_object_class->export_path = NM_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/Devices");
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
object_class->dispose = dispose;
|
|
|
|
|
object_class->finalize = finalize;
|
|
|
|
|
object_class->set_property = set_property;
|
|
|
|
|
object_class->get_property = get_property;
|
2015-12-09 10:29:15 +01:00
|
|
|
object_class->constructor = constructor;
|
2014-05-20 15:03:27 -05:00
|
|
|
object_class->constructed = constructed;
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
klass->link_changed = link_changed;
|
2012-08-01 11:16:48 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
klass->is_available = is_available;
|
|
|
|
|
klass->act_stage1_prepare = act_stage1_prepare;
|
|
|
|
|
klass->act_stage2_config = act_stage2_config;
|
|
|
|
|
klass->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
|
|
|
|
|
klass->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
|
|
|
|
|
klass->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
|
|
|
|
|
klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
|
2013-09-03 15:34:56 -05:00
|
|
|
|
2015-05-15 15:00:07 +02:00
|
|
|
klass->get_type_description = get_type_description;
|
2014-05-20 15:03:27 -05:00
|
|
|
klass->can_auto_connect = can_auto_connect;
|
|
|
|
|
klass->check_connection_compatible = check_connection_compatible;
|
|
|
|
|
klass->check_connection_available = check_connection_available;
|
2015-04-07 14:24:12 +02:00
|
|
|
klass->can_unmanaged_external_down = can_unmanaged_external_down;
|
2016-01-08 17:24:24 +01:00
|
|
|
klass->realize_start_notify = realize_start_notify;
|
2016-01-10 15:18:31 +01:00
|
|
|
klass->unrealize_notify = unrealize_notify;
|
2017-05-12 16:17:18 +02:00
|
|
|
klass->carrier_changed_notify = carrier_changed_notify;
|
2014-04-10 15:29:45 -05:00
|
|
|
klass->get_ip_iface_identifier = get_ip_iface_identifier;
|
2016-06-21 11:04:38 +02:00
|
|
|
klass->unmanaged_on_quit = unmanaged_on_quit;
|
2016-06-30 11:42:28 +02:00
|
|
|
klass->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
|
2016-12-26 11:12:39 +01:00
|
|
|
klass->parent_changed_notify = parent_changed_notify;
|
2017-03-03 12:06:58 +01:00
|
|
|
klass->can_reapply_change = can_reapply_change;
|
|
|
|
|
klass->reapply_connection = reapply_connection;
|
2013-09-03 15:34:56 -05:00
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_UDI] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_UDI, "", "",
|
|
|
|
|
NULL,
|
2017-05-17 15:01:10 +02:00
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
2016-02-29 13:13:54 +01:00
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_IFACE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_IFACE, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_IP_IFACE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_IP_IFACE, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_DRIVER] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_DRIVER, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_DRIVER_VERSION] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_FIRMWARE_VERSION] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "",
|
|
|
|
|
NULL,
|
2016-02-29 13:37:15 +01:00
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
2016-02-29 13:13:54 +01:00
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_CAPABILITIES] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_CAPABILITIES, "", "",
|
|
|
|
|
0, G_MAXUINT32, NM_DEVICE_CAP_NONE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_CARRIER] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_CARRIER, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_MTU] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_MTU, "", "",
|
|
|
|
|
0, G_MAXUINT32, 1500,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_IP4_ADDRESS] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, "", "",
|
|
|
|
|
0, G_MAXUINT32, 0, /* FIXME */
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_IP4_CONFIG] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_IP4_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_DHCP4_CONFIG] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_DHCP4_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_IP6_CONFIG] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_IP6_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_DHCP6_CONFIG] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_DHCP6_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_STATE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_STATE, "", "",
|
|
|
|
|
0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_STATE_REASON] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_variant (NM_DEVICE_STATE_REASON, "", "",
|
|
|
|
|
G_VARIANT_TYPE ("(uu)"),
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_ACTIVE_CONNECTION] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_ACTIVE_CONNECTION, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_DEVICE_TYPE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, "", "",
|
|
|
|
|
0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_LINK_TYPE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_LINK_TYPE, "", "",
|
|
|
|
|
0, G_MAXUINT32, NM_LINK_TYPE_NONE,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_MANAGED] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_MANAGED, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_AUTOCONNECT] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "",
|
|
|
|
|
DEFAULT_AUTOCONNECT,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_FIRMWARE_MISSING] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_NM_PLUGIN_MISSING] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_TYPE_DESC] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_TYPE_DESC, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_RFKILL_TYPE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, "", "",
|
|
|
|
|
RFKILL_TYPE_WLAN,
|
|
|
|
|
RFKILL_TYPE_MAX,
|
|
|
|
|
RFKILL_TYPE_UNKNOWN,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_IFINDEX] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_int (NM_DEVICE_IFINDEX, "", "",
|
|
|
|
|
0, G_MAXINT, 0,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_AVAILABLE_CONNECTIONS] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "",
|
|
|
|
|
G_TYPE_STRV,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_PHYSICAL_PORT_ID] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_MASTER] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_object (NM_DEVICE_MASTER, "", "",
|
|
|
|
|
NM_TYPE_DEVICE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-12-26 11:12:39 +01:00
|
|
|
obj_properties[PROP_PARENT] =
|
|
|
|
|
g_param_spec_string (NM_DEVICE_PARENT, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_HW_ADDRESS] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "",
|
|
|
|
|
NULL,
|
2016-06-15 11:25:29 +02:00
|
|
|
G_PARAM_READABLE |
|
2016-02-29 13:13:54 +01:00
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-06-17 18:53:45 +02:00
|
|
|
obj_properties[PROP_PERM_HW_ADDRESS] =
|
|
|
|
|
g_param_spec_string (NM_DEVICE_PERM_HW_ADDRESS, "", "",
|
|
|
|
|
NULL,
|
2016-06-15 11:25:29 +02:00
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
2016-06-17 18:53:45 +02:00
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_HAS_PENDING_ACTION] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_HAS_PENDING_ACTION, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2014-04-28 11:18:05 +02:00
|
|
|
|
2015-04-29 16:34:38 +02:00
|
|
|
/**
|
|
|
|
|
* NMDevice:metered:
|
|
|
|
|
*
|
|
|
|
|
* Whether the connection is metered.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_METERED] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_uint (NM_DEVICE_METERED, "", "",
|
|
|
|
|
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_LLDP_NEIGHBORS] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_variant (NM_DEVICE_LLDP_NEIGHBORS, "", "",
|
|
|
|
|
G_VARIANT_TYPE ("aa{sv}"),
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_REAL] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boolean (NM_DEVICE_REAL, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
obj_properties[PROP_SLAVES] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_param_spec_boxed (NM_DEVICE_SLAVES, "", "",
|
|
|
|
|
G_TYPE_STRV,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-02-29 16:27:27 +05:30
|
|
|
|
2016-08-10 11:54:31 +02:00
|
|
|
/* Statistics */
|
|
|
|
|
obj_properties[PROP_REFRESH_RATE_MS] =
|
|
|
|
|
g_param_spec_uint (NM_DEVICE_STATISTICS_REFRESH_RATE_MS, "", "",
|
|
|
|
|
0, UINT32_MAX, 0,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
obj_properties[PROP_TX_BYTES] =
|
|
|
|
|
g_param_spec_uint64 (NM_DEVICE_STATISTICS_TX_BYTES, "", "",
|
|
|
|
|
0, UINT64_MAX, 0,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
obj_properties[PROP_RX_BYTES] =
|
|
|
|
|
g_param_spec_uint64 (NM_DEVICE_STATISTICS_RX_BYTES, "", "",
|
|
|
|
|
0, UINT64_MAX, 0,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2017-03-20 13:36:00 +00:00
|
|
|
/* Connectivity */
|
|
|
|
|
obj_properties[PROP_CONNECTIVITY] =
|
|
|
|
|
g_param_spec_uint (NM_DEVICE_CONNECTIVITY, "", "",
|
|
|
|
|
NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2016-02-29 16:27:27 +05:30
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
2015-12-02 10:33:19 +01:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[STATE_CHANGED] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_STATE_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
G_STRUCT_OFFSET (NMDeviceClass, state_changed),
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 3,
|
|
|
|
|
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
2013-08-13 17:45:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[AUTOCONNECT_ALLOWED] =
|
2016-09-12 12:29:34 +02:00
|
|
|
g_signal_new (NM_DEVICE_AUTOCONNECT_ALLOWED,
|
2016-02-29 13:13:54 +01:00
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
autoconnect_allowed_accumulator, NULL, NULL,
|
|
|
|
|
G_TYPE_BOOLEAN, 0);
|
2013-08-13 17:45:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[AUTH_REQUEST] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_AUTH_REQUEST,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
/* context, connection, permission, allow_interaction, callback, user_data */
|
|
|
|
|
G_TYPE_NONE, 6, G_TYPE_DBUS_METHOD_INVOCATION, NM_TYPE_CONNECTION, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
|
2013-08-13 17:45:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[IP4_CONFIG_CHANGED] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
|
2013-12-09 12:55:04 -06:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[IP6_CONFIG_CHANGED] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
|
2013-08-13 17:45:34 -04:00
|
|
|
|
2016-11-03 12:05:12 +01:00
|
|
|
signals[IP6_PREFIX_DELEGATED] =
|
|
|
|
|
g_signal_new (NM_DEVICE_IP6_PREFIX_DELEGATED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
|
|
|
|
|
|
|
|
|
signals[IP6_SUBNET_NEEDED] =
|
|
|
|
|
g_signal_new (NM_DEVICE_IP6_SUBNET_NEEDED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[REMOVED] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_REMOVED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 0);
|
2013-08-13 17:45:34 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[RECHECK_AUTO_ACTIVATE] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_RECHECK_AUTO_ACTIVATE,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 0);
|
2013-10-11 14:59:26 -04:00
|
|
|
|
2014-05-20 15:03:27 -05:00
|
|
|
signals[RECHECK_ASSUME] =
|
2016-02-29 13:13:54 +01:00
|
|
|
g_signal_new (NM_DEVICE_RECHECK_ASSUME,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 0);
|
2013-10-11 14:59:26 -04:00
|
|
|
|
2015-04-13 13:31:42 -04:00
|
|
|
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
|
2015-04-15 14:53:30 -04:00
|
|
|
NMDBUS_TYPE_DEVICE_SKELETON,
|
2015-11-02 15:32:38 +01:00
|
|
|
"Reapply", impl_device_reapply,
|
2016-02-11 09:18:35 +01:00
|
|
|
"GetAppliedConnection", impl_device_get_applied_connection,
|
2015-04-15 14:53:30 -04:00
|
|
|
"Disconnect", impl_device_disconnect,
|
|
|
|
|
"Delete", impl_device_delete,
|
|
|
|
|
NULL);
|
2016-08-10 11:54:31 +02:00
|
|
|
|
|
|
|
|
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
|
|
|
|
|
NMDBUS_TYPE_DEVICE_STATISTICS_SKELETON,
|
|
|
|
|
NULL);
|
2013-12-16 15:16:43 +01:00
|
|
|
}
|