diff options
Diffstat (limited to 'src/devices')
71 files changed, 3220 insertions, 7676 deletions
diff --git a/src/devices/adsl/meson.build b/src/devices/adsl/meson.build deleted file mode 100644 index 4b0fade0..00000000 --- a/src/devices/adsl/meson.build +++ /dev/null @@ -1,34 +0,0 @@ -sources = files( - 'nm-atm-manager.c', - 'nm-device-adsl.c' -) - -deps = [ - libudev_dep, - nm_dep -] - -libnm_device_plugin_adsl = shared_module( - 'nm-device-plugin-adsl', - sources: sources, - dependencies: deps, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_adsl - -run_target( - 'check-local-devices-adsl', - command: [check_exports, libnm_device_plugin_adsl.full_path(), linker_script_devices], - depends: libnm_device_plugin_adsl -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-adsl: src/devices/adsl/libnm-device-plugin-adsl.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/adsl/.libs/libnm-device-plugin-adsl.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/adsl/.libs/libnm-device-plugin-adsl.so) -''' diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index 91331376..e9bd41ae 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -39,6 +39,8 @@ #include "nm-setting-adsl.h" #include "nm-utils.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Adsl.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF (NMDeviceAdsl); @@ -114,7 +116,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingAdsl *s_adsl; @@ -135,6 +137,8 @@ complete_connection (NMDevice *device, _("ADSL connection"), NULL, FALSE); /* No IPv6 yet by default */ + + return TRUE; } @@ -427,22 +431,8 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -ppp_ifindex_set (NMPPPManager *ppp_manager, - int ifindex, - const char *iface, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - if (!nm_device_set_ip_ifindex (device, ifindex)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } -} - -static void ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, NMIP4Config *config, gpointer user_data) { @@ -450,6 +440,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager, /* Ignore PPP IP4 events that come in after initial configuration */ if (nm_device_activate_ip4_state_in_conf (device)) { + nm_device_set_ip_iface (device, iface); nm_device_activate_schedule_ip4_config_result (device, config); } } @@ -508,9 +499,6 @@ act_stage3_ip4_config_start (NMDevice *device, g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK (ppp_ifindex_set), - self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -651,24 +639,10 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_adsl = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_ADSL, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_adsl_class_init (NMDeviceAdslClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); object_class->constructed = constructed; @@ -676,8 +650,6 @@ nm_device_adsl_class_init (NMDeviceAdslClass *klass) object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_adsl); - parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->check_connection_compatible = check_connection_compatible; @@ -694,4 +666,8 @@ nm_device_adsl_class_init (NMDeviceAdslClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_ADSL_SKELETON, + NULL); } diff --git a/src/devices/bluetooth/meson.build b/src/devices/bluetooth/meson.build deleted file mode 100644 index eb200679..00000000 --- a/src/devices/bluetooth/meson.build +++ /dev/null @@ -1,45 +0,0 @@ -sources = files( - 'nm-bluez-device.c', - 'nm-bluez-manager.c', - 'nm-bluez4-adapter.c', - 'nm-bluez4-manager.c', - 'nm-bluez5-manager.c', - 'nm-bt-error.c', - 'nm-device-bt.c' -) - -deps = [ - libnm_wwan_dep, - nm_dep -] - -if enable_bluez5_dun - sources += files('nm-bluez5-dun.c') - - deps += bluez5_dep -endif - -libnm_device_plugin_bluetooth = shared_module( - 'nm-device-plugin-bluetooth', - sources: sources, - dependencies: deps, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_bluetooth - -run_target( - 'check-local-devices-bluetooth', - command: [check_exports, libnm_device_plugin_bluetooth.full_path(), linker_script_devices], - depends: libnm_device_plugin_bluetooth -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-bluetooth: src/devices/bluetooth/libnm-device-plugin-bluetooth.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/bluetooth/.libs/libnm-device-plugin-bluetooth.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/bluetooth/.libs/libnm-device-plugin-bluetooth.so) -''' diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index cc9e38c8..bd3cf18a 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -254,7 +254,7 @@ pan_connection_check_create (NMBluezDevice *self) g_assert (connection_compatible (self, added)); g_assert (nm_connection_compare (added, connection, NM_SETTING_COMPARE_FLAG_EXACT)); - nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added), NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED, TRUE); + nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED, TRUE); priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); priv->pan_connection = added; @@ -1186,7 +1186,7 @@ dispose (GObject *object) /* Check whether we want to remove the created connection. If so, we take a reference * and delete it at the end of dispose(). */ if (NM_FLAGS_HAS (nm_settings_connection_get_flags (NM_SETTINGS_CONNECTION (priv->pan_connection)), - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED)) to_delete = g_object_ref (priv->pan_connection); priv->pan_connection = NULL; diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index c8ef7a27..0f19f998 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -25,6 +25,7 @@ #include <string.h> #include "nm-dbus-interface.h" +#include "nm-utils/nm-hash-utils.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-core-internal.h" diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index 5d3bd23a..de3f4072 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -30,7 +30,7 @@ #include "nm-core-internal.h" -#include "c-list/src/c-list.h" +#include "nm-utils/c-list.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "devices/nm-device-bridge.h" diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 1d237d92..977c1e1a 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -43,6 +43,8 @@ #include "devices/wwan/nm-modem-manager.h" #include "devices/wwan/nm-modem.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBt); @@ -215,7 +217,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); @@ -538,16 +540,11 @@ modem_ip4_config_result (NMModem *modem, } static void -ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); + NMDevice *self = NM_DEVICE (user_data); - if (!nm_device_set_ip_ifindex (device, - nm_modem_get_ip_ifindex (modem))) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } + nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); } static gboolean @@ -643,24 +640,29 @@ component_added (NMDevice *device, GObject *component) NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMModem *modem; + const gchar *modem_data_port; + const gchar *modem_control_port; + char *base; NMDeviceState state; NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - if ( !component - || !NM_IS_MODEM (component)) + if (!component || !NM_IS_MODEM (component)) return FALSE; - modem = NM_MODEM (component); + + modem_data_port = nm_modem_get_data_port (modem); + modem_control_port = nm_modem_get_control_port (modem); + g_return_val_if_fail (modem_data_port != NULL || modem_control_port != NULL, FALSE); + if (!priv->rfcomm_iface) return FALSE; - { - gs_free char *base = NULL; - - base = g_path_get_basename (priv->rfcomm_iface); - if (!nm_streq (base, nm_modem_get_control_port (modem))) - return FALSE; + base = g_path_get_basename (priv->rfcomm_iface); + if (g_strcmp0 (base, modem_data_port) && g_strcmp0 (base, modem_control_port)) { + g_free (base); + return FALSE; } + g_free (base); /* Got the modem */ nm_clear_g_source (&priv->timeout_id); @@ -694,7 +696,7 @@ component_added (NMDevice *device, GObject *component) g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); - g_signal_connect (modem, "notify::" NM_MODEM_IP_IFINDEX, G_CALLBACK (ip_ifindex_changed_cb), self); + g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); /* Kick off the modem connection */ if (!modem_stage1 (self, modem, &failure_reason)) @@ -751,7 +753,7 @@ bluez_connect_cb (GObject *object, GAsyncResult *res, void *user_data) { - gs_unref_object NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); GError *error = NULL; const char *device; @@ -759,9 +761,6 @@ bluez_connect_cb (GObject *object, device = nm_bluez_device_connect_finish (NM_BLUEZ_DEVICE (object), res, &error); - if (!nm_device_is_activating (NM_DEVICE (self))) - return; - if (!device) { _LOGW (LOGD_BT, "Error connecting with bluez: %s", error->message); g_clear_error (&error); @@ -769,6 +768,7 @@ bluez_connect_cb (GObject *object, nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); + g_object_unref (self); return; } @@ -776,13 +776,7 @@ bluez_connect_cb (GObject *object, g_free (priv->rfcomm_iface); priv->rfcomm_iface = g_strdup (device); } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { - if (!nm_device_set_ip_iface (NM_DEVICE (self), device)) { - _LOGW (LOGD_BT, "Error connecting with bluez: cannot find device %s", device); - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - return; - } + nm_device_set_ip_iface (NM_DEVICE (self), device); } _LOGD (LOGD_BT, "connect request successful"); @@ -790,6 +784,7 @@ bluez_connect_cb (GObject *object, /* Stage 3 gets scheduled when Bluez says we're connected */ priv->have_iface = TRUE; check_connect_continue (self); + g_object_unref (self); } static void @@ -1150,26 +1145,10 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_bluetooth = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_BLUETOOTH, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Name", "s", NM_DEVICE_BT_NAME), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("BtCapabilities", "u", NM_DEVICE_BT_CAPABILITIES), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_bt_class_init (NMDeviceBtClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->constructed = constructed; @@ -1178,8 +1157,6 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bluetooth); - device_class->get_generic_capabilities = get_generic_capabilities; device_class->can_auto_connect = can_auto_connect; device_class->deactivate = deactivate; @@ -1223,4 +1200,8 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) G_TYPE_NONE, 2, G_TYPE_UINT /*guint32 in_bytes*/, G_TYPE_UINT /*guint32 out_bytes*/); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_BLUETOOTH_SKELETON, + NULL); } diff --git a/src/devices/meson.build b/src/devices/meson.build deleted file mode 100644 index 2d874659..00000000 --- a/src/devices/meson.build +++ /dev/null @@ -1,22 +0,0 @@ -subdir('adsl') - -if enable_modem_manager - subdir('wwan') - subdir('bluetooth') -endif - -if enable_wifi - subdir('wifi') -endif - -if enable_teamdctl - subdir('team') -endif - -if enable_ovs - subdir('ovs') -endif - -if enable_tests - subdir('tests') -endif diff --git a/src/devices/nm-acd-manager.c b/src/devices/nm-acd-manager.c deleted file mode 100644 index 1bade4ff..00000000 --- a/src/devices/nm-acd-manager.c +++ /dev/null @@ -1,489 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * Copyright (C) 2015-2018 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-acd-manager.h" - -#include <netinet/in.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include "platform/nm-platform.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "n-acd/src/n-acd.h" - -/*****************************************************************************/ - -typedef enum { - STATE_INIT, - STATE_PROBING, - STATE_PROBE_DONE, - STATE_ANNOUNCING, -} State; - -typedef struct { - in_addr_t address; - gboolean duplicate; - NMAcdManager *manager; - NAcd *acd; - GIOChannel *channel; - guint event_id; -} AddressInfo; - -enum { - PROBE_TERMINATED, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct { - int ifindex; - guint8 hwaddr[ETH_ALEN]; - State state; - GHashTable *addresses; - guint completed; -} NMAcdManagerPrivate; - -struct _NMAcdManager { - GObject parent; - NMAcdManagerPrivate _priv; -}; - -struct _NMAcdManagerClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE (NMAcdManager, nm_acd_manager, G_TYPE_OBJECT) - -#define NM_ACD_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMAcdManager, NM_IS_ACD_MANAGER) - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_IP4 -#define _NMLOG_PREFIX_NAME "acd" -#define _NMLOG(level, ...) \ - G_STMT_START { \ - char _sbuf[64]; \ - int _ifindex = (self) ? NM_ACD_MANAGER_GET_PRIVATE (self)->ifindex : 0; \ - \ - nm_log ((level), _NMLOG_DOMAIN, \ - nm_platform_link_get_name (NM_PLATFORM_GET, _ifindex), \ - NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - self ? nm_sprintf_buf (_sbuf, "[%p,%d]", self, _ifindex) : "" \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } G_STMT_END - -/*****************************************************************************/ - -static const char * -_acd_event_to_string (unsigned int event) -{ - switch (event) { - case N_ACD_EVENT_READY: - return "ready"; - case N_ACD_EVENT_USED: - return "used"; - case N_ACD_EVENT_DEFENDED: - return "defended"; - case N_ACD_EVENT_CONFLICT: - return "conflict"; - case N_ACD_EVENT_DOWN: - return "down"; - } - return NULL; -} - -#define acd_event_to_string(event) NM_UTILS_LOOKUP_STR (_acd_event_to_string, event) - -static const char * -_acd_error_to_string (int error) -{ - if (error < 0) - return strerror(-error); - - switch (error) { - case _N_ACD_E_SUCCESS: - return "success"; - case N_ACD_E_DONE: - return "no more events (engine running)"; - case N_ACD_E_STOPPED: - return "no more events (engine stopped)"; - case N_ACD_E_PREEMPTED: - return "preempted"; - case N_ACD_E_INVALID_ARGUMENT: - return "invalid argument"; - case N_ACD_E_BUSY: - return "busy"; - } - return NULL; -} - -#define acd_error_to_string(error) NM_UTILS_LOOKUP_STR (_acd_error_to_string, error) - -/*****************************************************************************/ - -/** - * nm_acd_manager_add_address: - * @self: a #NMAcdManager - * @address: an IP address - * - * Add @address to the list of IP addresses to probe. - - * Returns: %TRUE on success, %FALSE if the address was already in the list - */ -gboolean -nm_acd_manager_add_address (NMAcdManager *self, in_addr_t address) -{ - NMAcdManagerPrivate *priv; - AddressInfo *info; - - g_return_val_if_fail (NM_IS_ACD_MANAGER (self), FALSE); - priv = NM_ACD_MANAGER_GET_PRIVATE (self); - g_return_val_if_fail (priv->state == STATE_INIT, FALSE); - - if (g_hash_table_lookup (priv->addresses, GUINT_TO_POINTER (address))) - return FALSE; - - info = g_slice_new0 (AddressInfo); - info->address = address; - info->manager = self; - - g_hash_table_insert (priv->addresses, GUINT_TO_POINTER (address), info); - - return TRUE; -} - -static gboolean -acd_event (GIOChannel *source, GIOCondition condition, gpointer data) -{ - AddressInfo *info = data; - NMAcdManager *self = info->manager; - NMAcdManagerPrivate *priv = NM_ACD_MANAGER_GET_PRIVATE (self); - NAcdEvent *event; - char address_str[INET_ADDRSTRLEN]; - gs_free char *hwaddr_str = NULL; - int r; - - if ( n_acd_dispatch (info->acd) - || n_acd_pop_event (info->acd, &event)) - return G_SOURCE_CONTINUE; - - switch (event->event) { - case N_ACD_EVENT_READY: - info->duplicate = FALSE; - if (priv->state == STATE_ANNOUNCING) { - r = n_acd_announce (info->acd, N_ACD_DEFEND_ONCE); - if (r) { - _LOGW ("couldn't announce address %s on interface '%s': %s", - nm_utils_inet4_ntop (info->address, address_str), - nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex), - acd_error_to_string (r)); - } else { - _LOGD ("announcing address %s", - nm_utils_inet4_ntop (info->address, address_str)); - } - } - break; - case N_ACD_EVENT_USED: - info->duplicate = TRUE; - break; - case N_ACD_EVENT_DEFENDED: - _LOGD ("defended address %s from host %s", - nm_utils_inet4_ntop (info->address, address_str), - (hwaddr_str = nm_utils_hwaddr_ntoa (event->defended.sender, - event->defended.n_sender))); - break; - case N_ACD_EVENT_CONFLICT: - _LOGW ("conflict for address %s detected with host %s on interface '%s'", - nm_utils_inet4_ntop (info->address, address_str), - (hwaddr_str = nm_utils_hwaddr_ntoa (event->defended.sender, - event->defended.n_sender)), - nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex)); - break; - default: - _LOGD ("event '%s' for address %s", - acd_event_to_string (event->event), - nm_utils_inet4_ntop (info->address, address_str)); - return G_SOURCE_CONTINUE; - } - - if ( priv->state == STATE_PROBING - && ++priv->completed == g_hash_table_size (priv->addresses)) { - priv->state = STATE_PROBE_DONE; - g_signal_emit (self, signals[PROBE_TERMINATED], 0); - } - - return G_SOURCE_CONTINUE; -} - -static gboolean -acd_probe_start (NMAcdManager *self, - AddressInfo *info, - guint64 timeout) -{ - NMAcdManagerPrivate *priv = NM_ACD_MANAGER_GET_PRIVATE (self); - NAcdConfig *config; - int r, fd; - - r = n_acd_new (&info->acd); - if (r) { - _LOGW ("could not create ACD for %s on interface '%s': %s", - nm_utils_inet4_ntop (info->address, NULL), - nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex), - acd_error_to_string (r)); - return FALSE; - } - - n_acd_get_fd (info->acd, &fd); - info->channel = g_io_channel_unix_new (fd); - info->event_id = g_io_add_watch (info->channel, G_IO_IN, acd_event, info); - - config = &(NAcdConfig) { - .ifindex = priv->ifindex, - .mac = priv->hwaddr, - .n_mac = ETH_ALEN, - .ip = info->address, - .timeout_msec = timeout, - .transport = N_ACD_TRANSPORT_ETHERNET, - }; - - r = n_acd_start (info->acd, config); - if (r) { - _LOGW ("could not start probe for %s on interface '%s': %s", - nm_utils_inet4_ntop (info->address, NULL), - nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex), - acd_error_to_string (r)); - return FALSE; - } - - _LOGD ("start probe for %s", nm_utils_inet4_ntop (info->address, NULL)); - - return TRUE; -} - -/** - * nm_acd_manager_start_probe: - * @self: a #NMAcdManager - * @timeout: maximum probe duration in milliseconds - * @error: location to store error, or %NULL - * - * Start probing IP addresses for duplicates; when the probe terminates a - * PROBE_TERMINATED signal is emitted. - * - * Returns: %TRUE if at least one probe could be started, %FALSE otherwise - */ -gboolean -nm_acd_manager_start_probe (NMAcdManager *self, guint timeout) -{ - NMAcdManagerPrivate *priv; - GHashTableIter iter; - AddressInfo *info; - gboolean success = FALSE; - - g_return_val_if_fail (NM_IS_ACD_MANAGER (self), FALSE); - priv = NM_ACD_MANAGER_GET_PRIVATE (self); - g_return_val_if_fail (priv->state == STATE_INIT, FALSE); - - priv->completed = 0; - - g_hash_table_iter_init (&iter, priv->addresses); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) - success |= acd_probe_start (self, info, timeout); - - if (success) - priv->state = STATE_PROBING; - - return success; -} - -/** - * nm_acd_manager_reset: - * @self: a #NMAcdManager - * - * Stop any operation in progress and reset @self to the initial state. - */ -void -nm_acd_manager_reset (NMAcdManager *self) -{ - NMAcdManagerPrivate *priv; - - g_return_if_fail (NM_IS_ACD_MANAGER (self)); - priv = NM_ACD_MANAGER_GET_PRIVATE (self); - - g_hash_table_remove_all (priv->addresses); - - priv->state = STATE_INIT; -} - -/** - * nm_acd_manager_destroy: - * @self: the #NMAcdManager - * - * Calls nm_acd_manager_reset() and unrefs @self. - */ -void -nm_acd_manager_destroy (NMAcdManager *self) -{ - g_return_if_fail (NM_IS_ACD_MANAGER (self)); - - nm_acd_manager_reset (self); - g_object_unref (self); -} - -/** - * nm_acd_manager_check_address: - * @self: a #NMAcdManager - * @address: an IP address - * - * Check if an IP address is duplicate. @address must have been added with - * nm_acd_manager_add_address(). - * - * Returns: %TRUE if the address is not duplicate, %FALSE otherwise - */ -gboolean -nm_acd_manager_check_address (NMAcdManager *self, in_addr_t address) -{ - NMAcdManagerPrivate *priv; - AddressInfo *info; - - g_return_val_if_fail (NM_IS_ACD_MANAGER (self), FALSE); - priv = NM_ACD_MANAGER_GET_PRIVATE (self); - g_return_val_if_fail ( priv->state == STATE_INIT - || priv->state == STATE_PROBE_DONE, FALSE); - - info = g_hash_table_lookup (priv->addresses, GUINT_TO_POINTER (address)); - g_return_val_if_fail (info, FALSE); - - return !info->duplicate; -} - -/** - * nm_acd_manager_announce_addresses: - * @self: a #NMAcdManager - * - * Start announcing addresses. - */ -void -nm_acd_manager_announce_addresses (NMAcdManager *self) -{ - NMAcdManagerPrivate *priv = NM_ACD_MANAGER_GET_PRIVATE (self); - GHashTableIter iter; - AddressInfo *info; - int r; - - if (priv->state == STATE_INIT) { - /* n-acd can't announce without probing, therefore let's - * start a fake probe with zero timeout and then perform - * the announce. */ - priv->state = STATE_ANNOUNCING; - g_hash_table_iter_init (&iter, priv->addresses); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) { - if (!acd_probe_start (self, info, 0)) { - _LOGW ("couldn't announce address %s on interface '%s'", - nm_utils_inet4_ntop (info->address, NULL), - nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex)); - } - } - } else if (priv->state == STATE_PROBE_DONE) { - priv->state = STATE_ANNOUNCING; - g_hash_table_iter_init (&iter, priv->addresses); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) { - if (info->duplicate) - continue; - r = n_acd_announce (info->acd, N_ACD_DEFEND_ONCE); - if (r) { - _LOGW ("couldn't announce address %s on interface '%s': %s", - nm_utils_inet4_ntop (info->address, NULL), - nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex), - acd_error_to_string (r)); - } else - _LOGD ("announcing address %s", nm_utils_inet4_ntop (info->address, NULL)); - } - } else - nm_assert_not_reached (); -} - -static void -destroy_address_info (gpointer data) -{ - AddressInfo *info = (AddressInfo *) data; - - g_clear_pointer (&info->channel, g_io_channel_unref); - g_clear_pointer (&info->acd, n_acd_free); - nm_clear_g_source (&info->event_id); - - g_slice_free (AddressInfo, info); -} - -/*****************************************************************************/ - -static void -nm_acd_manager_init (NMAcdManager *self) -{ - NMAcdManagerPrivate *priv = NM_ACD_MANAGER_GET_PRIVATE (self); - - priv->addresses = g_hash_table_new_full (nm_direct_hash, NULL, - NULL, destroy_address_info); - priv->state = STATE_INIT; -} - -NMAcdManager * -nm_acd_manager_new (int ifindex, const guint8 *hwaddr, size_t hwaddr_len) -{ - NMAcdManager *self; - NMAcdManagerPrivate *priv; - - g_return_val_if_fail (hwaddr, NULL); - g_return_val_if_fail (hwaddr_len == ETH_ALEN, NULL); - - self = g_object_new (NM_TYPE_ACD_MANAGER, NULL); - priv = NM_ACD_MANAGER_GET_PRIVATE (self); - priv->ifindex = ifindex; - memcpy (priv->hwaddr, hwaddr, ETH_ALEN); - - return self; -} - -static void -dispose (GObject *object) -{ - NMAcdManager *self = NM_ACD_MANAGER (object); - NMAcdManagerPrivate *priv = NM_ACD_MANAGER_GET_PRIVATE (self); - - g_clear_pointer (&priv->addresses, g_hash_table_destroy); - - G_OBJECT_CLASS (nm_acd_manager_parent_class)->dispose (object); -} - -static void -nm_acd_manager_class_init (NMAcdManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dispose; - - signals[PROBE_TERMINATED] = - g_signal_new (NM_ACD_MANAGER_PROBE_TERMINATED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/devices/nm-acd-manager.h b/src/devices/nm-acd-manager.h deleted file mode 100644 index eeede5da..00000000 --- a/src/devices/nm-acd-manager.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * Copyright (C) 2015-2018 Red Hat, Inc. - */ - -#ifndef __NM_ACD_MANAGER__ -#define __NM_ACD_MANAGER__ - -#include <netinet/in.h> - -#define NM_TYPE_ACD_MANAGER (nm_acd_manager_get_type ()) -#define NM_ACD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACD_MANAGER, NMAcdManager)) -#define NM_ACD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ACD_MANAGER, NMAcdManagerClass)) -#define NM_IS_ACD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ACD_MANAGER)) -#define NM_IS_ACD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ACD_MANAGER)) -#define NM_ACD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACD_MANAGER, NMAcdManagerClass)) - -#define NM_ACD_MANAGER_PROBE_TERMINATED "probe-terminated" - -typedef struct _NMAcdManagerClass NMAcdManagerClass; - -GType nm_acd_manager_get_type (void); - -NMAcdManager *nm_acd_manager_new (int ifindex, const guint8 *hwaddr, size_t hwaddr_len); -void nm_acd_manager_destroy (NMAcdManager *self); -gboolean nm_acd_manager_add_address (NMAcdManager *self, in_addr_t address); -gboolean nm_acd_manager_start_probe (NMAcdManager *self, guint timeout); -gboolean nm_acd_manager_check_address (NMAcdManager *self, in_addr_t address); -void nm_acd_manager_announce_addresses (NMAcdManager *self); -void nm_acd_manager_reset (NMAcdManager *self); - -#endif /* __NM_ACD_MANAGER__ */ diff --git a/src/devices/nm-arping-manager.c b/src/devices/nm-arping-manager.c new file mode 100644 index 00000000..51f80e08 --- /dev/null +++ b/src/devices/nm-arping-manager.c @@ -0,0 +1,474 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* 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. + * + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-arping-manager.h" + +#include <netinet/in.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "platform/nm-platform.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" + +/*****************************************************************************/ + +typedef enum { + STATE_INIT, + STATE_PROBING, + STATE_PROBE_DONE, + STATE_ANNOUNCING, +} State; + +typedef struct { + in_addr_t address; + GPid pid; + guint watch; + gboolean duplicate; + NMArpingManager *manager; +} AddressInfo; + +/*****************************************************************************/ + +enum { + PROBE_TERMINATED, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct { + int ifindex; + State state; + GHashTable *addresses; + guint completed; + guint timer; + guint round2_id; +} NMArpingManagerPrivate; + +struct _NMArpingManager { + GObject parent; + NMArpingManagerPrivate _priv; +}; + +struct _NMArpingManagerClass { + GObjectClass parent; +}; + +G_DEFINE_TYPE (NMArpingManager, nm_arping_manager, G_TYPE_OBJECT) + +#define NM_ARPING_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMArpingManager, NM_IS_ARPING_MANAGER) + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_IP4 +#define _NMLOG_PREFIX_NAME "arping" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + char _sbuf[64]; \ + int _ifindex = (self) ? NM_ARPING_MANAGER_GET_PRIVATE (self)->ifindex : 0; \ + \ + nm_log ((level), _NMLOG_DOMAIN, \ + nm_platform_link_get_name (NM_PLATFORM_GET, _ifindex), \ + NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + self ? nm_sprintf_buf (_sbuf, "[%p,%d]", self, _ifindex) : "" \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } G_STMT_END + +/*****************************************************************************/ + +/** + * nm_arping_manager_add_address: + * @self: a #NMArpingManager + * @address: an IP address + * + * Add @address to the list of IP addresses to probe. + + * Returns: %TRUE on success, %FALSE if the address was already in the list + */ +gboolean +nm_arping_manager_add_address (NMArpingManager *self, in_addr_t address) +{ + NMArpingManagerPrivate *priv; + AddressInfo *info; + + g_return_val_if_fail (NM_IS_ARPING_MANAGER (self), FALSE); + priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + g_return_val_if_fail (priv->state == STATE_INIT, FALSE); + + if (g_hash_table_lookup (priv->addresses, GUINT_TO_POINTER (address))) { + _LOGD ("address already exists"); + return FALSE; + } + + info = g_slice_new0 (AddressInfo); + info->address = address; + info->manager = self; + + g_hash_table_insert (priv->addresses, GUINT_TO_POINTER (address), info); + + return TRUE; +} + +static void +arping_watch_cb (GPid pid, gint status, gpointer user_data) +{ + AddressInfo *info = user_data; + NMArpingManager *self = info->manager; + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + const char *addr; + + info->pid = 0; + info->watch = 0; + addr = nm_utils_inet4_ntop (info->address, NULL); + + if (WIFEXITED (status)) { + if (WEXITSTATUS (status) != 0) { + _LOGD ("%s already used in the %s network", + addr, nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex)); + info->duplicate = TRUE; + } else + _LOGD ("DAD succeeded for %s", addr); + } else { + _LOGD ("stopped unexpectedly with status %d for %s", status, addr); + } + + if (++priv->completed == g_hash_table_size (priv->addresses)) { + priv->state = STATE_PROBE_DONE; + nm_clear_g_source (&priv->timer); + g_signal_emit (self, signals[PROBE_TERMINATED], 0); + } +} + +static gboolean +arping_timeout_cb (gpointer user_data) +{ + NMArpingManager *self = user_data; + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + AddressInfo *info; + + priv->timer = 0; + + g_hash_table_iter_init (&iter, priv->addresses); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) { + nm_clear_g_source (&info->watch); + if (info->pid) { + _LOGD ("DAD timed out for %s", + nm_utils_inet4_ntop (info->address, NULL)); + nm_utils_kill_child_async (info->pid, SIGTERM, LOGD_IP4, + "arping", 1000, NULL, NULL); + info->pid = 0; + } + } + + priv->state = STATE_PROBE_DONE; + g_signal_emit (self, signals[PROBE_TERMINATED], 0); + + return G_SOURCE_REMOVE; +} + +/** + * nm_arping_manager_start_probe: + * @self: a #NMArpingManager + * @timeout: maximum probe duration in milliseconds + * @error: location to store error, or %NULL + * + * Start probing IP addresses for duplicates; when the probe terminates a + * PROBE_TERMINATED signal is emitted. + * + * Returns: %TRUE if at least one probe could be started, %FALSE otherwise + */ +gboolean +nm_arping_manager_start_probe (NMArpingManager *self, guint timeout, GError **error) +{ + const char *argv[] = { NULL, "-D", "-q", "-I", NULL, "-c", NULL, "-w", NULL, NULL, NULL }; + NMArpingManagerPrivate *priv; + GHashTableIter iter; + AddressInfo *info; + gs_free char *timeout_str = NULL; + gboolean success = FALSE; + + g_return_val_if_fail (NM_IS_ARPING_MANAGER (self), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + g_return_val_if_fail (timeout, FALSE); + + priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + g_return_val_if_fail (priv->state == STATE_INIT, FALSE); + + argv[4] = nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex); + if (!argv[4]) { + /* The device was probably just removed. */ + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "can't find a name for ifindex %d", priv->ifindex); + return FALSE; + } + + priv->completed = 0; + + argv[0] = nm_utils_find_helper ("arping", NULL, NULL); + if (!argv[0]) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "arping could not be found"); + return FALSE; + } + + timeout_str = g_strdup_printf ("%u", timeout / 1000 + 2); + argv[6] = timeout_str; + argv[8] = timeout_str; + + g_hash_table_iter_init (&iter, priv->addresses); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) { + gs_free char *tmp_str = NULL; + + argv[9] = nm_utils_inet4_ntop (info->address, NULL); + _LOGD ("run %s", (tmp_str = g_strjoinv (" ", (char **) argv))); + + if (g_spawn_async (NULL, (char **) argv, NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, &info->pid, NULL)) { + info->watch = g_child_watch_add (info->pid, arping_watch_cb, info); + success = TRUE; + } + } + + if (success) { + priv->timer = g_timeout_add (timeout, arping_timeout_cb, self); + priv->state = STATE_PROBING; + } else { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "could not spawn arping process"); + } + + return success; +} + +/** + * nm_arping_manager_reset: + * @self: a #NMArpingManager + * + * Stop any operation in progress and reset @self to the initial state. + */ +void +nm_arping_manager_reset (NMArpingManager *self) +{ + NMArpingManagerPrivate *priv; + + g_return_if_fail (NM_IS_ARPING_MANAGER (self)); + priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + + nm_clear_g_source (&priv->timer); + nm_clear_g_source (&priv->round2_id); + g_hash_table_remove_all (priv->addresses); + + priv->state = STATE_INIT; +} + +/** + * nm_arping_manager_destroy: + * @self: the #NMArpingManager + * + * Calls nm_arping_manager_reset() and unrefs @self. + */ +void +nm_arping_manager_destroy (NMArpingManager *self) +{ + g_return_if_fail (NM_IS_ARPING_MANAGER (self)); + + nm_arping_manager_reset (self); + g_object_unref (self); +} + +/** + * nm_arping_manager_check_address: + * @self: a #NMArpingManager + * @address: an IP address + * + * Check if an IP address is duplicate. @address must have been added with + * nm_arping_manager_add_address(). + * + * Returns: %TRUE if the address is not duplicate, %FALSE otherwise + */ +gboolean +nm_arping_manager_check_address (NMArpingManager *self, in_addr_t address) +{ + NMArpingManagerPrivate *priv; + AddressInfo *info; + + g_return_val_if_fail (NM_IS_ARPING_MANAGER (self), FALSE); + priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + g_return_val_if_fail ( priv->state == STATE_INIT + || priv->state == STATE_PROBE_DONE, FALSE); + + info = g_hash_table_lookup (priv->addresses, GUINT_TO_POINTER (address)); + g_return_val_if_fail (info, FALSE); + + return !info->duplicate; +} + +static void +send_announcements (NMArpingManager *self, const char *mode_arg) +{ + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + const char *argv[] = { NULL, mode_arg, "-q", "-I", NULL, "-c", "1", NULL, NULL }; + int ip_arg = G_N_ELEMENTS (argv) - 2; + GError *error = NULL; + GHashTableIter iter; + AddressInfo *info; + + argv[4] = nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex); + if (!argv[4]) { + /* The device was probably just removed. */ + _LOGW ("can't find a name for ifindex %d", priv->ifindex); + return; + } + + argv[0] = nm_utils_find_helper ("arping", NULL, NULL); + if (!argv[0]) { + _LOGW ("arping could not be found; no ARPs will be sent"); + return; + } + + g_hash_table_iter_init (&iter, priv->addresses); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info)) { + gs_free char *tmp_str = NULL; + gboolean success; + + if (info->duplicate) + continue; + + argv[ip_arg] = nm_utils_inet4_ntop (info->address, NULL); + _LOGD ("run %s", (tmp_str = g_strjoinv (" ", (char **) argv))); + + success = g_spawn_async (NULL, (char **) argv, NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, &error); + if (!success) { + _LOGW ("could not send ARP for address %s: %s", argv[ip_arg], + error->message); + g_clear_error (&error); + } + } +} + +static gboolean +arp_announce_round2 (gpointer self) +{ + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE ((NMArpingManager *) self); + + priv->round2_id = 0; + send_announcements (self, "-U"); + priv->state = STATE_INIT; + g_hash_table_remove_all (priv->addresses); + + return G_SOURCE_REMOVE; +} + +/** + * nm_arping_manager_announce_addresses: + * @self: a #NMArpingManager + * + * Start announcing addresses. + */ +void +nm_arping_manager_announce_addresses (NMArpingManager *self) +{ + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + + g_return_if_fail ( priv->state == STATE_INIT + || priv->state == STATE_PROBE_DONE); + + send_announcements (self, "-A"); + nm_clear_g_source (&priv->round2_id); + priv->round2_id = g_timeout_add_seconds (2, arp_announce_round2, self); + priv->state = STATE_ANNOUNCING; +} + +static void +destroy_address_info (gpointer data) +{ + AddressInfo *info = (AddressInfo *) data; + + nm_clear_g_source (&info->watch); + + if (info->pid) { + nm_utils_kill_child_async (info->pid, SIGTERM, LOGD_IP4, "arping", + 1000, NULL, NULL); + } + + g_slice_free (AddressInfo, info); +} + +/*****************************************************************************/ + +static void +nm_arping_manager_init (NMArpingManager *self) +{ + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + + priv->addresses = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, destroy_address_info); + priv->state = STATE_INIT; +} + +NMArpingManager * +nm_arping_manager_new (int ifindex) +{ + NMArpingManager *self; + NMArpingManagerPrivate *priv; + + self = g_object_new (NM_TYPE_ARPING_MANAGER, NULL); + priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + priv->ifindex = ifindex; + return self; +} + +static void +dispose (GObject *object) +{ + NMArpingManager *self = NM_ARPING_MANAGER (object); + NMArpingManagerPrivate *priv = NM_ARPING_MANAGER_GET_PRIVATE (self); + + nm_clear_g_source (&priv->timer); + nm_clear_g_source (&priv->round2_id); + g_clear_pointer (&priv->addresses, g_hash_table_destroy); + + G_OBJECT_CLASS (nm_arping_manager_parent_class)->dispose (object); +} + +static void +nm_arping_manager_class_init (NMArpingManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = dispose; + + signals[PROBE_TERMINATED] = + g_signal_new (NM_ARPING_MANAGER_PROBE_TERMINATED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); +} diff --git a/src/devices/nm-arping-manager.h b/src/devices/nm-arping-manager.h new file mode 100644 index 00000000..c8a86af0 --- /dev/null +++ b/src/devices/nm-arping-manager.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* 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. + * + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_ARPING_MANAGER__ +#define __NM_ARPING_MANAGER__ + +#include <netinet/in.h> + +#define NM_TYPE_ARPING_MANAGER (nm_arping_manager_get_type ()) +#define NM_ARPING_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ARPING_MANAGER, NMArpingManager)) +#define NM_ARPING_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ARPING_MANAGER, NMArpingManagerClass)) +#define NM_IS_ARPING_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ARPING_MANAGER)) +#define NM_IS_ARPING_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ARPING_MANAGER)) +#define NM_ARPING_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ARPING_MANAGER, NMArpingManagerClass)) + +#define NM_ARPING_MANAGER_PROBE_TERMINATED "probe-terminated" + +typedef struct _NMArpingManagerClass NMArpingManagerClass; + +GType nm_arping_manager_get_type (void); + +NMArpingManager *nm_arping_manager_new (int ifindex); +void nm_arping_manager_destroy (NMArpingManager *self); +gboolean nm_arping_manager_add_address (NMArpingManager *self, in_addr_t address); +gboolean nm_arping_manager_start_probe (NMArpingManager *self, guint timeout, GError **error); +gboolean nm_arping_manager_check_address (NMArpingManager *self, in_addr_t address); +void nm_arping_manager_announce_addresses (NMArpingManager *self); +void nm_arping_manager_reset (NMArpingManager *self); + +#endif /* __NM_ARPING_MANAGER__ */ diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 2dd9494a..910dd0bf 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -32,6 +32,8 @@ #include "nm-core-internal.h" #include "nm-ip4-config.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Bond.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBond); @@ -76,7 +78,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingBond *s_bond; @@ -605,31 +607,13 @@ nm_device_bond_init (NMDeviceBond * self) nm_assert (nm_device_is_master (NM_DEVICE (self))); } -static const NMDBusInterfaceInfoExtended interface_info_device_bond = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_BOND, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Slaves", "ao", NM_DEVICE_SLAVES), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_bond_class_init (NMDeviceBondClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BOND_SETTING_NAME, NM_LINK_TYPE_BOND) - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bond); - parent_class->is_master = TRUE; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->check_connection_compatible = check_connection_compatible; @@ -645,6 +629,10 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) parent_class->release_slave = release_slave; parent_class->can_reapply_change = can_reapply_change; parent_class->reapply_connection = reapply_connection; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_BOND_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index c81a0253..74689aef 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -30,6 +30,8 @@ #include "nm-device-factory.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Bridge.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBridge); @@ -115,7 +117,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingBridge *s_bridge; @@ -486,31 +488,13 @@ nm_device_bridge_init (NMDeviceBridge * self) nm_assert (nm_device_is_master (NM_DEVICE (self))); } -static const NMDBusInterfaceInfoExtended interface_info_device_bridge = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_BRIDGE, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Slaves", "ao", NM_DEVICE_SLAVES), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_bridge_class_init (NMDeviceBridgeClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BRIDGE_SETTING_NAME, NM_LINK_TYPE_BRIDGE) - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_bridge); - parent_class->is_master = TRUE; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->check_connection_compatible = check_connection_compatible; @@ -527,6 +511,10 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_BRIDGE_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-dummy.c b/src/devices/nm-device-dummy.c index f8bc8e75..085c44e6 100644 --- a/src/devices/nm-device-dummy.c +++ b/src/devices/nm-device-dummy.c @@ -28,6 +28,8 @@ #include "nm-setting-dummy.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Dummy.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceDummy); @@ -55,7 +57,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingDummy *s_dummy; @@ -154,29 +156,13 @@ nm_device_dummy_init (NMDeviceDummy *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_dummy = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_DUMMY, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_dummy_class_init (NMDeviceDummyClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_DUMMY) - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_dummy); - device_class->connection_type = NM_SETTING_DUMMY_SETTING_NAME; device_class->complete_connection = complete_connection; device_class->check_connection_compatible = check_connection_compatible; @@ -185,6 +171,10 @@ nm_device_dummy_class_init (NMDeviceDummyClass *klass) device_class->update_connection = update_connection; device_class->act_stage1_prepare = act_stage1_prepare; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_DUMMY_SKELETON, + NULL); } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 9b46545b..3ca86e06 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <unistd.h> #include <errno.h> + #include <libudev.h> #include "nm-device-private.h" @@ -50,7 +51,8 @@ #include "nm-device-factory.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" -#include "nm-utils/nm-udev-utils.h" + +#include "introspection/org.freedesktop.NetworkManager.Device.Wired.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceEthernet); @@ -548,7 +550,7 @@ build_supplicant_config (NMDeviceEthernet *self, mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); - config = nm_supplicant_config_new (FALSE, FALSE); + config = nm_supplicant_config_new (); security = nm_connection_get_setting_802_1x (connection); if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, mtu, TRUE, error)) { @@ -656,9 +658,12 @@ handle_auth_or_fail (NMDeviceEthernet *self, NMActRequest *req, gboolean new_secrets) { + NMDeviceEthernetPrivate *priv; const char *setting_name; NMConnection *applied_connection; + priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + if (!nm_device_auth_retries_try_next (NM_DEVICE (self))) return NM_ACT_STAGE_RETURN_FAILURE; @@ -668,14 +673,13 @@ handle_auth_or_fail (NMDeviceEthernet *self, applied_connection = nm_act_request_get_applied_connection (req); setting_name = nm_connection_need_secrets (applied_connection, NULL); - if (!setting_name) { + if (setting_name) { + wired_secrets_get_secrets (self, setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); + } else _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); - return NM_ACT_STAGE_RETURN_FAILURE; - } - wired_secrets_get_secrets (self, setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -738,7 +742,7 @@ supplicant_interface_init (NMDeviceEthernet *self) return FALSE; } - /* Listen for its state signals */ + /* Listen for it's state signals */ priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface, NM_SUPPLICANT_INTERFACE_STATE, G_CALLBACK (supplicant_iface_state_cb), @@ -952,22 +956,8 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -ppp_ifindex_set (NMPPPManager *ppp_manager, - int ifindex, - const char *iface, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - if (!nm_device_set_ip_ifindex (device, ifindex)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } -} - -static void ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, NMIP4Config *config, gpointer user_data) { @@ -975,6 +965,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager, /* Ignore PPP IP4 events that come in after initial configuration */ if (nm_device_activate_ip4_state_in_conf (device)) { + nm_device_set_ip_iface (device, iface); nm_device_activate_schedule_ip4_config_result (device, config); } } @@ -1021,9 +1012,6 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *out_ g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK (ppp_ifindex_set), - self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -1373,7 +1361,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingWired *s_wired; @@ -1437,9 +1425,7 @@ new_default_connection (NMDevice *self) NMConnection *connection; NMSettingsConnection *const*connections; NMSetting *setting; - struct udev_device *dev; const char *perm_hw_addr; - const char *uprop = "0"; gs_free char *defname = NULL; gs_free char *uuid = NULL; gs_free char *machine_id = NULL; @@ -1484,26 +1470,6 @@ new_default_connection (NMDevice *self) g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL); nm_connection_add_setting (connection, setting); - /* Check if we should create a Link-Local only connection */ - dev = nm_platform_link_get_udev_device (nm_device_get_platform (NM_DEVICE (self)), nm_device_get_ip_ifindex (self)); - if (dev) - uprop = udev_device_get_property_value (dev, "NM_AUTO_DEFAULT_LINK_LOCAL_ONLY"); - - if (nm_udev_utils_property_as_boolean (uprop)) { - setting = nm_setting_ip4_config_new (); - g_object_set (setting, - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL, - NULL); - nm_connection_add_setting (connection, setting); - - setting = nm_setting_ip6_config_new (); - g_object_set (setting, - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, - NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, - NULL); - nm_connection_add_setting (connection, setting); - } - return connection; } @@ -1735,28 +1701,10 @@ set_property (GObject *object, guint prop_id, } } -static const NMDBusInterfaceInfoExtended interface_info_device_wired = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_WIRED, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PermHwAddress", "s", NM_DEVICE_PERM_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Speed", "u", NM_DEVICE_ETHERNET_SPEED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("S390Subchannels", "as", NM_DEVICE_ETHERNET_S390_SUBCHANNELS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate)); @@ -1768,8 +1716,6 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_wired); - parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; @@ -1803,6 +1749,10 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_ETHERNET_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-ethernet.h b/src/devices/nm-device-ethernet.h index 22fae293..a50a7d85 100644 --- a/src/devices/nm-device-ethernet.h +++ b/src/devices/nm-device-ethernet.h @@ -24,12 +24,12 @@ #include "nm-device.h" -#define NM_TYPE_DEVICE_ETHERNET (nm_device_ethernet_get_type ()) -#define NM_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet)) -#define NM_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) -#define NM_IS_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET)) -#define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET)) -#define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) +#define NM_TYPE_DEVICE_ETHERNET (nm_device_ethernet_get_type ()) +#define NM_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet)) +#define NM_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) +#define NM_IS_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET)) +#define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET)) +#define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) #define NM_DEVICE_ETHERNET_SPEED "speed" #define NM_DEVICE_ETHERNET_S390_SUBCHANNELS "s390-subchannels" @@ -37,12 +37,12 @@ struct _NMDeviceEthernetPrivate; typedef struct { - NMDevice parent; - struct _NMDeviceEthernetPrivate *_priv; + NMDevice parent; + struct _NMDeviceEthernetPrivate *_priv; } NMDeviceEthernet; typedef struct { - NMDeviceClass parent; + NMDeviceClass parent; } NMDeviceEthernetClass; GType nm_device_ethernet_get_type (void); diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index d8e30346..97f011c5 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -340,16 +340,42 @@ factories_list_unref (GSList *list) g_slist_free_full (list, g_object_unref); } -static void -load_factories_from_dir (const char *dirname, - NMDeviceFactoryManagerFactoryFunc callback, - gpointer user_data) +void +nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc callback, + gpointer user_data) { NMDeviceFactory *factory; GError *error = NULL; char **path, **paths; - paths = nm_utils_read_plugin_paths (dirname, PLUGIN_PREFIX); + g_return_if_fail (factories_by_link == NULL); + g_return_if_fail (factories_by_setting == NULL); + + factories_by_link = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); + factories_by_setting = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, (GDestroyNotify) factories_list_unref); + +#define _ADD_INTERNAL(get_type_fcn) \ + G_STMT_START { \ + GType get_type_fcn (void); \ + _load_internal_factory (get_type_fcn (), \ + callback, user_data); \ + } G_STMT_END + + _ADD_INTERNAL (nm_bond_device_factory_get_type); + _ADD_INTERNAL (nm_bridge_device_factory_get_type); + _ADD_INTERNAL (nm_dummy_device_factory_get_type); + _ADD_INTERNAL (nm_ethernet_device_factory_get_type); + _ADD_INTERNAL (nm_infiniband_device_factory_get_type); + _ADD_INTERNAL (nm_ip_tunnel_device_factory_get_type); + _ADD_INTERNAL (nm_macsec_device_factory_get_type); + _ADD_INTERNAL (nm_macvlan_device_factory_get_type); + _ADD_INTERNAL (nm_ppp_device_factory_get_type); + _ADD_INTERNAL (nm_tun_device_factory_get_type); + _ADD_INTERNAL (nm_veth_device_factory_get_type); + _ADD_INTERNAL (nm_vlan_device_factory_get_type); + _ADD_INTERNAL (nm_vxlan_device_factory_get_type); + + paths = nm_utils_read_plugin_paths (NMPLUGINDIR, PLUGIN_PREFIX); if (!paths) return; @@ -394,36 +420,3 @@ load_factories_from_dir (const char *dirname, g_strfreev (paths); } -void -nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc callback, - gpointer user_data) -{ - g_return_if_fail (factories_by_link == NULL); - g_return_if_fail (factories_by_setting == NULL); - - factories_by_link = g_hash_table_new_full (nm_direct_hash, NULL, NULL, g_object_unref); - factories_by_setting = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, (GDestroyNotify) factories_list_unref); - -#define _ADD_INTERNAL(get_type_fcn) \ - G_STMT_START { \ - GType get_type_fcn (void); \ - _load_internal_factory (get_type_fcn (), \ - callback, user_data); \ - } G_STMT_END - - _ADD_INTERNAL (nm_bond_device_factory_get_type); - _ADD_INTERNAL (nm_bridge_device_factory_get_type); - _ADD_INTERNAL (nm_dummy_device_factory_get_type); - _ADD_INTERNAL (nm_ethernet_device_factory_get_type); - _ADD_INTERNAL (nm_infiniband_device_factory_get_type); - _ADD_INTERNAL (nm_ip_tunnel_device_factory_get_type); - _ADD_INTERNAL (nm_macsec_device_factory_get_type); - _ADD_INTERNAL (nm_macvlan_device_factory_get_type); - _ADD_INTERNAL (nm_ppp_device_factory_get_type); - _ADD_INTERNAL (nm_tun_device_factory_get_type); - _ADD_INTERNAL (nm_veth_device_factory_get_type); - _ADD_INTERNAL (nm_vlan_device_factory_get_type); - _ADD_INTERNAL (nm_vxlan_device_factory_get_type); - - load_factories_from_dir (NMPLUGINDIR, callback, user_data); -} diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 27eaf8d6..f6a670b2 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -26,6 +26,8 @@ #include "platform/nm-platform.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Generic.h" + /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE_BASE ( @@ -201,25 +203,10 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_device_generic_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_generic = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_GENERIC, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("TypeDescription", "s", NM_DEVICE_GENERIC_TYPE_DESCRIPTION), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_generic_class_init (NMDeviceGenericClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_GENERIC_SETTING_NAME, NM_LINK_TYPE_ANY) @@ -229,8 +216,6 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_generic); - parent_class->realize_start_notify = realize_start_notify; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->get_type_description = get_type_description; @@ -244,4 +229,8 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_GENERIC_SKELETON, + NULL); } diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 781bbd69..09ad2855 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -32,6 +32,8 @@ #include "nm-device-factory.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Infiniband.h" + #define NM_DEVICE_INFINIBAND_IS_PARTITION "is-partition" /*****************************************************************************/ @@ -175,7 +177,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingInfiniband *s_infiniband; @@ -366,25 +368,10 @@ nm_device_infiniband_init (NMDeviceInfiniband * self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_infiniband = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_INFINIBAND, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_INFINIBAND_SETTING_NAME, NM_LINK_TYPE_INFINIBAND) @@ -392,8 +379,6 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_infiniband); - parent_class->create_and_realize = create_and_realize; parent_class->unrealize = unrealize; parent_class->get_generic_capabilities = get_generic_capabilities; @@ -411,6 +396,10 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_INFINIBAND_SKELETON, + NULL); } /*****************************************************************************/ @@ -444,7 +433,7 @@ create_device (NMDeviceFactory *factory, NM_DEVICE_TYPE_DESC, "InfiniBand", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_INFINIBAND, - /* NOTE: Partition should probably be a different link type! */ + /* XXX: Partition should probably be a different link type! */ NM_DEVICE_INFINIBAND_IS_PARTITION, is_partition, NULL); } diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 59ca9ed5..af3cfe4c 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -37,6 +37,8 @@ #include "nm-act-request.h" #include "nm-ip4-config.h" +#include "introspection/org.freedesktop.NetworkManager.Device.IPTunnel.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceIPTunnel); @@ -53,7 +55,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceIPTunnel, PROP_OUTPUT_KEY, PROP_ENCAPSULATION_LIMIT, PROP_FLOW_LABEL, - PROP_FLAGS, ); typedef struct { @@ -68,7 +69,6 @@ typedef struct { char *output_key; guint8 encap_limit; guint32 flow_label; - NMIPTunnelFlags flags; } NMDeviceIPTunnelPrivate; struct _NMDeviceIPTunnel { @@ -86,30 +86,6 @@ G_DEFINE_TYPE (NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE) /*****************************************************************************/ -static guint32 -ip6tnl_flags_setting_to_plat (NMIPTunnelFlags flags) -{ - G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT == IP6_TNL_F_IGN_ENCAP_LIMIT); - G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS == IP6_TNL_F_USE_ORIG_TCLASS); - G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL == IP6_TNL_F_USE_ORIG_FLOWLABEL); - G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV == IP6_TNL_F_MIP6_DEV); - G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY == IP6_TNL_F_RCV_DSCP_COPY); - G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK == IP6_TNL_F_USE_ORIG_FWMARK); - - /* NOTE: "accidentally", the numeric values correspond. - * For flags added in the future, that might no longer - * be the case. */ - return flags & _NM_IP_TUNNEL_FLAG_ALL_IP6TNL; -} - -static NMIPTunnelFlags -ip6tnl_flags_plat_to_setting (guint32 flags) -{ - return flags & ((guint32) _NM_IP_TUNNEL_FLAG_ALL_IP6TNL); -} - -/*****************************************************************************/ - static gboolean address_equal_pp (int family, const char *a, const char *b) { @@ -153,7 +129,6 @@ update_properties_from_ifindex (NMDevice *device, int ifindex) guint8 ttl = 0, tos = 0, encap_limit = 0; gboolean pmtud = FALSE; guint32 flow_label = 0; - NMIPTunnelFlags flags = NM_IP_TUNNEL_FLAG_NONE; char *key; if (ifindex <= 0) { @@ -271,7 +246,6 @@ clear: tos = lnk->tclass; encap_limit = lnk->encap_limit; flow_label = lnk->flow_label; - flags = ip6tnl_flags_plat_to_setting (lnk->flags); } else g_return_if_reached (); @@ -333,11 +307,6 @@ out: priv->flow_label = flow_label; _notify (self, PROP_FLOW_LABEL); } - - if (priv->flags != flags) { - priv->flags = flags; - _notify (self, PROP_FLAGS); - } } static void @@ -358,7 +327,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingIPTunnel *s_ip_tunnel; @@ -716,7 +685,6 @@ create_and_realize (NMDevice *device, lnk_ip6tnl.encap_limit = nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel); lnk_ip6tnl.flow_label = nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel); lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6; - lnk_ip6tnl.flags = ip6tnl_flags_setting_to_plat (nm_setting_ip_tunnel_get_flags (s_ip_tunnel)); plerr = nm_platform_link_ip6tnl_add (nm_device_get_platform (device), iface, &lnk_ip6tnl, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { @@ -846,9 +814,6 @@ get_property (GObject *object, guint prop_id, case PROP_FLOW_LABEL: g_value_set_uint (value, priv->flow_label); break; - case PROP_FLAGS: - g_value_set_uint (value, priv->flags); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -905,35 +870,10 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_ip_tunnel = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "u", NM_DEVICE_IP_TUNNEL_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Local", "s", NM_DEVICE_IP_TUNNEL_LOCAL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Remote", "s", NM_DEVICE_IP_TUNNEL_REMOTE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ttl", "y", NM_DEVICE_IP_TUNNEL_TTL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Tos", "y", NM_DEVICE_IP_TUNNEL_TOS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PathMtuDiscovery", "b", NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("InputKey", "s", NM_DEVICE_IP_TUNNEL_INPUT_KEY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("OutputKey", "s", NM_DEVICE_IP_TUNNEL_OUTPUT_KEY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("EncapsulationLimit", "y", NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("FlowLabel", "u", NM_DEVICE_IP_TUNNEL_FLOW_LABEL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Flags", "u", NM_DEVICE_IP_TUNNEL_FLAGS), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); object_class->constructed = constructed; @@ -941,8 +881,6 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ip_tunnel); - device_class->link_changed = link_changed; device_class->can_reapply_change = can_reapply_change; device_class->complete_connection = complete_connection; @@ -1021,13 +959,11 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_FLAGS] = - g_param_spec_uint (NM_DEVICE_IP_TUNNEL_FLAGS, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_IPTUNNEL_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h index 1109ace4..4bff6e33 100644 --- a/src/devices/nm-device-ip-tunnel.h +++ b/src/devices/nm-device-ip-tunnel.h @@ -41,7 +41,9 @@ #define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key" #define NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" #define NM_DEVICE_IP_TUNNEL_FLOW_LABEL "flow-label" -#define NM_DEVICE_IP_TUNNEL_FLAGS "flags" + +/* defined in the parent class, but exposed on D-Bus by the subclass. */ +#define NM_DEVICE_IP_TUNNEL_PARENT NM_DEVICE_PARENT typedef struct _NMDeviceIPTunnel NMDeviceIPTunnel; typedef struct _NMDeviceIPTunnelClass NMDeviceIPTunnelClass; diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c index 895ea34f..5ef8f938 100644 --- a/src/devices/nm-device-macsec.c +++ b/src/devices/nm-device-macsec.c @@ -33,6 +33,8 @@ #include "supplicant/nm-supplicant-interface.h" #include "supplicant/nm-supplicant-config.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Macsec.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceMacsec); @@ -184,12 +186,8 @@ update_properties (NMDevice *device) nm_device_parent_set_ifindex (device, props->parent_ifindex); #define CHECK_PROPERTY_CHANGED(field, prop) \ - G_STMT_START { \ - if (priv->props.field != props->field) { \ - priv->props.field = props->field; \ - _notify (self, prop); \ - } \ - } G_STMT_END + if (props->field != priv->props.field) \ + _notify (self, prop) CHECK_PROPERTY_CHANGED (sci, PROP_SCI); CHECK_PROPERTY_CHANGED (cipher_suite, PROP_CIPHER_SUITE); @@ -204,6 +202,7 @@ update_properties (NMDevice *device) CHECK_PROPERTY_CHANGED (scb, PROP_SCB); CHECK_PROPERTY_CHANGED (replay_protect, PROP_REPLAY_PROTECT); + priv->props = *props; g_object_thaw_notify ((GObject *) device); } @@ -223,7 +222,7 @@ build_supplicant_config (NMDeviceMacsec *self, GError **error) mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); - config = nm_supplicant_config_new (FALSE, FALSE); + config = nm_supplicant_config_new (); s_macsec = (NMSettingMacsec *) nm_device_get_applied_setting (NM_DEVICE (self), NM_TYPE_SETTING_MACSEC); @@ -478,9 +477,12 @@ handle_auth_or_fail (NMDeviceMacsec *self, NMActRequest *req, gboolean new_secrets) { + NMDeviceMacsecPrivate *priv; const char *setting_name; NMConnection *applied_connection; + priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); + if (!nm_device_auth_retries_try_next (NM_DEVICE (self))) return NM_ACT_STAGE_RETURN_FAILURE; @@ -490,14 +492,13 @@ handle_auth_or_fail (NMDeviceMacsec *self, applied_connection = nm_act_request_get_applied_connection (req); setting_name = nm_connection_need_secrets (applied_connection, NULL); - if (!setting_name) { + if (setting_name) { + macsec_secrets_get_secrets (self, setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); + } else _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); - return NM_ACT_STAGE_RETURN_FAILURE; - } - macsec_secrets_get_secrets (self, setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -811,36 +812,10 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_device_macsec_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_macsec = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_MACSEC, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Sci", "t", NM_DEVICE_MACSEC_SCI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("IcvLength", "y", NM_DEVICE_MACSEC_ICV_LENGTH), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("CipherSuite", "t", NM_DEVICE_MACSEC_CIPHER_SUITE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Window", "u", NM_DEVICE_MACSEC_WINDOW), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("EncodingSa", "y", NM_DEVICE_MACSEC_ENCODING_SA), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Validation", "s", NM_DEVICE_MACSEC_VALIDATION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Encrypt", "b", NM_DEVICE_MACSEC_ENCRYPT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Protect", "b", NM_DEVICE_MACSEC_PROTECT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("IncludeSci", "b", NM_DEVICE_MACSEC_INCLUDE_SCI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Es", "b", NM_DEVICE_MACSEC_ES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Scb", "b", NM_DEVICE_MACSEC_SCB), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ReplayProtect", "b", NM_DEVICE_MACSEC_REPLAY_PROTECT), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_macsec_class_init (NMDeviceMacsecClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACSEC) @@ -848,8 +823,6 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass) object_class->get_property = get_property; object_class->dispose = dispose; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_macsec); - parent_class->act_stage2_config = act_stage2_config; parent_class->check_connection_compatible = check_connection_compatible; parent_class->create_and_realize = create_and_realize; @@ -913,6 +886,10 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_MACSEC_SKELETON, + NULL); } /*************************************************************/ diff --git a/src/devices/nm-device-macsec.h b/src/devices/nm-device-macsec.h index 23e9d2c9..17b33bf5 100644 --- a/src/devices/nm-device-macsec.h +++ b/src/devices/nm-device-macsec.h @@ -43,6 +43,9 @@ #define NM_DEVICE_MACSEC_SCB "scb" #define NM_DEVICE_MACSEC_REPLAY_PROTECT "replay-protect" +/* defined in the parent class, but exposed on D-Bus by the subclass. */ +#define NM_DEVICE_MACSEC_PARENT NM_DEVICE_PARENT + typedef struct _NMDeviceMacsec NMDeviceMacsec; typedef struct _NMDeviceMacsecClass NMDeviceMacsecClass; diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index b8e748d6..2a461543 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -36,6 +36,8 @@ #include "nm-ip4-config.h" #include "nm-utils.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Macvlan.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceMacvlan); @@ -195,17 +197,12 @@ update_properties (NMDevice *device) g_object_freeze_notify (object); nm_device_parent_set_ifindex (device, plink->parent); + if (priv->props.mode != props->mode) + _notify (self, PROP_MODE); + if (priv->props.no_promisc != props->no_promisc) + _notify (self, PROP_NO_PROMISC); -#define CHECK_PROPERTY_CHANGED(field, prop) \ - G_STMT_START { \ - if (priv->props.field != props->field) { \ - priv->props.field = props->field; \ - _notify (self, prop); \ - } \ - } G_STMT_END - - CHECK_PROPERTY_CHANGED (mode, PROP_MODE); - CHECK_PROPERTY_CHANGED (no_promisc, PROP_NO_PROMISC); + priv->props = *props; g_object_thaw_notify (object); } @@ -334,7 +331,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingMacvlan *s_macvlan; @@ -473,27 +470,10 @@ nm_device_macvlan_init (NMDeviceMacvlan *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_macvlan = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_MACVLAN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "s", NM_DEVICE_MACVLAN_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("NoPromisc", "b", NM_DEVICE_MACVLAN_NO_PROMISC), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Tab", "b", NM_DEVICE_MACVLAN_TAP), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP) @@ -501,8 +481,6 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_macvlan); - device_class->act_stage1_prepare = act_stage1_prepare; device_class->check_connection_compatible = check_connection_compatible; device_class->complete_connection = complete_connection; @@ -535,6 +513,10 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_MACVLAN_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-macvlan.h b/src/devices/nm-device-macvlan.h index c7d4be7c..e6d3a333 100644 --- a/src/devices/nm-device-macvlan.h +++ b/src/devices/nm-device-macvlan.h @@ -34,6 +34,9 @@ #define NM_DEVICE_MACVLAN_NO_PROMISC "no-promisc" #define NM_DEVICE_MACVLAN_TAP "tap" +/* defined in the parent class, but exposed on D-Bus by the subclass. */ +#define NM_DEVICE_MACVLAN_PARENT NM_DEVICE_PARENT + typedef struct _NMDeviceMacvlan NMDeviceMacvlan; typedef struct _NMDeviceMacvlanClass NMDeviceMacvlanClass; diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c index 94df0cae..639ec44a 100644 --- a/src/devices/nm-device-ppp.c +++ b/src/devices/nm-device-ppp.c @@ -26,6 +26,8 @@ #include "ppp/nm-ppp-manager-call.h" #include "ppp/nm-ppp-status.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Ppp.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDevicePpp); @@ -33,7 +35,8 @@ _LOG_DECLARE_SELF(NMDevicePpp); typedef struct _NMDevicePppPrivate { NMPPPManager *ppp_manager; - NMIP4Config *ip4_config; + NMIP4Config *pending_ip4_config; + char *pending_ifname; } NMDevicePppPrivate; struct _NMDevicePpp { @@ -85,52 +88,46 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ case NM_PPP_STATUS_DEAD: nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); break; + case NM_PPP_STATUS_RUNNING: + nm_device_activate_schedule_stage3_ip_config_start (device); + break; default: break; } } static void -ppp_ifindex_set (NMPPPManager *ppp_manager, - int ifindex, - const char *iface, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - gs_free char *old_name = NULL; - - if (!nm_device_take_over_link (device, ifindex, &old_name)) { - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - if (old_name) - nm_manager_remove_device (nm_manager_get (), old_name, NM_DEVICE_TYPE_PPP); - - nm_device_activate_schedule_stage3_ip_config_start (device); -} - -static void ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, NMIP4Config *config, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDevicePpp *self = NM_DEVICE_PPP (device); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); + gboolean renamed; _LOGT (LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd"); if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { if (nm_device_activate_ip4_state_in_conf (device)) { + if (!nm_device_take_over_link (device, iface, &renamed)) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + if (renamed) + nm_manager_remove_device (nm_manager_get (), iface, NM_DEVICE_TYPE_PPP); + nm_device_activate_schedule_ip4_config_result (device, config); return; } } else { - if (priv->ip4_config) - g_object_unref (priv->ip4_config); - priv->ip4_config = g_object_ref (config); + if (priv->pending_ip4_config) + g_object_unref (priv->pending_ip4_config); + priv->pending_ip4_config = g_object_ref (config); + g_free (priv->pending_ifname); + priv->pending_ifname = g_strdup (iface); } } @@ -149,7 +146,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting ((NMDevice *) self, NM_TYPE_SETTING_PPPOE); g_return_val_if_fail (s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); - g_clear_object (&priv->ip4_config); + g_clear_object (&priv->pending_ip4_config); + nm_clear_g_free (&priv->pending_ifname); priv->ppp_manager = nm_ppp_manager_create (nm_setting_pppoe_get_parent (s_pppoe), &error); @@ -177,9 +175,6 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK (ppp_ifindex_set), - self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -194,12 +189,17 @@ act_stage3_ip4_config_start (NMDevice *device, { NMDevicePpp *self = NM_DEVICE_PPP (device); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); + gboolean renamed; - if (priv->ip4_config) { + if (priv->pending_ip4_config) { + if (!nm_device_take_over_link (device, priv->pending_ifname, &renamed)) + return NM_ACT_STAGE_RETURN_FAILURE; + if (renamed) + nm_manager_remove_device (nm_manager_get (), priv->pending_ifname, NM_DEVICE_TYPE_PPP); if (out_config) - *out_config = g_steal_pointer (&priv->ip4_config); + *out_config = g_steal_pointer (&priv->pending_ip4_config); else - g_clear_object (&priv->ip4_config); + g_clear_object (&priv->pending_ip4_config); return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -207,6 +207,14 @@ act_stage3_ip4_config_start (NMDevice *device, return NM_ACT_STAGE_RETURN_POSTPONE; } +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *self, + NMIP6Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + return NM_ACT_STAGE_RETURN_IP_FAIL; +} + static gboolean create_and_realize (NMDevice *device, NMConnection *connection, @@ -255,40 +263,33 @@ dispose (GObject *object) NMDevicePpp *self = NM_DEVICE_PPP (object); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); - g_clear_object (&priv->ip4_config); + g_clear_object (&priv->pending_ip4_config); + nm_clear_g_free (&priv->pending_ifname); G_OBJECT_CLASS (nm_device_ppp_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_ppp = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_PPP, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_ppp_class_init (NMDevicePppClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_PPPOE_SETTING_NAME, NM_LINK_TYPE_PPP) object_class->dispose = dispose; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ppp); - parent_class->act_stage2_config = act_stage2_config; parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; parent_class->check_connection_compatible = check_connection_compatible; parent_class->create_and_realize = create_and_realize; parent_class->deactivate = deactivate; parent_class->get_generic_capabilities = get_generic_capabilities; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_PPP_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index b0d3ffa4..f1486c54 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -45,8 +45,6 @@ enum NMActStageReturn { NMSettings *nm_device_get_settings (NMDevice *self); -gboolean nm_device_set_ip_ifindex (NMDevice *self, int ifindex); - gboolean nm_device_set_ip_iface (NMDevice *self, const char *iface); void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *device); @@ -59,7 +57,7 @@ gboolean nm_device_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmwar void nm_device_take_down (NMDevice *self, gboolean block); -gboolean nm_device_take_over_link (NMDevice *self, int ifindex, char **old_name); +gboolean nm_device_take_over_link (NMDevice *self, const char *ifname, gboolean *renamed); gboolean nm_device_hw_addr_set (NMDevice *device, const char *addr, @@ -141,4 +139,4 @@ gboolean nm_device_match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr); -#endif /* NM_DEVICE_PRIVATE_H */ +#endif /* NM_DEVICE_PRIVATE_H */ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index c3ce4b73..a7d7c0bf 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -25,7 +25,6 @@ #include <stdlib.h> #include <string.h> #include <sys/types.h> -#include <linux/if_tun.h> #include "nm-act-request.h" #include "nm-device-private.h" @@ -35,6 +34,8 @@ #include "nm-setting-tun.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Tun.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceTun); @@ -50,7 +51,8 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceTun, ); typedef struct { - NMPlatformLnkTun props; + NMPlatformTunProperties props; + const char *mode; } NMDeviceTunPrivate; struct _NMDeviceTun { @@ -69,62 +71,48 @@ G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE) /*****************************************************************************/ static void -update_properties_from_struct (NMDeviceTun *self, - const NMPlatformLnkTun *props) -{ - NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); - const NMPlatformLnkTun props0 = { }; - - if (!props) { - /* allow passing %NULL to reset all properties. */ - props = &props0; - } - - g_object_freeze_notify (G_OBJECT (self)); - -#define CHECK_PROPERTY_CHANGED_VALID(field, prop) \ - G_STMT_START { \ - if ( priv->props.field != props->field \ - || priv->props.field##_valid != props->field##_valid) { \ - priv->props.field##_valid = props->field##_valid; \ - priv->props.field = props->field; \ - _notify (self, prop); \ - } \ - } G_STMT_END - -#define CHECK_PROPERTY_CHANGED(field, prop) \ - G_STMT_START { \ - if (priv->props.field != props->field) { \ - priv->props.field = props->field; \ - _notify (self, prop); \ - } \ - } G_STMT_END - - CHECK_PROPERTY_CHANGED_VALID (owner, PROP_OWNER); - CHECK_PROPERTY_CHANGED_VALID (group, PROP_GROUP); - CHECK_PROPERTY_CHANGED (type, PROP_MODE); - CHECK_PROPERTY_CHANGED (pi, PROP_NO_PI); - CHECK_PROPERTY_CHANGED (vnet_hdr, PROP_VNET_HDR); - CHECK_PROPERTY_CHANGED (multi_queue, PROP_MULTI_QUEUE); - - g_object_thaw_notify (G_OBJECT (self)); -} - -static void update_properties (NMDeviceTun *self) { - NMPlatformLnkTun props_storage; - const NMPlatformLnkTun *props = NULL; + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + GObject *object = G_OBJECT (self); + NMPlatformTunProperties props; int ifindex; ifindex = nm_device_get_ifindex (NM_DEVICE (self)); - if ( ifindex > 0 - && nm_platform_link_tun_get_properties (nm_device_get_platform (NM_DEVICE (self)), - ifindex, - &props_storage)) - props = &props_storage; - - update_properties_from_struct (self, props); + if (ifindex > 0) { + if (!nm_platform_link_tun_get_properties (nm_device_get_platform (NM_DEVICE (self)), ifindex, &props)) { + _LOGD (LOGD_DEVICE, "tun-properties: cannot loading tun properties from platform for ifindex %d", ifindex); + ifindex = 0; + } else if (g_strcmp0 (priv->mode, props.mode) != 0) { + /* if the mode differs, we ignore what we loaded. A NMDeviceTun cannot + * change the mode after construction. */ + _LOGD (LOGD_DEVICE, "tun-properties: loading tun properties yielded tun-mode %s%s%s, but %s%s%s expected (ifindex %d)", + NM_PRINT_FMT_QUOTE_STRING (props.mode), + NM_PRINT_FMT_QUOTE_STRING (priv->mode), + ifindex); + ifindex = 0; + } + } else + _LOGD (LOGD_DEVICE, "tun-properties: ignore loading properties due to missing ifindex"); + if (ifindex <= 0) + memset (&props, 0, sizeof (props)); + + g_object_freeze_notify (object); + + if (priv->props.owner != props.owner) + _notify (self, PROP_OWNER); + if (priv->props.group != props.group) + _notify (self, PROP_GROUP); + if (priv->props.no_pi != props.no_pi) + _notify (self, PROP_NO_PI); + if (priv->props.vnet_hdr != props.vnet_hdr) + _notify (self, PROP_VNET_HDR); + if (priv->props.multi_queue != props.multi_queue) + _notify (self, PROP_MULTI_QUEUE); + + memcpy (&priv->props, &props, sizeof (NMPlatformTunProperties)); + + g_object_thaw_notify (object); } static NMDeviceCapabilities @@ -145,7 +133,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingTun *s_tun; @@ -169,57 +157,61 @@ complete_connection (NMDevice *device, return TRUE; } +static int +tun_mode_from_string (const char *string) +{ + if (!g_strcmp0 (string, "tap")) + return NM_SETTING_TUN_MODE_TAP; + else + return NM_SETTING_TUN_MODE_TUN; +} + static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceTun *self = NM_DEVICE_TUN (device); - NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); - NMSettingTun *s_tun; + NMSettingTun *s_tun = nm_connection_get_setting_tun (connection); + NMPlatformTunProperties props; NMSettingTunMode mode; - char s_buf[100]; - const char *str; - - /* Note: since we read tun properties from sysctl for older kernels, - * we don't get proper change notifications. Make sure that all our - * tun properties are up to date at this point. We should not do this, - * if we would entirely rely on netlink events. */ - update_properties (NM_DEVICE_TUN (device)); + gint64 user, group; + char *str; - switch (priv->props.type) { - case IFF_TUN: mode = NM_SETTING_TUN_MODE_TUN; break; - case IFF_TAP: mode = NM_SETTING_TUN_MODE_TAP; break; - default: - /* Huh? */ - return; - } - - s_tun = nm_connection_get_setting_tun (connection); if (!s_tun) { s_tun = (NMSettingTun *) nm_setting_tun_new (); nm_connection_add_setting (connection, (NMSetting *) s_tun); } + if (!nm_platform_link_tun_get_properties (nm_device_get_platform (device), nm_device_get_ifindex (device), &props)) { + _LOGW (LOGD_PLATFORM, "failed to get TUN interface info while updating connection."); + return; + } + + mode = tun_mode_from_string (props.mode); + if (mode != nm_setting_tun_get_mode (s_tun)) - g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MODE, (guint) mode, NULL); + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MODE, mode, NULL); + + user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); + group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); - str = priv->props.owner_valid - ? nm_sprintf_buf (s_buf, "%" G_GINT32_FORMAT, priv->props.owner) - : NULL; - if (!nm_streq0 (str, nm_setting_tun_get_owner (s_tun))) + if (props.owner != user) { + str = props.owner >= 0 ? g_strdup_printf ("%" G_GINT32_FORMAT, (gint32) props.owner) : NULL; g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_OWNER, str, NULL); + g_free (str); + } - str = priv->props.group_valid - ? nm_sprintf_buf (s_buf, "%" G_GINT32_FORMAT, priv->props.group) - : NULL; - if (!nm_streq0 (str, nm_setting_tun_get_group (s_tun))) + if (props.group != group) { + str = props.group >= 0 ? g_strdup_printf ("%" G_GINT32_FORMAT, (gint32) props.group) : NULL; g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_GROUP, str, NULL); + g_free (str); + } - if (priv->props.pi != nm_setting_tun_get_pi (s_tun)) - g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_PI, (gboolean) priv->props.pi, NULL); - if (priv->props.vnet_hdr != nm_setting_tun_get_vnet_hdr (s_tun)) - g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_VNET_HDR, (gboolean) priv->props.vnet_hdr, NULL); - if (priv->props.multi_queue != nm_setting_tun_get_multi_queue (s_tun)) - g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MULTI_QUEUE, (gboolean) priv->props.multi_queue, NULL); + if ((!props.no_pi) != nm_setting_tun_get_pi (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_PI, !props.no_pi, NULL); + if (props.vnet_hdr != nm_setting_tun_get_vnet_hdr (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_VNET_HDR, props.vnet_hdr, NULL); + if (props.multi_queue != nm_setting_tun_get_multi_queue (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MULTI_QUEUE, props.multi_queue, NULL); } static gboolean @@ -230,42 +222,23 @@ create_and_realize (NMDevice *device, GError **error) { const char *iface = nm_device_get_iface (device); - NMPlatformLnkTun props = { }; NMPlatformError plerr; NMSettingTun *s_tun; - gint64 owner, group; + gint64 user, group; s_tun = nm_connection_get_setting_tun (connection); - g_return_val_if_fail (s_tun, FALSE); - - switch (nm_setting_tun_get_mode (s_tun)) { - case NM_SETTING_TUN_MODE_TAP: props.type = IFF_TAP; break; - case NM_SETTING_TUN_MODE_TUN: props.type = IFF_TUN; break; - default: - g_return_val_if_reached (FALSE); - } + g_assert (s_tun); - owner = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); - if (owner != -1) { - props.owner_valid = TRUE; - props.owner = owner; - } + user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); - if (group != -1) { - props.group_valid = TRUE; - props.group = group; - } - props.pi = nm_setting_tun_get_pi (s_tun); - props.vnet_hdr = nm_setting_tun_get_vnet_hdr (s_tun); - props.multi_queue = nm_setting_tun_get_multi_queue (s_tun); - props.persist = TRUE; - - plerr = nm_platform_link_tun_add (nm_device_get_platform (device), - iface, - &props, - out_plink, - NULL); + plerr = nm_platform_link_tun_add (nm_device_get_platform (device), iface, + nm_setting_tun_get_mode (s_tun) == NM_SETTING_TUN_MODE_TAP, + user, group, + nm_setting_tun_get_pi (s_tun), + nm_setting_tun_get_vnet_hdr (s_tun), + nm_setting_tun_get_multi_queue (s_tun), + out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create TUN/TAP interface '%s' for '%s': %s", @@ -279,22 +252,13 @@ create_and_realize (NMDevice *device, } static gboolean -_same_og (const char *str, gboolean og_valid, guint32 og_num) -{ - gint64 v; - - v = _nm_utils_ascii_str_to_int64 (str, 10, 0, G_MAXINT32, -1); - return (!og_valid && ( v == (gint64) -1)) - || ( og_valid && (((guint32) v) == og_num )); -} - -static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); NMSettingTunMode mode; NMSettingTun *s_tun; + gint64 user, group; if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection)) return FALSE; @@ -304,21 +268,18 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return FALSE; if (nm_device_is_real (device)) { - switch (priv->props.type) { - case IFF_TUN: mode = NM_SETTING_TUN_MODE_TUN; break; - case IFF_TAP: mode = NM_SETTING_TUN_MODE_TAP; break; - default: - /* Huh? */ - return FALSE; - } - + mode = tun_mode_from_string (priv->mode); if (mode != nm_setting_tun_get_mode (s_tun)) return FALSE; - if (!_same_og (nm_setting_tun_get_owner (s_tun), priv->props.owner_valid, priv->props.owner)) + + user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); + group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); + + if (user != priv->props.owner) return FALSE; - if (!_same_og (nm_setting_tun_get_group (s_tun), priv->props.group_valid, priv->props.group)) + if (group != priv->props.group) return FALSE; - if (nm_setting_tun_get_pi (s_tun) != priv->props.pi) + if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi) return FALSE; if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr) return FALSE; @@ -341,7 +302,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) return ret; /* Nothing to do for TUN devices */ - if (priv->props.type == IFF_TUN) + if (g_strcmp0 (priv->mode, "tap")) return NM_ACT_STAGE_RETURN_SUCCESS; if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) @@ -353,8 +314,16 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) static void unrealize_notify (NMDevice *device) { + NMDeviceTun *self = NM_DEVICE_TUN (device); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + guint i; + NM_DEVICE_CLASS (nm_device_tun_parent_class)->unrealize_notify (device); - update_properties_from_struct (NM_DEVICE_TUN (device), NULL); + + memset (&priv->props, 0, sizeof (NMPlatformTunProperties)); + + for (i = 1; i < _PROPERTY_ENUMS_LAST; i++) + g_object_notify_by_pspec ((GObject *) self, obj_properties[i]); } /*****************************************************************************/ @@ -365,25 +334,19 @@ get_property (GObject *object, guint prop_id, { NMDeviceTun *self = NM_DEVICE_TUN (object); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); - const char *s; switch (prop_id) { case PROP_OWNER: - g_value_set_int64 (value, priv->props.owner_valid ? (gint64) priv->props.owner : (gint64) -1); + g_value_set_int64 (value, priv->props.owner); break; case PROP_GROUP: - g_value_set_int64 (value, priv->props.group_valid ? (gint64) priv->props.group : (gint64) -1); + g_value_set_int64 (value, priv->props.group); break; case PROP_MODE: - switch (priv->props.type) { - case IFF_TUN: s = "tun"; break; - case IFF_TAP: s = "tap"; break; - default: s = NULL; break; - } - g_value_set_static_string (value, s); + g_value_set_string (value, priv->mode); break; case PROP_NO_PI: - g_value_set_boolean (value, !priv->props.pi); + g_value_set_boolean (value, priv->props.no_pi); break; case PROP_VNET_HDR: g_value_set_boolean (value, priv->props.vnet_hdr); @@ -397,6 +360,33 @@ get_property (GObject *object, guint prop_id, } } +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDeviceTun *self = NM_DEVICE_TUN (object); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + const char *str; + + switch (prop_id) { + case PROP_MODE: + /* construct-only */ + str = g_value_get_string (value); + + /* mode is G_PARAM_STATIC_STRINGS */ + if (g_strcmp0 (str, "tun") == 0) + priv->mode = "tun"; + else if (g_strcmp0 (str, "tap") == 0) + priv->mode = "tap"; + else + g_return_if_fail (FALSE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + /*****************************************************************************/ static void @@ -404,37 +394,16 @@ nm_device_tun_init (NMDeviceTun *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_tun = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_TUN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Owner", "x", NM_DEVICE_TUN_OWNER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Group", "x", NM_DEVICE_TUN_GROUP), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "s", NM_DEVICE_TUN_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("NoPi", "b", NM_DEVICE_TUN_NO_PI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("VnetHdr", "b", NM_DEVICE_TUN_VNET_HDR), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("MultiQueue", "b", NM_DEVICE_TUN_MULTI_QUEUE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_tun_class_init (NMDeviceTunClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN) + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP) object_class->get_property = get_property; - - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_tun); + object_class->set_property = set_property; device_class->connection_type = NM_SETTING_TUN_SETTING_NAME; device_class->link_changed = link_changed; @@ -459,8 +428,9 @@ nm_device_tun_class_init (NMDeviceTunClass *klass) obj_properties[PROP_MODE] = g_param_spec_string (NM_DEVICE_TUN_MODE, "", "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + "tun", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_NO_PI] = g_param_spec_boolean (NM_DEVICE_TUN_NO_PI, "", "", @@ -478,6 +448,10 @@ nm_device_tun_class_init (NMDeviceTunClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_TUN_SKELETON, + NULL); } @@ -493,19 +467,42 @@ create_device (NMDeviceFactory *factory, NMConnection *connection, gboolean *out_ignore) { - g_return_val_if_fail (!plink || plink->type == NM_LINK_TYPE_TUN, NULL); - g_return_val_if_fail (!connection || nm_streq0 (nm_connection_get_connection_type (connection), NM_SETTING_TUN_SETTING_NAME), NULL); + NMSettingTun *s_tun; + NMLinkType link_type = NM_LINK_TYPE_UNKNOWN; + const char *mode; + + if (plink) { + link_type = plink->type; + } else if (connection) { + s_tun = nm_connection_get_setting_tun (connection); + if (!s_tun) + return NULL; + switch (nm_setting_tun_get_mode (s_tun)) { + case NM_SETTING_TUN_MODE_TUN: + link_type = NM_LINK_TYPE_TUN; + break; + case NM_SETTING_TUN_MODE_TAP: + link_type = NM_LINK_TYPE_TAP; + break; + case NM_SETTING_TUN_MODE_UNKNOWN: + g_return_val_if_reached (NULL); + } + } + + g_return_val_if_fail (link_type != NM_LINK_TYPE_UNKNOWN, NULL); + mode = link_type == NM_LINK_TYPE_TUN ? "tun" : "tap"; return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TUN, NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Tun", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TUN, - NM_DEVICE_LINK_TYPE, (guint) NM_LINK_TYPE_TUN, + NM_DEVICE_LINK_TYPE, link_type, + NM_DEVICE_TUN_MODE, mode, NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL (TUN, Tun, tun, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TUN) + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_TUN_SETTING_NAME), factory_class->create_device = create_device; ); diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index 186173eb..a8c4bcc8 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -30,6 +30,8 @@ #include "platform/nm-platform.h" #include "nm-device-factory.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Veth.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVeth); @@ -99,18 +101,11 @@ nm_device_veth_init (NMDeviceVeth *self) } static void -parent_changed_notify (NMDevice *device, - int old_ifindex, - NMDevice *old_parent, - int new_ifindex, - NMDevice *new_parent) +notify (GObject *object, GParamSpec *pspec) { - NM_DEVICE_CLASS (nm_device_veth_parent_class)->parent_changed_notify (device, - old_ifindex, - old_parent, - new_ifindex, - new_parent); - _notify (NM_DEVICE_VETH (device), PROP_PEER); + if (nm_streq (pspec->name, NM_DEVICE_PARENT)) + _notify (NM_DEVICE_VETH (object), PROP_PEER); + G_OBJECT_CLASS (nm_device_veth_parent_class)->notify (object, pspec); } static void @@ -125,7 +120,7 @@ get_property (GObject *object, guint prop_id, peer = nm_device_parent_get_device (NM_DEVICE (self)); if (peer && !NM_IS_DEVICE_VETH (peer)) peer = NULL; - nm_dbus_utils_g_value_set_object_path (value, peer); + nm_utils_g_value_set_object_path (value, peer); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -133,35 +128,19 @@ get_property (GObject *object, guint prop_id, } } -static const NMDBusInterfaceInfoExtended interface_info_device_veth = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_VETH, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Peer", "o", NM_DEVICE_VETH_PEER), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_veth_class_init (NMDeviceVethClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH) object_class->get_property = get_property; - - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_veth); + object_class->notify = notify; device_class->can_unmanaged_external_down = can_unmanaged_external_down; device_class->link_changed = link_changed; - device_class->parent_changed_notify = parent_changed_notify; obj_properties[PROP_PEER] = g_param_spec_string (NM_DEVICE_VETH_PEER, "", "", @@ -170,6 +149,10 @@ nm_device_veth_class_init (NMDeviceVethClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_VETH_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index ae6a0f36..81512335 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -37,6 +37,8 @@ #include "nm-core-internal.h" #include "platform/nmp-object.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Vlan.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVlan); @@ -132,7 +134,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent, */ s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) - nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6); + nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6, FALSE); } } @@ -379,7 +381,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingVlan *s_vlan; @@ -575,35 +577,16 @@ nm_device_vlan_init (NMDeviceVlan * self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_vlan = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_VLAN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("VlanId", "u", NM_DEVICE_VLAN_ID), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_vlan_class_init (NMDeviceVlanClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN) object_class->get_property = get_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_vlan); - parent_class->create_and_realize = create_and_realize; parent_class->link_changed = link_changed; parent_class->unrealize_notify = unrealize_notify; @@ -625,6 +608,10 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_VLAN_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-vlan.h b/src/devices/nm-device-vlan.h index 375e8fa4..0d788940 100644 --- a/src/devices/nm-device-vlan.h +++ b/src/devices/nm-device-vlan.h @@ -36,8 +36,12 @@ typedef enum { NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ } NMVlanError; +/* D-Bus exported properties */ #define NM_DEVICE_VLAN_ID "vlan-id" +/* defined in the parent class, but exposed on D-Bus by the subclass. */ +#define NM_DEVICE_VLAN_PARENT NM_DEVICE_PARENT + typedef struct _NMDeviceVlan NMDeviceVlan; typedef struct _NMDeviceVlanClass NMDeviceVlanClass; diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index e1252223..d9efe840 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -35,6 +35,8 @@ #include "nm-act-request.h" #include "nm-ip4-config.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Vxlan.h" + #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVxlan); @@ -95,40 +97,42 @@ update_properties (NMDevice *device) if (priv->props.parent_ifindex != props->parent_ifindex) nm_device_parent_set_ifindex (device, props->parent_ifindex); - -#define CHECK_PROPERTY_CHANGED(field, prop) \ - G_STMT_START { \ - if (priv->props.field != props->field) { \ - priv->props.field = props->field; \ - _notify (self, prop); \ - } \ - } G_STMT_END - -#define CHECK_PROPERTY_CHANGED_IN6ADDR(field, prop) \ - G_STMT_START { \ - if (memcmp (&priv->props.field, &props->field, sizeof (props->field)) != 0) { \ - priv->props.field = props->field; \ - _notify (self, prop); \ - } \ - } G_STMT_END - - CHECK_PROPERTY_CHANGED (id, PROP_ID); - CHECK_PROPERTY_CHANGED (local, PROP_LOCAL); - CHECK_PROPERTY_CHANGED_IN6ADDR (local6, PROP_LOCAL); - CHECK_PROPERTY_CHANGED (group, PROP_GROUP); - CHECK_PROPERTY_CHANGED_IN6ADDR (group6, PROP_GROUP); - CHECK_PROPERTY_CHANGED (tos, PROP_TOS); - CHECK_PROPERTY_CHANGED (ttl, PROP_TTL); - CHECK_PROPERTY_CHANGED (learning, PROP_LEARNING); - CHECK_PROPERTY_CHANGED (ageing, PROP_AGEING); - CHECK_PROPERTY_CHANGED (limit, PROP_LIMIT); - CHECK_PROPERTY_CHANGED (src_port_min, PROP_SRC_PORT_MIN); - CHECK_PROPERTY_CHANGED (src_port_max, PROP_SRC_PORT_MAX); - CHECK_PROPERTY_CHANGED (dst_port, PROP_DST_PORT); - CHECK_PROPERTY_CHANGED (proxy, PROP_PROXY); - CHECK_PROPERTY_CHANGED (rsc, PROP_RSC); - CHECK_PROPERTY_CHANGED (l2miss, PROP_L2MISS); - CHECK_PROPERTY_CHANGED (l3miss, PROP_L3MISS); + if (priv->props.id != props->id) + _notify (self, PROP_ID); + if (priv->props.local != props->local) + _notify (self, PROP_LOCAL); + if (memcmp (&priv->props.local6, &props->local6, sizeof (props->local6)) != 0) + _notify (self, PROP_LOCAL); + if (priv->props.group != props->group) + _notify (self, PROP_GROUP); + if (memcmp (&priv->props.group6, &props->group6, sizeof (props->group6)) != 0) + _notify (self, PROP_GROUP); + if (priv->props.tos != props->tos) + _notify (self, PROP_TOS); + if (priv->props.ttl != props->ttl) + _notify (self, PROP_TTL); + if (priv->props.learning != props->learning) + _notify (self, PROP_LEARNING); + if (priv->props.ageing != props->ageing) + _notify (self, PROP_AGEING); + if (priv->props.limit != props->limit) + _notify (self, PROP_LIMIT); + if (priv->props.src_port_min != props->src_port_min) + _notify (self, PROP_SRC_PORT_MIN); + if (priv->props.src_port_max != props->src_port_max) + _notify (self, PROP_SRC_PORT_MAX); + if (priv->props.dst_port != props->dst_port) + _notify (self, PROP_DST_PORT); + if (priv->props.proxy != props->proxy) + _notify (self, PROP_PROXY); + if (priv->props.rsc != props->rsc) + _notify (self, PROP_RSC); + if (priv->props.l2miss != props->l2miss) + _notify (self, PROP_L2MISS); + if (priv->props.l3miss != props->l3miss) + _notify (self, PROP_L3MISS); + + priv->props = *props; g_object_thaw_notify (object); } @@ -314,7 +318,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingVxlan *s_vxlan; @@ -541,48 +545,16 @@ nm_device_vxlan_init (NMDeviceVxlan *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_vxlan = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_VXLAN, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Parent", "o", NM_DEVICE_PARENT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Id", "u", NM_DEVICE_VXLAN_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Group", "s", NM_DEVICE_VXLAN_GROUP), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Local", "s", NM_DEVICE_VXLAN_LOCAL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Tos", "y", NM_DEVICE_VXLAN_TOS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ttl", "y", NM_DEVICE_VXLAN_TTL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Learning", "b", NM_DEVICE_VXLAN_LEARNING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ageing", "u", NM_DEVICE_VXLAN_AGEING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Limit", "u", NM_DEVICE_VXLAN_LIMIT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("DstPort", "q", NM_DEVICE_VXLAN_DST_PORT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("SrcPortMin", "q", NM_DEVICE_VXLAN_SRC_PORT_MIN), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("SrcPortMax", "q", NM_DEVICE_VXLAN_SRC_PORT_MAX), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Proxy", "b", NM_DEVICE_VXLAN_PROXY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Rsc", "b", NM_DEVICE_VXLAN_RSC), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("L2miss", "b", NM_DEVICE_VXLAN_L2MISS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("L3miss", "b", NM_DEVICE_VXLAN_L3MISS), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VXLAN) object_class->get_property = get_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_vxlan); - device_class->link_changed = link_changed; device_class->unrealize_notify = unrealize_notify; device_class->connection_type = NM_SETTING_VXLAN_SETTING_NAME; @@ -685,6 +657,10 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_VXLAN_SKELETON, + NULL); } /*****************************************************************************/ diff --git a/src/devices/nm-device-vxlan.h b/src/devices/nm-device-vxlan.h index 511b7156..6f0102dc 100644 --- a/src/devices/nm-device-vxlan.h +++ b/src/devices/nm-device-vxlan.h @@ -46,6 +46,9 @@ #define NM_DEVICE_VXLAN_L2MISS "l2miss" #define NM_DEVICE_VXLAN_L3MISS "l3miss" +/* defined in the parent class, but exposed on D-Bus by the subclass. */ +#define NM_DEVICE_VXLAN_PARENT NM_DEVICE_PARENT + typedef struct _NMDeviceVxlan NMDeviceVxlan; typedef struct _NMDeviceVxlanClass NMDeviceVxlanClass; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 815de29a..e79bc541 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -34,7 +34,6 @@ #include <arpa/inet.h> #include <fcntl.h> #include <linux/if_addr.h> -#include <linux/if_arp.h> #include <linux/rtnetlink.h> #include <linux/pkt_sched.h> @@ -49,7 +48,6 @@ #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" #include "dhcp/nm-dhcp-manager.h" -#include "dhcp/nm-dhcp-utils.h" #include "nm-act-request.h" #include "nm-proxy-config.h" #include "nm-ip4-config.h" @@ -66,13 +64,13 @@ #include "nm-netns.h" #include "nm-dispatcher.h" #include "nm-config.h" -#include "c-list/src/c-list.h" +#include "nm-utils/c-list.h" #include "dns/nm-dns-manager.h" -#include "nm-acd-manager.h" #include "nm-core-internal.h" #include "systemd/nm-sd.h" #include "nm-lldp-listener.h" #include "nm-audit-manager.h" +#include "nm-arping-manager.h" #include "nm-connectivity.h" #include "nm-dbus-interface.h" #include "nm-device-vlan.h" @@ -80,6 +78,9 @@ #include "nm-device-logging.h" _LOG_DECLARE_SELF (NMDevice); +#include "introspection/org.freedesktop.NetworkManager.Device.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Statistics.h" + /*****************************************************************************/ #define DEFAULT_AUTOCONNECT TRUE @@ -129,13 +130,13 @@ typedef struct { int ifindex; } DeleteOnDeactivateData; -typedef void (*AcdCallback) (NMDevice *, NMIP4Config **, gboolean); +typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean); typedef struct { - AcdCallback callback; + ArpingCallback callback; NMDevice *device; NMIP4Config **configs; -} AcdData; +} ArpingData; typedef enum { HW_ADDR_TYPE_UNSET = 0, @@ -151,24 +152,6 @@ typedef enum { FIREWALL_STATE_WAIT_IP_CONFIG, } FirewallState; -typedef struct { - NMIPConfig *orig; /* the original configuration applied to the device */ - NMIPConfig *current; /* configuration after external changes. NULL means - that the original configuration didn't change. */ -} AppliedConfig; - -struct _NMDeviceConnectivityHandle { - CList concheck_lst; - NMDevice *self; - NMDeviceConnectivityCallback callback; - gpointer user_data; - NMConnectivityCheckHandle *c_handle; - guint64 seq; - bool is_periodic:1; - bool is_periodic_bump:1; - bool is_periodic_bump_on_complete:1; -}; - /*****************************************************************************/ enum { @@ -182,7 +165,6 @@ enum { REMOVED, RECHECK_AUTO_ACTIVATE, RECHECK_ASSUME, - CONNECTIVITY_CHANGED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -247,18 +229,12 @@ typedef struct _NMDevicePrivate { NMDeviceStateReason reason; } queued_state; - union { - struct { - guint queued_ip_config_id_6; - guint queued_ip_config_id_4; - }; - guint queued_ip_config_id_x[2]; - }; - + guint queued_ip4_config_id; + guint queued_ip6_config_id; GSList *pending_actions; GSList *dad6_failed_addrs; - NMDBusTrackObjPath parent_device; + NMDevice *parent_device; char * udi; char * iface; /* may change, could be renamed by user */ @@ -282,13 +258,11 @@ typedef struct _NMDevicePrivate { bool queued_ip4_config_pending:1; bool queued_ip6_config_pending:1; - bool update_ip_config_completed_v4:1; - bool update_ip_config_completed_v6:1; - char * ip_iface; int ip_ifindex; NMDeviceType type; char * type_desc; + char * type_description; NMLinkType link_type; NMDeviceCapabilities capabilities; char * driver; @@ -323,7 +297,9 @@ typedef struct _NMDevicePrivate { NMActRequest * queued_act_request; bool queued_act_request_is_waiting_for_carrier:1; - NMDBusTrackObjPath act_request; + bool act_request_public:1; + NMActRequest *act_request; + gulong act_request_id; ActivationHandleData act_handle4; /* for layer2 and IPv4. */ ActivationHandleData act_handle6; guint recheck_assume_id; @@ -380,12 +356,6 @@ typedef struct _NMDevicePrivate { NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:4; - bool is_enslaved:1; - bool master_ready_handled:1; - - bool ipv6ll_handle:1; /* TRUE if NM handles the device's IPv6LL address */ - bool ipv6ll_has:1; - /* Generic DHCP stuff */ char * dhcp_anycast_address; @@ -396,56 +366,17 @@ typedef struct _NMDevicePrivate { NMPacrunnerManager *pacrunner_manager; NMPacrunnerCallId *pacrunner_call_id; - /* IP configuration info. Combined config from VPN, settings, and device */ - union { - struct { - NMIP6Config *ip_config_6; - NMIP4Config *ip_config_4; - }; - NMIPConfig *ip_config_x[2]; - }; - + /* IP4 configuration info */ + NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */ union { const IpState ip4_state; IpState ip4_state_; }; - AppliedConfig dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ - - /* config from the setting */ - union { - struct { - NMIP6Config *con_ip_config_6; - NMIP4Config *con_ip_config_4; - }; - NMIPConfig *con_ip_config_x[2]; - }; - - /* Stuff added outside NM */ - union { - struct { - NMIP6Config *ext_ip_config_6; - NMIP4Config *ext_ip_config_4; - }; - NMIPConfig *ext_ip_config_x[2]; - }; - - /* VPNs which use this device */ - union { - struct { - GSList *vpn_configs_6; - GSList *vpn_configs_4; - }; - GSList *vpn_configs_x[2]; - }; - - /* WWAN configuration */ - union { - struct { - AppliedConfig wwan_ip_config_6; - AppliedConfig wwan_ip_config_4; - }; - AppliedConfig wwan_ip_config_x[2]; - }; + NMIP4Config * con_ip4_config; /* config from the setting */ + NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ + NMIP4Config * ext_ip4_config; /* Stuff added outside NM */ + NMIP4Config * wwan_ip4_config; /* WWAN configuration */ + GSList * vpn4_configs; /* VPNs which use this device */ bool v4_has_shadowed_routes; const char *ip4_rp_filter; @@ -465,8 +396,8 @@ typedef struct _NMDevicePrivate { guint timeout; guint watch; GPid pid; - char *binary; - char *address; + const char *binary; + const char *address; guint deadline; } gw_ping; @@ -487,17 +418,22 @@ typedef struct _NMDevicePrivate { /* IPv4 DAD stuff */ struct { GSList * dad_list; - NMAcdManager * announcing; - } acd; + NMArpingManager * announcing; + } arping; + /* IP6 configuration info */ + NMIP6Config * ip6_config; union { const IpState ip6_state; IpState ip6_state_; }; - AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */ + NMIP6Config * con_ip6_config; /* config from the setting */ + NMIP6Config * wwan_ip6_config; + NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ + GSList * vpn6_configs; /* VPNs which use this device */ + bool nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ NMIP6Config * dad6_ip6_config; - struct in6_addr ipv6ll_addr; GHashTable * rt6_temporary_not_available; @@ -505,6 +441,8 @@ typedef struct _NMDevicePrivate { gulong ndisc_changed_id; gulong ndisc_timeout_id; NMSettingIP6ConfigPrivacy ndisc_use_tempaddr; + /* IP6 config from autoconf */ + NMIP6Config * ac_ip6_config; guint linklocal6_timeout_id; guint8 linklocal6_dad_counter; @@ -518,7 +456,7 @@ typedef struct _NMDevicePrivate { gulong prefix_sigid; NMDhcp6Config * config; /* IP6 config from DHCP */ - AppliedConfig ip6_config; + NMIP6Config * ip6_config; /* Event ID of the current IP6 config from DHCP */ char * event_id; guint needed_prefixes; @@ -530,6 +468,8 @@ typedef struct _NMDevicePrivate { /* master interface for bridge/bond/team slave */ NMDevice * master; + bool is_enslaved; + bool master_ready_handled; gulong master_ready_id; /* slave management */ @@ -542,26 +482,9 @@ typedef struct _NMDevicePrivate { NMNetns *netns; NMLldpListener *lldp_listener; - - NMConnectivity *concheck_mgr; - - /* if periodic checks are enabled, this is the source id for the next check. */ - guint concheck_p_cur_id; - - /* the currently configured max periodic interval. */ - guint concheck_p_max_interval; - - /* the current interval. If we are probing, the interval might be lower - * then the configured max interval. */ - guint concheck_p_cur_interval; - - /* the timestamp, when we last scheduled the timer concheck_p_cur_id with current interval - * concheck_p_cur_interval. */ - gint64 concheck_p_cur_basetime_ns; - NMConnectivityState connectivity_state; - - CList concheck_lst_head; + gulong concheck_periodic_id; + guint64 concheck_seq; guint check_delete_unrealized_id; @@ -574,35 +497,35 @@ typedef struct _NMDevicePrivate { } NMDevicePrivate; -G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) +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) /*****************************************************************************/ -static const NMDBusInterfaceInfoExtended interface_info_device; -static const GDBusSignalInfo signal_info_state_changed; - static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url); -static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_configs); +static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs); -static gboolean nm_device_set_ip_config (NMDevice *self, - int addr_family, - NMIPConfig *config, - gboolean commit, - GPtrArray *ip4_dev_route_blacklist); +static gboolean nm_device_set_ip4_config (NMDevice *self, + NMIP4Config *config, + gboolean commit, + GPtrArray *ip4_dev_route_blacklist); +static gboolean ip4_config_merge_and_apply (NMDevice *self, + gboolean commit); -static gboolean ip_config_merge_and_apply (NMDevice *self, - int addr_family, - gboolean commit); +static gboolean nm_device_set_ip6_config (NMDevice *self, + NMIP6Config *config, + gboolean commit); +static gboolean ip6_config_merge_and_apply (NMDevice *self, + gboolean commit); static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success); static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason); -static void addrconf6_start_with_link_ready (NMDevice *self); -static gboolean linklocal6_start (NMDevice *self); +static gboolean addrconf6_start_with_link_ready (NMDevice *self); +static NMActStageReturn linklocal6_start (NMDevice *self); static void _carrier_wait_check_queued_act_request (NMDevice *self); static gint64 _get_carrier_wait_ms (NMDevice *self); @@ -632,8 +555,6 @@ static void _set_mtu (NMDevice *self, guint32 mtu); static void _commit_mtu (NMDevice *self, const NMIP4Config *config); static void _cancel_activation (NMDevice *self); -static void concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_periodic); - /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState, @@ -758,16 +679,6 @@ nm_device_get_platform (NMDevice *self) return nm_netns_get_platform (nm_device_get_netns (self)); } -static NMConnectivity * -concheck_get_mgr (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (G_UNLIKELY (!priv->concheck_mgr)) - priv->concheck_mgr = g_object_ref (nm_connectivity_get ()); - return priv->concheck_mgr; -} - static NMIP4Config * _ip4_config_new (NMDevice *self) { @@ -782,105 +693,6 @@ _ip6_config_new (NMDevice *self) nm_device_get_ip_ifindex (self)); } -static NMIPConfig * -_ip_config_new (NMDevice *self, int addr_family) -{ - nm_assert_addr_family (addr_family); - - return addr_family == AF_INET - ? (gpointer) _ip4_config_new (self) - : (gpointer) _ip6_config_new (self); -} - -static void -applied_config_clear (AppliedConfig *config) -{ - g_clear_object (&config->current); - g_clear_object (&config->orig); -} - -static void -applied_config_init (AppliedConfig *config, gpointer ip_config) -{ - nm_g_object_ref (ip_config); - applied_config_clear (config); - config->orig = ip_config; -} - -static void -applied_config_init_new (AppliedConfig *config, NMDevice *self, int addr_family) -{ - gs_unref_object NMIPConfig *c = _ip_config_new (self, addr_family); - - applied_config_init (config, c); -} - -static NMIPConfig * -applied_config_get_current (AppliedConfig *config) -{ - return config->current ?: config->orig; -} - -static void -applied_config_add_address (AppliedConfig *config, const NMPlatformIPAddress *address) -{ - if (config->orig) - nm_ip_config_add_address (config->orig, address); - else - nm_assert (!config->current); - - if (config->current) - nm_ip_config_add_address (config->current, address); -} - -static void -applied_config_add_nameserver (AppliedConfig *config, const NMIPAddr *ns) -{ - if (config->orig) - nm_ip_config_add_nameserver (config->orig, ns); - else - nm_assert (!config->current); - - if (config->current) - nm_ip_config_add_nameserver (config->current, ns); -} - -static void -applied_config_add_search (AppliedConfig *config, const char *new) -{ - if (config->orig) - nm_ip_config_add_search (config->orig, new); - else - nm_assert (!config->current); - - if (config->current) - nm_ip_config_add_search (config->current, new); -} - -static void -applied_config_reset_searches (AppliedConfig *config) -{ - if (config->orig) - nm_ip_config_reset_searches (config->orig); - else - nm_assert (!config->current); - - if (config->current) - nm_ip_config_reset_searches (config->current); -} - -static void -applied_config_reset_nameservers (AppliedConfig *config) -{ - if (config->orig) - nm_ip_config_reset_nameservers (config->orig); - else - nm_assert (!config->current); - - if (config->current) - nm_ip_config_reset_nameservers (config->current); -} - /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_sys_iface_state_to_str, NMDeviceSysIfaceState, @@ -1010,18 +822,29 @@ nm_device_assume_state_reset (NMDevice *self) /*****************************************************************************/ static void -init_ip_config_dns_priority (NMDevice *self, NMIPConfig *config) +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, - (nm_ip_config_get_addr_family (config) == AF_INET) - ? "ipv4.dns-priority" - : "ipv6.dns-priority", + "ipv4.dns-priority", self); priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); - nm_ip_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); + 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); } /*****************************************************************************/ @@ -1060,11 +883,6 @@ nm_device_ipv4_sysctl_get_effective_uint32 (NMDevice *self, const char *property if (!nm_device_get_ip_ifindex (self)) return fallback; - /* for this kind of sysctl (e.g. "rp_filter"), kernel effectively uses the - * MAX of the per-device value and the "all" value. - * - * Also do that, by reading both sysctls and return the maximum. */ - v = nm_platform_sysctl_get_int_checked (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, @@ -1230,7 +1048,7 @@ _set_ip_state (NMDevice *self, int addr_family, IpState new_state) p = (addr_family == AF_INET) ? &priv->ip4_state_ - : &priv->ip6_state_; + : &priv->ip6_state_; if (*p != new_state) { _LOGT (LOGD_DEVICE, "ip%c-state: set to %d (%s)", @@ -1271,26 +1089,28 @@ nm_device_get_iface (NMDevice *self) } gboolean -nm_device_take_over_link (NMDevice *self, int ifindex, char **old_name) +nm_device_take_over_link (NMDevice *self, const char *ifname, gboolean *renamed) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const NMPlatformLink *plink; NMPlatform *platform; gboolean up, success = TRUE; - gs_free char *name = NULL; + int ifindex; g_return_val_if_fail (priv->ifindex <= 0, FALSE); + g_return_val_if_fail (ifname, FALSE); - NM_SET_OUT (old_name, NULL); + NM_SET_OUT (renamed, FALSE); platform = nm_device_get_platform (self); - plink = nm_platform_link_get (platform, ifindex); + plink = nm_platform_link_get_by_ifname (platform, ifname); if (!plink) return FALSE; - if (!nm_streq (plink->name, nm_device_get_iface (self))) { + ifindex = plink->ifindex; + + if (!nm_streq (ifname, nm_device_get_iface (self))) { up = NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP); - name = g_strdup (plink->name); /* Rename the link to the device ifname */ if (up) @@ -1299,8 +1119,7 @@ nm_device_take_over_link (NMDevice *self, int ifindex, char **old_name) if (up) nm_platform_link_set_up (platform, ifindex, NULL); - if (success) - NM_SET_OUT (old_name, g_steal_pointer (&name)); + NM_SET_OUT (renamed, success); } if (success) { @@ -1372,102 +1191,71 @@ nm_device_get_ip_ifindex (const NMDevice *self) return priv->ip_iface ? priv->ip_ifindex : priv->ifindex; } -static void -_set_ip_ifindex (NMDevice *self, - int ifindex, - const char *ifname) +/** + * 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 +nm_device_set_ip_iface (NMDevice *self, const char *iface) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMPlatform *platform; - gboolean eq_name; - - /* normalize arguments */ - if (ifindex <= 0) { - ifindex = 0; - ifname = NULL; - } - - eq_name = nm_streq0 (priv->ip_iface, ifname); + NMDevicePrivate *priv; + int ifindex; - if ( eq_name - && priv->ip_ifindex == ifindex) - return; + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - _LOGD (LOGD_DEVICE, "ip-ifindex: update ip-interface to %s%s%s, ifindex %d", - NM_PRINT_FMT_QUOTE_STRING (ifname), - ifindex); + priv = NM_DEVICE_GET_PRIVATE (self); + if (nm_streq0 (iface, priv->ip_iface)) { + if (!iface) + return FALSE; + ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), iface); + if ( ifindex <= 0 + || priv->ip_ifindex == ifindex) + return FALSE; - priv->ip_ifindex = ifindex; - if (!eq_name) { + 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 (ifname); - _notify (self, PROP_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. + */ + priv->ip_ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), iface); + 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); + } else { + priv->ip_ifindex = 0; + _LOGD (LOGD_DEVICE, "ip-ifname: clear ifname"); + } } if (priv->ip_ifindex > 0) { - platform = nm_device_get_platform (self); - - nm_platform_process_events_ensure_link (platform, - priv->ip_ifindex, - priv->ip_iface); - - if (nm_platform_check_kernel_support (platform, + if (nm_platform_check_kernel_support (nm_device_get_platform (self), NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) - nm_platform_link_set_user_ipv6ll_enabled (platform, priv->ip_ifindex, TRUE); + nm_platform_link_set_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ip_ifindex, TRUE); - if (!nm_platform_link_is_up (platform, priv->ip_ifindex)) - nm_platform_link_set_up (platform, priv->ip_ifindex, NULL); + 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); } /* We don't care about any saved values from the old iface */ g_hash_table_remove_all (priv->ip6_saved_properties); -} -gboolean -nm_device_set_ip_ifindex (NMDevice *self, int ifindex) -{ - char ifname_buf[IFNAMSIZ]; - const char *ifname = NULL; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (nm_device_is_activating (self), FALSE); - - if (ifindex > 0) { - ifname = nm_platform_if_indextoname (nm_device_get_platform (self), ifindex, ifname_buf); - if (!ifname) - _LOGW (LOGD_DEVICE, "ip-ifindex: ifindex %d not found", ifindex); - } - - _set_ip_ifindex (self, ifindex, ifname); - return ifindex > 0; -} - -/** - * nm_device_set_ip_iface: - * @self: the #NMDevice - * @ifname: the new IP interface name - * - * Updates the IP interface name and possibly the ifindex. - * - * Returns: %TRUE if an interface with name @ifname exists, - * and %FALSE, if @ifname is %NULL or no such interface exists. - */ -gboolean -nm_device_set_ip_iface (NMDevice *self, const char *ifname) -{ - int ifindex = 0; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (nm_device_is_activating (self), FALSE); - - if (ifname) { - ifindex = nm_platform_if_nametoindex (nm_device_get_platform (self), ifname); - if (ifindex <= 0) - _LOGW (LOGD_DEVICE, "ip-ifindex: ifname %s not found", ifname); - } - - _set_ip_ifindex (self, ifindex, ifname); - return ifindex > 0; + _notify (self, PROP_IP_IFACE); + return TRUE; } static gboolean @@ -1514,9 +1302,12 @@ nm_device_parent_get_ifindex (NMDevice *self) NMDevice * nm_device_parent_get_device (NMDevice *self) { + NMDevicePrivate *priv; + g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->parent_device.obj; + priv = NM_DEVICE_GET_PRIVATE (self); + return priv->parent_device; } static void @@ -1538,7 +1329,7 @@ _parent_set_ifindex (NMDevice *self, NMDevice *parent_device; gboolean changed = FALSE; int old_ifindex; - gs_unref_object NMDevice *old_device = NULL; + NMDevice *old_device; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -1548,15 +1339,16 @@ _parent_set_ifindex (NMDevice *self, 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.obj - && nm_device_get_ifindex (priv->parent_device.obj) == parent_ifindex) + && priv->parent_device + && nm_device_get_ifindex (priv->parent_device) == parent_ifindex) return FALSE; } else { - if (!priv->parent_device.obj) + if (!priv->parent_device) return FALSE; } } else { @@ -1571,23 +1363,24 @@ _parent_set_ifindex (NMDevice *self, } else parent_device = NULL; - if (parent_device != priv->parent_device.obj) { - old_device = nm_g_object_ref (priv->parent_device.obj); - nm_dbus_track_obj_path_set (&priv->parent_device, parent_device, TRUE); + 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.obj) + 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.obj, nm_device_get_iface (priv->parent_device.obj)); + 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.obj); + 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; } @@ -1612,7 +1405,7 @@ nm_device_parent_notify_changed (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); if (priv->parent_ifindex > 0) { - if ( priv->parent_device.obj == change_candidate + 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); } @@ -1918,13 +1711,16 @@ nm_device_get_route_metric_default (NMDeviceType device_type) static gboolean default_route_metric_penalty_detect (NMDevice *self) { +#if WITH_CONCHECK NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); /* currently we don't differentiate between IPv4 and IPv6 when detecting * connectivity. */ if ( priv->connectivity_state != NM_CONNECTIVITY_FULL - && nm_connectivity_check_enabled (concheck_get_mgr (self))) + && nm_connectivity_check_enabled (nm_connectivity_get ())) { return TRUE; + } +#endif return FALSE; } @@ -1992,34 +1788,6 @@ out: return nm_utils_ip_route_metric_normalize (addr_family, route_metric); } -static NMSettingConnectionMdns -_get_mdns (NMDevice *self) -{ - NMConnection *connection; - NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - - g_return_val_if_fail (NM_IS_DEVICE (self), NM_SETTING_CONNECTION_MDNS_DEFAULT); - - connection = nm_device_get_applied_connection (self); - if (connection) - mdns = nm_setting_connection_get_mdns (nm_connection_get_setting_connection (connection)); - - if (mdns == NM_SETTING_CONNECTION_MDNS_DEFAULT) { - gs_free char *value = NULL; - - value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, - "connection.mdns", - self); - mdns = _nm_utils_ascii_str_to_int64 (value, - 10, - NM_SETTING_CONNECTION_MDNS_NO, - NM_SETTING_CONNECTION_MDNS_YES, - NM_SETTING_CONNECTION_MDNS_DEFAULT); - } - - return mdns; -} - guint32 nm_device_get_route_table (NMDevice *self, int addr_family, @@ -2096,12 +1864,12 @@ nm_device_get_best_default_route (NMDevice *self, switch (addr_family) { case AF_INET: - return priv->ip_config_4 ? nm_ip4_config_best_default_route_get (priv->ip_config_4) : NULL; + return priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL; case AF_INET6: - return priv->ip_config_6 ? nm_ip6_config_best_default_route_get (priv->ip_config_6) : NULL; + return priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL; case AF_UNSPEC: - return (priv->ip_config_4 ? nm_ip4_config_best_default_route_get (priv->ip_config_4) : NULL) - ?: (priv->ip_config_6 ? nm_ip6_config_best_default_route_get (priv->ip_config_6) : NULL); + return (priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL) + ?: (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL); default: g_return_val_if_reached (NULL); } @@ -2129,23 +1897,18 @@ nm_device_get_type_description (NMDevice *self) static const char * get_type_description (NMDevice *self) { - NMDeviceClass *klass; - - nm_assert (NM_IS_DEVICE (self)); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - klass = NM_DEVICE_GET_CLASS (self); - if (G_UNLIKELY (!klass->default_type_description)) { + if (!priv->type_description) { const char *typename; - gs_free char *s = NULL; typename = G_OBJECT_TYPE_NAME (self); if (g_str_has_prefix (typename, "NMDevice")) typename += 8; - s = g_ascii_strdown (typename, -1); - klass->default_type_description = g_intern_string (s); + priv->type_description = g_ascii_strdown (typename, -1); } - return klass->default_type_description; + return priv->type_description; } gboolean @@ -2159,7 +1922,7 @@ nm_device_get_act_request (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->act_request.obj; + return NM_DEVICE_GET_PRIVATE (self)->act_request; } NMSettingsConnection * @@ -2167,7 +1930,7 @@ nm_device_get_settings_connection (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - return priv->act_request.obj ? nm_act_request_get_settings_connection (priv->act_request.obj) : NULL; + return priv->act_request ? nm_act_request_get_settings_connection (priv->act_request) : NULL; } NMConnection * @@ -2179,7 +1942,7 @@ nm_device_get_applied_connection (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); - return priv->act_request.obj ? nm_act_request_get_applied_connection (priv->act_request.obj) : NULL; + return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL; } gboolean @@ -2187,10 +1950,10 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (!priv->act_request.obj) + if (!priv->act_request) return FALSE; - return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request.obj, compare_flags); + return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags); } NMSetting * @@ -2218,549 +1981,127 @@ nm_device_get_physical_port_id (NMDevice *self) /*****************************************************************************/ -typedef enum { - CONCHECK_SCHEDULE_UPDATE_INTERVAL, - CONCHECK_SCHEDULE_CHECK_EXTERNAL, - CONCHECK_SCHEDULE_CHECK_PERIODIC, - CONCHECK_SCHEDULE_RETURNED_MIN, - CONCHECK_SCHEDULE_RETURNED_BUMP, - CONCHECK_SCHEDULE_RETURNED_MAX, -} ConcheckScheduleMode; - -static NMDeviceConnectivityHandle *concheck_start (NMDevice *self, - NMDeviceConnectivityCallback callback, - gpointer user_data, - gboolean is_periodic); - -static void concheck_periodic_schedule_set (NMDevice *self, - ConcheckScheduleMode mode); - -static gboolean -concheck_periodic_timeout_cb (gpointer user_data) -{ - NMDevice *self = user_data; - - _LOGt (LOGD_CONCHECK, "connectivity: periodic timeout"); - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_CHECK_PERIODIC); - return G_SOURCE_REMOVE; -} - -static gboolean -concheck_is_possible (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if ( !nm_device_is_real (self) - || NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_LOOPBACK)) - return FALSE; - - /* we enable periodic checks for every device state (except UNKNOWN). Especially with - * unmanaged devices, it is interesting to know whether we have connectivity on that device. */ - if (priv->state == NM_DEVICE_STATE_UNKNOWN) - return FALSE; - - return TRUE; -} - -static gboolean -concheck_periodic_schedule_do (NMDevice *self, gint64 interval_ns) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gboolean periodic_check_disabled = FALSE; - - /* we always cancel whatever was pending. */ - if (nm_clear_g_source (&priv->concheck_p_cur_id)) - periodic_check_disabled = TRUE; - - if (priv->concheck_p_max_interval == 0) { - /* periodic checks are disabled */ - goto out; - } - - nm_assert (interval_ns >= 0); - - if (!concheck_is_possible (self)) - goto out; - - _LOGT (LOGD_CONCHECK, "connectivity: periodic-check: %sscheduled in %u milliseconds (%u seconds interval)", - periodic_check_disabled ? "re-" : "", - (guint) (interval_ns / NM_UTILS_NS_PER_MSEC), - priv->concheck_p_cur_interval); - - nm_assert (priv->concheck_p_cur_interval > 0); - priv->concheck_p_cur_id = g_timeout_add (interval_ns / NM_UTILS_NS_PER_MSEC, - concheck_periodic_timeout_cb, - self); - return TRUE; -out: - if (periodic_check_disabled) - _LOGT (LOGD_CONCHECK, "connectivity: periodic-check: unscheduled"); - return FALSE; -} - -#define CONCHECK_P_PROBE_INTERVAL 1 - -static void -concheck_periodic_schedule_set (NMDevice *self, - ConcheckScheduleMode mode) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gint64 new_expiry, exp_expiry, cur_expiry, tdiff; - gint64 now_ns = 0; - - if (priv->concheck_p_max_interval == 0) { - /* periodic check is disabled. Nothing to do. */ - return; - } - - if (!priv->concheck_p_cur_id) { - /* we currently don't have a timeout scheduled. No need to reschedule - * another one... */ - if (mode == CONCHECK_SCHEDULE_UPDATE_INTERVAL) { - /* ... unless, we are initalizing. In this case, setup the current current - * interval and schedule a perform a check right away. */ - priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL); - priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns); - if (concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND)) - concheck_start (self, NULL, NULL, TRUE); - } - return; - } - - switch (mode) { - case CONCHECK_SCHEDULE_UPDATE_INTERVAL: - /* called with "UPDATE_INTERVAL" and already have a concheck_p_cur_id scheduled. */ - - nm_assert (priv->concheck_p_max_interval > 0); - nm_assert (priv->concheck_p_cur_interval > 0); - - if (priv->concheck_p_cur_interval <= priv->concheck_p_max_interval) { - /* we currently have a shorter interval set, than what we now have. Either, - * because we are probing, or because the previous max interval was shorter. - * - * Either way, the current timer is set just fine. Nothing to do, we will - * probe our way up. */ - return; - } - - cur_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_max_interval * NM_UTILS_NS_PER_SECOND); - nm_utils_get_monotonic_timestamp_ns_cached (&now_ns); - - priv->concheck_p_cur_interval = priv->concheck_p_max_interval; - if (cur_expiry <= now_ns) { - /* Since the last time we scheduled a periodic check, already more than the - * new max_interval passed. We need to start a check right away (and - * schedule a timeout in cur-interval in the future). */ - priv->concheck_p_cur_basetime_ns = now_ns; - if (concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND)) - concheck_start (self, NULL, NULL, TRUE); - } else { - /* we are reducing the max-interval to a shorter interval that we have currently - * scheduled (with cur_interval). - * - * However, since the last time we scheduled the check, not even the new max-interval - * expired. All we need to do, is reschedule the timer to expire sooner. The cur_basetime - * is unchanged. */ - concheck_periodic_schedule_do (self, cur_expiry - now_ns); - } - return; - - case CONCHECK_SCHEDULE_CHECK_EXTERNAL: - /* a external connectivity check delays our periodic check. We reset the counter. */ - priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns); - concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND); - return; - - case CONCHECK_SCHEDULE_CHECK_PERIODIC: - { - gboolean any_periodic_pending; - NMDeviceConnectivityHandle *handle; - guint old_interval = priv->concheck_p_cur_interval; - - any_periodic_pending = FALSE; - c_list_for_each_entry (handle, &priv->concheck_lst_head, concheck_lst) { - if (handle->is_periodic_bump) { - handle->is_periodic_bump = FALSE; - handle->is_periodic_bump_on_complete = FALSE; - any_periodic_pending = TRUE; - } - } - if (any_periodic_pending) { - /* we reached a timeout to schedule a new periodic request, however we still - * have period requests pending that didn't complete yet. We need to bump the - * interval already. */ - priv->concheck_p_cur_interval = NM_MIN (old_interval * 2, priv->concheck_p_max_interval); - } - - /* we just reached a timeout. The expected expiry (exp_expiry) should be - * pretty close to now_ns. - * - * We want to reschedule the timeout at exp_expiry (aka now) + cur_interval. */ - nm_utils_get_monotonic_timestamp_ns_cached (&now_ns); - exp_expiry = priv->concheck_p_cur_basetime_ns + (old_interval * NM_UTILS_NS_PER_SECOND); - new_expiry = exp_expiry + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND); - tdiff = NM_MAX (new_expiry - now_ns, 0); - priv->concheck_p_cur_basetime_ns = (now_ns + tdiff) - (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND); - concheck_periodic_schedule_do (self, tdiff); - handle = concheck_start (self, NULL, NULL, TRUE); - if (old_interval != priv->concheck_p_cur_interval) { - /* we just bumped the interval already when scheduling this check. - * When the handle returns, don't bump a second time. - * - * But if we reach the timeout again before the handle returns (this - * code here) we will still bump the interval. */ - handle->is_periodic_bump_on_complete = FALSE; - } - return; - } - - /* we just got an event that we lost connectivity (that is, concheck returned). We reset - * the interval to min/max or increase the probe interval (bump). */ - case CONCHECK_SCHEDULE_RETURNED_MIN: - priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL); - break; - case CONCHECK_SCHEDULE_RETURNED_MAX: - priv->concheck_p_cur_interval = priv->concheck_p_max_interval; - break; - case CONCHECK_SCHEDULE_RETURNED_BUMP: - priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_cur_interval * 2, priv->concheck_p_max_interval); - break; - } - - /* we are here, because we returned from a connectivity check and adjust the current interval. - * - * But note that we calculate the new timeout based on the time when we scheduled the - * last check, instead of counting from now. The reaons is, that we want that the times - * when we schedule checks be at precise intervals, without including the time it took for - * the connectivity check. */ - new_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND); - tdiff = NM_MAX (new_expiry - nm_utils_get_monotonic_timestamp_ns_cached (&now_ns), 0); - priv->concheck_p_cur_basetime_ns = now_ns + tdiff - (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND); - concheck_periodic_schedule_do (self, tdiff); -} - -void -nm_device_check_connectivity_update_interval (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - guint new_interval; - - new_interval = nm_connectivity_get_interval (concheck_get_mgr (self)); - - new_interval = NM_MIN (new_interval, 7 *24 * 3600); - - if (new_interval != priv->concheck_p_max_interval) { - _LOGT (LOGD_CONCHECK, "connectivity: periodic-check: set interval to %u seconds", new_interval); - priv->concheck_p_max_interval = new_interval; - } - - if (!new_interval) { - /* this will cancel any potentially pending timeout. */ - concheck_periodic_schedule_do (self, 0); - - /* also update the fake connectivity state. */ - concheck_update_state (self, NM_CONNECTIVITY_FAKE, TRUE); - return; - } - - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_UPDATE_INTERVAL); -} - static void -concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow_periodic_bump) +update_connectivity_state (NMDevice *self, NMConnectivityState state) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - /* @state is a result of the connectivity check. We only expect a precise - * number of possible values. */ - nm_assert (NM_IN_SET (state, NM_CONNECTIVITY_LIMITED, - NM_CONNECTIVITY_PORTAL, - NM_CONNECTIVITY_FULL, - NM_CONNECTIVITY_FAKE, - NM_CONNECTIVITY_ERROR)); - - if (state == NM_CONNECTIVITY_ERROR) { - /* on error, we don't change the current connectivity state, - * except making UNKNOWN to NONE. */ - state = priv->connectivity_state; - if (state == NM_CONNECTIVITY_UNKNOWN) - state = NM_CONNECTIVITY_NONE; - } else if (state == NM_CONNECTIVITY_FAKE) { - /* If the connectivity check is disabled and we obtain a fake - * result, make an optimistic guess. */ + /* If the connectivity check is disabled, make an optimistic guess. */ + if (state == NM_CONNECTIVITY_UNKNOWN) { if (priv->state == NM_DEVICE_STATE_ACTIVATED) { - /* FIXME: the fake connectivity state depends on the availablility of - * a default route. However, we have no mechanism that rechecks the - * value if a device route appears/disappears after the device - * was activated. */ if (nm_device_get_best_default_route (self, AF_UNSPEC)) state = NM_CONNECTIVITY_FULL; else state = NM_CONNECTIVITY_LIMITED; - } else + } else { state = NM_CONNECTIVITY_NONE; + } } - if (priv->connectivity_state == state) { - /* we got a connectivty update, but the state didn't change. If we were probing, - * we bump the probe frequency. */ - if (allow_periodic_bump) - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP); - return; - } - /* we need to update the probe interval before emitting signals. Emitting - * a signal might call back into NMDevice and change the probe settings. - * So, do that first. */ - if (state == NM_CONNECTIVITY_FULL) { - /* we reached full connectivity state. Stop probing by setting the - * interval to the max. */ - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MAX); - } else if (priv->connectivity_state == NM_CONNECTIVITY_FULL) { - /* we are about to loose connectivity. (re)start probing by setting - * the timeout interval to the min. */ - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MIN); - } else { - if (allow_periodic_bump) - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP); - } - - _LOGD (LOGD_CONCHECK, "connectivity state changed from %s to %s", - nm_connectivity_state_to_string (priv->connectivity_state), - nm_connectivity_state_to_string (state)); - priv->connectivity_state = state; - - _notify (self, PROP_CONNECTIVITY); - g_signal_emit (self, signals[CONNECTIVITY_CHANGED], 0); + 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); - if ( priv->state == NM_DEVICE_STATE_ACTIVATED - && !nm_device_sys_iface_state_is_external (self)) { - if ( nm_device_get_best_default_route (self, AF_INET) - && !ip_config_merge_and_apply (self, AF_INET, TRUE)) - _LOGW (LOGD_IP4, "Failed to update IPv4 route metric"); - if ( nm_device_get_best_default_route (self, AF_INET6) - && !ip_config_merge_and_apply (self, AF_INET6, TRUE)) - _LOGW (LOGD_IP6, "Failed to update IPv6 route metric"); + if ( priv->state == NM_DEVICE_STATE_ACTIVATED + && !nm_device_sys_iface_state_is_external (self)) { + if ( nm_device_get_best_default_route (self, AF_INET) + && !ip4_config_merge_and_apply (self, TRUE)) + _LOGW (LOGD_IP4, "Failed to update IPv4 route metric"); + if ( nm_device_get_best_default_route (self, AF_INET6) + && !ip6_config_merge_and_apply (self, TRUE)) + _LOGW (LOGD_IP6, "Failed to update IPv6 route metric"); + } } } +typedef struct { + NMDevice *self; + NMDeviceConnectivityCallback callback; + gpointer user_data; + guint64 seq; +} ConnectivityCheckData; + static void -concheck_handle_complete (NMDeviceConnectivityHandle *handle, - GError *error) +concheck_done (ConnectivityCheckData *data) { - /* The moment we invoke the callback, we unlink it. It signals - * that @handle is handled -- as far as the callee of callback - * is concerned. */ - c_list_unlink (&handle->concheck_lst); - - if (handle->c_handle) - nm_connectivity_check_cancel (handle->c_handle); - - if (handle->callback) { - handle->callback (handle->self, - handle, - NM_DEVICE_GET_PRIVATE (handle->self)->connectivity_state, - error, - handle->user_data); - } + NMDevice *self = data->self; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - g_slice_free (NMDeviceConnectivityHandle, handle); + /* 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 (NMConnectivity *connectivity, - NMConnectivityCheckHandle *c_handle, - NMConnectivityState state, - GError *error, - gpointer user_data) +concheck_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { - _nm_unused gs_unref_object NMDevice *self_keep_alive = NULL; - NMDevice *self; - NMDevicePrivate *priv; - NMDeviceConnectivityHandle *handle; - NMDeviceConnectivityHandle *other_handle; - gboolean handle_is_alive; - gboolean allow_periodic_bump; - gboolean any_periodic_before; - gboolean any_periodic_after; - guint64 seq; - - handle = user_data; - nm_assert (handle->c_handle == c_handle); - nm_assert (NM_IS_DEVICE (handle->self)); - - handle->c_handle = NULL; - self = handle->self; - - if (nm_utils_error_is_cancelled (error, FALSE)) { - /* the only place where we nm_connectivity_check_cancel(@c_handle), is - * from inside concheck_handle_complete(). This is a recursive call, - * nothing to do. */ - _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, cancelled)", - (long long unsigned) handle->seq); - return; - } - - self_keep_alive = g_object_ref (self); - - _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, state:%s%s%s%s)", - (long long unsigned) handle->seq, - nm_connectivity_state_to_string (state), - NM_PRINT_FMT_QUOTED (error, ", error: ", error->message, "", "")); - - /* we keep NMConnectivity instance alive. It cannot be disposing. */ - nm_assert (!nm_utils_error_is_cancelled (error, TRUE)); - - /* keep @self alive, while we invoke callbacks. */ - priv = NM_DEVICE_GET_PRIVATE (self); - - nm_assert (!handle || c_list_contains (&priv->concheck_lst_head, &handle->concheck_lst)); - - seq = handle->seq; - - /* find out, if there are any periodic checks pending (either whether they - * were scheduled before or after @handle. */ - any_periodic_before = FALSE; - any_periodic_after = FALSE; - c_list_for_each_entry (other_handle, &priv->concheck_lst_head, concheck_lst) { - if (other_handle->is_periodic_bump_on_complete) { - if (other_handle->seq < seq) - any_periodic_before = TRUE; - else if (other_handle->seq > seq) - any_periodic_after = TRUE; - } - } - if (NM_IN_SET (state, NM_CONNECTIVITY_ERROR)) { - /* the request failed. We consider this periodic check only as completed if - * this was a periodic check, and there are not checks pending (either - * before or after this one). - * - * We allow_periodic_bump, if the request failed and there are - * still other requests periodic pending. */ - allow_periodic_bump = handle->is_periodic_bump_on_complete - && !any_periodic_before - && !any_periodic_after; - } else { - /* the request succeeded. This marks the completion of a periodic check, - * if this handle was periodic, or any previously scheduled one (that - * we are going to complete below). */ - allow_periodic_bump = handle->is_periodic_bump_on_complete - || any_periodic_before; - } - - /* first update the new state, and emit signals. */ - concheck_update_state (self, state, allow_periodic_bump); - - handle_is_alive = FALSE; - - /* we might have invoked callbacks during concheck_update_state(). The caller might have - * cancelled and thus destroyed @handle. We have to check whether handle is still alive, - * by searching it in the list of alive handles. - * - * Also, we might want to complete all pending callbacks that were started before - * @handle, as they are automatically obsoleted. */ -check_handles: - c_list_for_each_entry (other_handle, &priv->concheck_lst_head, concheck_lst) { - if (other_handle->seq >= seq) { - /* it's not guaranteed that @handle is still in the list. It might already - * be canceled while invoking callbacks for a previous other_handle. - * If it is already cancelled, @handle is a dangling pointer. - * - * Since @seq is assigned uniquely and increasing, either @other_handle is - * @handle (and thus, handle is alive), or it isn't. */ - if (other_handle == handle) - handle_is_alive = TRUE; - break; - } - - nm_assert (other_handle != handle); - - if (!NM_IN_SET (state, NM_CONNECTIVITY_ERROR)) { - /* we also want to complete handles that were started before the current - * @handle. Their response is out-dated. */ - concheck_handle_complete (other_handle, NULL); - - /* we invoked callbacks, other handles might be cancelled and removed from the list. - * Need to iterate the list from the start. */ - goto check_handles; - } - } + 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; - if (!handle_is_alive) { - /* We didn't find @handle in the list of alive handles. Thus, the handles - * was cancelled while we were invoking events. Nothing to do, and don't - * touch the dangling pointer. */ - return; + 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); } - concheck_handle_complete (handle, NULL); + if (data->seq == priv->concheck_seq) + update_connectivity_state (data->self, state); + concheck_done (data); } +#endif /* WITH_CONCHECK */ -static NMDeviceConnectivityHandle * -concheck_start (NMDevice *self, - NMDeviceConnectivityCallback callback, - gpointer user_data, - gboolean is_periodic) +static gboolean +no_concheck (gpointer user_data) { - static guint64 seq_counter = 0; - NMDevicePrivate *priv; - NMDeviceConnectivityHandle *handle; - - g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - - priv = NM_DEVICE_GET_PRIVATE (self); - - handle = g_slice_new0 (NMDeviceConnectivityHandle); - handle->seq = ++seq_counter; - handle->self = self; - handle->callback = callback; - handle->user_data = user_data; - handle->is_periodic = is_periodic; - handle->is_periodic_bump = is_periodic; - handle->is_periodic_bump_on_complete = is_periodic; + ConnectivityCheckData *data = user_data; - c_list_link_tail (&priv->concheck_lst_head, &handle->concheck_lst); - - _LOGT (LOGD_CONCHECK, "connectivity: start check (seq:%llu%s)", - (long long unsigned) handle->seq, - is_periodic ? ", periodic-check" : ""); - - handle->c_handle = nm_connectivity_check_start (concheck_get_mgr (self), - nm_device_get_ip_iface (self), - concheck_cb, - handle); - return handle; + concheck_done (data); + return G_SOURCE_REMOVE; } -NMDeviceConnectivityHandle * +void nm_device_check_connectivity (NMDevice *self, NMDeviceConnectivityCallback callback, gpointer user_data) { - NMDeviceConnectivityHandle *handle; - - if (!concheck_is_possible (self)) - return NULL; - - concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_CHECK_EXTERNAL); - handle = concheck_start (self, callback, user_data, FALSE); - return handle; -} + ConnectivityCheckData *data; +#if WITH_CONCHECK + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); +#endif -void -nm_device_check_connectivity_cancel (NMDeviceConnectivityHandle *handle) -{ - gs_free_error GError *cancelled_error = NULL; + data = g_slice_new0 (ConnectivityCheckData); + data->self = g_object_ref (self); + data->callback = callback; + data->user_data = user_data; - g_return_if_fail (handle); - g_return_if_fail (NM_IS_DEVICE (handle->self)); - g_return_if_fail (!c_list_is_empty (&handle->concheck_lst)); +#if WITH_CONCHECK + if (priv->concheck_periodic_id) { + data->seq = ++priv->concheck_seq; - /* nobody has access to periodic handles, and cannot cancel - * them externally. */ - nm_assert (!handle->is_periodic); + /* Kick off a real connectivity check. */ + nm_connectivity_check_async (nm_connectivity_get (), + nm_device_get_ip_iface (self), + concheck_cb, + data); + return; + } +#endif - nm_utils_error_set_cancelled (&cancelled_error, FALSE, "NMDevice"); - concheck_handle_complete (handle, cancelled_error); + /* Fake one. */ + g_idle_add (no_concheck, data); } NMConnectivityState @@ -2771,6 +2112,43 @@ nm_device_get_connectivity_state (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->connectivity_state; } +#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) + && nm_device_get_best_default_route (self, AF_UNSPEC); + + 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. */ + nm_clear_g_signal_handler (nm_connectivity_get (), &priv->concheck_periodic_id); + update_connectivity_state (self, NM_CONNECTIVITY_NONE); + } +#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 +} + /*****************************************************************************/ static SlaveInfo * @@ -2848,7 +2226,7 @@ nm_device_master_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *c /* Since slave devices don't have their own IP configuration, * set the MTU here. */ - _commit_mtu (slave, NM_DEVICE_GET_PRIVATE (slave)->ip_config_4); + _commit_mtu (slave, NM_DEVICE_GET_PRIVATE (slave)->ip4_config); return success; } @@ -2986,6 +2364,8 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) { NMDevicePrivate *priv; GError *error = NULL; + gconstpointer addr; + size_t addr_length; g_return_if_fail (NM_IS_DEVICE (self)); @@ -3018,6 +2398,8 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) if (priv->lldp_listener && nm_lldp_listener_is_running (priv->lldp_listener)) { nm_lldp_listener_stop (priv->lldp_listener); + addr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &addr_length); + if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) { _LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s", priv->lldp_listener, error->message); @@ -3054,12 +2436,12 @@ carrier_changed (NMDevice *self, gboolean 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); - } + /* If needed, also resume IP configuration that is + * waiting for carrier. */ + 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); return; } /* fall-through and change state of device */ @@ -3254,14 +2636,12 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) now = nm_utils_get_monotonic_timestamp_s (); - head_entry = nm_ip6_config_lookup_addresses (priv->ip_config_6); + 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); NMNDiscAddress *ndisc_addr; - guint32 lifetime, preferred; - gint32 base; if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) continue; @@ -3273,35 +2653,19 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) if (addr->plen != 64) continue; - /* resolve the timestamps relative to a new base. - * - * Note that for convenience, platform @addr might have timestamp and/or - * lifetime unset. We don't allow that flexibility for ndisc and require - * well defined timestamps. */ - if (addr->timestamp) { - nm_assert (addr->timestamp < G_MAXINT32); - base = addr->timestamp; - } else - base = now; - - lifetime = nm_utils_lifetime_get (addr->timestamp, addr->lifetime, addr->preferred, - base, &preferred); - if (!lifetime) - continue; - g_array_set_size (addresses, addresses->len+1); ndisc_addr = &g_array_index (addresses, NMNDiscAddress, addresses->len-1); ndisc_addr->address = addr->address; - ndisc_addr->timestamp = base; - ndisc_addr->lifetime = lifetime; - ndisc_addr->preferred = preferred; + ndisc_addr->timestamp = addr->timestamp; + ndisc_addr->lifetime = addr->lifetime; + ndisc_addr->preferred = addr->preferred; } - len = nm_ip6_config_get_num_nameservers (priv->ip_config_6); + len = nm_ip6_config_get_num_nameservers (priv->ip6_config); dns_servers = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscDNSServer), len); g_array_set_size (dns_servers, len); for (i = 0; i < len; i++) { - const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip_config_6, i); + const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip6_config, i); NMNDiscDNSServer *ndisc_nameserver; ndisc_nameserver = &g_array_index (dns_servers, NMNDiscDNSServer, i); @@ -3310,11 +2674,11 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME; } - len = nm_ip6_config_get_num_searches (priv->ip_config_6); + len = nm_ip6_config_get_num_searches (priv->ip6_config); dns_domains = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscDNSDomain), len); g_array_set_size (dns_domains, len); for (i = 0; i < len; i++) { - const char *search = nm_ip6_config_get_search (priv->ip_config_6, i); + const char *search = nm_ip6_config_get_search (priv->ip6_config, i); NMNDiscDNSDomain *ndisc_search; ndisc_search = &g_array_index (dns_domains, NMNDiscDNSDomain, i); @@ -3440,11 +2804,11 @@ device_link_changed (NMDevice *self) /* 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) { - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + if (!ip4_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); } if (priv->ip6_state == IP_DONE) { - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); } } @@ -3948,8 +3312,8 @@ realize_start_setup (NMDevice *self, g_return_if_fail (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)); g_return_if_fail (priv->ip_ifindex <= 0); g_return_if_fail (priv->ip_iface == NULL); - g_return_if_fail (!priv->queued_ip_config_id_4); - g_return_if_fail (!priv->queued_ip_config_id_6); + g_return_if_fail (!priv->queued_ip4_config_id); + g_return_if_fail (!priv->queued_ip6_config_id); _LOGD (LOGD_DEVICE, "start setup of %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), plink ? plink->ifindex : 0); @@ -3996,7 +3360,7 @@ realize_start_setup (NMDevice *self, if (nm_platform_check_kernel_support (nm_device_get_platform (self), NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) - priv->ipv6ll_handle = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex); + priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex); if (nm_platform_link_supports_sriov (nm_device_get_platform (self), priv->ifindex)) capabilities |= NM_DEVICE_CAP_SRIOV; @@ -4095,9 +3459,6 @@ nm_device_realize_finish (NMDevice *self, const NMPlatformLink *plink) if (plink) device_recheck_slave_status (self, plink); - priv->update_ip_config_completed_v4 = FALSE; - priv->update_ip_config_completed_v6 = FALSE; - priv->real = TRUE; _notify (self, PROP_REAL); @@ -4323,7 +3684,7 @@ nm_device_notify_component_added (NMDevice *self, GObject *component) * because that ethernet interface is controlled by the WWAN device and cannot * be used independently of the WWAN device. * - * Returns: %TRUE if @self or its components own the interface name, + * Returns: %TRUE if @self or it's components owns the interface name, * %FALSE if not */ gboolean @@ -4613,7 +3974,7 @@ check_ip_state (NMDevice *self, gboolean may_fail, gboolean full_state_update) /* 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.obj)) + if ( nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request)) && !priv->is_enslaved) return; @@ -4801,8 +4162,8 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config) if (!unconfigure_ip_config) return; - nm_device_set_ip_config (self, AF_INET, NULL, FALSE, NULL); - nm_device_set_ip_config (self, AF_INET6, NULL, FALSE, NULL); + nm_device_set_ip4_config (self, NULL, FALSE, NULL); + nm_device_set_ip6_config (self, NULL, FALSE); } static gboolean @@ -5054,9 +4415,9 @@ device_has_config (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); /* Check for IP configuration. */ - if (priv->ip_config_4 && nm_ip4_config_get_num_addresses (priv->ip_config_4)) + if (priv->ip4_config && nm_ip4_config_get_num_addresses (priv->ip4_config)) return TRUE; - if (priv->ip_config_6 && nm_ip6_config_get_num_addresses (priv->ip_config_6)) + if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config)) return TRUE; /* The existence of a software device is good enough. */ @@ -5181,10 +4542,10 @@ nm_device_generate_connection (NMDevice *self, } } else { /* Only regular and master devices get IP configuration; slaves do not */ - s_ip4 = nm_ip4_config_create_setting (priv->ip_config_4); + s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); nm_connection_add_setting (connection, s_ip4); - s_ip6 = nm_ip6_config_create_setting (priv->ip_config_6); + s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); nm_connection_add_setting (connection, s_ip6); nm_connection_add_setting (connection, nm_setting_proxy_new ()); @@ -5241,45 +4602,34 @@ nm_device_generate_connection (NMDevice *self, return g_steal_pointer (&connection); } -/** - * nm_device_complete_connection: - * - * Complete the connection. This is solely used for AddAndActivate where the user - * may pass in an incomplete connection and a device, and the device tries to - * make sense of it and complete it for activation. Otherwise, this is not - * used. - * - * Returns: success or failure. - */ gboolean nm_device_complete_connection (NMDevice *self, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { - NMDeviceClass *klass; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + gboolean success = FALSE; - klass = NM_DEVICE_GET_CLASS (self); + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (connection != NULL, FALSE); - if (!klass->complete_connection) { + if (!NM_DEVICE_GET_CLASS (self)->complete_connection) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "Device class %s had no complete_connection method", G_OBJECT_TYPE_NAME (self)); return FALSE; } - if (!klass->complete_connection (self, - connection, - specific_object, - existing_connections, - error)) - 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 nm_connection_verify (connection, error); + return success; } gboolean @@ -5388,12 +4738,15 @@ nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection) 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); + if (!nm_device_is_master (self)) return FALSE; @@ -5806,9 +5159,8 @@ activate_stage1_device_prepare (NMDevice *self) _set_ip_state (self, AF_INET6, IP_NONE); /* Notify the new ActiveConnection along with the state change */ - nm_dbus_track_obj_path_set (&priv->act_request, - priv->act_request.obj, - TRUE); + priv->act_request_public = TRUE; + _notify (self, PROP_ACTIVE_CONNECTION); nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); @@ -5844,7 +5196,7 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request.obj); + g_return_if_fail (priv->act_request); activation_source_schedule (self, activate_stage1_device_prepare, AF_INET); } @@ -5862,6 +5214,8 @@ lldp_init (NMDevice *self, gboolean restart) 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)) @@ -5875,6 +5229,8 @@ lldp_init (NMDevice *self, gboolean restart) } if (!nm_lldp_listener_is_running (priv->lldp_listener)) { + addr = nm_platform_link_get_address (nm_device_get_platform (self), priv->ifindex, &addr_length); + 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 { @@ -6021,7 +5377,7 @@ activate_stage2_device_config (NMDevice *self) if (slave_state == NM_DEVICE_STATE_IP_CONFIG) nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave)); - else if ( priv->act_request.obj + else if ( priv->act_request && nm_device_sys_iface_state_is_external (self) && slave_state <= NM_DEVICE_STATE_DISCONNECTED) nm_device_queue_recheck_assume (info->slave); @@ -6046,10 +5402,10 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request.obj); + g_return_if_fail (priv->act_request); if (!priv->master_ready_handled) { - NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request.obj); + NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); NMActiveConnection *master; master = nm_active_connection_get_master (active); @@ -6087,9 +5443,13 @@ nm_device_ip_method_failed (NMDevice *self, int addr_family, NMDeviceStateReason reason) { + NMDevicePrivate *priv; + g_return_if_fail (NM_IS_DEVICE (self)); g_return_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6)); + priv = NM_DEVICE_GET_PRIVATE (self); + _set_ip_state (self, addr_family, IP_FAIL); if (get_ip_config_may_fail (self, addr_family)) @@ -6130,16 +5490,16 @@ get_ipv4_dad_timeout (NMDevice *self) } static void -acd_data_destroy (gpointer ptr, GClosure *closure) +arping_data_destroy (gpointer ptr, GClosure *closure) { - AcdData *data = ptr; + 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 (AcdData, data); + g_slice_free (ArpingData, data); } } @@ -6159,7 +5519,7 @@ ipv4_manual_method_apply (NMDevice *self, NMIP4Config **configs, gboolean succes } static void -acd_manager_probe_terminated (NMAcdManager *acd_manager, AcdData *data) +arping_manager_probe_terminated (NMArpingManager *arping_manager, ArpingData *data) { NMDevice *self; NMDevicePrivate *priv; @@ -6174,7 +5534,7 @@ acd_manager_probe_terminated (NMAcdManager *acd_manager, AcdData *data) for (i = 0; data->configs && data->configs[i]; i++) { nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, data->configs[i], &address) { - result = nm_acd_manager_check_address (acd_manager, address->address); + result = nm_arping_manager_check_address (arping_manager, address->address); success &= result; _NMLOG (result ? LOGL_DEBUG : LOGL_WARN, @@ -6187,8 +5547,8 @@ acd_manager_probe_terminated (NMAcdManager *acd_manager, AcdData *data) data->callback (self, data->configs, success); - priv->acd.dad_list = g_slist_remove (priv->acd.dad_list, acd_manager); - nm_acd_manager_destroy (acd_manager); + priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager); + nm_arping_manager_destroy (arping_manager); } /** @@ -6202,17 +5562,18 @@ acd_manager_probe_terminated (NMAcdManager *acd_manager, AcdData *data) * be started. @configs will be unreferenced after @cb has been called. */ static void -ipv4_dad_start (NMDevice *self, NMIP4Config **configs, AcdCallback cb) +ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMAcdManager *acd_manager; + NMArpingManager *arping_manager; const NMPlatformIP4Address *address; NMDedupMultiIter ipconf_iter; - AcdData *data; + ArpingData *data; guint timeout; gboolean ret, addr_found; - const guint8 *hwaddr_arr; - size_t length; + const guint8 *hw_addr; + size_t hw_addr_len = 0; + GError *error = NULL; guint i; g_return_if_fail (NM_IS_DEVICE (self)); @@ -6227,14 +5588,14 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, AcdCallback cb) } timeout = get_ipv4_dad_timeout (self); - hwaddr_arr = nm_platform_link_get_address (nm_device_get_platform (self), - nm_device_get_ip_ifindex (self), - &length); + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + &hw_addr_len); if ( !timeout - || !hwaddr_arr + || !hw_addr + || !hw_addr_len || !addr_found - || length != ETH_ALEN || nm_device_sys_iface_state_is_external_or_assume (self)) { /* DAD not needed, signal success */ @@ -6247,36 +5608,36 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, AcdCallback cb) return; } - /* don't take additional references of @acd_manager that outlive @self. + /* 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. */ - acd_manager = nm_acd_manager_new (nm_device_get_ip_ifindex (self), hwaddr_arr, length); - priv->acd.dad_list = g_slist_append (priv->acd.dad_list, acd_manager); + 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 (AcdData); + data = g_slice_new0 (ArpingData); data->configs = configs; data->callback = cb; data->device = self; for (i = 0; configs[i]; i++) { nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, configs[i], &address) - nm_acd_manager_add_address (acd_manager, address->address); + nm_arping_manager_add_address (arping_manager, address->address); } - g_signal_connect_data (acd_manager, NM_ACD_MANAGER_PROBE_TERMINATED, - G_CALLBACK (acd_manager_probe_terminated), data, - acd_data_destroy, 0); + g_signal_connect_data (arping_manager, NM_ARPING_MANAGER_PROBE_TERMINATED, + G_CALLBACK (arping_manager_probe_terminated), data, + arping_data_destroy, 0); - ret = nm_acd_manager_start_probe (acd_manager, timeout); + ret = nm_arping_manager_start_probe (arping_manager, timeout, &error); if (!ret) { - _LOGW (LOGD_DEVICE, "acd probe failed"); + _LOGW (LOGD_DEVICE, "arping probe failed: %s", error->message); /* DAD could not be started, signal success */ cb (self, configs, TRUE); - priv->acd.dad_list = g_slist_remove (priv->acd.dad_list, acd_manager); - nm_acd_manager_destroy (acd_manager); + priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager); + nm_arping_manager_destroy (arping_manager); } } @@ -6338,10 +5699,10 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) NMIP4Config *config; int r; - if (priv->act_request.obj == NULL) + if (priv->act_request == NULL) return; - connection = nm_act_request_get_applied_connection (priv->act_request.obj); + connection = nm_act_request_get_applied_connection (priv->act_request); g_assert (connection); /* Ignore if the connection isn't an AutoIP connection */ @@ -6375,8 +5736,9 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) nm_clear_g_source (&priv->ipv4ll_timeout); nm_device_activate_schedule_ip4_config_result (self, config); } else if (priv->ip4_state == IP_DONE) { - applied_config_init (&priv->dev_ip4_config, config); - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) { + g_clear_object (&priv->dev_ip4_config); + priv->dev_ip4_config = g_object_ref (config); + if (!ip4_config_merge_and_apply (self, TRUE)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } @@ -6472,42 +5834,55 @@ ipv4ll_start (NMDevice *self) /*****************************************************************************/ static void -ensure_con_ip_config (NMDevice *self, int addr_family) +ensure_con_ip4_config (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; - const gboolean IS_IPv4 = (addr_family == AF_INET); - NMIPConfig *con_ip_config; - if (priv->con_ip_config_x[IS_IPv4]) + if (priv->con_ip4_config) return; connection = nm_device_get_applied_connection (self); if (!connection) return; - con_ip_config = _ip_config_new (self, addr_family); + priv->con_ip4_config = _ip4_config_new (self); + nm_ip4_config_merge_setting (priv->con_ip4_config, + nm_connection_get_setting_ip4_config (connection), + nm_device_get_route_table (self, AF_INET, TRUE), + nm_device_get_route_metric (self, AF_INET)); - if (IS_IPv4) { - nm_ip4_config_merge_setting (NM_IP4_CONFIG (con_ip_config), - nm_connection_get_setting_ip4_config (connection), - _get_mdns (self), - nm_device_get_route_table (self, addr_family, TRUE), - nm_device_get_route_metric (self, addr_family)); - } else { - nm_ip6_config_merge_setting (NM_IP6_CONFIG (con_ip_config), - nm_connection_get_setting_ip6_config (connection), - nm_device_get_route_table (self, addr_family, TRUE), - nm_device_get_route_metric (self, addr_family)); + if (nm_device_sys_iface_state_is_external_or_assume (self)) { + /* 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); } +} + +static void +ensure_con_ip6_config (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + + if (priv->con_ip6_config) + return; + + connection = nm_device_get_applied_connection (self); + if (!connection) + return; + + priv->con_ip6_config = _ip6_config_new (self); + nm_ip6_config_merge_setting (priv->con_ip6_config, + nm_connection_get_setting_ip6_config (connection), + nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_metric (self, AF_INET6)); if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* For assumed connections ignore all addresses and routes. */ - nm_ip_config_reset_addresses (con_ip_config); - nm_ip_config_reset_routes (con_ip_config); + nm_ip6_config_reset_addresses (priv->con_ip6_config); + nm_ip6_config_reset_routes (priv->con_ip6_config); } - - priv->con_ip_config_x[IS_IPv4] = con_ip_config; } /*****************************************************************************/ @@ -6535,222 +5910,105 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) } if (priv->dhcp4.config) { - nm_dbus_object_clear_and_unexport (&priv->dhcp4.config); + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); _notify (self, PROP_DHCP4_CONFIG); } } static gboolean -ip_config_merge_and_apply (NMDevice *self, - int addr_family, - gboolean commit) +ip4_config_merge_and_apply (NMDevice *self, + gboolean commit) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gboolean success; - gs_unref_object NMIPConfig *composite = NULL; - NMIPConfig *config; - gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; NMConnection *connection; + gboolean success; + NMIP4Config *composite; gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; gboolean ignore_default_routes = FALSE; GSList *iter; - const char *ip6_addr_gen_token = NULL; - const gboolean IS_IPv4 = (addr_family == AF_INET); + gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; if (nm_device_sys_iface_state_is_external (self)) - commit = FALSE; - - connection = nm_device_get_applied_connection (self); + commit = 0; /* Apply ignore-auto-routes and ignore-auto-dns settings */ + connection = nm_device_get_applied_connection (self); if (connection) { - NMSettingIPConfig *s_ip = IS_IPv4 - ? nm_connection_get_setting_ip4_config (connection) - : nm_connection_get_setting_ip6_config (connection); + NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip) { - ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip); - ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip); + 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); /* 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_ip) - || nm_setting_ip_config_get_gateway (s_ip); - - if (!IS_IPv4) { - NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (s_ip); - - if (nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) - ip6_addr_gen_token = nm_setting_ip6_config_get_token (s_ip6); - } + ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip4) + || nm_setting_ip_config_get_gateway (s_ip4); } } - composite = _ip_config_new (self, addr_family); - - if (!IS_IPv4) { - nm_ip6_config_set_privacy (NM_IP6_CONFIG (composite), - priv->ndisc - ? priv->ndisc_use_tempaddr - : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - } - - init_ip_config_dns_priority (self, composite); + composite = _ip4_config_new (self); + init_ip4_config_dns_priority (self, composite); if (commit) { - if (priv->queued_ip_config_id_x[IS_IPv4]) - update_ext_ip_config (self, addr_family, FALSE); - ensure_con_ip_config (self, addr_family); - } - - if (!IS_IPv4) { - if ( commit - && priv->ipv6ll_has) { - const NMPlatformIP6Address ll_a = { - .address = priv->ipv6ll_addr, - .plen = 64, - .addr_source = NM_IP_CONFIG_SOURCE_IP6LL, - }; - const NMPlatformIP6Route ll_r = { - .network.s6_addr16[0] = htons (0xfe80u), - .plen = 64, - .metric = nm_device_get_route_metric (self, addr_family), - .rt_source = NM_IP_CONFIG_SOURCE_IP6LL, - }; - - nm_assert (IN6_IS_ADDR_LINKLOCAL (&priv->ipv6ll_addr)); - - nm_ip6_config_add_address (NM_IP6_CONFIG (composite), &ll_a); - nm_ip6_config_add_route (NM_IP6_CONFIG (composite), &ll_r, NULL); - } - } - - if (commit) { - gboolean v; - - v = default_route_metric_penalty_detect (self); - if (IS_IPv4) - priv->default_route_metric_penalty_ip4_has = v; - else - priv->default_route_metric_penalty_ip6_has = v; - } - - /* Merge all the IP configs into the composite config */ - - if (IS_IPv4) { - config = applied_config_get_current (&priv->dev_ip4_config); - if (config) { - nm_ip4_config_merge (NM_IP4_CONFIG (composite), NM_IP4_CONFIG (config), - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (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, addr_family)); - } + if (priv->queued_ip4_config_id) + update_ext_ip_config (self, AF_INET, FALSE, FALSE); + ensure_con_ip4_config (self); } - if (!IS_IPv4) { - config = applied_config_get_current (&priv->ac_ip6_config); - if (config) { - nm_ip6_config_merge (NM_IP6_CONFIG (composite), NM_IP6_CONFIG (config), - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (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, addr_family)); - } - } + if (commit) + priv->default_route_metric_penalty_ip4_has = default_route_metric_penalty_detect (self); - if (!IS_IPv4) { - config = applied_config_get_current (&priv->dhcp6.ip6_config); - if (config) { - nm_ip6_config_merge (NM_IP6_CONFIG (composite), NM_IP6_CONFIG (config), - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (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, addr_family)); - } + if (priv->dev_ip4_config) { + nm_ip4_config_merge (composite, priv->dev_ip4_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (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)); } - for (iter = priv->vpn_configs_x[IS_IPv4]; iter; iter = iter->next) - nm_ip_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); + for (iter = priv->vpn4_configs; iter; iter = iter->next) + nm_ip4_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); - if (priv->ext_ip_config_x[IS_IPv4]) - nm_ip_config_merge (composite, priv->ext_ip_config_x[IS_IPv4], NM_IP_CONFIG_MERGE_DEFAULT, 0); + if (priv->ext_ip4_config) + nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, 0); /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. */ - config = applied_config_get_current (&priv->wwan_ip_config_x[IS_IPv4]); - if (config) { - nm_ip_config_merge (composite, config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (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, addr_family)); - } - - if (!IS_IPv4) { - 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 (NM_IP6_CONFIG (composite), - NMP_OBJECT_CAST_IP6_ROUTE (o), - NULL); - } - } + if (priv->wwan_ip4_config) { + nm_ip4_config_merge (composite, priv->wwan_ip4_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (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)); } /* Merge user overrides into the composite config. For assumed connections, - * con_ip_config_x is empty. */ - if (priv->con_ip_config_x[IS_IPv4]) { - nm_ip_config_merge (composite, priv->con_ip_config_x[IS_IPv4], NM_IP_CONFIG_MERGE_DEFAULT, - default_route_metric_penalty_get (self, addr_family)); + * con_ip4_config is empty. */ + 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)); } if (commit) { - if (IS_IPv4) { - nm_ip4_config_add_dependent_routes (NM_IP4_CONFIG (composite), - nm_device_get_route_table (self, addr_family, TRUE), - nm_device_get_route_metric (self, addr_family), - &ip4_dev_route_blacklist); - } else { - nm_ip6_config_add_dependent_routes (NM_IP6_CONFIG (composite), - nm_device_get_route_table (self, addr_family, TRUE), - nm_device_get_route_metric (self, addr_family)); - } + 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); } - if (IS_IPv4) { - if (commit) { - if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) - NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, NM_IP4_CONFIG (composite)); - } - } - - if (!IS_IPv4) { - if (commit) { - NMUtilsIPv6IfaceId iid; - - if ( ip6_addr_gen_token - && nm_utils_ipv6_interface_identifier_get_from_token (&iid, ip6_addr_gen_token)) { - nm_platform_link_set_ipv6_token (nm_device_get_platform (self), - nm_device_get_ip_ifindex (self), - iid); - } - } - } - - success = nm_device_set_ip_config (self, addr_family, composite, commit, ip4_dev_route_blacklist); if (commit) { - if (IS_IPv4) - priv->v4_commit_first_time = FALSE; - else - priv->v6_commit_first_time = FALSE; + if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) + NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite); } + success = nm_device_set_ip4_config (self, composite, commit, ip4_dev_route_blacklist); + g_object_unref (composite); + + if (commit) + priv->v4_commit_first_time = FALSE; return success; } @@ -6761,9 +6019,10 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) g_return_val_if_fail (config, FALSE); - applied_config_init (&priv->dev_ip4_config, config); + g_clear_object (&priv->dev_ip4_config); + priv->dev_ip4_config = g_object_ref (config); - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) { + if (!ip4_config_merge_and_apply (self, TRUE)) { _LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); return FALSE; } @@ -6803,8 +6062,8 @@ dhcp4_fail (NMDevice *self, gboolean timeout) * on the interface. */ if ( priv->ip4_state == IP_DONE - && priv->con_ip_config_4 - && nm_ip4_config_get_num_addresses (priv->con_ip_config_4) > 0) + && priv->con_ip4_config + && nm_ip4_config_get_num_addresses (priv->con_ip4_config) > 0) goto clear_config; /* Fail the method in case of timeout or failure during initial @@ -6835,7 +6094,7 @@ dhcp4_fail (NMDevice *self, gboolean timeout) clear_config: /* The previous configuration is no longer valid */ if (priv->dhcp4.config) { - nm_dbus_object_clear_and_unexport (&priv->dhcp4.config); + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); priv->dhcp4.config = nm_dhcp4_config_new (); _notify (self, PROP_DHCP4_CONFIG); } @@ -6900,7 +6159,6 @@ dhcp4_state_changed (NMDhcpClient *client, manual = _ip4_config_new (self); nm_ip4_config_merge_setting (manual, nm_connection_get_setting_ip4_config (connection), - NM_SETTING_CONNECTION_MDNS_DEFAULT, nm_device_get_route_table (self, AF_INET, TRUE), nm_device_get_route_metric (self, AF_INET)); @@ -6976,100 +6234,14 @@ get_dhcp_timeout (NMDevice *self, int addr_family) return timeout ?: NM_DHCP_TIMEOUT_DEFAULT; } -static GBytes * -dhcp4_get_client_id (NMDevice *self, NMConnection *connection) -{ - NMSettingIPConfig *s_ip4; - const char *client_id; - gs_free char *client_id_default = NULL; - guint8 *client_id_buf; - gboolean is_mac; - - s_ip4 = nm_connection_get_setting_ip4_config (connection); - client_id = nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)); - - if (!client_id) { - client_id_default = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, - "ipv4.dhcp-client-id", self); - if (client_id_default && client_id_default[0]) - client_id = client_id_default; - } - - if (!client_id) - return NULL; - - if ( (is_mac = nm_streq (client_id, "mac")) - || nm_streq (client_id, "perm-mac")) { - const char *hwaddr; - char addr_buf[NM_UTILS_HWADDR_LEN_MAX]; - gsize addr_len; - guint8 addr_type; - - hwaddr = is_mac - ? nm_device_get_hw_address (self) - : nm_device_get_permanent_hw_address (self); - if (!hwaddr) - return NULL; - - if (!_nm_utils_hwaddr_aton (hwaddr, addr_buf, sizeof (addr_buf), &addr_len)) - g_return_val_if_reached (NULL); - - switch (addr_len) { - case ETH_ALEN: - addr_type = ARPHRD_ETHER; - break; - default: - /* unsupported type. */ - return NULL; - } - - client_id_buf = g_malloc (addr_len + 1); - client_id_buf[0] = addr_type; - memcpy (&client_id_buf[1], addr_buf, addr_len); - return g_bytes_new_take (client_id_buf, addr_len + 1); - } - - if (nm_streq (client_id, "stable")) { - NMUtilsStableType stable_type; - const char *stable_id; - GChecksum *sum; - guint8 buf[20]; - gsize buf_size; - guint32 salted_header; - - stable_id = _get_stable_id (self, connection, &stable_type); - if (!stable_id) - g_return_val_if_reached (NULL); - - salted_header = htonl (2011610591 + stable_type); - - sum = g_checksum_new (G_CHECKSUM_SHA1); - - g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header)); - g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id)); - - buf_size = sizeof (buf); - g_checksum_get_digest (sum, buf, &buf_size); - nm_assert (buf_size == sizeof (buf)); - - g_checksum_free (sum); - - client_id_buf = g_malloc (1 + 15); - client_id_buf[0] = 0; - memcpy (&client_id_buf[1], buf, 15); - return g_bytes_new_take (client_id_buf, 1 + 15); - } - - return nm_dhcp_utils_client_id_string_to_bytes (client_id); -} - static NMActStageReturn dhcp4_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingIPConfig *s_ip4; - gs_unref_bytes GBytes *hwaddr = NULL; - gs_unref_bytes GBytes *client_id = NULL; + const guint8 *hw_addr; + size_t hw_addr_len = 0; + GByteArray *tmp = NULL; NMConnection *connection; connection = nm_device_get_applied_connection (self); @@ -7078,31 +6250,36 @@ dhcp4_start (NMDevice *self) s_ip4 = nm_connection_get_setting_ip4_config (connection); /* Clear old exported DHCP options */ - nm_dbus_object_clear_and_unexport (&priv->dhcp4.config); + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); priv->dhcp4.config = nm_dhcp4_config_new (); - hwaddr = nm_platform_link_get_address_as_bytes (nm_device_get_platform (self), - nm_device_get_ip_ifindex (self)); - - client_id = dhcp4_get_client_id (self, connection); + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len); + if (hw_addr_len) { + tmp = g_byte_array_sized_new (hw_addr_len); + g_byte_array_append (tmp, hw_addr, hw_addr_len); + } + /* Begin DHCP on the interface */ g_warn_if_fail (priv->dhcp4.client == NULL); priv->dhcp4.client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), nm_netns_get_multi_idx (nm_device_get_netns (self)), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), - hwaddr, + tmp, nm_connection_get_uuid (connection), nm_device_get_route_table (self, AF_INET, TRUE), nm_device_get_route_metric (self, AF_INET), nm_setting_ip_config_get_dhcp_send_hostname (s_ip4), nm_setting_ip_config_get_dhcp_hostname (s_ip4), nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)), - client_id, + nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)), get_dhcp_timeout (self, AF_INET), priv->dhcp_anycast_address, NULL); + if (tmp) + g_byte_array_free (tmp, TRUE); + if (!priv->dhcp4.client) return NM_ACT_STAGE_RETURN_FAILURE; @@ -7175,7 +6352,7 @@ shared4_new_config (NMDevice *self, NMConnection *connection) guint32 count = 0; if (G_UNLIKELY (!shared_ips)) - shared_ips = g_hash_table_new (nm_direct_hash, NULL); + 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); @@ -7360,7 +6537,6 @@ act_stage3_ip4_config_start (NMDevice *self, config = _ip4_config_new (self); nm_ip4_config_merge_setting (config, nm_connection_get_setting_ip4_config (connection), - NM_SETTING_CONNECTION_MDNS_DEFAULT, nm_device_get_route_table (self, AF_INET, TRUE), nm_device_get_route_metric (self, AF_INET)); @@ -7397,7 +6573,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE; - applied_config_clear (&priv->dhcp6.ip6_config); + g_clear_object (&priv->dhcp6.ip6_config); g_clear_pointer (&priv->dhcp6.event_id, g_free); nm_clear_g_source (&priv->dhcp6.grace_id); @@ -7415,18 +6591,148 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE); if (priv->dhcp6.config) { - nm_dbus_object_clear_and_unexport (&priv->dhcp6.config); + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); _notify (self, PROP_DHCP6_CONFIG); } } static gboolean +ip6_config_merge_and_apply (NMDevice *self, + gboolean commit) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + gboolean success; + NMIP6Config *composite; + gboolean ignore_auto_routes = FALSE; + gboolean ignore_auto_dns = FALSE; + gboolean ignore_default_routes = FALSE; + const char *token = NULL; + GSList *iter; + + if (nm_device_sys_iface_state_is_external (self)) + commit = 0; + + /* Apply ignore-auto-routes and ignore-auto-dns settings */ + connection = nm_device_get_applied_connection (self); + if (connection) { + NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); + + if (s_ip6) { + NMSettingIP6Config *ip6 = NM_SETTING_IP6_CONFIG (s_ip6); + + 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); + + /* 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); + + 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); + } + } + + composite = _ip6_config_new (self); + nm_ip6_config_set_privacy (composite, + priv->ndisc ? + priv->ndisc_use_tempaddr : + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + init_ip6_config_dns_priority (self, composite); + + if (commit) { + if (priv->queued_ip6_config_id) + update_ext_ip_config (self, AF_INET6, FALSE, FALSE); + ensure_con_ip6_config (self); + } + + if (commit) + priv->default_route_metric_penalty_ip6_has = default_route_metric_penalty_detect (self); + + /* Merge all the IP configs into the composite config */ + if (priv->ac_ip6_config) { + nm_ip6_config_merge (composite, priv->ac_ip6_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (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)); + } + if (priv->dhcp6.ip6_config) { + nm_ip6_config_merge (composite, priv->dhcp6.ip6_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (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)); + } + + for (iter = priv->vpn6_configs; iter; iter = iter->next) + nm_ip6_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); + + if (priv->ext_ip6_config) + nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT, 0); + + /* Merge WWAN config *last* to ensure modem-given settings overwrite + * any external stuff set by pppd or other scripts. + */ + if (priv->wwan_ip6_config) { + nm_ip6_config_merge (composite, priv->wwan_ip6_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (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)); + } + + 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); + } + } + + /* Merge user overrides into the composite config. For assumed connections, + * con_ip6_config is empty. */ + 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)); + } + + if (commit) { + nm_ip6_config_add_dependent_routes (composite, + nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_metric (self, AF_INET6)); + } + + /* Allow setting MTU etc */ + if (commit) { + NMUtilsIPv6IfaceId iid; + + if (token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, token)) { + nm_platform_link_set_ipv6_token (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + iid); + } + } + + success = nm_device_set_ip6_config (self, composite, commit); + g_object_unref (composite); + if (commit) + priv->v6_commit_first_time = FALSE; + return success; +} + +static gboolean dhcp6_lease_change (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; - if (!applied_config_get_current (&priv->dhcp6.ip6_config)) { + if (priv->dhcp6.ip6_config == NULL) { _LOGW (LOGD_DHCP6, "failed to get DHCPv6 config for rebind"); return FALSE; } @@ -7437,7 +6743,7 @@ dhcp6_lease_change (NMDevice *self) g_assert (settings_connection); /* Apply the updated config */ - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) { + if (!ip6_config_merge_and_apply (self, TRUE)) { _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event"); return FALSE; } @@ -7481,8 +6787,8 @@ dhcp6_fail (NMDevice *self, gboolean timeout) * on the interface. */ if ( priv->ip6_state == IP_DONE - && priv->con_ip_config_6 - && nm_ip6_config_get_num_addresses (priv->con_ip_config_6)) + && priv->con_ip6_config + && nm_ip6_config_get_num_addresses (priv->con_ip6_config)) goto clear_config; /* Fail the method in case of timeout or failure during initial @@ -7519,7 +6825,7 @@ dhcp6_fail (NMDevice *self, gboolean timeout) clear_config: /* The previous configuration is no longer valid */ if (priv->dhcp6.config) { - nm_dbus_object_clear_and_unexport (&priv->dhcp6.config); + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); priv->dhcp6.config = nm_dhcp6_config_new (); _notify (self, PROP_DHCP6_CONFIG); } @@ -7571,16 +6877,16 @@ dhcp6_state_changed (NMDhcpClient *client, const NMPlatformIP6Address *a; nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6_config, &a) - applied_config_add_address (&priv->dhcp6.ip6_config, NM_PLATFORM_IP_ADDRESS_CAST (a)); + nm_ip6_config_add_address (priv->dhcp6.ip6_config, a); } else { + g_clear_object (&priv->dhcp6.ip6_config); g_clear_pointer (&priv->dhcp6.event_id, g_free); if (ip6_config) { - applied_config_init (&priv->dhcp6.ip6_config, ip6_config); + 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); _notify (self, PROP_DHCP6_CONFIG); - } else - applied_config_clear (&priv->dhcp6.ip6_config); + } } /* After long time we have been able to renew the lease: @@ -7590,7 +6896,7 @@ dhcp6_state_changed (NMDhcpClient *client, _set_ip_state (self, AF_INET6, IP_CONF); if (priv->ip6_state == IP_CONF) { - if (!applied_config_get_current (&priv->dhcp6.ip6_config)) { + if (priv->dhcp6.ip6_config == NULL) { nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED); break; } @@ -7641,32 +6947,34 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingIPConfig *s_ip6; - gs_unref_bytes GBytes *hwaddr = NULL; + GByteArray *tmp = NULL; + const guint8 *hw_addr; + size_t hw_addr_len = 0; const NMPlatformIP6Address *ll_addr = NULL; g_assert (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); - if (priv->ext_ip6_config_captured) { - ll_addr = nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); - } + 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; } - hwaddr = nm_platform_link_get_address_as_bytes (nm_device_get_platform (self), - nm_device_get_ip_ifindex (self)); + hw_addr = nm_platform_link_get_address (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), &hw_addr_len); + if (hw_addr_len) { + tmp = g_byte_array_sized_new (hw_addr_len); + g_byte_array_append (tmp, hw_addr, hw_addr_len); + } priv->dhcp6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_multi_index (self), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), - hwaddr, + tmp, &ll_addr->address, nm_connection_get_uuid (connection), nm_device_get_route_table (self, AF_INET6, TRUE), @@ -7678,6 +6986,8 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)), priv->dhcp6.needed_prefixes); + if (tmp) + g_byte_array_free (tmp, TRUE); if (priv->dhcp6.client) { priv->dhcp6.state_sigid = g_signal_connect (priv->dhcp6.client, @@ -7703,11 +7013,11 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll) NMConnection *connection; NMSettingIPConfig *s_ip6; - nm_dbus_object_clear_and_unexport (&priv->dhcp6.config); + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); priv->dhcp6.config = nm_dhcp6_config_new (); - nm_assert (!applied_config_get_current (&priv->dhcp6.ip6_config)); - applied_config_clear (&priv->dhcp6.ip6_config); + 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); connection = nm_device_get_applied_connection (self); @@ -7718,12 +7028,17 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll) nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP6, TRUE); if (wait_for_ll) { + NMActStageReturn ret; + /* ensure link local is ready... */ - if (!linklocal6_start (self)) { - /* wait for the LL address to show up */ + ret = linklocal6_start (self); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + /* success; wait for the LL address to show up */ return TRUE; } - /* already have the LL address; kick off DHCP */ + + /* success; already have the LL address; kick off DHCP */ + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); } if (!dhcp6_start_with_link_ready (self, connection)) @@ -7785,19 +7100,19 @@ nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMPlatformIP6Address address = *subnet; - if (!applied_config_get_current (&priv->ac_ip6_config)) - applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6); + if (!priv->ac_ip6_config) + priv->ac_ip6_config = _ip6_config_new (self); /* Assign a ::1 address in the subnet for us. */ address.address.s6_addr32[3] |= htonl (1); - applied_config_add_address (&priv->ac_ip6_config, NM_PLATFORM_IP_ADDRESS_CAST (&address)); + 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. */ - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing"); } @@ -7812,11 +7127,11 @@ nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device) NMIP6Config *from_config = NULL; guint i, len; - if (applied_config_get_current (&priv->ac_ip6_config)) { - applied_config_reset_nameservers (&priv->ac_ip6_config); - applied_config_reset_searches (&priv->ac_ip6_config); + if (priv->ac_ip6_config) { + nm_ip6_config_reset_nameservers (priv->ac_ip6_config); + nm_ip6_config_reset_searches (priv->ac_ip6_config); } else - applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6); + priv->ac_ip6_config = _ip6_config_new (self); if (from_device) from_config = nm_device_get_ip6_config (from_device); @@ -7825,28 +7140,34 @@ nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device) len = nm_ip6_config_get_num_nameservers (from_config); for (i = 0; i < len; i++) { - applied_config_add_nameserver (&priv->ac_ip6_config, - (const NMIPAddr *) nm_ip6_config_get_nameserver (from_config, i)); + nm_ip6_config_add_nameserver (priv->ac_ip6_config, + nm_ip6_config_get_nameserver (from_config, i)); } len = nm_ip6_config_get_num_searches (from_config); for (i = 0; i < len; i++) { - applied_config_add_search (&priv->ac_ip6_config, - nm_ip6_config_get_search (from_config, i)); + nm_ip6_config_add_search (priv->ac_ip6_config, + nm_ip6_config_get_search (from_config, i)); } - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing"); } /*****************************************************************************/ static void -linklocal6_failed (NMDevice *self) +linklocal6_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); nm_clear_g_source (&priv->linklocal6_timeout_id); +} + +static void +linklocal6_failed (NMDevice *self) +{ + linklocal6_cleanup (self); nm_device_activate_schedule_ip6_config_timeout (self); } @@ -7861,26 +7182,17 @@ linklocal6_timeout_cb (gpointer user_data) } static void -linklocal6_check_complete (NMDevice *self) +linklocal6_complete (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; const char *method; - if (!priv->linklocal6_timeout_id) { - /* we are not waiting for linklocal to complete. Nothing to do. */ - return; - } + g_assert (priv->linklocal6_timeout_id); + g_assert (priv->ext_ip6_config_captured); + g_assert (nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)); - if ( !priv->ext_ip6_config_captured - || !nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) { - /* we don't have a non-tentative link local address yet. Wait longer. */ - return; - } - - nm_clear_g_source (&priv->linklocal6_timeout_id); + linklocal6_cleanup (self); connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -7890,9 +7202,12 @@ linklocal6_check_complete (NMDevice *self) _LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses successful, continue with method %s", method); if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 - || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) - addrconf6_start_with_link_ready (self); - else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { + || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) { + if (!addrconf6_start_with_link_ready (self)) { + /* Time out IPv6 instead of failing the entire activation */ + nm_device_activate_schedule_ip6_config_timeout (self); + } + } 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); @@ -7907,26 +7222,27 @@ 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; NMConnection *connection; NMSettingIP6Config *s_ip6 = NULL; GError *error = NULL; - const char *addr_type; - if (!priv->ipv6ll_handle) + if (priv->nm_ipv6ll == FALSE) return; - if ( priv->ext_ip6_config_captured - && nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) { - /* Already have an LL address, nothing to do */ - return; - } + if (priv->ext_ip6_config_captured) { + NMDedupMultiIter ipconf_iter; + const NMPlatformIP6Address *addr; - priv->ipv6ll_has = FALSE; - memset (&priv->ipv6ll_addr, 0, sizeof (priv->ipv6ll_addr)); + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, priv->ext_ip6_config_captured, &addr) { + if ( IN6_IS_ADDR_LINKLOCAL (&addr->address) + && !(addr->n_ifa_flags & IFA_F_DADFAILED)) { + /* Already have an LL address, nothing to do */ + return; + } + } + } memset (&lladdr, 0, sizeof (lladdr)); lladdr.s6_addr16[0] = htons (0xfe80); @@ -7952,7 +7268,7 @@ check_and_add_ipv6ll_addr (NMDevice *self) linklocal6_failed (self); return; } - addr_type = "stable-privacy"; + _LOGD (LOGD_IP6, "linklocal6: using IPv6 stable-privacy addressing"); } else { NMUtilsIPv6IfaceId iid; @@ -7968,30 +7284,37 @@ check_and_add_ipv6ll_addr (NMDevice *self) _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"); + nm_utils_ipv6_addr_set_interface_identifier (&lladdr, iid); - addr_type = "EUI-64"; } - _LOGD (LOGD_IP6, "linklocal6: generated %s IPv6LL address %s", addr_type, nm_utils_inet6_ntop (&lladdr, NULL)); - priv->ipv6ll_has = TRUE; - priv->ipv6ll_addr = lladdr; - ip_config_merge_and_apply (self, AF_INET6, TRUE); + _LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); + if (!nm_platform_ip6_address_add (nm_device_get_platform (self), + ip_ifindex, + lladdr, + 64, + in6addr_any, + 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)); + } } -static gboolean +static NMActStageReturn linklocal6_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; const char *method; - nm_clear_g_source (&priv->linklocal6_timeout_id); + linklocal6_cleanup (self); if ( priv->ext_ip6_config_captured - && nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) - return TRUE; + && nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) + return NM_ACT_STAGE_RETURN_SUCCESS; connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -8007,7 +7330,8 @@ linklocal6_start (NMDevice *self) * (rh #1101809) */ priv->linklocal6_timeout_id = g_timeout_add_seconds (15, linklocal6_timeout_cb, self); - return FALSE; + + return NM_ACT_STAGE_RETURN_POSTPONE; } /*****************************************************************************/ @@ -8072,7 +7396,7 @@ _set_mtu (NMDevice *self, guint32 mtu) if (priv->master) { /* changing the MTU of a slave, might require the master to reset - * its MTU. Note that the master usually cannot set a MTU larger + * 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); @@ -8249,7 +7573,7 @@ nm_device_commit_mtu (NMDevice *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)->ip_config_4); + _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)); } @@ -8261,10 +7585,10 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); guint i; - g_return_if_fail (priv->act_request.obj); + g_return_if_fail (priv->act_request); - if (!applied_config_get_current (&priv->ac_ip6_config)) - applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6); + if (!priv->ac_ip6_config) + priv->ac_ip6_config = _ip6_config_new (self); if (changed & NM_NDISC_CONFIG_ADDRESSES) { guint8 plen; @@ -8285,23 +7609,16 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in } else plen = 128; - nm_ip6_config_reset_addresses_ndisc ((NMIP6Config *) priv->ac_ip6_config.orig, + nm_ip6_config_reset_addresses_ndisc (priv->ac_ip6_config, rdata->addresses, rdata->addresses_n, plen, ifa_flags); - if (priv->ac_ip6_config.current) { - nm_ip6_config_reset_addresses_ndisc ((NMIP6Config *) priv->ac_ip6_config.current, - rdata->addresses, - rdata->addresses_n, - plen, - ifa_flags); - } } if (NM_FLAGS_ANY (changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) { - nm_ip6_config_reset_routes_ndisc ((NMIP6Config *) priv->ac_ip6_config.orig, + nm_ip6_config_reset_routes_ndisc (priv->ac_ip6_config, rdata->gateways, rdata->gateways_n, rdata->routes, @@ -8310,34 +7627,22 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in nm_device_get_route_metric (self, AF_INET6), nm_platform_check_kernel_support (nm_device_get_platform (self), NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF)); - if (priv->ac_ip6_config.current) { - nm_ip6_config_reset_routes_ndisc ((NMIP6Config *) priv->ac_ip6_config.current, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table (self, AF_INET6, TRUE), - nm_device_get_route_metric (self, AF_INET6), - nm_platform_check_kernel_support (nm_device_get_platform (self), - NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF)); - } - } if (changed & NM_NDISC_CONFIG_DNS_SERVERS) { /* Rebuild DNS server list from neighbor discovery cache. */ - applied_config_reset_nameservers (&priv->ac_ip6_config); + nm_ip6_config_reset_nameservers (priv->ac_ip6_config); for (i = 0; i < rdata->dns_servers_n; i++) - applied_config_add_nameserver (&priv->ac_ip6_config, (const NMIPAddr *) &rdata->dns_servers[i].address); + nm_ip6_config_add_nameserver (priv->ac_ip6_config, &rdata->dns_servers[i].address); } if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) { /* Rebuild domain list from neighbor discovery cache. */ - applied_config_reset_searches (&priv->ac_ip6_config); + nm_ip6_config_reset_searches (priv->ac_ip6_config); for (i = 0; i < rdata->dns_domains_n; i++) - applied_config_add_search (&priv->ac_ip6_config, rdata->dns_domains[i].domain); + nm_ip6_config_add_search (priv->ac_ip6_config, rdata->dns_domains[i].domain); } if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) { @@ -8387,21 +7692,16 @@ ndisc_ra_timeout (NMNDisc *ndisc, NMDevice *self) * 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. - * - * FIXME: it doesn't seem correct to determine this based on which - * addresses we find inside priv->ip_config_6. */ - if ( priv->ip_config_6 - && nm_ip6_config_find_first_address (priv->ip_config_6, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)) + if ( priv->ip6_config + && nm_ip6_config_get_address_first_nontentative (priv->ip6_config, FALSE)) nm_device_activate_schedule_ip6_config_result (self); else nm_device_activate_schedule_ip6_config_timeout (self); } } -static void +static gboolean addrconf6_start_with_link_ready (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -8419,10 +7719,12 @@ addrconf6_start_with_link_ready (NMDevice *self) } /* Apply any manual configuration before starting RA */ - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) { _LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration"); + g_clear_object (&priv->con_ip6_config); + } - /* FIXME: These sysctls would probably be better set by the lndp ndisc itself. */ + /* 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. */ @@ -8453,7 +7755,7 @@ addrconf6_start_with_link_ready (NMDevice *self) ndisc_set_router_config (priv->ndisc, self); nm_ndisc_start (priv->ndisc); - return; + return TRUE; } static NMNDiscNodeType @@ -8476,6 +7778,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; + NMActStageReturn ret; NMSettingIP6Config *s_ip6 = NULL; GError *error = NULL; NMUtilsStableType stable_type; @@ -8484,8 +7787,11 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) connection = nm_device_get_applied_connection (self); g_assert (connection); - nm_assert (!applied_config_get_current (&priv->ac_ip6_config)); - applied_config_clear (&priv->ac_ip6_config); + 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; + } g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); @@ -8522,14 +7828,15 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) nm_device_add_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, TRUE); /* ensure link local is ready... */ - if (!linklocal6_start (self)) { - /* wait for the LL address to show up */ + ret = linklocal6_start (self); + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + /* success; wait for the LL address to show up */ return TRUE; } - /* already have the LL address; kick off neighbor discovery */ - addrconf6_start_with_link_ready (self); - return TRUE; + /* success; already have the LL address; kick off neighbor discovery */ + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + return addrconf6_start_with_link_ready (self); } static void @@ -8542,7 +7849,7 @@ addrconf6_cleanup (NMDevice *self) nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE); - applied_config_clear (&priv->ac_ip6_config); + g_clear_object (&priv->ac_ip6_config); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); g_clear_object (&priv->ndisc); @@ -8596,8 +7903,7 @@ restore_ip6_properties (NMDevice *self) g_hash_table_iter_init (&iter, priv->ip6_saved_properties); while (g_hash_table_iter_next (&iter, &key, &value)) { /* Don't touch "disable_ipv6" if we're doing userland IPv6LL */ - if ( priv->ipv6ll_handle - && nm_streq (key, "disable_ipv6")) + if (priv->nm_ipv6ll && strcmp (key, "disable_ipv6") == 0) continue; nm_device_ipv6_sysctl_set (self, key, value); } @@ -8607,7 +7913,7 @@ 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)->ipv6ll_handle) + if (NM_DEVICE_GET_PRIVATE (self)->nm_ipv6ll == FALSE) nm_device_ipv6_sysctl_set (self, "disable_ipv6", value); } @@ -8622,7 +7928,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) return; - priv->ipv6ll_handle = enable; + priv->nm_ipv6ll = enable; if (ifindex > 0) { NMPlatformError plerr; const char *detail = enable ? "enable" : "disable"; @@ -8771,14 +8077,14 @@ act_stage3_ip6_config_start (NMDevice *self, if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) { if ( !priv->master && !nm_device_sys_iface_state_is_external (self)) { - gboolean ipv6ll_handle_old = priv->ipv6ll_handle; + gboolean old_nm_ipv6ll = priv->nm_ipv6ll; /* 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); - if (ipv6ll_handle_old) + if (old_nm_ipv6ll == TRUE) nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); restore_ip6_properties (self); } @@ -8789,7 +8095,7 @@ act_stage3_ip6_config_start (NMDevice *self, * 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. */ - _commit_mtu (self, priv->ip_config_4); + _commit_mtu (self, priv->ip4_config); /* Any method past this point requires an IPv6LL address. Use NM-controlled * IPv6LL if this is not an assumed connection, since assumed connections @@ -8810,6 +8116,7 @@ act_stage3_ip6_config_start (NMDevice *self, priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self), nm_device_get_platform (self), nm_device_get_ip_ifindex (self), + FALSE, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); ip6_privacy = _ip6_privacy_get (self); @@ -8822,9 +8129,7 @@ act_stage3_ip6_config_start (NMDevice *self, } else ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { - ret = linklocal6_start (self) - ? NM_ACT_STAGE_RETURN_SUCCESS - : NM_ACT_STAGE_RETURN_POSTPONE; + ret = linklocal6_start (self); } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED; if (!dhcp6_start (self, TRUE)) { @@ -8934,8 +8239,8 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) /* Here we get a static IPv6 config, like for Shared where it's * autogenerated or from modems where it comes from ModemManager. */ - nm_assert (!applied_config_get_current (&priv->ac_ip6_config)); - applied_config_init (&priv->ac_ip6_config, ip6_config); + 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); @@ -9073,7 +8378,7 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request.obj); + g_return_if_fail (priv->act_request); /* Add the interface to the specified firewall zone */ if (priv->fw_state == FIREWALL_STATE_UNMANAGED) { @@ -9145,7 +8450,7 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request.obj); + g_return_if_fail (priv->act_request); activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET); } @@ -9201,7 +8506,7 @@ nm_device_activate_schedule_ip6_config_timeout (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request.obj); + g_return_if_fail (priv->act_request); activation_source_schedule (self, activate_stage4_ip6_config_timeout, AF_INET6); } @@ -9319,9 +8624,9 @@ arp_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->acd.announcing) { - nm_acd_manager_destroy (priv->acd.announcing); - priv->acd.announcing = NULL; + if (priv->arping.announcing) { + nm_arping_manager_destroy (priv->arping.announcing); + priv->arping.announcing = NULL; } } @@ -9341,7 +8646,7 @@ arp_announce (NMDevice *self) nm_device_get_ip_ifindex (self), &hw_addr_len); - if (!hw_addr || hw_addr_len != ETH_ALEN) + if (!hw_addr_len || !hw_addr) return; /* We only care about manually-configured addresses; DHCP- and autoip-configured @@ -9357,19 +8662,19 @@ arp_announce (NMDevice *self) if (num == 0) return; - priv->acd.announcing = nm_acd_manager_new (nm_device_get_ip_ifindex (self), hw_addr, hw_addr_len); + 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_acd_manager_add_address (priv->acd.announcing, addr); + nm_arping_manager_add_address (priv->arping.announcing, addr); else g_warn_if_reached (); } - nm_acd_manager_announce_addresses (priv->acd.announcing); + nm_arping_manager_announce_addresses (priv->arping.announcing); } static void @@ -9394,7 +8699,8 @@ activate_stage5_ip4_config_result (NMDevice *self) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) { + /* NULL to use the existing priv->dev_ip4_config */ + if (!ip4_config_merge_and_apply (self, TRUE)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; @@ -9406,7 +8712,7 @@ activate_stage5_ip4_config_result (NMDevice *self) if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { gs_free_error GError *error = NULL; - if (!start_sharing (self, priv->ip_config_4, &error)) { + if (!start_sharing (self, priv->ip4_config, &error)) { _LOGW (LOGD_SHARING, "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s", error->message); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); return; @@ -9442,7 +8748,10 @@ nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *conf g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - applied_config_init (&priv->dev_ip4_config, config); + g_clear_object (&priv->dev_ip4_config); + if (config) + priv->dev_ip4_config = g_object_ref (config); + activation_source_schedule (self, activate_stage5_ip4_config_result, AF_INET); } @@ -9467,32 +8776,6 @@ nm_device_activate_ip4_state_done (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_DONE; } -static void -dad6_add_pending_address (NMDevice *self, - NMPlatform *platform, - int ifindex, - const struct in6_addr *address, - NMIP6Config **dad6_config) -{ - const NMPlatformIP6Address *pl_addr; - - pl_addr = nm_platform_ip6_address_get (platform, - ifindex, - *address); - 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) - *dad6_config = _ip6_config_new (self); - - nm_ip6_config_add_address (*dad6_config, pl_addr); - } -} - /* * Returns a NMIP6Config containing NM-configured addresses which * have the tentative flag, or NULL if none is present. @@ -9501,43 +8784,42 @@ static NMIP6Config * dad6_get_pending_addresses (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMIP6Config *confs[] = { (NMIP6Config *) applied_config_get_current (&priv->ac_ip6_config), - (NMIP6Config *) applied_config_get_current (&priv->dhcp6.ip6_config), - priv->con_ip_config_6, - (NMIP6Config *) applied_config_get_current (&priv->wwan_ip_config_6) }; - const NMPlatformIP6Address *addr; + 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; NMDedupMultiIter ipconf_iter; guint i; int ifindex; - NMPlatform *platform; ifindex = nm_device_get_ip_ifindex (self); g_return_val_if_fail (ifindex > 0, NULL); - platform = nm_device_get_platform (self); - - if (priv->ipv6ll_has) { - dad6_add_pending_address (self, - platform, - ifindex, - &priv->ipv6ll_addr, - &dad6_config); - } - /* 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]) - continue; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) { - dad6_add_pending_address (self, - platform, - ifindex, - &addr->address, - &dad6_config); + if (confs[i]) { + + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) { + pl_addr = nm_platform_ip6_address_get (nm_device_get_platform (self), + ifindex, + addr->address); + 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) + dad6_config = _ip6_config_new (self); + + nm_ip6_config_add_address (dad6_config, pl_addr); + } + } } } @@ -9569,10 +8851,10 @@ activate_stage5_ip6_config_commit (NMDevice *self) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } - if (ip_config_merge_and_apply (self, AF_INET6, TRUE)) { + if (ip6_config_merge_and_apply (self, TRUE)) { if ( priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE && priv->ip6_state == IP_CONF) { - if (applied_config_get_current (&priv->dhcp6.ip6_config)) { + if (priv->dhcp6.ip6_config) { /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ @@ -9659,26 +8941,43 @@ nm_device_activate_ip6_state_done (NMDevice *self) /*****************************************************************************/ static void +act_request_set_cb (NMActRequest *act_request, + GParamSpec *pspec, + NMDevice *self) +{ + _notify (self, PROP_ACTIVE_CONNECTION); +} + +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.visible - && priv->act_request.obj == act_request) + if ( !priv->act_request_public + && priv->act_request == act_request) return; /* always clear the public flag. The few callers that set a new @act_request * don't want that the property is public yet. */ - nm_dbus_track_obj_path_set (&priv->act_request, - act_request, - FALSE); + priv->act_request_public = FALSE; + + nm_clear_g_signal_handler (priv->act_request, &priv->act_request_id); + + old_act_requst = priv->act_request; + priv->act_request = nm_g_object_ref (act_request); if (act_request) { + priv->act_request_id = g_signal_connect (act_request, + "notify::"NM_EXPORTED_OBJECT_PATH, + G_CALLBACK (act_request_set_cb), + self); + switch (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request))) { case NM_ACTIVATION_TYPE_EXTERNAL: break; @@ -9695,6 +8994,8 @@ act_request_set (NMDevice *self, NMActRequest *act_request) break; } } + + _notify (self, PROP_ACTIVE_CONNECTION); } static void @@ -9720,9 +9021,9 @@ _update_ip4_address (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); - if ( priv->ip_config_4 + if ( priv->ip4_config && ip_config_valid (priv->state) - && (address = nm_ip4_config_get_first_address (priv->ip_config_4))) { + && (address = nm_ip4_config_get_first_address (priv->ip4_config))) { if (address->address != priv->ip4_address) { priv->ip4_address = address->address; _notify (self, PROP_IP4_ADDRESS); @@ -9816,31 +9117,37 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex) } static void -_cleanup_ip_pre (NMDevice *self, int addr_family, CleanupType cleanup_type) +_cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const gboolean IS_IPv4 = (addr_family == AF_INET); - _set_ip_state (self, addr_family, IP_NONE); + _set_ip_state (self, AF_INET, IP_NONE); - if (nm_clear_g_source (&priv->queued_ip_config_id_x[IS_IPv4])) { - _LOGD (LOGD_DEVICE, "clearing queued IP%c config change", - nm_utils_addr_family_to_char (addr_family)); - } + if (nm_clear_g_source (&priv->queued_ip4_config_id)) + _LOGD (LOGD_DEVICE, "clearing queued IP4 config change"); + priv->queued_ip4_config_pending = FALSE; - if (IS_IPv4) { - priv->queued_ip4_config_pending = FALSE; - dhcp4_cleanup (self, cleanup_type, FALSE); - arp_cleanup (self); - dnsmasq_cleanup (self); - ipv4ll_cleanup (self); - } else { - priv->queued_ip6_config_pending = FALSE; - g_clear_object (&priv->dad6_ip6_config); - dhcp6_cleanup (self, cleanup_type, FALSE); - nm_clear_g_source (&priv->linklocal6_timeout_id); - addrconf6_cleanup (self); - } + 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); + + _set_ip_state (self, AF_INET6, IP_NONE); + + if (nm_clear_g_source (&priv->queued_ip6_config_id)) + _LOGD (LOGD_DEVICE, "clearing queued IP6 config change"); + priv->queued_ip6_config_pending = FALSE; + + g_clear_object (&priv->dad6_ip6_config); + dhcp6_cleanup (self, cleanup_type, FALSE); + linklocal6_cleanup (self); + addrconf6_cleanup (self); } gboolean @@ -9859,7 +9166,7 @@ _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, gs_unref_hashtable GHashTable *check_dups = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, NULL); for (i = 0; argv[i]; i++) { - if (!g_hash_table_add (check_dups, (char *) argv[i])) + if (!nm_g_hash_table_add (check_dups, (char *) argv[i])) nm_assert (FALSE); } nm_assert (g_hash_table_size (check_dups) > 0); @@ -9910,7 +9217,8 @@ _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, void nm_device_reactivate_ip4_config (NMDevice *self, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new) + NMSettingIPConfig *s_ip4_new, + gboolean force_restart) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -9919,31 +9227,31 @@ nm_device_reactivate_ip4_config (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); if (priv->ip4_state != IP_NONE) { - g_clear_object (&priv->con_ip_config_4); - g_clear_object (&priv->ext_ip_config_4); - g_clear_object (&priv->dev_ip4_config.current); - g_clear_object (&priv->wwan_ip_config_4.current); - priv->con_ip_config_4 = _ip4_config_new (self); - nm_ip4_config_merge_setting (priv->con_ip_config_4, + g_clear_object (&priv->con_ip4_config); + g_clear_object (&priv->ext_ip4_config); + priv->con_ip4_config = _ip4_config_new (self); + nm_ip4_config_merge_setting (priv->con_ip4_config, s_ip4_new, - _get_mdns (self), nm_device_get_route_table (self, AF_INET, TRUE), nm_device_get_route_metric (self, AF_INET)); - 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; + 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); + } - if (!nm_streq0 (method_old, method_new)) { - _cleanup_ip_pre (self, AF_INET, CLEANUP_TYPE_DECONFIGURE); + if (force_restart) { + _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); } else { - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + if (!ip4_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); } } @@ -9952,7 +9260,8 @@ nm_device_reactivate_ip4_config (NMDevice *self, void nm_device_reactivate_ip6_config (NMDevice *self, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new) + NMSettingIPConfig *s_ip6_new, + gboolean force_restart) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -9961,34 +9270,31 @@ nm_device_reactivate_ip6_config (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); if (priv->ip6_state != IP_NONE) { - g_clear_object (&priv->con_ip_config_6); - g_clear_object (&priv->ext_ip_config_6); - g_clear_object (&priv->ac_ip6_config.current); - g_clear_object (&priv->dhcp6.ip6_config.current); - g_clear_object (&priv->wwan_ip_config_6.current); - if ( priv->ipv6ll_handle - && !IN6_IS_ADDR_UNSPECIFIED (&priv->ipv6ll_addr)) - priv->ipv6ll_has = TRUE; - priv->con_ip_config_6 = _ip6_config_new (self); - nm_ip6_config_merge_setting (priv->con_ip_config_6, + g_clear_object (&priv->con_ip6_config); + g_clear_object (&priv->ext_ip6_config); + priv->con_ip6_config = _ip6_config_new (self); + nm_ip6_config_merge_setting (priv->con_ip6_config, s_ip6_new, nm_device_get_route_table (self, AF_INET6, TRUE), nm_device_get_route_metric (self, AF_INET6)); - 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; + 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); + } - if (!nm_streq0 (method_old, method_new)) { - _cleanup_ip_pre (self, AF_INET6, CLEANUP_TYPE_DECONFIGURE); + if (force_restart) { + _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); } else { - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); } } @@ -10033,7 +9339,7 @@ can_reapply_change (NMDevice *self, const char *setting_name, * allowed to differ. * * This includes UUID, there is no principal problem with reapplying a - * connection and changing its UUID. In fact, disallowing it makes it + * 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, @@ -10159,7 +9465,7 @@ check_and_reapply_connection (NMDevice *self, } if ( version_id != 0 - && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request.obj)) { + && 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, @@ -10172,10 +9478,10 @@ check_and_reapply_connection (NMDevice *self, *************************************************************************/ if (diffs) - nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request.obj); + nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request); _LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)", - (unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request.obj)), + (unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)), diffs ? "" : " (unmodified)"); if (diffs) { @@ -10231,8 +9537,8 @@ check_and_reapply_connection (NMDevice *self, s_ip6_old = nm_connection_get_setting_ip6_config (con_old); s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); - nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); + 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); reactivate_proxy_config (self); @@ -10301,33 +9607,25 @@ reapply_cb (NMDevice *self, } static void -impl_device_reapply (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *dbus_connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_device_reapply (NMDevice *self, + GDBusMethodInvocation *context, + GVariant *settings, + guint64 version_id, + guint32 flags) { - NMDevice *self = NM_DEVICE (obj); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; NMConnection *connection = NULL; GError *error = NULL; ReapplyData *reapply_data; - gs_unref_variant GVariant *settings = NULL; - guint64 version_id; - guint32 flags; - - g_variant_get (parameters, "(@a{sa{sv}}tu)", &settings, &version_id, &flags); /* No flags supported as of now. */ if (flags != 0) { error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "Invalid flags specified"); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, invocation, error->message); - g_dbus_method_invocation_take_error (invocation, error); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message); + g_dbus_method_invocation_take_error (context, error); return; } @@ -10335,8 +9633,8 @@ impl_device_reapply (NMDBusObject *obj, error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, "Device is not activated"); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, invocation, error->message); - g_dbus_method_invocation_take_error (invocation, error); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message); + g_dbus_method_invocation_take_error (context, error); return; } @@ -10351,8 +9649,8 @@ impl_device_reapply (NMDBusObject *obj, &error); if (!connection) { g_prefix_error (&error, "The settings specified are invalid: "); - nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, invocation, error->message); - g_dbus_method_invocation_take_error (invocation, error); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, NULL, context, error->message); + g_dbus_method_invocation_take_error (context, error); return; } nm_connection_clear_secrets (connection); @@ -10365,8 +9663,9 @@ impl_device_reapply (NMDBusObject *obj, } else reapply_data = NULL; + /* Ask the manager to authenticate this request for us */ g_signal_emit (self, signals[AUTH_REQUEST], 0, - invocation, + context, nm_device_get_applied_connection (self), NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, @@ -10425,44 +9724,40 @@ get_applied_connection_cb (NMDevice *self, 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.obj))); + nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request))); } static void -impl_device_get_applied_connection (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_device_get_applied_connection (NMDevice *self, + GDBusMethodInvocation *context, + guint32 flags) { - NMDevice *self = NM_DEVICE (obj); NMConnection *applied_connection; - guint32 flags; + GError *error = NULL; - g_variant_get (parameters, "(u)", &flags); + g_return_if_fail (NM_IS_DEVICE (self)); /* No flags supported as of now. */ if (flags != 0) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_FAILED, - "Invalid flags specified"); + 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) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ACTIVE, - "Device is not activated"); + 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, - invocation, + context, applied_connection, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, @@ -10611,31 +9906,25 @@ _clear_queued_act_request (NMDevicePrivate *priv) } static void -impl_device_disconnect (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *dbus_connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_device_disconnect (NMDevice *self, GDBusMethodInvocation *context) { - NMDevice *self = NM_DEVICE (obj); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; + GError *error = NULL; - if (!priv->act_request.obj) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ACTIVE, - "This device is not active"); + if (NM_DEVICE_GET_PRIVATE (self)->act_request == NULL) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "This device is not active"); + g_dbus_method_invocation_take_error (context, error); return; } connection = nm_device_get_applied_connection (self); - nm_assert (connection); + g_assert (connection); + /* Ask the manager to authenticate this request for us */ g_signal_emit (self, signals[AUTH_REQUEST], 0, - invocation, + context, connection, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, @@ -10667,27 +9956,21 @@ delete_cb (NMDevice *self, } static void -impl_device_delete (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_device_delete (NMDevice *self, GDBusMethodInvocation *context) { - NMDevice *self = NM_DEVICE (obj); + GError *error = NULL; - if ( !nm_device_is_software (self) - || !nm_device_is_real (self)) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_SOFTWARE, - "This device is not a software device or is not realized"); + if (!nm_device_is_software (self) || !nm_device_is_real (self)) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_SOFTWARE, + "This device is not a software device or is not realized"); + 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, - invocation, + context, NULL, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, @@ -10811,8 +10094,8 @@ nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection) && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request))) _clear_queued_act_request (priv); - if ( priv->act_request.obj - && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request.obj)) + if ( priv->act_request + && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request)) && priv->state < NM_DEVICE_STATE_DEACTIVATING) { nm_device_state_changed (self, NM_DEVICE_STATE_DEACTIVATING, @@ -10828,7 +10111,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req) must_queue = _carrier_wait_check_act_request_must_queue (self, req); - if ( !priv->act_request.obj + if ( !priv->act_request && !must_queue && nm_device_is_real (self)) { _device_activate (self, req); @@ -10843,7 +10126,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req) _LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect"); /* Deactivate existing activation request first */ - if (priv->act_request.obj) { + if (priv->act_request) { _LOGI (LOGD_DEVICE, "disconnecting for new activation request."); nm_device_state_changed (self, NM_DEVICE_STATE_DEACTIVATING, @@ -10928,155 +10211,116 @@ nm_device_get_ip4_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->ip_config_4; + return NM_DEVICE_GET_PRIVATE (self)->ip4_config; } static gboolean -nm_device_set_ip_config (NMDevice *self, - int addr_family, - NMIPConfig *new_config, - gboolean commit, - GPtrArray *ip4_dev_route_blacklist) +nm_device_set_ip4_config (NMDevice *self, + NMIP4Config *new_config, + gboolean commit, + GPtrArray *ip4_dev_route_blacklist) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const gboolean IS_IPv4 = (addr_family == AF_INET); - NMIPConfig *old_config; + NMDevicePrivate *priv; + NMIP4Config *old_config = NULL; gboolean has_changes = FALSE; gboolean success = TRUE; - NMSettingsConnection *settings_connection; - nm_assert_addr_family (addr_family); - nm_assert (!new_config || nm_ip_config_get_addr_family (new_config) == addr_family); + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + _LOGD (LOGD_IP4, "ip4-config: update (commit=%d, new-config=%p)", + commit, new_config); + nm_assert ( !new_config || ( new_config && ({ int ip_ifindex = nm_device_get_ip_ifindex (self); ( ip_ifindex > 0 - && ip_ifindex == nm_ip_config_get_ifindex (new_config)); + && ip_ifindex == nm_ip4_config_get_ifindex (new_config)); }))); - nm_assert (IS_IPv4 || !ip4_dev_route_blacklist); - _LOGD (LOGD_IP_from_af (addr_family), - "ip%c-config: update (commit=%d, new-config=%p)", - nm_utils_addr_family_to_char (addr_family), - commit, - new_config); + priv = NM_DEVICE_GET_PRIVATE (self); + + old_config = priv->ip4_config; /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { - - _commit_mtu (self, - IS_IPv4 - ? NM_IP4_CONFIG (new_config) - : priv->ip_config_4); - - if (IS_IPv4) { - success = nm_ip4_config_commit (NM_IP4_CONFIG (new_config), - nm_device_get_platform (self), - nm_device_get_route_table (self, addr_family, FALSE) - ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL - : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN); - nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), - nm_ip_config_get_ifindex (new_config), - ip4_dev_route_blacklist); + _commit_mtu (self, new_config); + success = nm_ip4_config_commit (new_config, + nm_device_get_platform (self), + nm_device_get_route_table (self, AF_INET, FALSE) + ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL + : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN); + nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), + nm_ip4_config_get_ifindex (new_config), + ip4_dev_route_blacklist); + } + + if (new_config) { + 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) { + _LOGD (LOGD_IP4, "ip4-config: update IP4Config instance (%s)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); + } } else { - gs_unref_ptrarray GPtrArray *temporary_not_available = NULL; - - success = nm_ip6_config_commit (NM_IP6_CONFIG (new_config), - nm_device_get_platform (self), - nm_device_get_route_table (self, addr_family, FALSE) - ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL - : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, - &temporary_not_available); - - if (!_rt6_temporary_not_available_set (self, temporary_not_available)) - success = FALSE; - } - } + has_changes = TRUE; + priv->ip4_config = g_object_ref (new_config); - old_config = priv->ip_config_x[IS_IPv4]; + if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config))) + nm_exported_object_export (NM_EXPORTED_OBJECT (new_config)); - if (new_config && 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_ip_config_replace (old_config, new_config, &has_changes); - if (has_changes) { - _LOGD (LOGD_IP_from_af (addr_family), - "ip%c-config: update IP Config instance (%s)", - nm_utils_addr_family_to_char (addr_family), - nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); + _LOGD (LOGD_IP4, "ip4-config: set IP4Config instance (%s)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config))); } - } else if (new_config /*&& !old_config*/) { - has_changes = TRUE; - priv->ip_config_x[IS_IPv4] = g_object_ref (new_config); - if (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (new_config))) - nm_dbus_object_export (NM_DBUS_OBJECT (new_config)); - - _LOGD (LOGD_IP_from_af (addr_family), - "ip%c-config: set IP Config instance (%s)", - nm_utils_addr_family_to_char (addr_family), - nm_dbus_object_get_path (NM_DBUS_OBJECT (new_config))); - } else if (old_config /*&& !new_config*/) { + } else if (old_config) { has_changes = TRUE; - priv->ip_config_x[IS_IPv4] = NULL; - _LOGD (LOGD_IP_from_af (addr_family), - "ip%c-config: clear IP Config instance (%s)", - nm_utils_addr_family_to_char (addr_family), - nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); - if (IS_IPv4) { - /* Device config is invalid if combined config is invalid */ - applied_config_clear (&priv->dev_ip4_config); - } else - priv->needs_ip6_subnet = FALSE; + priv->ip4_config = NULL; + _LOGD (LOGD_IP4, "ip4-config: clear IP4Config instance (%s)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); + /* Device config is invalid if combined config is invalid */ + g_clear_object (&priv->dev_ip4_config); } - if (IS_IPv4) { - if (!nm_device_sys_iface_state_is_external_or_assume (self)) - ip4_rp_filter_update (self); - } + concheck_periodic_update (self); - if (has_changes) { + if (!nm_device_sys_iface_state_is_external_or_assume (self)) + ip4_rp_filter_update (self); - if (IS_IPv4) - _update_ip4_address (self); + if (has_changes) { + NMSettingsConnection *settings_connection; - if (old_config != priv->ip_config_x[IS_IPv4]) - _notify (self, IS_IPv4 ? PROP_IP4_CONFIG : PROP_IP6_CONFIG); + _update_ip4_address (self); - g_signal_emit (self, - signals[IS_IPv4 ? IP4_CONFIG_CHANGED : IP6_CONFIG_CHANGED], - 0, - priv->ip_config_x[IS_IPv4], - old_config); + if (old_config != priv->ip4_config) + _notify (self, PROP_IP4_CONFIG); + g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config); - if (old_config != priv->ip_config_x[IS_IPv4]) - nm_dbus_object_clear_and_unexport (&old_config); + if (old_config != priv->ip4_config) + nm_exported_object_clear_and_unexport (&old_config); if ( nm_device_sys_iface_state_is_external (self) && (settings_connection = nm_device_get_settings_connection (self)) && NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED) - && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request.obj)) == NM_ACTIVATION_TYPE_EXTERNAL) { + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED) + && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { + NMSetting *s_ip4; + g_object_freeze_notify (G_OBJECT (settings_connection)); - nm_connection_add_setting (NM_CONNECTION (settings_connection), - IS_IPv4 - ? nm_ip4_config_create_setting (priv->ip_config_4) - : nm_ip6_config_create_setting (priv->ip_config_6)); + + nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); + nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip4); + g_object_thaw_notify (G_OBJECT (settings_connection)); } nm_device_queue_recheck_assume (self); - - if (!IS_IPv4) { - if (priv->ndisc) - ndisc_set_router_config (priv->ndisc, self); - } } - nm_assert (!old_config || old_config == priv->ip_config_x[IS_IPv4]); - return success; } @@ -11123,11 +10367,11 @@ nm_device_replace_vpn4_config (NMDevice *self, NMIP4Config *old, NMIP4Config *co 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)); - if (!_replace_vpn_config_in_list (&priv->vpn_configs_4, (GObject *) old, (GObject *) config)) + if (!_replace_vpn_config_in_list (&priv->vpn4_configs, (GObject *) old, (GObject *) config)) return; /* NULL to use existing configs */ - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + if (!ip4_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "failed to set VPN routes for device"); } @@ -11136,11 +10380,125 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - applied_config_init (&priv->wwan_ip_config_4, config); - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + 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 */ + if (!ip4_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "failed to set WWAN IPv4 configuration"); } +static gboolean +nm_device_set_ip6_config (NMDevice *self, + NMIP6Config *new_config, + gboolean commit) +{ + NMDevicePrivate *priv; + NMIP6Config *old_config = NULL; + gboolean has_changes = FALSE; + gboolean success = TRUE; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + _LOGD (LOGD_IP6, "ip6-config: update (commit=%d, new-config=%p)", + commit, new_config); + + nm_assert ( !new_config + || ( new_config + && ({ + int ip_ifindex = nm_device_get_ip_ifindex (self); + + ( ip_ifindex > 0 + && ip_ifindex == nm_ip6_config_get_ifindex (new_config)); + }))); + + priv = NM_DEVICE_GET_PRIVATE (self); + + old_config = priv->ip6_config; + + /* Always commit to nm-platform to update lifetimes */ + if (commit && new_config) { + gs_unref_ptrarray GPtrArray *temporary_not_available = NULL; + + _commit_mtu (self, priv->ip4_config); + + success = nm_ip6_config_commit (new_config, + nm_device_get_platform (self), + nm_device_get_route_table (self, AF_INET6, FALSE) + ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL + : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, + &temporary_not_available); + + if (!_rt6_temporary_not_available_set (self, temporary_not_available)) + success = FALSE; + } + + if (new_config) { + 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) { + _LOGD (LOGD_IP6, "ip6-config: update IP6Config instance (%s)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); + } + } else { + has_changes = TRUE; + priv->ip6_config = g_object_ref (new_config); + + if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config))) + nm_exported_object_export (NM_EXPORTED_OBJECT (new_config)); + + _LOGD (LOGD_IP6, "ip6-config: set IP6Config instance (%s)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config))); + } + } else if (old_config) { + has_changes = TRUE; + priv->ip6_config = NULL; + priv->needs_ip6_subnet = FALSE; + _LOGD (LOGD_IP6, "ip6-config: clear IP6Config instance (%s)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); + } + + if (has_changes) { + NMSettingsConnection *settings_connection; + + if (old_config != priv->ip6_config) + _notify (self, PROP_IP6_CONFIG); + g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config); + + if (old_config != priv->ip6_config) + nm_exported_object_clear_and_unexport (&old_config); + + if ( nm_device_sys_iface_state_is_external (self) + && (settings_connection = nm_device_get_settings_connection (self)) + && NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED) + && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { + NMSetting *s_ip6; + + g_object_freeze_notify (G_OBJECT (settings_connection)); + + nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); + nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip6); + + g_object_thaw_notify (G_OBJECT (settings_connection)); + } + + nm_device_queue_recheck_assume (self); + + if (priv->ndisc) + ndisc_set_router_config (priv->ndisc, self); + } + + return success; +} + void nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *config) { @@ -11151,11 +10509,11 @@ nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *co 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)); - if (!_replace_vpn_config_in_list (&priv->vpn_configs_6, (GObject *) old, (GObject *) config)) + if (!_replace_vpn_config_in_list (&priv->vpn6_configs, (GObject *) old, (GObject *) config)) return; /* NULL to use existing configs */ - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed to set VPN routes for device"); } @@ -11164,8 +10522,15 @@ nm_device_set_wwan_ip6_config (NMDevice *self, NMIP6Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - applied_config_init (&priv->wwan_ip_config_6, config); - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + 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 */ + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed to set WWAN IPv6 configuration"); } @@ -11182,7 +10547,7 @@ nm_device_get_ip6_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->ip_config_6; + return NM_DEVICE_GET_PRIVATE (self)->ip6_config; } /*****************************************************************************/ @@ -11373,7 +10738,7 @@ start_ping (NMDevice *self, 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 */ + priv->gw_ping.deadline = timeout + 10; /* the proper termination is enforced by a timer */ if (spawn_ping (self)) { priv->gw_ping.watch = g_child_watch_add (priv->gw_ping.pid, ip_check_ping_watch_cb, self); @@ -11416,15 +10781,15 @@ nm_device_start_ip_check (NMDevice *self) if (timeout) { const NMPObject *gw; - if (priv->ip_config_4 && priv->ip4_state == IP_DONE) { - gw = nm_ip4_config_best_default_route_get (priv->ip_config_4); + 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; } - } else if (priv->ip_config_6 && priv->ip6_state == IP_DONE) { - gw = nm_ip6_config_best_default_route_get (priv->ip_config_6); + } else if (priv->ip6_config && priv->ip6_state == IP_DONE) { + 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); @@ -11564,11 +10929,11 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) /* when the link comes up, we must restore IP configuration if necessary. */ if (priv->ip4_state == IP_DONE) { - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + if (!ip4_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after bringing link up"); } if (priv->ip6_state == IP_DONE) { - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if (!ip6_config_merge_and_apply (self, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after bringing link up"); } @@ -11633,37 +10998,122 @@ nm_device_get_firmware_missing (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->firmware_missing; } +static NMIP4Config * +find_ip4_lease_config (NMDevice *self, + NMConnection *connection, + NMIP4Config *ext_ip4_config) +{ + const char *ip_iface = nm_device_get_ip_iface (self); + int ip_ifindex = nm_device_get_ip_ifindex (self); + GSList *leases, *liter; + NMIP4Config *found = NULL; + + g_return_val_if_fail (NM_IS_IP4_CONFIG (ext_ip4_config), NULL); + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + leases = nm_dhcp_manager_get_lease_ip_configs (nm_dhcp_manager_get (), + nm_device_get_multi_index (self), + AF_INET, + ip_iface, + ip_ifindex, + nm_connection_get_uuid (connection), + nm_device_get_route_table (self, AF_INET, TRUE), + nm_device_get_route_metric (self, AF_INET)); + for (liter = leases; liter && !found; liter = liter->next) { + NMIP4Config *lease_config = liter->data; + const NMPlatformIP4Address *address = nm_ip4_config_get_first_address (lease_config); + const NMPObject *gw1, *gw2; + + g_assert (address); + if (!nm_ip4_config_address_exists (ext_ip4_config, address)) + continue; + 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) + continue; + found = g_object_ref (lease_config); + } + + g_slist_free_full (leases, g_object_unref); + return found; +} + static void -intersect_ext_config (NMDevice *self, AppliedConfig *config) +capture_lease_config (NMDevice *self, + NMIP4Config *ext_ip4_config, + NMIP4Config **out_ip4_config, + NMIP6Config *ext_ip6_config, + NMIP6Config **out_ip6_config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMIPConfig *ext; - guint32 penalty; - int family; + NMSettingsConnection *const*connections; + guint i; + gboolean dhcp_used = FALSE; + NMDedupMultiIter ipconf_iter; + + /* 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) { + const NMPlatformIP4Address *addr; + + nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ext_ip4_config, &addr) { + if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { + dhcp_used = TRUE; + break; + } + } + } else if (ext_ip6_config && out_ip6_config) { + const NMPlatformIP6Address *addr; + + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ext_ip6_config, &addr) { + 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)); + } - if (!config->orig) + if (!dhcp_used) return; - family = nm_ip_config_get_addr_family (config->orig); - penalty = default_route_metric_penalty_get (self, family); - ext = family == AF_INET - ? (NMIPConfig *) priv->ext_ip_config_4 - : (NMIPConfig *) priv->ext_ip_config_6; + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMConnection *candidate = (NMConnection *) connections[i]; + const char *method; + + if (!nm_device_check_connection_compatible (self, candidate)) + continue; - if (config->current) - nm_ip_config_intersect (config->current, ext, penalty); - else { - config->current = nm_ip_config_intersect_alloc (config->orig, - ext, - penalty); + /* 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) { + *out_ip4_config = find_ip4_lease_config (self, candidate, ext_ip4_config); + if (*out_ip4_config) + return; + } + + /* 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() */ + } } } static gboolean -update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_configs) +update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; + gboolean capture_resolv_conf; GSList *iter; nm_assert_addr_family (addr_family); @@ -11672,110 +11122,122 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config if (!ifindex) return FALSE; + capture_resolv_conf = initial + && nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ()); + if (addr_family == AF_INET) { - g_clear_object (&priv->ext_ip_config_4); - priv->ext_ip_config_4 = nm_ip4_config_capture (nm_device_get_multi_index (self), + 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); - if (priv->ext_ip_config_4) { + 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); + } + 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. */ - if (priv->con_ip_config_4) { - nm_ip4_config_intersect (priv->con_ip_config_4, priv->ext_ip_config_4, + 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)); } - - intersect_ext_config (self, &priv->dev_ip4_config); - intersect_ext_config (self, &priv->wwan_ip_config_4); - - for (iter = priv->vpn_configs_4; iter; iter = iter->next) - nm_ip4_config_intersect (iter->data, priv->ext_ip_config_4, 0); + 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)); + } + for (iter = priv->vpn4_configs; iter; iter = iter->next) + nm_ip4_config_intersect (iter->data, priv->ext_ip4_config, 0); } - /* Remove parts from ext_ip_config_4 to only contain the information that + /* Remove parts from ext_ip4_config to only contain the information that * was configured externally -- we already have the same configuration from * internal origins. */ - if (priv->con_ip_config_4) { - nm_ip4_config_subtract (priv->ext_ip_config_4, priv->con_ip_config_4, + 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 (applied_config_get_current (&priv->dev_ip4_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_4, - applied_config_get_current (&priv->dev_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 (applied_config_get_current (&priv->wwan_ip_config_4)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_4, - applied_config_get_current (&priv->wwan_ip_config_4), - 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)); } - for (iter = priv->vpn_configs_4; iter; iter = iter->next) - nm_ip4_config_subtract (priv->ext_ip_config_4, iter->data, 0); + for (iter = priv->vpn4_configs; iter; iter = iter->next) + nm_ip4_config_subtract (priv->ext_ip4_config, iter->data, 0); } } else { nm_assert (addr_family == AF_INET6); - g_clear_object (&priv->ext_ip_config_6); + 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_ip_config_6 = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); + priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); 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. */ - if (priv->con_ip_config_6) { - nm_ip6_config_intersect (priv->con_ip_config_6, priv->ext_ip_config_6, + 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)); } - - intersect_ext_config (self, &priv->ac_ip6_config); - intersect_ext_config (self, &priv->dhcp6.ip6_config); - intersect_ext_config (self, &priv->wwan_ip_config_6); - - for (iter = priv->vpn_configs_6; iter; iter = iter->next) - nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, 0); - - if ( priv->ipv6ll_has - && !nm_ip6_config_lookup_address (priv->ext_ip_config_6, &priv->ipv6ll_addr)) - priv->ipv6ll_has = FALSE; + 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)); + } + for (iter = priv->vpn6_configs; iter; iter = iter->next) + nm_ip6_config_intersect (iter->data, priv->ext_ip6_config, 0); } - /* Remove parts from ext_ip_config_6 to only contain the information that + /* Remove parts from ext_ip6_config to only contain the information that * was configured externally -- we already have the same configuration from * internal origins. */ - if (priv->con_ip_config_6) { - nm_ip6_config_subtract (priv->ext_ip_config_6, priv->con_ip_config_6, + 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 (applied_config_get_current (&priv->ac_ip6_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_6, - applied_config_get_current (&priv->ac_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 (applied_config_get_current (&priv->dhcp6.ip6_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_6, - applied_config_get_current (&priv->dhcp6.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 (applied_config_get_current (&priv->wwan_ip_config_6)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_6, - applied_config_get_current (&priv->wwan_ip_config_6), - 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)); } - for (iter = priv->vpn_configs_6; iter; iter = iter->next) - nm_ip6_config_subtract (priv->ext_ip_config_6, iter->data, 0); + for (iter = priv->vpn6_configs; iter; iter = iter->next) + nm_ip6_config_subtract (priv->ext_ip6_config, iter->data, 0); } } @@ -11783,139 +11245,156 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config } static void -update_ip_config (NMDevice *self, int addr_family) +update_ip_config (NMDevice *self, int addr_family, gboolean initial) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); nm_assert_addr_family (addr_family); - if (addr_family == AF_INET) - priv->update_ip_config_completed_v4 = TRUE; - else - priv->update_ip_config_completed_v6 = TRUE; - - if (update_ext_ip_config (self, addr_family, TRUE)) { + if (update_ext_ip_config (self, addr_family, initial, TRUE)) { if (addr_family == AF_INET) { - if (priv->ext_ip_config_4) - ip_config_merge_and_apply (self, AF_INET, FALSE); + if (priv->ext_ip4_config) + ip4_config_merge_and_apply (self, FALSE); } else { if (priv->ext_ip6_config_captured) - ip_config_merge_and_apply (self, AF_INET6, FALSE); + ip6_config_merge_and_apply (self, FALSE); } } + + if ( addr_family == AF_INET6 + && priv->linklocal6_timeout_id + && priv->ext_ip6_config_captured + && nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) { + /* 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); + } } void nm_device_capture_initial_config (NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (!priv->update_ip_config_completed_v4) - update_ip_config (self, AF_INET); - if (!priv->update_ip_config_completed_v6) - update_ip_config (self, AF_INET6); + update_ip_config (self, AF_INET, TRUE); + update_ip_config (self, AF_INET6, TRUE); } static gboolean -queued_ip_config_change (NMDevice *self, int addr_family) +queued_ip4_config_change (gpointer user_data) { + NMDevice *self = user_data; NMDevicePrivate *priv; - gboolean need_ipv6ll = FALSE; - const gboolean IS_IPv4 = (addr_family == AF_INET); - NMPlatform *platform; g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); priv = NM_DEVICE_GET_PRIVATE (self); - nm_assert (IS_IPv4 ? !priv->queued_ip4_config_pending : !priv->queued_ip6_config_pending); + nm_assert (!priv->queued_ip4_config_pending); /* Wait for any queued state changes */ if (priv->queued_state.id) - return G_SOURCE_CONTINUE; + return TRUE; - priv->queued_ip_config_id_x[IS_IPv4] = 0; + priv->queued_ip4_config_id = 0; /* 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, - IS_IPv4 - ? activate_stage5_ip4_config_result - : activate_stage5_ip6_config_commit, - addr_family)) { - if (IS_IPv4) { - priv->queued_ip4_config_pending = FALSE; - priv->queued_ip_config_id_4 = g_idle_add (queued_ip4_config_change, self); - } else { - priv->queued_ip6_config_pending = FALSE; - priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self); - } - _LOGT (LOGD_DEVICE, "IP%c update was postponed", - nm_utils_addr_family_to_char (addr_family)); - } else { - update_ip_config (self, addr_family); + 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); - if (!IS_IPv4) { - /* Check whether we need to complete waiting for link-local. - * We are also called from an idle handler, so no problem doing state transitions - * now. */ - linklocal6_check_complete (self); - } + set_unmanaged_external_down (self, TRUE); + + 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); } - if (!IS_IPv4) { - if ( priv->state < NM_DEVICE_STATE_DEACTIVATING - && (platform = nm_device_get_platform (self)) - && nm_platform_link_get (platform, priv->ifindex)) { - /* Handle DAD failures */ - while (priv->dad6_failed_addrs) { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformIP6Address *addr; + return FALSE; +} - obj = priv->dad6_failed_addrs->data; - priv->dad6_failed_addrs = g_slist_delete_link (priv->dad6_failed_addrs, priv->dad6_failed_addrs); +static gboolean +queued_ip6_config_change (gpointer user_data) +{ + NMDevice *self = user_data; + NMDevicePrivate *priv; + GSList *iter; + gboolean need_ipv6ll = FALSE; - if (!nm_ndisc_dad_addr_is_fail_candidate (platform, obj)) - continue; + g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); - addr = NMP_OBJECT_CAST_IP6_ADDRESS (obj); + priv = NM_DEVICE_GET_PRIVATE (self); - _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", - nm_platform_ip6_address_to_string (addr, NULL, 0)); + nm_assert (!priv->queued_ip4_config_pending); - if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) - need_ipv6ll = TRUE; - else if (priv->ndisc) - nm_ndisc_dad_failed (priv->ndisc, &addr->address); - } + /* Wait for any queued state changes */ + if (priv->queued_state.id) + return TRUE; - /* 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->ip_config_6 - && nm_ip6_config_get_num_addresses (priv->ip_config_6)) - need_ipv6ll = TRUE; + priv->queued_ip6_config_id = 0; - if (need_ipv6ll) - check_and_add_ipv6ll_addr (self); - } else { - g_slist_free_full (priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); - priv->dad6_failed_addrs = NULL; + /* 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); + + if (priv->state < NM_DEVICE_STATE_DEACTIVATING + && nm_platform_link_get (nm_device_get_platform (self), priv->ifindex)) { + /* Handle DAD failures */ + for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) { + NMPlatformIP6Address *addr = iter->data; + + if (addr->addr_source >= NM_IP_CONFIG_SOURCE_USER) + continue; + + _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", + nm_platform_ip6_address_to_string (addr, NULL, 0)); + + if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) + need_ipv6ll = TRUE; + else if (priv->ndisc) + nm_ndisc_dad_failed (priv->ndisc, &addr->address); } - /* Check if DAD is still pending */ - if ( priv->ip6_state == IP_CONF - && priv->dad6_ip6_config - && priv->ext_ip6_config_captured - && !nm_ip6_config_has_any_dad_pending (priv->ext_ip6_config_captured, - priv->dad6_ip6_config)) { + /* 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)) + need_ipv6ll = TRUE; + + if (need_ipv6ll) + check_and_add_ipv6ll_addr (self); + } + + g_slist_free_full (priv->dad6_failed_addrs, g_free); + priv->dad6_failed_addrs = NULL; + + /* 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); - _set_ip_state (self, addr_family, IP_DONE); + _set_ip_state (self, AF_INET6, IP_DONE); check_ip_state (self, FALSE, TRUE); if (priv->rt6_temporary_not_available) nm_device_activate_schedule_ip6_config_result (self); @@ -11924,40 +11403,21 @@ queued_ip_config_change (NMDevice *self, int addr_family) set_unmanaged_external_down (self, TRUE); - if (IS_IPv4) { - 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); - } - } - - return G_SOURCE_REMOVE; -} - -static gboolean -queued_ip4_config_change (gpointer user_data) -{ - return queued_ip_config_change (user_data, AF_INET); -} - -static gboolean -queued_ip6_config_change (gpointer user_data) -{ - return queued_ip_config_change (user_data, AF_INET6); + return FALSE; } static void device_ipx_changed (NMPlatform *platform, int obj_type_i, int ifindex, - gconstpointer platform_object, + gpointer platform_object, int change_type_i, NMDevice *self) { const NMPObjectType obj_type = obj_type_i; const NMPlatformSignalChangeType change_type = change_type_i; NMDevicePrivate *priv; - const NMPlatformIP6Address *addr; + NMPlatformIP6Address *addr; if (nm_device_get_ip_ifindex (self) != ifindex) return; @@ -11969,10 +11429,10 @@ device_ipx_changed (NMPlatform *platform, case NMP_OBJECT_TYPE_IP4_ROUTE: 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_ip_config_id_4)); - } else if (!priv->queued_ip_config_id_4) { + 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; - priv->queued_ip_config_id_4 = g_idle_add (queued_ip4_config_change, self); + priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); _LOGD (LOGD_DEVICE, "queued IP4 config change"); } break; @@ -11981,18 +11441,19 @@ device_ipx_changed (NMPlatform *platform, if ( priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING - && nm_ndisc_dad_addr_is_fail_candidate_event (change_type, addr)) { - priv->dad6_failed_addrs = g_slist_prepend (priv->dad6_failed_addrs, - (gpointer) nmp_object_ref (NMP_OBJECT_UP_CAST (addr))); + && ( (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))) { + priv->dad6_failed_addrs = g_slist_append (priv->dad6_failed_addrs, + g_memdup (addr, sizeof (NMPlatformIP6Address))); } /* fall through */ case NMP_OBJECT_TYPE_IP6_ROUTE: 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_ip_config_id_6)); - } else if (!priv->queued_ip_config_id_6) { + 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; - priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self); + priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); _LOGD (LOGD_DEVICE, "queued IP6 config change"); } break; @@ -12260,14 +11721,14 @@ _set_unmanaged_flags (NMDevice *self, if (priv->queued_ip4_config_pending) { priv->queued_ip4_config_pending = FALSE; - nm_assert_se (!nm_clear_g_source (&priv->queued_ip_config_id_4)); - priv->queued_ip_config_id_4 = g_idle_add (queued_ip4_config_change, self); + 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_ip_config_id_6)); - priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self); + 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); } if (!priv->pending_actions) { @@ -12533,7 +11994,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)), nm_setting_connection_get_zone (s_con_applied)) != 0) { - version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request.obj); + version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request); _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (unsigned long long) version_id); g_object_set (G_OBJECT (s_con_applied), @@ -12545,7 +12006,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) { - version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request.obj); + version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request); _LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (unsigned long long) version_id); g_object_set (G_OBJECT (s_con_applied), @@ -12601,27 +12062,13 @@ nm_device_update_metered (NMDevice *self) /* Try to guess a value using the metered flag in IP configuration */ if (value == NM_METERED_INVALID) { - if ( priv->ip_config_4 + if ( priv->ip4_config && priv->ip4_state == IP_DONE - && nm_ip4_config_get_metered (priv->ip_config_4)) - value = NM_METERED_GUESS_YES; - } - - /* Otherwise look at connection type. For Bluetooth, we look at the type of - * Bluetooth sharing: for PANU/DUN (where we are receiving internet from - * another device) we set GUESS_YES; for NAP (where we are sharing internet - * to another device) we set GUESS_NO. We ignore WiMAX here as it’s no - * longer supported by NetworkManager. */ - if ( value == NM_METERED_INVALID - && nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) { - - if (_nm_connection_get_setting_bluetooth_for_nap (connection)) { - /* NAP types are not metered, but other types are. */ - value = NM_METERED_GUESS_NO; - } else + && 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)) @@ -12712,7 +12159,7 @@ nm_device_check_connection_available (NMDevice *self, 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_ANY (i, j)) { + if (NM_FLAGS_HAS (i, j)) { k = i & ~j; nm_assert ( available_all[i] == available_all[k] || available_all[i]); @@ -12737,7 +12184,7 @@ available_connections_del_all (NMDevice *self) static gboolean available_connections_add (NMDevice *self, NMConnection *connection) { - return g_hash_table_add (self->_priv->available_connections, g_object_ref (connection)); + return nm_g_hash_table_add (self->_priv->available_connections, g_object_ref (connection)); } static gboolean @@ -12795,7 +12242,7 @@ nm_device_recheck_available_connections (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE(self); if (g_hash_table_size (priv->available_connections) > 0) { - prune_list = g_hash_table_new (nm_direct_hash, NULL); + 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); @@ -12904,19 +12351,19 @@ cp_connection_added_or_updated (NMDevice *self, NMConnection *connection) } static void -cp_connection_added (NMSettings *settings, NMConnection *connection, gpointer user_data) +cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { cp_connection_added_or_updated (user_data, connection); } static void -cp_connection_updated (NMSettings *settings, NMConnection *connection, gboolean by_user, gpointer user_data) +cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gboolean by_user, gpointer user_data) { cp_connection_added_or_updated (user_data, connection); } static void -cp_connection_removed (NMSettings *settings, NMConnection *connection, gpointer user_data) +cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { NMDevice *self = user_data; @@ -13098,8 +12545,8 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) queued_state_clear (self); - _cleanup_ip_pre (self, AF_INET, cleanup_type); - _cleanup_ip_pre (self, AF_INET6, cleanup_type); + _cleanup_ip4_pre (self, cleanup_type); + _cleanup_ip6_pre (self, cleanup_type); } static void @@ -13121,41 +12568,39 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ - nm_device_set_ip_config (self, AF_INET, NULL, TRUE, NULL); - nm_device_set_ip_config (self, AF_INET6, NULL, TRUE, NULL); + nm_device_set_ip4_config (self, NULL, TRUE, NULL); + nm_device_set_ip6_config (self, NULL, TRUE); g_clear_object (&priv->proxy_config); - g_clear_object (&priv->con_ip_config_4); - applied_config_clear (&priv->dev_ip4_config); - applied_config_clear (&priv->wwan_ip_config_4); - g_clear_object (&priv->ext_ip_config_4); - g_clear_object (&priv->ip_config_4); - g_clear_object (&priv->con_ip_config_6); - applied_config_clear (&priv->ac_ip6_config); - g_clear_object (&priv->ext_ip_config_6); + g_clear_object (&priv->con_ip4_config); + g_clear_object (&priv->dev_ip4_config); + g_clear_object (&priv->ext_ip4_config); + g_clear_object (&priv->wwan_ip4_config); + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->con_ip6_config); + g_clear_object (&priv->ac_ip6_config); + g_clear_object (&priv->ext_ip6_config); g_clear_object (&priv->ext_ip6_config_captured); - applied_config_clear (&priv->wwan_ip_config_6); - g_clear_object (&priv->ip_config_6); + g_clear_object (&priv->wwan_ip6_config); + g_clear_object (&priv->ip6_config); g_clear_object (&priv->dad6_ip6_config); - priv->ipv6ll_has = FALSE; - memset (&priv->ipv6ll_addr, 0, sizeof (priv->ipv6ll_addr)); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); - g_slist_free_full (priv->vpn_configs_4, g_object_unref); - priv->vpn_configs_4 = NULL; - g_slist_free_full (priv->vpn_configs_6, g_object_unref); - priv->vpn_configs_6 = NULL; + 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; - /* We no longer accept the delegations. nm_device_set_ip_config(NULL) + /* We no longer accept the delegations. nm_device_set_ip6_config(NULL) * above disables them. */ nm_assert (priv->needs_ip6_subnet == FALSE); - if (priv->act_request.obj) { - nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request.obj), AF_INET, FALSE); + if (priv->act_request) { + nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), AF_INET, FALSE); priv->master_ready_handled = FALSE; - nm_clear_g_signal_handler (priv->act_request.obj, &priv->master_ready_id); + nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id); act_request_set (self, NULL); } @@ -13177,7 +12622,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) * those are identified by ip_iface, not by iface (which might be a tty * or ATM device). */ - _set_ip_ifindex (self, 0, NULL); + nm_device_set_ip_iface (self, NULL); } /* @@ -13297,10 +12742,10 @@ find_dhcp4_address (NMDevice *self) const NMPlatformIP4Address *a; NMDedupMultiIter ipconf_iter; - if (!priv->ip_config_4) + if (!priv->ip4_config) return NULL; - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip_config_4, &a) { + nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip4_config, &a) { if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP) return g_strdup (nm_utils_inet4_ntop (a->address, NULL)); } @@ -13607,7 +13052,7 @@ _set_state_full (NMDevice *self, g_cancellable_cancel (priv->deactivating_cancellable); /* Cache the activation request for the dispatcher */ - req = nm_g_object_ref (priv->act_request.obj); + req = nm_g_object_ref (priv->act_request); if ( state > NM_DEVICE_STATE_UNMANAGED && state <= NM_DEVICE_STATE_ACTIVATED @@ -13715,8 +13160,8 @@ _set_state_full (NMDevice *self, /* Clean up any half-done IP operations if the device's layer2 * finds out it needs authentication during IP config. */ - _cleanup_ip_pre (self, AF_INET, CLEANUP_TYPE_DECONFIGURE); - _cleanup_ip_pre (self, AF_INET6, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); } break; default: @@ -13730,13 +13175,6 @@ _set_state_full (NMDevice *self, _notify (self, PROP_STATE); _notify (self, PROP_STATE_REASON); - nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self), - &interface_info_device, - &signal_info_state_changed, - "(uuu)", - (guint32) state, - (guint32) old_state, - (guint32) reason); g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) state, (guint) old_state, (guint) reason); /* Post-process the event after internal notification */ @@ -13887,7 +13325,7 @@ _set_state_full (NMDevice *self, if (ip_config_valid (old_state) && !ip_config_valid (state)) notify_ip_properties (self); - nm_device_check_connectivity_update_interval (self); + concheck_periodic_update (self); /* Dispose of the cached activation request */ if (req) @@ -14849,15 +14287,8 @@ nm_device_init (NMDevice *self) self->_priv = priv; - c_list_init (&priv->concheck_lst_head); - c_list_init (&self->devices_lst); c_list_init (&priv->slaves); - priv->connectivity_state = NM_CONNECTIVITY_UNKNOWN; - - nm_dbus_track_obj_path_init (&priv->parent_device, G_OBJECT (self), obj_properties[PROP_PARENT]); - nm_dbus_track_obj_path_init (&priv->act_request, G_OBJECT (self), obj_properties[PROP_ACTIVE_CONNECTION]); - priv->netns = g_object_ref (NM_NETNS_GET); priv->autoconnect_blocked_flags = DEFAULT_AUTOCONNECT @@ -14872,7 +14303,7 @@ nm_device_init (NMDevice *self) priv->rfkill_type = RFKILL_TYPE_UNKNOWN; priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT; priv->unmanaged_mask = priv->unmanaged_flags; - priv->available_connections = g_hash_table_new_full (nm_direct_hash, NULL, g_object_unref, NULL); + priv->available_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); priv->ip6_saved_properties = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_free); priv->sys_iface_state = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; @@ -14971,19 +14402,9 @@ dispose (GObject *object) NMDevice *self = NM_DEVICE (object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMPlatform *platform; - NMDeviceConnectivityHandle *con_handle; - gs_free_error GError *cancelled_error = NULL; _LOGD (LOGD_DEVICE, "disposing"); - nm_assert (c_list_is_empty (&self->devices_lst)); - - while ((con_handle = c_list_first_entry (&priv->concheck_lst_head, NMDeviceConnectivityHandle, concheck_lst))) { - if (!cancelled_error) - nm_utils_error_set_cancelled (&cancelled_error, FALSE, "NMDevice"); - concheck_handle_complete (con_handle, cancelled_error); - } - nm_clear_g_cancellable (&priv->deactivating_cancellable); nm_device_assume_state_reset (self); @@ -14994,8 +14415,8 @@ dispose (GObject *object) 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); - g_slist_free_full (priv->acd.dad_list, (GDestroyNotify) nm_acd_manager_destroy); - priv->acd.dad_list = NULL; + g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy); + priv->arping.dad_list = NULL; arp_cleanup (self); @@ -15057,8 +14478,6 @@ dispose (GObject *object) g_clear_object (&priv->lldp_listener); } - nm_clear_g_source (&priv->concheck_p_cur_id); - G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); if (nm_clear_g_source (&priv->queued_state.id)) { @@ -15081,7 +14500,7 @@ finalize (GObject *object) g_free (priv->hw_addr_perm); g_free (priv->hw_addr_initial); g_slist_free (priv->pending_actions); - g_slist_free_full (priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); + g_slist_free_full (priv->dad6_failed_addrs, g_free); g_clear_pointer (&priv->physical_port_id, g_free); g_free (priv->udi); g_free (priv->iface); @@ -15090,22 +14509,19 @@ finalize (GObject *object) g_free (priv->driver_version); g_free (priv->firmware_version); g_free (priv->type_desc); + g_free (priv->type_description); g_free (priv->dhcp_anycast_address); g_free (priv->current_stable_id); g_hash_table_unref (priv->ip6_saved_properties); g_hash_table_unref (priv->available_connections); - nm_dbus_track_obj_path_deinit (&priv->parent_device); - nm_dbus_track_obj_path_deinit (&priv->act_request); - G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); /* for testing, NMDeviceTest does not invoke NMDevice::constructed, * and thus @settings might be unset. */ - nm_g_object_unref (priv->settings); - - nm_g_object_unref (priv->concheck_mgr); + if (priv->settings) + g_object_unref (priv->settings); g_object_unref (priv->netns); } @@ -15215,6 +14631,9 @@ get_property (GObject *object, guint prop_id, { NMDevice *self = NM_DEVICE (object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + GPtrArray *array; + GHashTableIter iter; + NMConnection *connection; GVariantBuilder array_builder; switch (prop_id) { @@ -15270,16 +14689,16 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->mtu); break; case PROP_IP4_CONFIG: - nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip_config_4 : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip4_config : NULL); break; case PROP_DHCP4_CONFIG: - nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4.config : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4.config : NULL); break; case PROP_IP6_CONFIG: - nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip_config_6 : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip6_config : NULL); break; case PROP_DHCP6_CONFIG: - nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6.config : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6.config : NULL); break; case PROP_STATE: g_value_set_uint (value, priv->state); @@ -15289,7 +14708,7 @@ get_property (GObject *object, guint prop_id, g_variant_new ("(uu)", priv->state, priv->state_reason)); break; case PROP_ACTIVE_CONNECTION: - g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->act_request)); + nm_utils_g_value_set_object_path (value, priv->act_request_public ? priv->act_request : NULL); break; case PROP_DEVICE_TYPE: g_value_set_uint (value, priv->type); @@ -15320,9 +14739,12 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->rfkill_type); break; case PROP_AVAILABLE_CONNECTIONS: - nm_dbus_utils_g_value_set_object_path_from_hash (value, - priv->available_connections, - TRUE); + 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))); + g_ptr_array_add (array, NULL); + g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE)); break; case PROP_PHYSICAL_PORT_ID: g_value_set_string (value, priv->physical_port_id); @@ -15331,7 +14753,7 @@ get_property (GObject *object, guint prop_id, g_value_set_object (value, nm_device_get_master (self)); break; case PROP_PARENT: - g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->parent_device)); + nm_utils_g_value_set_object_path (value, priv->parent_device); break; case PROP_HW_ADDRESS: g_value_set_string (value, priv->hw_addr); @@ -15376,7 +14798,7 @@ get_property (GObject *object, guint prop_id, if (!NM_DEVICE_GET_PRIVATE (info->slave)->is_enslaved) continue; - path = nm_dbus_object_get_path (NM_DBUS_OBJECT (info->slave)); + path = nm_exported_object_get_path ((NMExportedObject *) info->slave); if (path) slave_list[i++] = g_strdup (path); } @@ -15403,115 +14825,15 @@ get_property (GObject *object, guint prop_id, } } -static const GDBusSignalInfo signal_info_state_changed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( - "StateChanged", - .args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("new_state", "u"), - NM_DEFINE_GDBUS_ARG_INFO ("old_state", "u"), - NM_DEFINE_GDBUS_ARG_INFO ("reason", "u"), - ), -); - -static const NMDBusInterfaceInfoExtended interface_info_device = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE, - .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "Reapply", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), - NM_DEFINE_GDBUS_ARG_INFO ("version_id", "t"), - NM_DEFINE_GDBUS_ARG_INFO ("flags", "u"), - ), - ), - .handle = impl_device_reapply, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetAppliedConnection", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("flags", "u"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), - NM_DEFINE_GDBUS_ARG_INFO ("version_id", "t"), - ), - ), - .handle = impl_device_get_applied_connection, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "Disconnect", - ), - .handle = impl_device_disconnect, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "Delete", - ), - .handle = impl_device_delete, - ), - ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &signal_info_state_changed, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Udi", "s", NM_DEVICE_UDI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Interface", "s", NM_DEVICE_IFACE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("IpInterface", "s", NM_DEVICE_IP_IFACE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Driver", "s", NM_DEVICE_DRIVER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("DriverVersion", "s", NM_DEVICE_DRIVER_VERSION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("FirmwareVersion", "s", NM_DEVICE_FIRMWARE_VERSION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Capabilities", "u", NM_DEVICE_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ip4Address", "u", NM_DEVICE_IP4_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("State", "u", NM_DEVICE_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("StateReason", "(uu)", NM_DEVICE_STATE_REASON), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ActiveConnection", "o", NM_DEVICE_ACTIVE_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ip4Config", "o", NM_DEVICE_IP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Dhcp4Config", "o", NM_DEVICE_DHCP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ip6Config", "o", NM_DEVICE_IP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Dhcp6Config", "o", NM_DEVICE_DHCP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("Managed", "b", NM_DEVICE_MANAGED, NM_AUTH_PERMISSION_NETWORK_CONTROL, NM_AUDIT_OP_DEVICE_MANAGED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("Autoconnect", "b", NM_DEVICE_AUTOCONNECT, NM_AUTH_PERMISSION_NETWORK_CONTROL, NM_AUDIT_OP_DEVICE_AUTOCONNECT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("FirmwareMissing", "b", NM_DEVICE_FIRMWARE_MISSING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("NmPluginMissing", "b", NM_DEVICE_NM_PLUGIN_MISSING), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("DeviceType", "u", NM_DEVICE_DEVICE_TYPE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("AvailableConnections", "ao", NM_DEVICE_AVAILABLE_CONNECTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PhysicalPortId", "s", NM_DEVICE_PHYSICAL_PORT_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mtu", "u", NM_DEVICE_MTU), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Metered", "u", NM_DEVICE_METERED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("LldpNeighbors", "aa{sv}", NM_DEVICE_LLDP_NEIGHBORS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Real", "b", NM_DEVICE_REAL), - ), - ), -}; - -const NMDBusInterfaceInfoExtended nm_interface_info_device_statistics = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_STATISTICS, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE ("RefreshRateMs", "u", NM_DEVICE_STATISTICS_REFRESH_RATE_MS, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, NM_AUDIT_OP_STATISTICS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("TxBytes", "t", NM_DEVICE_STATISTICS_TX_BYTES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("RxBytes", "t", NM_DEVICE_STATISTICS_RX_BYTES), - ), - ), -}; - static void nm_device_class_init (NMDeviceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (NMDevicePrivate)); - dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/Devices"); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device, - &nm_interface_info_device_statistics); + exported_object_class->export_path = NM_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/Devices"); object_class->dispose = dispose; object_class->finalize = finalize; @@ -15743,6 +15065,7 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /* Statistics */ obj_properties[PROP_REFRESH_RATE_MS] = g_param_spec_uint (NM_DEVICE_STATISTICS_REFRESH_RATE_MS, "", "", 0, UINT32_MAX, 0, @@ -15759,6 +15082,7 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /* Connectivity */ obj_properties[PROP_CONNECTIVITY] = g_param_spec_uint (NM_DEVICE_CONNECTIVITY, "", "", NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN, @@ -15841,11 +15165,15 @@ nm_device_class_init (NMDeviceClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - signals[CONNECTIVITY_CHANGED] = - g_signal_new (NM_DEVICE_CONNECTIVITY_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_SKELETON, + "Reapply", impl_device_reapply, + "GetAppliedConnection", impl_device_get_applied_connection, + "Disconnect", impl_device_disconnect, + "Delete", impl_device_delete, + NULL); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_STATISTICS_SKELETON, + NULL); } diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 66720f01..ac73ee0c 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -24,8 +24,7 @@ #include <netinet/in.h> -#include "nm-setting-connection.h" -#include "nm-dbus-object.h" +#include "nm-exported-object.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-rfkill-manager.h" @@ -114,7 +113,8 @@ nm_device_state_reason_check (NMDeviceStateReason reason) #define NM_DEVICE_PARENT "parent" /* the "slaves" property is internal in the parent class, but exposed - * by the derived classes NMDeviceBond, NMDeviceBridge and NMDeviceTeam. */ + * by the derived classes NMDeviceBond, NMDeviceBridge and NMDeviceTeam. + * It is thus important that the property name matches. */ #define NM_DEVICE_SLAVES "slaves" /* partially internal */ #define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ @@ -135,7 +135,6 @@ nm_device_state_reason_check (NMDeviceStateReason reason) #define NM_DEVICE_STATE_CHANGED "state-changed" #define NM_DEVICE_LINK_INITIALIZED "link-initialized" #define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed" -#define NM_DEVICE_CONNECTIVITY_CHANGED "connectivity-changed" #define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms" #define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes" @@ -173,9 +172,10 @@ typedef enum { /*< skip >*/ struct _NMDevicePrivate; struct _NMDevice { - NMDBusObject parent; + NMExportedObject parent; + + /* private */ struct _NMDevicePrivate *_priv; - CList devices_lst; }; /* The flags have an relaxing meaning, that means, specifying more flags, can make @@ -190,9 +190,7 @@ typedef enum { /*< skip >*/ } NMDeviceCheckDevAvailableFlags; typedef struct { - NMDBusObjectClass parent; - - const char *default_type_description; + NMExportedObjectClass parent; const char *connection_type; const NMLinkType *link_types; @@ -314,7 +312,7 @@ typedef struct { gboolean (* complete_connection) (NMDevice *self, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error); NMActStageReturn (* act_stage1_prepare) (NMDevice *self, @@ -522,7 +520,7 @@ gboolean nm_device_can_auto_connect (NMDevice *self, gboolean nm_device_complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connection, GError **error); gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection); @@ -756,10 +754,12 @@ void nm_device_update_firewall_zone (NMDevice *self); void nm_device_update_metered (NMDevice *self); void nm_device_reactivate_ip4_config (NMDevice *device, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new); + NMSettingIPConfig *s_ip4_new, + gboolean force_restart); void nm_device_reactivate_ip6_config (NMDevice *device, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new); + NMSettingIPConfig *s_ip6_new, + gboolean force_restart); gboolean nm_device_update_hw_address (NMDevice *self); void nm_device_update_initial_hw_address (NMDevice *self); @@ -776,22 +776,12 @@ gboolean nm_device_hw_addr_get_cloned (NMDevice *self, gboolean *preserve, GError **error); -typedef struct _NMDeviceConnectivityHandle NMDeviceConnectivityHandle; - typedef void (*NMDeviceConnectivityCallback) (NMDevice *self, - NMDeviceConnectivityHandle *handle, NMConnectivityState state, - GError *error, gpointer user_data); - -void nm_device_check_connectivity_update_interval (NMDevice *self); - -NMDeviceConnectivityHandle *nm_device_check_connectivity (NMDevice *self, - NMDeviceConnectivityCallback callback, - gpointer user_data); - -void nm_device_check_connectivity_cancel (NMDeviceConnectivityHandle *handle); - +void nm_device_check_connectivity (NMDevice *self, + NMDeviceConnectivityCallback callback, + gpointer user_data); NMConnectivityState nm_device_get_connectivity_state (NMDevice *self); typedef struct _NMBtVTableNetworkServer NMBtVTableNetworkServer; diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index f637825b..2ed2a7d9 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -286,21 +286,19 @@ lldp_neighbor_id_hash (gconstpointer ptr) } static int -lldp_neighbor_id_cmp (const LldpNeighbor *x, const LldpNeighbor *y) +lldp_neighbor_id_cmp (gconstpointer a, gconstpointer b) { - NM_CMP_SELF (x, y); - NM_CMP_FIELD (x, y, chassis_id_type); - NM_CMP_FIELD (x, y, port_id_type); - NM_CMP_FIELD_STR0 (x, y, chassis_id); - NM_CMP_FIELD_STR0 (x, y, port_id); - return 0; -} - -static int -lldp_neighbor_id_cmp_p (gconstpointer a, gconstpointer b, gpointer user_data) -{ - return lldp_neighbor_id_cmp (*((const LldpNeighbor *const*) a), - *((const LldpNeighbor *const*) b)); + const LldpNeighbor *x = a, *y = b; + int c; + + if (x->chassis_id_type != y->chassis_id_type) + return x->chassis_id_type < y->chassis_id_type ? -1 : 1; + if (x->port_id_type != y->port_id_type) + return x->port_id_type < y->port_id_type ? -1 : 1; + c = g_strcmp0 (x->chassis_id, y->chassis_id); + if (c == 0) + c = g_strcmp0 (x->port_id, y->port_id); + return c < 0 ? -1 : (c > 0 ? 1 : 0); } static gboolean @@ -840,23 +838,20 @@ GVariant * nm_lldp_listener_get_neighbors (NMLldpListener *self) { NMLldpListenerPrivate *priv; + GVariantBuilder array_builder; + GList *neighbors, *iter; g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - if (G_UNLIKELY (!priv->variant)) { - GVariantBuilder array_builder; - gs_free LldpNeighbor **neighbors = NULL; - guint i, n; - + if (!priv->variant) { g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); - neighbors = (LldpNeighbor **) nm_utils_hash_keys_to_array (priv->lldp_neighbors, - lldp_neighbor_id_cmp_p, - NULL, - &n); - for (i = 0; i < n; i++) - g_variant_builder_add_value (&array_builder, lldp_neighbor_to_variant (neighbors[i])); + neighbors = g_hash_table_get_keys (priv->lldp_neighbors); + neighbors = g_list_sort (neighbors, lldp_neighbor_id_cmp); + for (iter = neighbors; iter; iter = iter->next) + g_variant_builder_add_value (&array_builder, lldp_neighbor_to_variant (iter->data)); + g_list_free (neighbors); priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); } return priv->variant; diff --git a/src/devices/ovs/meson.build b/src/devices/ovs/meson.build deleted file mode 100644 index 7b1c4617..00000000 --- a/src/devices/ovs/meson.build +++ /dev/null @@ -1,38 +0,0 @@ -sources = files( - 'nm-device-ovs-bridge.c', - 'nm-device-ovs-interface.c', - 'nm-device-ovs-port.c', - 'nm-ovsdb.c', - 'nm-ovs-factory.c' -) - -deps = [ - jansson_dep, - nm_dep -] - -libnm_device_plugin_ovs = shared_module( - 'nm-device-plugin-ovs', - sources: sources, - dependencies: deps, - c_args: '-DRUNSTATEDIR="@0@"'.format(nm_runstatedir), - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_ovs - -run_target( - 'check-local-devices-ovs', - command: [check_exports, libnm_device_plugin_ovs.full_path(), linker_script_devices], - depends: libnm_device_plugin_ovs -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-ovs: src/devices/ovs/libnm-device-plugin-ovs.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/ovs/.libs/libnm-device-plugin-ovs.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/ovs/.libs/libnm-device-plugin-ovs.so) -''' diff --git a/src/devices/ovs/nm-device-ovs-bridge.c b/src/devices/ovs/nm-device-ovs-bridge.c index 5244ca8b..53ea2b82 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.c +++ b/src/devices/ovs/nm-device-ovs-bridge.c @@ -28,8 +28,10 @@ #include "nm-setting-connection.h" #include "nm-setting-ovs-bridge.h" +#include "introspection/org.freedesktop.NetworkManager.Device.OvsBridge.h" + #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF (NMDeviceOvsBridge); +_LOG_DECLARE_SELF(NMDeviceOvsBridge); /*****************************************************************************/ @@ -131,24 +133,11 @@ nm_device_ovs_bridge_init (NMDeviceOvsBridge *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_ovs_bridge = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_bridge); - device_class->connection_type = NM_SETTING_OVS_BRIDGE_SETTING_NAME; device_class->is_master = TRUE; device_class->get_type_description = get_type_description; @@ -160,4 +149,8 @@ nm_device_ovs_bridge_class_init (NMDeviceOvsBridgeClass *klass) device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; device_class->enslave_slave = enslave_slave; device_class->release_slave = release_slave; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_OVS_BRIDGE_SKELETON, + NULL); } diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index eefe38c8..ce32c2dd 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -28,6 +28,8 @@ #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-port.h" +#include "introspection/org.freedesktop.NetworkManager.Device.OvsInterface.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceOvsInterface); @@ -183,26 +185,13 @@ nm_device_ovs_interface_init (NMDeviceOvsInterface *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_ovs_interface = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_OPENVSWITCH); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_interface); - device_class->connection_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->get_type_description = get_type_description; device_class->create_and_realize = create_and_realize; @@ -213,4 +202,8 @@ nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass) device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; device_class->can_unmanaged_external_down = can_unmanaged_external_down; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_OVS_INTERFACE_SKELETON, + NULL); } diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c index 3f1fe974..cb0915af 100644 --- a/src/devices/ovs/nm-device-ovs-port.c +++ b/src/devices/ovs/nm-device-ovs-port.c @@ -28,8 +28,10 @@ #include "nm-setting-ovs-port.h" #include "nm-setting-ovs-port.h" +#include "introspection/org.freedesktop.NetworkManager.Device.OvsPort.h" + #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF (NMDeviceOvsPort); +_LOG_DECLARE_SELF(NMDeviceOvsPort); /*****************************************************************************/ @@ -178,24 +180,11 @@ nm_device_ovs_port_init (NMDeviceOvsPort *self) { } -static const NMDBusInterfaceInfoExtended interface_info_device_ovs_port = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OVS_PORT, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_ovs_port_class_init (NMDeviceOvsPortClass *klass) { - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ovs_port); - device_class->connection_type = NM_SETTING_OVS_PORT_SETTING_NAME; device_class->is_master = TRUE; device_class->get_type_description = get_type_description; @@ -206,4 +195,8 @@ nm_device_ovs_port_class_init (NMDeviceOvsPortClass *klass) device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; device_class->enslave_slave = enslave_slave; device_class->release_slave = release_slave; + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_OVS_PORT_SKELETON, + NULL); } diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index b8f5a935..92fcfa01 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -22,20 +22,37 @@ #include "nm-ovsdb.h" #include <string.h> +#include <jansson.h> #include <gmodule.h> #include <gio/gunixsocketaddress.h> -#include "nm-utils/nm-jansson.h" #include "devices/nm-device.h" #include "platform/nm-platform.h" #include "nm-core-internal.h" -/*****************************************************************************/ +/* Added in Jansson v2.4 (released Sep 23 2012), but travis.ci has v2.2. */ +#ifndef json_boolean +#define json_boolean(val) ((val) ? json_true() : json_false()) +#endif + +/* Added in Jansson v2.5 (released Sep 19 2013), but travis.ci has v2.2. */ +#ifndef json_array_foreach +#define json_array_foreach(array, index, value) \ + for (index = 0; \ + index < json_array_size(array) && (value = json_array_get(array, index)); \ + index++) +#endif -#if JANSSON_VERSION_HEX < 0x020400 -#warning "requires at least libjansson 2.4" +/* Added in Jansson v2.3 (released Jan 27 2012) */ +#ifndef json_object_foreach +#define json_object_foreach(object, key, value) \ + for(key = json_object_iter_key(json_object_iter(object)); \ + key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ + key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key)))) #endif +/*****************************************************************************/ + typedef struct { char *name; char *connection_uuid; @@ -78,7 +95,7 @@ typedef struct { GHashTable *interfaces; /* interface uuid => OpenvswitchInterface */ GHashTable *ports; /* port uuid => OpenvswitchPort */ GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */ - char *db_uuid; + const char *db_uuid; } NMOvsdbPrivate; struct _NMOvsdb { @@ -127,7 +144,7 @@ typedef struct { OvsdbMethodCallback callback; gpointer user_data; union { - char *ifname; + const char *ifname; struct { NMConnection *bridge; NMConnection *port; @@ -867,7 +884,7 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg) if (ovs) { iter = json_object_iter (ovs); - priv->db_uuid = iter ? g_strdup (json_object_iter_key (iter)) : NULL; + priv->db_uuid = g_strdup (iter ? json_object_iter_key (iter) : NULL); } /* Interfaces */ diff --git a/src/devices/team/meson.build b/src/devices/team/meson.build deleted file mode 100644 index 4a533bc5..00000000 --- a/src/devices/team/meson.build +++ /dev/null @@ -1,35 +0,0 @@ -sources = files( - 'nm-device-team.c', - 'nm-team-factory.c' -) - -deps = [ - jansson_dep, - libteamdctl_dep, - nm_dep -] - -libnm_device_plugin_team = shared_module( - 'nm-device-plugin-team', - sources: sources, - dependencies: deps, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_team - -run_target( - 'check-local-devices-team', - command: [check_exports, libnm_device_plugin_team.full_path(), linker_script_devices], - depends: libnm_device_plugin_team -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-team: src/devices/team/libnm-device-plugin-team.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/team/.libs/libnm-device-plugin-team.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/team/.libs/libnm-device-plugin-team.so) -''' diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index f83ba22b..098cd437 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -28,8 +28,8 @@ #include <sys/wait.h> #include <teamdctl.h> #include <stdlib.h> +#include <jansson.h> -#include "nm-utils/nm-jansson.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "platform/nm-platform.h" @@ -37,6 +37,8 @@ #include "nm-ip4-config.h" #include "nm-dbus-compat.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Team.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceTeam); @@ -104,7 +106,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingTeam *s_team; @@ -889,27 +891,10 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_team = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_TEAM, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Carrier", "b", NM_DEVICE_CARRIER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Slaves", "ao", NM_DEVICE_SLAVES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Config", "s", NM_DEVICE_TEAM_CONFIG), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_team_class_init (NMDeviceTeamClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_TEAM_SETTING_NAME, NM_LINK_TYPE_TEAM) @@ -918,8 +903,6 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) object_class->dispose = dispose; object_class->get_property = get_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_team); - parent_class->is_master = TRUE; parent_class->create_and_realize = create_and_realize; parent_class->get_generic_capabilities = get_generic_capabilities; @@ -941,4 +924,8 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_TEAM_SKELETON, + NULL); } diff --git a/src/devices/tests/meson.build b/src/devices/tests/meson.build deleted file mode 100644 index 02c61ced..00000000 --- a/src/devices/tests/meson.build +++ /dev/null @@ -1,18 +0,0 @@ -test_units = [ - 'test-acd', - 'test-lldp' -] - -foreach test_unit: test_units - exe = executable( - test_unit, - test_unit + '.c', - dependencies: test_nm_dep - ) - - test( - 'devices/' + test_unit, - test_script, - args: test_args + [exe.full_path()] - ) -endforeach diff --git a/src/devices/tests/test-acd.c b/src/devices/tests/test-arping.c index 8a2852a2..f0537545 100644 --- a/src/devices/tests/test-acd.c +++ b/src/devices/tests/test-arping.c @@ -20,7 +20,7 @@ #include "nm-default.h" -#include "devices/nm-acd-manager.h" +#include "devices/nm-arping-manager.h" #include "platform/tests/test-common.h" #define IFACE_VETH0 "nm-test-veth0" @@ -34,10 +34,6 @@ typedef struct { int ifindex0; int ifindex1; - const guint8 *hwaddr0; - const guint8 *hwaddr1; - size_t hwaddr0_len; - size_t hwaddr1_len; } test_fixture; static void @@ -49,9 +45,6 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0, NULL)); g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1, NULL)); - - fixture->hwaddr0 = nm_platform_link_get_address (NM_PLATFORM_GET, fixture->ifindex0, &fixture->hwaddr0_len); - fixture->hwaddr1 = nm_platform_link_get_address (NM_PLATFORM_GET, fixture->ifindex1, &fixture->hwaddr1_len); } typedef struct { @@ -61,21 +54,26 @@ typedef struct { } TestInfo; static void -acd_manager_probe_terminated (NMAcdManager *acd_manager, GMainLoop *loop) +arping_manager_probe_terminated (NMArpingManager *arping_manager, GMainLoop *loop) { g_main_loop_quit (loop); } static void -test_acd_common (test_fixture *fixture, TestInfo *info) +test_arping_common (test_fixture *fixture, TestInfo *info) { - gs_unref_object NMAcdManager *manager = NULL; + gs_unref_object NMArpingManager *manager = NULL; GMainLoop *loop; int i; const guint WAIT_TIME_OPTIMISTIC = 50; guint wait_time; gulong signal_id; + if (!nm_utils_find_helper ("arping", NULL, NULL)) { + g_test_skip ("arping binary is missing"); + return; + } + /* first, try with a short waittime. We hope that this is long enough * to successfully complete the test. Only if that's not the case, we * assume the computer is currently busy (high load) and we retry with @@ -83,11 +81,11 @@ test_acd_common (test_fixture *fixture, TestInfo *info) wait_time = WAIT_TIME_OPTIMISTIC; again: - manager = nm_acd_manager_new (fixture->ifindex0, fixture->hwaddr0, fixture->hwaddr0_len); + manager = nm_arping_manager_new (fixture->ifindex0); g_assert (manager != NULL); for (i = 0; info->addresses[i]; i++) - g_assert (nm_acd_manager_add_address (manager, info->addresses[i])); + g_assert (nm_arping_manager_add_address (manager, info->addresses[i])); for (i = 0; info->peer_addresses[i]; i++) { nmtstp_ip4_address_add (NULL, FALSE, fixture->ifindex1, info->peer_addresses[i], @@ -95,9 +93,9 @@ again: } loop = g_main_loop_new (NULL, FALSE); - signal_id = g_signal_connect (manager, NM_ACD_MANAGER_PROBE_TERMINATED, - G_CALLBACK (acd_manager_probe_terminated), loop); - g_assert (nm_acd_manager_start_probe (manager, wait_time)); + signal_id = g_signal_connect (manager, NM_ARPING_MANAGER_PROBE_TERMINATED, + G_CALLBACK (arping_manager_probe_terminated), loop); + g_assert (nm_arping_manager_start_probe (manager, wait_time, NULL)); g_assert (nmtst_main_loop_run (loop, 2000)); g_signal_handler_disconnect (manager, signal_id); g_main_loop_unref (loop); @@ -105,7 +103,7 @@ again: for (i = 0; info->addresses[i]; i++) { gboolean val; - val = nm_acd_manager_check_address (manager, info->addresses[i]); + val = nm_arping_manager_check_address (manager, info->addresses[i]); if (val == info->expected_result[i]) continue; @@ -124,41 +122,23 @@ again: } static void -test_acd_probe_1 (test_fixture *fixture, gconstpointer user_data) +test_arping_1 (test_fixture *fixture, gconstpointer user_data) { TestInfo info = { .addresses = { ADDR1, ADDR2, ADDR3 }, .peer_addresses = { ADDR4 }, .expected_result = { TRUE, TRUE, TRUE } }; - test_acd_common (fixture, &info); + test_arping_common (fixture, &info); } static void -test_acd_probe_2 (test_fixture *fixture, gconstpointer user_data) +test_arping_2 (test_fixture *fixture, gconstpointer user_data) { TestInfo info = { .addresses = { ADDR1, ADDR2, ADDR3, ADDR4 }, .peer_addresses = { ADDR3, ADDR2 }, .expected_result = { TRUE, FALSE, FALSE, TRUE } }; - test_acd_common (fixture, &info); -} - -static void -test_acd_announce (test_fixture *fixture, gconstpointer user_data) -{ - gs_unref_object NMAcdManager *manager = NULL; - GMainLoop *loop; - - manager = nm_acd_manager_new (fixture->ifindex0, fixture->hwaddr0, fixture->hwaddr0_len); - g_assert (manager != NULL); - - g_assert (nm_acd_manager_add_address (manager, ADDR1)); - g_assert (nm_acd_manager_add_address (manager, ADDR2)); - - loop = g_main_loop_new (NULL, FALSE); - nm_acd_manager_announce_addresses (manager); - g_assert (!nmtst_main_loop_run (loop, 200)); - g_main_loop_unref (loop); + test_arping_common (fixture, &info); } static void @@ -179,7 +159,6 @@ _nmtstp_init_tests (int *argc, char ***argv) void _nmtstp_setup_tests (void) { - g_test_add ("/acd/probe/1", test_fixture, NULL, fixture_setup, test_acd_probe_1, fixture_teardown); - g_test_add ("/acd/probe/2", test_fixture, NULL, fixture_setup, test_acd_probe_2, fixture_teardown); - g_test_add ("/acd/announce", test_fixture, NULL, fixture_setup, test_acd_announce, fixture_teardown); + g_test_add ("/arping/1", test_fixture, NULL, fixture_setup, test_arping_1, fixture_teardown); + g_test_add ("/arping/2", test_fixture, NULL, fixture_setup, test_arping_2, fixture_teardown); } diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 5d0625f8..c3c4f0d2 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -347,7 +347,8 @@ static void _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { const NMPlatformLink *link; - nm_auto_close int fd = -1; + struct ifreq ifr = { }; + int fd, s; fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); if (fd == -1) { @@ -356,45 +357,20 @@ _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) return; } - if (nmtst_get_rand_bool ()) { - const NMPlatformLnkTun lnk = { - .type = IFF_TAP, - .pi = FALSE, - .vnet_hdr = FALSE, - .multi_queue = FALSE, - .persist = FALSE, - }; - - nm_close (nm_steal_fd (&fd)); - - link = nmtstp_link_tun_add (NM_PLATFORM_GET, - FALSE, - TEST_IFNAME, - &lnk, - &fd); - g_assert (link); - nmtstp_link_set_updown (NM_PLATFORM_GET, -1, link->ifindex, TRUE); - link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 0); - } else { - int s; - struct ifreq ifr = { }; - - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); - g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); - - /* Bring the interface up */ - s = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - g_assert (s >= 0); - ifr.ifr_flags |= IFF_UP; - g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); - nm_close (s); - - link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 100); - } + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); + g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); + + /* Bring the interface up */ + s = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + g_assert (s >= 0); + ifr.ifr_flags |= IFF_UP; + g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); + nm_close (s); + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TAP, 100); fixture->ifindex = link->ifindex; - fixture->fd = nm_steal_fd (&fd); + fixture->fd = fd; memcpy (fixture->mac, link->addr.data, ETH_ALEN); } diff --git a/src/devices/wifi/meson.build b/src/devices/wifi/meson.build deleted file mode 100644 index 27eaeea6..00000000 --- a/src/devices/wifi/meson.build +++ /dev/null @@ -1,51 +0,0 @@ -common_sources = files( - 'nm-wifi-ap.c', - 'nm-wifi-utils.c' -) - -sources = common_sources + files( - 'nm-wifi-factory.c', - 'nm-wifi-common.c', - 'nm-device-wifi.c', - 'nm-device-olpc-mesh.c' -) - -if enable_iwd - sources += files( - 'nm-device-iwd.c', - 'nm-iwd-manager.c', - ) -endif - -deps = [ - nm_dep -] - -libnm_device_plugin_wifi = shared_module( - 'nm-device-plugin-wifi', - sources: sources, - dependencies: deps, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_wifi - -run_target( - 'check-local-devices-wifi', - command: [check_exports, libnm_device_plugin_wifi.full_path(), linker_script_devices], - depends: libnm_device_plugin_wifi -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-wifi: src/devices/wifi/libnm-device-plugin-wifi.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so) -''' - -if enable_tests - subdir('tests') -endif diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c deleted file mode 100644 index eeff5bd3..00000000 --- a/src/devices/wifi/nm-device-iwd.c +++ /dev/null @@ -1,1921 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * 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. - * - * Copyright (C) 2017 Intel Corporation - */ - -#include "nm-default.h" - -#include "nm-device-iwd.h" - -#include <string.h> - -#include "nm-common-macros.h" -#include "devices/nm-device.h" -#include "devices/nm-device-private.h" -#include "nm-utils.h" -#include "nm-act-request.h" -#include "nm-setting-connection.h" -#include "nm-setting-wireless.h" -#include "nm-setting-wireless-security.h" -#include "nm-setting-8021x.h" -#include "settings/nm-settings-connection.h" -#include "settings/nm-settings.h" -#include "nm-wifi-utils.h" -#include "nm-wifi-common.h" -#include "nm-core-internal.h" -#include "nm-config.h" -#include "nm-iwd-manager.h" -#include "nm-dbus-manager.h" - -#include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceIwd); - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceIwd, - PROP_MODE, - PROP_BITRATE, - PROP_ACCESS_POINTS, - PROP_ACTIVE_ACCESS_POINT, - PROP_CAPABILITIES, - PROP_SCANNING, -); - -enum { - SCANNING_PROHIBITED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct { - GDBusObject * dbus_obj; - GDBusProxy * dbus_proxy; - CList aps_lst_head; - NMWifiAP * current_ap; - GCancellable * cancellable; - NMDeviceWifiCapabilities capabilities; - NMActRequestGetSecretsCallId *wifi_secrets_id; - GDBusMethodInvocation *secrets_request; - guint periodic_scan_id; - bool enabled:1; - bool can_scan:1; - bool can_connect:1; - bool scanning:1; - bool scan_requested:1; -} NMDeviceIwdPrivate; - -struct _NMDeviceIwd { - NMDevice parent; - NMDeviceIwdPrivate _priv; -}; - -struct _NMDeviceIwdClass { - NMDeviceClass parent; - - /* Signals */ - gboolean (*scanning_prohibited) (NMDeviceIwd *device, gboolean periodic); -}; - -/*****************************************************************************/ - -G_DEFINE_TYPE (NMDeviceIwd, nm_device_iwd, NM_TYPE_DEVICE) - -#define NM_DEVICE_IWD_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDeviceIwd, NM_IS_DEVICE_IWD) - -/*****************************************************************************/ - -static void schedule_periodic_scan (NMDeviceIwd *self, - NMDeviceState current_state); - -/*****************************************************************************/ - -static void -_ap_dump (NMDeviceIwd *self, - NMLogLevel log_level, - const NMWifiAP *ap, - const char *prefix, - gint32 now_s) -{ - char buf[1024]; - - buf[0] = '\0'; - _NMLOG (log_level, LOGD_WIFI_SCAN, "wifi-ap: %-7s %s", - prefix, - nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s)); -} - -/* Callers ensure we're not removing current_ap */ -static void -ap_add_remove (NMDeviceIwd *self, - gboolean is_adding, /* or else is removing */ - NMWifiAP *ap, - gboolean recheck_available_connections) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - if (is_adding) { - g_object_ref (ap); - ap->wifi_device = NM_DEVICE (self); - c_list_link_tail (&priv->aps_lst_head, &ap->aps_lst); - nm_dbus_object_export (NM_DBUS_OBJECT (ap)); - _ap_dump (self, LOGL_DEBUG, ap, "added", 0); - nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, TRUE); - } else { - ap->wifi_device = NULL; - c_list_unlink (&ap->aps_lst); - _ap_dump (self, LOGL_DEBUG, ap, "removed", 0); - } - - _notify (self, PROP_ACCESS_POINTS); - - if (!is_adding) { - nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, FALSE); - nm_dbus_object_clear_and_unexport (&ap); - } - - nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); - if (recheck_available_connections) - nm_device_recheck_available_connections (NM_DEVICE (self)); -} - -static void -set_current_ap (NMDeviceIwd *self, NMWifiAP *new_ap, gboolean recheck_available_connections) -{ - NMDeviceIwdPrivate *priv; - NMWifiAP *old_ap; - - g_return_if_fail (NM_IS_DEVICE_IWD (self)); - - priv = NM_DEVICE_IWD_GET_PRIVATE (self); - old_ap = priv->current_ap; - - if (old_ap == new_ap) - return; - - if (new_ap) - priv->current_ap = g_object_ref (new_ap); - else - priv->current_ap = NULL; - - if (old_ap) { - if (nm_wifi_ap_get_fake (old_ap)) - ap_add_remove (self, FALSE, old_ap, recheck_available_connections); - g_object_unref (old_ap); - } - - _notify (self, PROP_ACTIVE_ACCESS_POINT); - _notify (self, PROP_MODE); -} - -static void -remove_all_aps (NMDeviceIwd *self) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMWifiAP *ap, *ap_safe; - - if (c_list_is_empty (&priv->aps_lst_head)) - return; - - set_current_ap (self, NULL, FALSE); - - c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) - ap_add_remove (self, FALSE, ap, FALSE); - - nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); - nm_device_recheck_available_connections (NM_DEVICE (self)); -} - -static GVariant * -vardict_from_network_type (const gchar *type) -{ - GVariantBuilder builder; - const gchar *key_mgmt = ""; - const gchar *pairwise = "ccmp"; - - if (!strcmp (type, "psk")) - key_mgmt = "wpa-psk"; - else if (!strcmp (type, "8021x")) - key_mgmt = "wpa-eap"; - else - return NULL; - - g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&builder, "{sv}", "KeyMgmt", - g_variant_new_strv (&key_mgmt, 1)); - g_variant_builder_add (&builder, "{sv}", "Pairwise", - g_variant_new_strv (&pairwise, 1)); - g_variant_builder_add (&builder, "{sv}", "Group", - g_variant_new_string ("ccmp")); - return g_variant_new ("a{sv}", &builder); -} - -static void -get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data) -{ - NMDeviceIwd *self = user_data; - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *variant = NULL; - GVariantIter *networks; - const gchar *path, *name, *type; - int16_t signal; - NMWifiAP *ap, *ap_safe; - gboolean changed = FALSE; - GHashTableIter ap_iter; - gs_unref_hashtable GHashTable *new_aps = NULL; - - variant = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, - G_VARIANT_TYPE ("(a(osns))"), - &error); - if (!variant) { - _LOGE (LOGD_WIFI, "Device.GetOrderedNetworks failed: %s", - error->message); - return; - } - - new_aps = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref); - - g_variant_get (variant, "(a(osns))", &networks); - - while (g_variant_iter_next (networks, "(&o&sn&s)", &path, &name, &signal, &type)) { - GVariantBuilder builder; - gs_unref_variant GVariant *props = NULL; - GVariant *rsn; - static uint32_t ap_id = 0; - uint8_t bssid[6]; - - /* - * What we get from IWD are networks, or ESSs, that may - * contain multiple APs, or BSSs, each. We don't get - * information about any specific BSSs within an ESS but - * we can safely present each ESS as an individual BSS to - * NM, which will be seen as ESSs comprising a single BSS - * each. NM won't be able to handle roaming but IWD already - * does that. We fake the BSSIDs as they don't play any - * role either. - */ - bssid[0] = 0x00; - bssid[1] = 0x01; - bssid[2] = 0x02; - bssid[3] = ap_id >> 16; - bssid[4] = ap_id >> 8; - bssid[5] = ap_id++; - - /* WEP not supported */ - if (!strcmp (type, "wep")) - continue; - - g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&builder, "{sv}", "BSSID", - g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, bssid, 6, 1)); - g_variant_builder_add (&builder, "{sv}", "Mode", - g_variant_new_string ("infrastructure")); - - rsn = vardict_from_network_type (type); - if (rsn) - g_variant_builder_add (&builder, "{sv}", "RSN", rsn); - - props = g_variant_new ("a{sv}", &builder); - - ap = nm_wifi_ap_new_from_properties (path, props); - if (name[0] != '\0') - nm_wifi_ap_set_ssid (ap, (const guint8 *) name, strlen (name)); - nm_wifi_ap_set_strength (ap, nm_wifi_utils_level_to_quality (signal / 100)); - nm_wifi_ap_set_freq (ap, 2417); - nm_wifi_ap_set_max_bitrate (ap, 65000); - g_hash_table_insert (new_aps, - (gpointer) nm_wifi_ap_get_supplicant_path (ap), - ap); - } - - g_variant_iter_free (networks); - - c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) { - - ap = g_hash_table_lookup (new_aps, - nm_wifi_ap_get_supplicant_path (ap)); - if (ap) { - if (nm_wifi_ap_set_strength (ap, nm_wifi_ap_get_strength (ap))) { - _ap_dump (self, LOGL_TRACE, ap, "updated", 0); - changed = TRUE; - } - g_hash_table_remove (new_aps, - nm_wifi_ap_get_supplicant_path (ap)); - continue; - } - - if (ap == priv->current_ap) { - /* Normally IWD will prevent the current AP from being - * removed from the list and set a low signal strength, - * but just making sure. - */ - continue; - } - - ap_add_remove (self, FALSE, ap, FALSE); - changed = TRUE; - } - - g_hash_table_iter_init (&ap_iter, new_aps); - while (g_hash_table_iter_next (&ap_iter, NULL, (gpointer) &ap)) { - ap_add_remove (self, TRUE, ap, FALSE); - g_hash_table_iter_remove (&ap_iter); - changed = TRUE; - } - - if (changed) { - nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); - nm_device_recheck_available_connections (NM_DEVICE (self)); - } -} - -static void -update_aps (NMDeviceIwd *self) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - if (!priv->cancellable) - priv->cancellable = g_cancellable_new (); - - g_dbus_proxy_call (priv->dbus_proxy, "GetOrderedNetworks", - g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, - 2000, priv->cancellable, - get_ordered_networks_cb, self); -} - -static void -send_disconnect (NMDeviceIwd *self) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - g_dbus_proxy_call (priv->dbus_proxy, "Disconnect", g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); -} - -static void -wifi_secrets_cancel (NMDeviceIwd *self) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - if (priv->wifi_secrets_id) - nm_act_request_cancel_secrets (NULL, priv->wifi_secrets_id); - nm_assert (!priv->wifi_secrets_id); - - if (priv->secrets_request) { - g_dbus_method_invocation_return_error_literal (priv->secrets_request, NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "NM secrets request cancelled"); - priv->secrets_request = NULL; - } - -} - -static void -cleanup_association_attempt (NMDeviceIwd *self, gboolean disconnect) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - wifi_secrets_cancel (self); - - set_current_ap (self, NULL, TRUE); - - if (disconnect && priv->dbus_obj) - send_disconnect (self); -} - -static void -deactivate (NMDevice *device) -{ - cleanup_association_attempt (NM_DEVICE_IWD (device), TRUE); -} - -static gboolean -deactivate_async_finish (NMDevice *device, GAsyncResult *res, GError **error) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (NM_DEVICE_IWD (device)); - gs_unref_variant GVariant *variant = NULL; - - variant = g_dbus_proxy_call_finish (priv->dbus_proxy, res, error); - return variant != NULL; -} - -typedef struct { - NMDeviceIwd *self; - GAsyncReadyCallback callback; - gpointer user_data; -} DeactivateContext; - -static void -disconnect_cb (GObject *source, GAsyncResult *res, gpointer user_data) -{ - DeactivateContext *ctx = user_data; - - ctx->callback (G_OBJECT (ctx->self), res, ctx->user_data); - - g_object_unref (ctx->self); - g_slice_free (DeactivateContext, ctx); -} - -static void -deactivate_async (NMDevice *device, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - DeactivateContext *ctx; - - ctx = g_slice_new0 (DeactivateContext); - ctx->self = g_object_ref (self); - ctx->callback = callback; - ctx->user_data = user_data; - - g_dbus_proxy_call (priv->dbus_proxy, "Disconnect", g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, -1, cancellable, disconnect_cb, ctx); -} - -static NMIwdNetworkSecurity -get_connection_iwd_security (NMConnection *connection) -{ - NMSettingWirelessSecurity *s_wireless_sec; - const char *key_mgmt = NULL; - - s_wireless_sec = nm_connection_get_setting_wireless_security (connection); - if (!s_wireless_sec) - return NM_IWD_NETWORK_SECURITY_NONE; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec); - nm_assert (key_mgmt); - - if (!strcmp (key_mgmt, "none") || !strcmp (key_mgmt, "ieee8021x")) - return NM_IWD_NETWORK_SECURITY_WEP; - - if (!strcmp (key_mgmt, "wpa-psk")) - return NM_IWD_NETWORK_SECURITY_PSK; - - nm_assert (!strcmp (key_mgmt, "wpa-eap")); - return NM_IWD_NETWORK_SECURITY_8021X; -} - -static gboolean -is_connection_known_network (NMConnection *connection) -{ - NMSettingWireless *s_wireless; - GBytes *ssid; - gs_free gchar *str_ssid = NULL; - - s_wireless = nm_connection_get_setting_wireless (connection); - if (!s_wireless) - return FALSE; - - ssid = nm_setting_wireless_get_ssid (s_wireless); - if (!ssid) - return FALSE; - - str_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), - g_bytes_get_size (ssid)); - - return nm_iwd_manager_is_known_network (nm_iwd_manager_get (), - str_ssid, - get_connection_iwd_security (connection)); -} - -static gboolean -check_connection_compatible (NMDevice *device, NMConnection *connection) -{ - NMSettingConnection *s_con; - NMSettingWireless *s_wireless; - const char *mac; - const char * const *mac_blacklist; - int i; - const char *mode; - const char *perm_hw_addr; - - if (!NM_DEVICE_CLASS (nm_device_iwd_parent_class)->check_connection_compatible (device, connection)) - return FALSE; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME)) - return FALSE; - - s_wireless = nm_connection_get_setting_wireless (connection); - if (!s_wireless) - return FALSE; - - perm_hw_addr = nm_device_get_permanent_hw_address (device); - mac = nm_setting_wireless_get_mac_address (s_wireless); - if (perm_hw_addr) { - if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1)) - return FALSE; - - /* Check for MAC address blacklist */ - mac_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless); - for (i = 0; mac_blacklist[i]; i++) { - if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) { - g_warn_if_reached (); - return FALSE; - } - - if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_hw_addr, -1)) - return FALSE; - } - } else if (mac) - return FALSE; - - mode = nm_setting_wireless_get_mode (s_wireless); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) - return FALSE; - - /* 8021x networks can only be used if they've been provisioned on the IWD side and - * thus are Known Networks. - */ - if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) { - if (!is_connection_known_network (connection)) - return FALSE; - } - - return TRUE; -} - -static gboolean -check_connection_available (NMDevice *device, - NMConnection *connection, - NMDeviceCheckConAvailableFlags flags, - const char *specific_object) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMSettingWireless *s_wifi; - const char *mode; - - s_wifi = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wifi, FALSE); - - /* Only Infrastrusture mode at this time */ - mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) - return FALSE; - - /* Hidden SSIDs not supported yet */ - if (nm_setting_wireless_get_hidden (s_wifi)) - return FALSE; - - /* 8021x networks can only be used if they've been provisioned on the IWD side and - * thus are Known Networks. - */ - if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) { - if (!is_connection_known_network (connection)) - return FALSE; - } - - /* a connection that is available for a certain @specific_object, MUST - * also be available in general (without @specific_object). */ - - if (specific_object) { - NMWifiAP *ap; - - ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); - return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE; - } - - if (NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP)) - return TRUE; - - /* Check at least one AP is compatible with this connection */ - return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - NMConnection *const*existing_connections, - GError **error) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMSettingWireless *s_wifi; - const char *setting_mac; - char *str_ssid = NULL; - NMWifiAP *ap; - const GByteArray *ssid = NULL; - GByteArray *tmp_ssid = NULL; - GBytes *setting_ssid = NULL; - const char *perm_hw_addr; - const char *mode; - - s_wifi = nm_connection_get_setting_wireless (connection); - - mode = s_wifi ? nm_setting_wireless_get_mode (s_wifi) : NULL; - - if (s_wifi && !nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_INFRA)) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "Only Infrastructure mode is supported."); - return FALSE; - } - - if (!specific_object) { - /* If not given a specific object, we need at minimum an SSID */ - if (!s_wifi) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting is required if no AP path was given."); - return FALSE; - } - - setting_ssid = nm_setting_wireless_get_ssid (s_wifi); - if (!setting_ssid || g_bytes_get_size (setting_ssid) == 0) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting with a valid SSID is required if no AP path was given."); - return FALSE; - } - - /* Find a compatible AP in the scan list */ - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); - if (!ap) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "No compatible AP in the scan list and hidden SSIDs not supported."); - return FALSE; - } - } else { - ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); - if (!ap) { - g_set_error (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, - "The access point %s was not in the scan list.", - specific_object); - return FALSE; - } - } - - /* Add a wifi setting if one doesn't exist yet */ - if (!s_wifi) { - s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wifi)); - } - - ssid = nm_wifi_ap_get_ssid (ap); - - if (ssid == NULL) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting with a valid SSID is required."); - return FALSE; - } - - if (!nm_wifi_ap_complete_connection (ap, - connection, - nm_wifi_utils_is_manf_default_ssid (ssid), - error)) { - if (tmp_ssid) - g_byte_array_unref (tmp_ssid); - return FALSE; - } - - str_ssid = nm_utils_ssid_to_utf8 (ssid->data, ssid->len); - - nm_utils_complete_generic (nm_device_get_platform (device), - connection, - NM_SETTING_WIRELESS_SETTING_NAME, - existing_connections, - str_ssid, - str_ssid, - NULL, - TRUE); - g_free (str_ssid); - if (tmp_ssid) - g_byte_array_unref (tmp_ssid); - - /* 8021x networks can only be used if they've been provisioned on the IWD side and - * thus are Known Networks. - */ - if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) { - if (!is_connection_known_network (connection)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "This 8021x network has not been provisioned on this machine"); - return FALSE; - } - } - - perm_hw_addr = nm_device_get_permanent_hw_address (device); - if (perm_hw_addr) { - setting_mac = nm_setting_wireless_get_mac_address (s_wifi); - if (setting_mac) { - /* Make sure the setting MAC (if any) matches the device's permanent MAC */ - if (!nm_utils_hwaddr_matches (setting_mac, -1, perm_hw_addr, -1)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - "connection does not match device"); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS); - return FALSE; - } - } else { - guint8 tmp[ETH_ALEN]; - - /* Lock the connection to this device by default if it uses a - * permanent MAC address (ie not a 'locally administered' one) - */ - nm_utils_hwaddr_aton (perm_hw_addr, tmp, ETH_ALEN); - if (!(tmp[0] & 0x02)) { - g_object_set (G_OBJECT (s_wifi), - NM_SETTING_WIRELESS_MAC_ADDRESS, perm_hw_addr, - NULL); - } - } - } - - return TRUE; -} - -static gboolean -is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - gs_unref_variant GVariant *value = NULL; - - if (!priv->enabled || !priv->dbus_obj) - return FALSE; - - value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "Powered"); - return g_variant_get_boolean (value); -} - -static gboolean -get_autoconnect_allowed (NMDevice *device) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (NM_DEVICE_IWD (device)); - - return is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE) - && priv->can_connect; -} - -static gboolean -can_auto_connect (NMDevice *device, - NMConnection *connection, - char **specific_object) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMSettingWireless *s_wifi; - NMWifiAP *ap; - const char *mode; - guint64 timestamp = 0; - - nm_assert (!specific_object || !*specific_object); - - if (!NM_DEVICE_CLASS (nm_device_iwd_parent_class)->can_auto_connect (device, connection, NULL)) - return FALSE; - - s_wifi = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wifi, FALSE); - - /* Only Infrastrusture mode */ - mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) - return FALSE; - - /* Don't autoconnect to networks that have been tried at least once - * but haven't been successful, since these are often accidental choices - * from the menu and the user may not know the password. - */ - if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) { - if (timestamp == 0) - return FALSE; - } - - /* 8021x networks can only be used if they've been provisioned on the IWD side and - * thus are Known Networks. - */ - if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) { - if (!is_connection_known_network (connection)) - return FALSE; - } - - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); - if (ap) { - /* All good; connection is usable */ - NM_SET_OUT (specific_object, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)))); - return TRUE; - } - - return FALSE; -} - -const CList * -_nm_device_iwd_get_aps (NMDeviceIwd *self) -{ - return &NM_DEVICE_IWD_GET_PRIVATE (self)->aps_lst_head; -} - -static gboolean -check_scanning_prohibited (NMDeviceIwd *self, gboolean periodic) -{ - gboolean prohibited = FALSE; - - g_signal_emit (self, signals[SCANNING_PROHIBITED], 0, periodic, &prohibited); - return prohibited; -} - -static void -scan_cb (GObject *source, GAsyncResult *res, gpointer user_data) -{ - NMDeviceIwd *self = user_data; - NMDeviceIwdPrivate *priv; - gs_free_error GError *error = NULL; - - if ( !_nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, - G_VARIANT_TYPE ("()"), &error) - && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - priv = NM_DEVICE_IWD_GET_PRIVATE (self); - priv->scan_requested = FALSE; - - /* On success, priv->scanning becomes true right before or right - * after this callback, so the next automatic scan will be - * scheduled when priv->scanning goes back to false. On error, - * schedule a retry now. - */ - if (error && !priv->scanning) { - NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); - - schedule_periodic_scan (self, state); - } -} - -static void -dbus_request_scan_cb (NMDevice *device, - GDBusMethodInvocation *context, - NMAuthSubject *subject, - GError *error, - gpointer user_data) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv; - gs_unref_variant GVariant *scan_options = user_data; - - if (error) { - g_dbus_method_invocation_return_gerror (context, error); - return; - } - - if (check_scanning_prohibited (self, FALSE)) { - g_dbus_method_invocation_return_error_literal (context, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed at this time"); - return; - } - - priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - if ( !priv->enabled - || !priv->dbus_obj - || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED - || nm_device_is_activating (device)) { - g_dbus_method_invocation_return_error_literal (context, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed while unavailable"); - return; - } - - if (scan_options) { - gs_unref_variant GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL); - - if (val) { - g_dbus_method_invocation_return_error_literal (context, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "'ssid' scan option not supported"); - return; - } - } - - if (!priv->scanning && !priv->scan_requested) { - g_dbus_proxy_call (priv->dbus_proxy, "Scan", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, -1, - priv->cancellable, scan_cb, self); - priv->scan_requested = TRUE; - } - - g_dbus_method_invocation_return_value (context, NULL); -} - -void -_nm_device_iwd_request_scan (NMDeviceIwd *self, - GVariant *options, - GDBusMethodInvocation *invocation) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - - if ( !priv->enabled - || !priv->dbus_obj - || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED - || nm_device_is_activating (device)) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed while unavailable"); - return; - } - - g_signal_emit_by_name (device, - NM_DEVICE_AUTH_REQUEST, - invocation, - NULL, - NM_AUTH_PERMISSION_NETWORK_CONTROL, - TRUE, - dbus_request_scan_cb, - options ? g_variant_ref (options) : NULL); -} - -static gboolean -scanning_prohibited (NMDeviceIwd *self, gboolean periodic) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - g_return_val_if_fail (priv->dbus_obj != NULL, TRUE); - - switch (nm_device_get_state (NM_DEVICE (self))) { - case NM_DEVICE_STATE_UNKNOWN: - case NM_DEVICE_STATE_UNMANAGED: - case NM_DEVICE_STATE_UNAVAILABLE: - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_DEACTIVATING: - /* Prohibit scans when unusable or activating */ - return TRUE; - case NM_DEVICE_STATE_DISCONNECTED: - case NM_DEVICE_STATE_FAILED: - /* Can always scan when disconnected */ - return FALSE; - case NM_DEVICE_STATE_ACTIVATED: - break; - } - - /* Prohibit scans if IWD is busy */ - return !priv->can_scan; -} - -static void -wifi_secrets_cb (NMActRequest *req, - NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection *s_connection, - GError *error, - gpointer user_data) -{ - NMDevice *device = user_data; - NMDeviceIwd *self = user_data; - NMDeviceIwdPrivate *priv; - NMSettingWirelessSecurity *s_wireless_sec; - const gchar *psk; - - g_return_if_fail (NM_IS_DEVICE_IWD (self)); - g_return_if_fail (NM_IS_ACT_REQUEST (req)); - - priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - g_return_if_fail (priv->wifi_secrets_id == call_id); - - priv->wifi_secrets_id = NULL; - - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - g_return_if_fail (priv->secrets_request); - g_return_if_fail (req == nm_device_get_act_request (device)); - g_return_if_fail (nm_act_request_get_settings_connection (req) == s_connection); - - if (nm_device_get_state (device) != NM_DEVICE_STATE_NEED_AUTH) - goto secrets_error; - - if (error) { - _LOGW (LOGD_WIFI, "%s", error->message); - goto secrets_error; - } - - s_wireless_sec = nm_connection_get_setting_wireless_security (nm_act_request_get_applied_connection (req)); - if (!s_wireless_sec) - goto secrets_error; - - psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - if (!psk) - goto secrets_error; - - _LOGD (LOGD_DEVICE | LOGD_WIFI, - "Returning a new PSK to the IWD Agent"); - - g_dbus_method_invocation_return_value (priv->secrets_request, - g_variant_new ("(s)", psk)); - priv->secrets_request = NULL; - - /* Change state back to what it was before NEED_AUTH */ - nm_device_state_changed (device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); - return; - -secrets_error: - if (priv->secrets_request) { - g_dbus_method_invocation_return_error_literal (priv->secrets_request, NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "NM secrets request failed"); - priv->secrets_request = NULL; - } - - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - - cleanup_association_attempt (self, TRUE); -} - -static void -wifi_secrets_get_secrets (NMDeviceIwd *self, - const char *setting_name, - NMSecretAgentGetSecretsFlags flags) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMActRequest *req; - - wifi_secrets_cancel (self); - - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_if_fail (NM_IS_ACT_REQUEST (req)); - - priv->wifi_secrets_id = nm_act_request_get_secrets (req, - TRUE, - setting_name, - flags, - NULL, - wifi_secrets_cb, - self); -} - -static void -network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data) -{ - NMDeviceIwd *self = user_data; - NMDevice *device = NM_DEVICE (self); - gs_free_error GError *error = NULL; - NMConnection *connection; - NMSettingWireless *s_wifi; - GBytes *ssid; - gs_free gchar *str_ssid = NULL; - - if (!_nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, - G_VARIANT_TYPE ("()"), - &error)) { - gs_free gchar *dbus_error = NULL; - - /* Connection failed; radio problems or if the network wasn't - * open, the passwords or certificates may be wrong. - */ - - _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) Network.Connect failed: %s", - error->message); - - connection = nm_device_get_applied_connection (device); - if (!connection) - goto failed; - - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) - dbus_error = g_dbus_error_get_remote_error (error); - - /* If secrets were wrong, we'd be getting a net.connman.iwd.Failed */ - if (nm_streq0 (dbus_error, "net.connman.iwd.Failed")) { - nm_connection_clear_secrets (connection); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); - } else if ( !nm_utils_error_is_cancelled (error, TRUE) - && nm_device_is_activating (device)) - goto failed; - - /* Call Disconnect to make sure IWD's autoconnect is disabled */ - cleanup_association_attempt (self, TRUE); - - return; - } - - nm_assert (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG); - - connection = nm_device_get_applied_connection (device); - if (!connection) - goto failed; - - s_wifi = nm_connection_get_setting_wireless (connection); - if (!s_wifi) - goto failed; - - ssid = nm_setting_wireless_get_ssid (s_wifi); - if (!ssid) - goto failed; - - str_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), - g_bytes_get_size (ssid)); - - _LOGI (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Connected to '%s'.", - str_ssid); - nm_device_activate_schedule_stage3_ip_config_start (device); - - nm_iwd_manager_network_connected (nm_iwd_manager_get (), str_ssid, - get_connection_iwd_security (connection)); - - return; - -failed: - cleanup_association_attempt (self, FALSE); - nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); -} - -static void -set_powered (NMDeviceIwd *self, gboolean powered) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - g_dbus_proxy_call (priv->dbus_proxy, - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", NM_IWD_DEVICE_INTERFACE, - "Powered", - g_variant_new ("b", powered)), - G_DBUS_CALL_FLAGS_NONE, 2000, - NULL, NULL, NULL); -} - -/*****************************************************************************/ - -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMActStageReturn ret; - NMWifiAP *ap = NULL; - NMActRequest *req; - NMConnection *connection; - NMSettingWireless *s_wireless; - const char *ap_path; - - ret = NM_DEVICE_CLASS (nm_device_iwd_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - req = nm_device_get_act_request (device); - g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); - g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); - - s_wireless = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wireless, NM_ACT_STAGE_RETURN_FAILURE); - - ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL; - if (!ap) { - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); - - /* TODO: assuming hidden networks aren't supported do we need - * to consider the case of APs that are not in the scan list - * yet, for which nm-device-wifi.c creates the temporary fake - * AP object? - */ - - nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); - } - - set_current_ap (self, ap, FALSE); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMActRequest *req; - NMWifiAP *ap; - NMConnection *connection; - GError *error = NULL; - GDBusProxy *network_proxy; - - req = nm_device_get_act_request (device); - g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); - - ap = priv->current_ap; - if (!ap) { - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - goto out; - } - - connection = nm_act_request_get_applied_connection (req); - g_assert (connection); - - /* 802.1x networks that are not IWD Known Networks will definitely - * fail, for other combinations we will let the Connect call fail - * or ask us for any missing secrets through the Agent. - */ - if ( !is_connection_known_network (connection) - && nm_connection_get_setting_802_1x (connection)) { - _LOGI (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) access point '%s' has 802.1x security, but is not configured.", - nm_connection_get_id (connection)); - - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS); - ret = NM_ACT_STAGE_RETURN_FAILURE; - goto out; - } - - /* Locate the IWD Network object */ - network_proxy = g_dbus_proxy_new_for_bus_sync (NM_IWD_BUS_TYPE, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - NM_IWD_SERVICE, - nm_wifi_ap_get_supplicant_path (ap), - NM_IWD_NETWORK_INTERFACE, - NULL, &error); - if (!network_proxy) { - _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) could not get Network interface proxy for %s: %s", - nm_wifi_ap_get_supplicant_path (ap), - error->message); - g_clear_error (&error); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - goto out; - } - - if (!priv->cancellable) - priv->cancellable = g_cancellable_new (); - - /* Call Network.Connect. No timeout because IWD already handles - * timeouts. - */ - g_dbus_proxy_call (network_proxy, "Connect", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, G_MAXINT, - priv->cancellable, network_connect_cb, self); - - g_object_unref (network_proxy); - - /* We'll get stage3 started when the supplicant connects */ - ret = NM_ACT_STAGE_RETURN_POSTPONE; - -out: - if (ret == NM_ACT_STAGE_RETURN_FAILURE) - cleanup_association_attempt (self, FALSE); - - return ret; -} - -static guint32 -get_configured_mtu (NMDevice *device, gboolean *out_is_user_config) -{ - NMSettingWireless *setting; - gint64 mtu_default; - guint32 mtu; - - nm_assert (NM_IS_DEVICE (device)); - nm_assert (out_is_user_config); - - setting = NM_SETTING_WIRELESS (nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRELESS)); - if (!setting) - g_return_val_if_reached (0); - - mtu = nm_setting_wireless_get_mtu (setting); - if (mtu == 0) { - mtu_default = nm_device_get_configured_mtu_from_connection_default (device, "wifi.mtu"); - if (mtu_default >= 0) { - *out_is_user_config = TRUE; - return (guint32) mtu_default; - } - } - *out_is_user_config = (mtu != 0); - return mtu; -} - -static gboolean -periodic_scan_timeout_cb (gpointer user_data) -{ - NMDeviceIwd *self = user_data; - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - priv->periodic_scan_id = 0; - - if (priv->scanning || priv->scan_requested) - return FALSE; - - g_dbus_proxy_call (priv->dbus_proxy, "Scan", g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, -1, - priv->cancellable, scan_cb, self); - priv->scan_requested = TRUE; - - return FALSE; -} - -static void -schedule_periodic_scan (NMDeviceIwd *self, NMDeviceState current_state) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - guint interval; - - if (current_state <= NM_DEVICE_STATE_UNAVAILABLE) - return; - - if (current_state == NM_DEVICE_STATE_DISCONNECTED) - interval = 10; - else - interval = 20; - - nm_clear_g_source (&priv->periodic_scan_id); - priv->periodic_scan_id = g_timeout_add_seconds (interval, - periodic_scan_timeout_cb, - self); -} - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { - remove_all_aps (self); - nm_clear_g_source (&priv->periodic_scan_id); - } else if (old_state <= NM_DEVICE_STATE_UNAVAILABLE) { - update_aps (self); - schedule_periodic_scan (self, new_state); - } - - switch (new_state) { - case NM_DEVICE_STATE_UNMANAGED: - break; - case NM_DEVICE_STATE_UNAVAILABLE: - /* - * If the device is enabled and the IWD manager is ready, - * transition to DISCONNECTED because the device is now - * ready to use. - */ - if (priv->enabled && priv->dbus_obj) { - nm_device_queue_recheck_available (device, - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - break; - case NM_DEVICE_STATE_NEED_AUTH: - break; - case NM_DEVICE_STATE_IP_CHECK: - break; - case NM_DEVICE_STATE_ACTIVATED: - break; - case NM_DEVICE_STATE_FAILED: - break; - case NM_DEVICE_STATE_DISCONNECTED: - break; - default: - break; - } -} - -static gboolean -get_enabled (NMDevice *device) -{ - return NM_DEVICE_IWD_GET_PRIVATE ((NMDeviceIwd *) device)->enabled; -} - -static void -set_enabled (NMDevice *device, gboolean enabled) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMDeviceState state; - - enabled = !!enabled; - - if (priv->enabled == enabled) - return; - - priv->enabled = enabled; - - _LOGD (LOGD_WIFI, "device now %s", enabled ? "enabled" : "disabled"); - - state = nm_device_get_state (device); - if (state < NM_DEVICE_STATE_UNAVAILABLE) { - _LOGD (LOGD_WIFI, "(%s): device blocked by UNMANAGED state", - enabled ? "enable" : "disable"); - return; - } - - if (priv->dbus_proxy) - set_powered (self, enabled); - - if (enabled) { - if (state != NM_DEVICE_STATE_UNAVAILABLE) - _LOGW (LOGD_CORE, "not in expected unavailable state!"); - - if (priv->dbus_obj) - nm_device_queue_recheck_available (device, - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } else { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NONE); - } -} - -static gboolean -can_reapply_change (NMDevice *device, - const char *setting_name, - NMSetting *s_old, - NMSetting *s_new, - GHashTable *diffs, - GError **error) -{ - NMDeviceClass *device_class; - - /* Only handle wireless setting here, delegate other settings to parent class */ - if (nm_streq (setting_name, NM_SETTING_WIRELESS_SETTING_NAME)) { - return nm_device_hash_check_invalid_keys (diffs, - NM_SETTING_WIRELESS_SETTING_NAME, - error, - NM_SETTING_WIRELESS_MTU); /* reapplied with IP config */ - } - - device_class = NM_DEVICE_CLASS (nm_device_iwd_parent_class); - return device_class->can_reapply_change (device, - setting_name, - s_old, - s_new, - diffs, - error); -} - -/*****************************************************************************/ - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (object); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - const char **list; - - switch (prop_id) { - case PROP_MODE: - if (priv->current_ap) - g_value_set_uint (value, NM_802_11_MODE_INFRA); - else - g_value_set_uint (value, NM_802_11_MODE_UNKNOWN); - break; - case PROP_BITRATE: - g_value_set_uint (value, 65000); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_ACCESS_POINTS: - list = nm_wifi_aps_get_paths (&priv->aps_lst_head, TRUE); - g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list)); - break; - case PROP_ACTIVE_ACCESS_POINT: - nm_dbus_utils_g_value_set_object_path (value, priv->current_ap); - break; - case PROP_SCANNING: - g_value_set_boolean (value, priv->scanning); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMDeviceIwd *device = NM_DEVICE_IWD (object); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (device); - - switch (prop_id) { - case PROP_CAPABILITIES: - /* construct-only */ - priv->capabilities = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -state_changed (NMDeviceIwd *self, const gchar *new_state) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMDevice *device = NM_DEVICE (self); - NMDeviceState dev_state = nm_device_get_state (device); - gboolean iwd_connection = FALSE; - gboolean can_connect; - - _LOGI (LOGD_DEVICE | LOGD_WIFI, "new IWD device state is %s", new_state); - - if ( dev_state >= NM_DEVICE_STATE_CONFIG - && dev_state <= NM_DEVICE_STATE_ACTIVATED) - iwd_connection = TRUE; - - /* Don't allow scanning while connecting, disconnecting or roaming */ - priv->can_scan = NM_IN_STRSET (new_state, "connected", "disconnected"); - - /* Don't allow new connection until iwd exits disconnecting */ - can_connect = NM_IN_STRSET (new_state, "disconnected"); - if (can_connect != priv->can_connect) { - priv->can_connect = can_connect; - nm_device_emit_recheck_auto_activate (device); - } - - if (NM_IN_STRSET (new_state, "connecting", "connected", "roaming")) { - /* If we were connecting, do nothing, the confirmation of - * a connection success is handled in the Device.Connect - * method return callback. Otherwise IWD must have connected - * without Network Manager's will so for simplicity force a - * disconnect. - */ - if (iwd_connection) - return; - - _LOGW (LOGD_DEVICE | LOGD_WIFI, - "Unsolicited connection success, asking IWD to disconnect"); - send_disconnect (self); - - return; - } else if (NM_IN_STRSET (new_state, "disconnecting", "disconnected")) { - if (!iwd_connection) - return; - - /* Call Disconnect on the IWD device object to make sure it - * disables its own autoconnect. - * - * Note we could instead call net.connman.iwd.KnownNetworks.ForgetNetwork - * and leave the device in autoconnect. This way if NetworkManager - * changes any settings for this connection, they'd be taken into - * account on the next connection attempt. But both methods are - * a hack, we'll perhaps need an IWD API to "connect once" without - * storing anything. - */ - send_disconnect (self); - - /* - * If IWD is still handling the Connect call, let our callback - * for the dbus method handle the failure. - */ - if (dev_state == NM_DEVICE_STATE_CONFIG) - return; - - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - - return; - } - - _LOGE (LOGD_WIFI, "State %s unknown", new_state); -} - -static void -scanning_changed (NMDeviceIwd *self, gboolean new_scanning) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); - - if (new_scanning == priv->scanning) - return; - - priv->scanning = new_scanning; - - _notify (self, PROP_SCANNING); - - if (!priv->scanning) { - update_aps (self); - - if (!priv->scan_requested) - schedule_periodic_scan (self, state); - } -} - -static void -powered_changed (NMDeviceIwd *self, gboolean new_powered) -{ - nm_device_queue_recheck_available (NM_DEVICE (self), - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); -} - -static void -properties_changed (GDBusProxy *proxy, GVariant *changed_properties, - GStrv invalidate_properties, gpointer user_data) -{ - NMDeviceIwd *self = user_data; - GVariantIter *iter; - const gchar *key; - GVariant *value; - - g_variant_get (changed_properties, "a{sv}", &iter); - while (g_variant_iter_next (iter, "{&sv}", &key, &value)) { - if (!strcmp (key, "State")) - state_changed (self, g_variant_get_string (value, NULL)); - - if (!strcmp (key, "Scanning")) - scanning_changed (self, g_variant_get_boolean (value)); - - if (!strcmp (key, "Powered")) - powered_changed (self, g_variant_get_boolean (value)); - - g_variant_unref (value); - } - - g_variant_iter_free (iter); -} - -void -nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - GDBusInterface *interface; - GVariant *value; - - if (!nm_g_object_ref_set ((GObject **) &priv->dbus_obj, (GObject *) object)) - return; - - if (priv->dbus_proxy) { - g_signal_handlers_disconnect_by_func (priv->dbus_proxy, - properties_changed, self); - - g_clear_object (&priv->dbus_proxy); - } - - if (priv->enabled) - nm_device_queue_recheck_available (NM_DEVICE (self), - NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - - if (!object) { - priv->can_scan = FALSE; - - cleanup_association_attempt (self, FALSE); - return; - } - - interface = g_dbus_object_get_interface (object, NM_IWD_DEVICE_INTERFACE); - priv->dbus_proxy = G_DBUS_PROXY (interface); - - value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "Scanning"); - priv->scanning = g_variant_get_boolean (value); - g_variant_unref (value); - priv->scan_requested = FALSE; - - value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "State"); - state_changed (self, g_variant_get_string (value, NULL)); - g_variant_unref (value); - - g_signal_connect (priv->dbus_proxy, "g-properties-changed", - G_CALLBACK (properties_changed), self); - - set_powered (self, priv->enabled); - - /* Call Disconnect to make sure IWD's autoconnect is disabled. - * Autoconnect is the default state after device is brought UP. - */ - if (priv->enabled) - send_disconnect (self); -} - -gboolean -nm_device_iwd_agent_psk_query (NMDeviceIwd *self, - GDBusMethodInvocation *invocation) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMActRequest *req; - NMSettingWirelessSecurity *s_wireless_sec; - const gchar *psk; - - req = nm_device_get_act_request (NM_DEVICE (self)); - if (!req) - return FALSE; - - s_wireless_sec = nm_connection_get_setting_wireless_security (nm_act_request_get_applied_connection (req)); - if (!s_wireless_sec) - return FALSE; - - psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - if (psk) { - _LOGD (LOGD_DEVICE | LOGD_WIFI, - "Returning the PSK to the IWD Agent"); - - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", psk)); - return TRUE; - } - - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, - NM_DEVICE_STATE_REASON_NO_SECRETS); - wifi_secrets_get_secrets (self, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW); - - priv->secrets_request = invocation; - return TRUE; -} - -/*****************************************************************************/ - -static const char * -get_type_description (NMDevice *device) -{ - nm_assert (NM_IS_DEVICE_IWD (device)); - - return "wifi"; -} - -/*****************************************************************************/ - -static void -nm_device_iwd_init (NMDeviceIwd *self) -{ - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - c_list_init (&priv->aps_lst_head); - - /* Make sure the manager is running */ - (void) nm_iwd_manager_get (); -} - -NMDevice * -nm_device_iwd_new (const char *iface, NMDeviceWifiCapabilities capabilities) -{ - return g_object_new (NM_TYPE_DEVICE_IWD, - NM_DEVICE_IFACE, iface, - NM_DEVICE_TYPE_DESC, "802.11 WiFi", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI, - NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, - NM_DEVICE_IWD_CAPABILITIES, (guint) capabilities, - NULL); -} - -static void -dispose (GObject *object) -{ - NMDeviceIwd *self = NM_DEVICE_IWD (object); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - - nm_clear_g_cancellable (&priv->cancellable); - - nm_clear_g_source (&priv->periodic_scan_id); - - cleanup_association_attempt (self, TRUE); - - g_clear_object (&priv->dbus_proxy); - g_clear_object (&priv->dbus_obj); - - remove_all_aps (self); - - G_OBJECT_CLASS (nm_device_iwd_parent_class)->dispose (object); - - nm_assert (c_list_is_empty (&priv->aps_lst_head)); -} - -static void -nm_device_iwd_class_init (NMDeviceIwdClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI) - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless); - - parent_class->can_auto_connect = can_auto_connect; - parent_class->is_available = is_available; - parent_class->get_autoconnect_allowed = get_autoconnect_allowed; - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->check_connection_available = check_connection_available; - parent_class->complete_connection = complete_connection; - parent_class->get_enabled = get_enabled; - parent_class->set_enabled = set_enabled; - parent_class->get_type_description = get_type_description; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->act_stage2_config = act_stage2_config; - parent_class->get_configured_mtu = get_configured_mtu; - parent_class->deactivate = deactivate; - parent_class->deactivate_async = deactivate_async; - parent_class->deactivate_async_finish = deactivate_async_finish; - parent_class->can_reapply_change = can_reapply_change; - - parent_class->state_changed = device_state_changed; - - klass->scanning_prohibited = scanning_prohibited; - - obj_properties[PROP_MODE] = - g_param_spec_uint (NM_DEVICE_IWD_MODE, "", "", - NM_802_11_MODE_UNKNOWN, - NM_802_11_MODE_AP, - NM_802_11_MODE_INFRA, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_BITRATE] = - g_param_spec_uint (NM_DEVICE_IWD_BITRATE, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ACCESS_POINTS] = - g_param_spec_boxed (NM_DEVICE_IWD_ACCESS_POINTS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ACTIVE_ACCESS_POINT] = - g_param_spec_string (NM_DEVICE_IWD_ACTIVE_ACCESS_POINT, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CAPABILITIES] = - g_param_spec_uint (NM_DEVICE_IWD_CAPABILITIES, "", "", - 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_SCANNING] = - g_param_spec_boolean (NM_DEVICE_IWD_SCANNING, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[SCANNING_PROHIBITED] = - g_signal_new (NM_DEVICE_IWD_SCANNING_PROHIBITED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceIwdClass, scanning_prohibited), - NULL, NULL, NULL, - G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); -} diff --git a/src/devices/wifi/nm-device-iwd.h b/src/devices/wifi/nm-device-iwd.h deleted file mode 100644 index 699ba1bb..00000000 --- a/src/devices/wifi/nm-device-iwd.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * 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. - * - * Copyright (C) 2017 Intel Corporation - */ - -#ifndef __NETWORKMANAGER_DEVICE_IWD_H__ -#define __NETWORKMANAGER_DEVICE_IWD_H__ - -#include "devices/nm-device.h" -#include "nm-wifi-ap.h" -#include "nm-device-wifi.h" - -#define NM_TYPE_DEVICE_IWD (nm_device_iwd_get_type ()) -#define NM_DEVICE_IWD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_IWD, NMDeviceIwd)) -#define NM_DEVICE_IWD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_IWD, NMDeviceIwdClass)) -#define NM_IS_DEVICE_IWD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_IWD)) -#define NM_IS_DEVICE_IWD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_IWD)) -#define NM_DEVICE_IWD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_IWD, NMDeviceIwdClass)) - -#define NM_DEVICE_IWD_MODE NM_DEVICE_WIFI_MODE -#define NM_DEVICE_IWD_BITRATE NM_DEVICE_WIFI_BITRATE -#define NM_DEVICE_IWD_ACCESS_POINTS NM_DEVICE_WIFI_ACCESS_POINTS -#define NM_DEVICE_IWD_ACTIVE_ACCESS_POINT NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT -#define NM_DEVICE_IWD_CAPABILITIES NM_DEVICE_WIFI_CAPABILITIES -#define NM_DEVICE_IWD_SCANNING NM_DEVICE_WIFI_SCANNING - -#define NM_DEVICE_IWD_SCANNING_PROHIBITED NM_DEVICE_WIFI_SCANNING_PROHIBITED - -typedef struct _NMDeviceIwd NMDeviceIwd; -typedef struct _NMDeviceIwdClass NMDeviceIwdClass; - -GType nm_device_iwd_get_type (void); - -NMDevice *nm_device_iwd_new (const char *iface, NMDeviceWifiCapabilities capabilities); - -void nm_device_iwd_set_dbus_object (NMDeviceIwd *device, GDBusObject *object); - -gboolean nm_device_iwd_agent_psk_query (NMDeviceIwd *device, - GDBusMethodInvocation *invocation); - -const CList *_nm_device_iwd_get_aps (NMDeviceIwd *self); - -void _nm_device_iwd_request_scan (NMDeviceIwd *self, - GVariant *options, - GDBusMethodInvocation *invocation); - -#endif /* __NETWORKMANAGER_DEVICE_IWD_H__ */ diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index cd2c68af..3a4a027a 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -48,6 +48,11 @@ #include "nm-manager.h" #include "platform/nm-platform.h" +/* This is a bug; but we can't really change API now... */ +#include "nm-vpn-dbus-interface.h" + +#include "introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceOlpcMesh); @@ -113,7 +118,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMSettingOlpcMesh *s_mesh; @@ -387,8 +392,7 @@ static void find_companion (NMDeviceOlpcMesh *self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - const CList *tmp_lst; - NMDevice *candidate; + const GSList *list; if (priv->companion) return; @@ -396,8 +400,8 @@ find_companion (NMDeviceOlpcMesh *self) nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_COMPANION, TRUE); /* Try to find the companion if it's already known to the NMManager */ - nm_manager_for_each_device (priv->manager, candidate, tmp_lst) { - if (check_companion (self, candidate)) { + for (list = nm_manager_get_devices (priv->manager); list ; list = g_slist_next (list)) { + if (check_companion (self, NM_DEVICE (list->data))) { nm_device_queue_recheck_available (NM_DEVICE (self), NM_DEVICE_STATE_REASON_NONE, NM_DEVICE_STATE_REASON_NONE); @@ -436,7 +440,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_COMPANION: - nm_dbus_utils_g_value_set_object_path (value, priv->companion); + nm_utils_g_value_set_object_path (value, priv->companion); break; case PROP_ACTIVE_CHANNEL: g_value_set_uint (value, nm_platform_mesh_get_channel (nm_device_get_platform (device), nm_device_get_ifindex (device))); @@ -496,26 +500,10 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_olpc_mesh = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Companion", "o", NM_DEVICE_OLPC_MESH_COMPANION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ActiveChannel", "u", NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH) @@ -524,8 +512,6 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) object_class->get_property = get_property; object_class->dispose = dispose; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_olpc_mesh); - parent_class->check_connection_compatible = check_connection_compatible; parent_class->get_autoconnect_allowed = get_autoconnect_allowed; parent_class->complete_connection = complete_connection; @@ -548,5 +534,9 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_OLPC_MESH_SKELETON, + NULL); } diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index de4af42c..bf021095 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -28,11 +28,9 @@ #include <unistd.h> #include <errno.h> -#include "nm-wifi-ap.h" #include "nm-common-macros.h" #include "devices/nm-device.h" #include "devices/nm-device-private.h" -#include "nm-dbus-manager.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-act-request.h" @@ -50,11 +48,11 @@ #include "nm-auth-utils.h" #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" -#include "nm-wifi-utils.h" -#include "nm-wifi-common.h" #include "nm-core-internal.h" #include "nm-config.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Wireless.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceWifi); @@ -77,6 +75,8 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi, ); enum { + ACCESS_POINT_ADDED, + ACCESS_POINT_REMOVED, SCANNING_PROHIBITED, LAST_SIGNAL @@ -87,8 +87,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { gint8 invalid_strength_counter; - CList aps_lst_head; - + GHashTable * aps; NMWifiAP * current_ap; guint32 rate; bool enabled:1; /* rfkilled or not */ @@ -188,7 +187,7 @@ static void request_wireless_scan (NMDeviceWifi *self, const GPtrArray *ssids); static void ap_add_remove (NMDeviceWifi *self, - gboolean is_adding, + guint signum, NMWifiAP *ap, gboolean recheck_available_connections); @@ -346,6 +345,30 @@ supplicant_interface_release (NMDeviceWifi *self) _notify_scanning (self); } +static NMWifiAP * +get_ap_by_path (NMDeviceWifi *self, const char *path) +{ + g_return_val_if_fail (path != NULL, NULL); + return g_hash_table_lookup (NM_DEVICE_WIFI_GET_PRIVATE (self)->aps, path); + +} + +static NMWifiAP * +get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path) +{ + GHashTableIter iter; + NMWifiAP *ap; + + g_return_val_if_fail (path != NULL, NULL); + + g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + if (g_strcmp0 (path, nm_wifi_ap_get_supplicant_path (ap)) == 0) + return ap; + } + return NULL; +} + static void update_seen_bssids_cache (NMDeviceWifi *self, NMWifiAP *ap) { @@ -392,7 +415,7 @@ set_current_ap (NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available /* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */ if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_wifi_ap_get_fake (old_ap)) - ap_add_remove (self, FALSE, old_ap, recheck_available_connections); + ap_add_remove (self, ACCESS_POINT_REMOVED, old_ap, recheck_available_connections); g_object_unref (old_ap); } @@ -459,32 +482,32 @@ periodic_update_cb (gpointer user_data) static void ap_add_remove (NMDeviceWifi *self, - gboolean is_adding, /* or else removing */ + guint signum, NMWifiAP *ap, gboolean recheck_available_connections) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - if (is_adding) { - g_object_ref (ap); - ap->wifi_device = NM_DEVICE (self); - c_list_link_tail (&priv->aps_lst_head, &ap->aps_lst); - nm_dbus_object_export (NM_DBUS_OBJECT (ap)); + nm_assert (NM_IN_SET (signum, ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED)); + + if (signum == ACCESS_POINT_ADDED) { + g_hash_table_insert (priv->aps, + (gpointer) nm_exported_object_export ((NMExportedObject *) ap), + g_object_ref (ap)); _ap_dump (self, LOGL_DEBUG, ap, "added", 0); - nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, TRUE); - } else { - ap->wifi_device = NULL; - c_list_unlink (&ap->aps_lst); + } else _ap_dump (self, LOGL_DEBUG, ap, "removed", 0); - } - _notify (self, PROP_ACCESS_POINTS); + g_signal_emit (self, signals[signum], 0, ap); - if (!is_adding) { - nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, FALSE); - nm_dbus_object_clear_and_unexport (&ap); + if (signum == ACCESS_POINT_REMOVED) { + g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap)); + nm_exported_object_unexport ((NMExportedObject *) ap); + g_object_unref (ap); } + _notify (self, PROP_ACCESS_POINTS); + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); if (recheck_available_connections) nm_device_recheck_available_connections (NM_DEVICE (self)); @@ -494,15 +517,20 @@ static void remove_all_aps (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GHashTableIter iter; NMWifiAP *ap; - if (c_list_is_empty (&priv->aps_lst_head)) + if (!g_hash_table_size (priv->aps)) return; set_current_ap (self, NULL, FALSE); - while ((ap = c_list_first_entry (&priv->aps_lst_head, NMWifiAP, aps_lst))) - ap_add_remove (self, FALSE, ap, FALSE); +again: + g_hash_table_iter_init (&iter, priv->aps); + if (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + ap_add_remove (self, ACCESS_POINT_REMOVED, ap, FALSE); + goto again; + } nm_device_recheck_available_connections (NM_DEVICE (self)); } @@ -652,14 +680,35 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return TRUE; } +static NMWifiAP * +find_first_compatible_ap (NMDeviceWifi *self, + NMConnection *connection, + gboolean allow_unstable_order) +{ + GHashTableIter iter; + NMWifiAP *ap; + NMWifiAP *cand_ap = NULL; + + g_return_val_if_fail (connection != NULL, NULL); + + g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + if (!nm_wifi_ap_check_compatible (ap, connection)) + continue; + if (allow_unstable_order) + return ap; + if (!cand_ap || (nm_wifi_ap_get_id (cand_ap) < nm_wifi_ap_get_id (ap))) + cand_ap = ap; + } + return cand_ap; +} + static gboolean check_connection_available (NMDevice *device, NMConnection *connection, NMDeviceCheckConAvailableFlags flags, const char *specific_object) { - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; const char *mode; @@ -672,7 +721,7 @@ check_connection_available (NMDevice *device, if (specific_object) { NMWifiAP *ap; - ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); + ap = get_ap_by_path (NM_DEVICE_WIFI (device), specific_object); return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE; } @@ -696,18 +745,50 @@ check_connection_available (NMDevice *device, return TRUE; /* check at least one AP is compatible with this connection */ - return !!nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); + return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE); +} + +static gboolean +is_manf_default_ssid (const GByteArray *ssid) +{ + int i; + /* + * List of manufacturer default SSIDs that are often unchanged by users. + * + * NOTE: this list should *not* contain networks that you would like to + * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". + */ + static const char *manf_defaults[] = { + "linksys", + "linksys-a", + "linksys-g", + "default", + "belkin54g", + "NETGEAR", + "o2DSL", + "WLAN", + "ALICE-WLAN", + "Speedport W 501V", + "TURBONETT", + }; + + for (i = 0; i < G_N_ELEMENTS (manf_defaults); i++) { + if (ssid->len == strlen (manf_defaults[i])) { + if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0) + return TRUE; + } + } + return FALSE; } static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; const char *setting_mac; char *str_ssid = NULL; @@ -744,7 +825,7 @@ complete_connection (NMDevice *device, if (!nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_AP)) { /* Find a compatible AP in the scan list */ - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); + ap = find_first_compatible_ap (self, connection, FALSE); /* If we still don't have an AP, then the WiFI settings needs to be * fully specified by the client. Might not be able to find an AP @@ -766,7 +847,7 @@ complete_connection (NMDevice *device, return FALSE; ap = NULL; } else { - ap = nm_wifi_ap_lookup_for_device (NM_DEVICE (self), specific_object); + ap = get_ap_by_path (self, specific_object); if (!ap) { g_set_error (error, NM_DEVICE_ERROR, @@ -819,7 +900,7 @@ complete_connection (NMDevice *device, */ if (!nm_wifi_ap_complete_connection (ap, connection, - nm_wifi_utils_is_manf_default_ssid (ssid), + is_manf_default_ssid (ssid), error)) { if (tmp_ssid) g_byte_array_unref (tmp_ssid); @@ -926,7 +1007,6 @@ can_auto_connect (NMDevice *device, char **specific_object) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; NMWifiAP *ap; const char *method, *mode; @@ -958,20 +1038,102 @@ can_auto_connect (NMDevice *device, return FALSE; } - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); + ap = find_first_compatible_ap (self, connection, FALSE); if (ap) { /* All good; connection is usable */ - NM_SET_OUT (specific_object, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)))); + NM_SET_OUT (specific_object, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)))); return TRUE; } return FALSE; } -const CList * -_nm_device_wifi_get_aps (NMDeviceWifi *self) +static int +ap_id_compare (gconstpointer p_a, gconstpointer p_b, gpointer user_data) +{ + guint64 a_id = nm_wifi_ap_get_id (*((NMWifiAP **) p_a)); + guint64 b_id = nm_wifi_ap_get_id (*((NMWifiAP **) p_b)); + + return a_id < b_id ? -1 : (a_id == b_id ? 0 : 1); +} + +static NMWifiAP ** +ap_list_get_sorted (NMDeviceWifi *self, gboolean include_without_ssid) +{ + NMDeviceWifiPrivate *priv; + NMWifiAP **list; + GHashTableIter iter; + NMWifiAP *ap; + gsize i, n; + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + n = g_hash_table_size (priv->aps); + list = g_new (NMWifiAP *, n + 1); + + i = 0; + if (n > 0) { + g_hash_table_iter_init (&iter, priv->aps); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + nm_assert (i < n); + if ( include_without_ssid + || nm_wifi_ap_get_ssid (ap)) + list[i++] = ap; + } + nm_assert (i <= n); + nm_assert (!include_without_ssid || i == n); + + g_qsort_with_data (list, + i, + sizeof (gpointer), + ap_id_compare, + NULL); + } + list[i] = NULL; + return list; +} + +static const char ** +ap_list_get_sorted_paths (NMDeviceWifi *self, gboolean include_without_ssid) { - return &NM_DEVICE_WIFI_GET_PRIVATE (self)->aps_lst_head; + gpointer *list; + gsize i, j; + + list = (gpointer *) ap_list_get_sorted (self, include_without_ssid); + for (i = 0, j = 0; list[i]; i++) { + NMWifiAP *ap = list[i]; + const char *path; + + /* update @list inplace to hold instead the export-path. */ + path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)); + nm_assert (path); + list[j++] = (gpointer) path; + } + return (const char **) list; +} + +static void +impl_device_wifi_get_access_points (NMDeviceWifi *self, + GDBusMethodInvocation *context) +{ + gs_free const char **list = NULL; + GVariant *v; + + list = ap_list_get_sorted_paths (self, FALSE); + v = g_variant_new_objv (list, -1); + g_dbus_method_invocation_return_value (context, g_variant_new_tuple (&v, 1)); +} + +static void +impl_device_wifi_get_all_access_points (NMDeviceWifi *self, + GDBusMethodInvocation *context) +{ + gs_free const char **list = NULL; + GVariant *v; + + list = ap_list_get_sorted_paths (self, TRUE); + v = g_variant_new_objv (list, -1); + g_dbus_method_invocation_return_value (context, g_variant_new_tuple (&v, 1)); } static void @@ -991,7 +1153,7 @@ _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset) priv = NM_DEVICE_WIFI_GET_PRIVATE (self); randomize = nm_config_data_get_device_config_boolean (NM_CONFIG_GET_DATA, - NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_RAND_MAC_ADDRESS, + "wifi.scan-rand-mac-address", device, TRUE, TRUE); @@ -1077,6 +1239,7 @@ dbus_request_scan_cb (NMDevice *device, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv; gs_unref_variant GVariant *scan_options = user_data; gs_unref_ptrarray GPtrArray *ssids = NULL; @@ -1093,6 +1256,8 @@ dbus_request_scan_cb (NMDevice *device, return; } + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + if (scan_options) { gs_unref_variant GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL); @@ -1119,10 +1284,10 @@ dbus_request_scan_cb (NMDevice *device, g_dbus_method_invocation_return_value (context, NULL); } -void -_nm_device_wifi_request_scan (NMDeviceWifi *self, - GVariant *options, - GDBusMethodInvocation *invocation) +static void +impl_device_wifi_request_scan (NMDeviceWifi *self, + GDBusMethodInvocation *context, + GVariant *options) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); @@ -1132,7 +1297,7 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self, || !priv->sup_iface || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED || nm_device_is_activating (device)) { - g_dbus_method_invocation_return_error_literal (invocation, + g_dbus_method_invocation_return_error_literal (context, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, "Scanning not allowed while unavailable or activating"); @@ -1140,7 +1305,7 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self, } if (nm_supplicant_interface_get_scanning (priv->sup_iface)) { - g_dbus_method_invocation_return_error_literal (invocation, + g_dbus_method_invocation_return_error_literal (context, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, "Scanning not allowed while already scanning"); @@ -1149,16 +1314,17 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self, last_scan = nm_supplicant_interface_get_last_scan_time (priv->sup_iface); if (last_scan && (nm_utils_get_monotonic_timestamp_s () - last_scan) < 10) { - g_dbus_method_invocation_return_error_literal (invocation, + g_dbus_method_invocation_return_error_literal (context, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED, "Scanning not allowed immediately following previous scan"); return; } + /* Ask the manager to authenticate this request for us */ g_signal_emit_by_name (device, NM_DEVICE_AUTH_REQUEST, - invocation, + context, NULL, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, @@ -1442,15 +1608,17 @@ ap_list_dump (gpointer user_data) priv->ap_dump_id = 0; if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) { - NMWifiAP *ap; + gs_free NMWifiAP **list = NULL; + gsize i; gint32 now_s = nm_utils_get_monotonic_timestamp_s (); _LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]", now_s, priv->last_scan, priv->scheduled_scan_time); - c_list_for_each_entry (ap, &priv->aps_lst_head, aps_lst) - _ap_dump (self, LOGL_DEBUG, ap, "dump", now_s); + list = ap_list_get_sorted (self, TRUE); + for (i = 0; list[i]; i++) + _ap_dump (self, LOGL_DEBUG, list[i], "dump", now_s); } return G_SOURCE_REMOVE; } @@ -1521,7 +1689,7 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) return; - found_ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, object_path); + found_ap = get_ap_by_supplicant_path (self, object_path); if (found_ap) { if (!nm_wifi_ap_update_from_properties (found_ap, object_path, properties)) return; @@ -1553,7 +1721,7 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, } } - ap_add_remove (self, TRUE, ap, TRUE); + ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); } /* Update the current AP if the supplicant notified a current BSS change @@ -1577,7 +1745,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, g_return_if_fail (object_path != NULL); priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, object_path); + ap = get_ap_by_supplicant_path (self, object_path); if (!ap) return; @@ -1590,7 +1758,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, if (nm_wifi_ap_set_fake (ap, TRUE)) _ap_dump (self, LOGL_DEBUG, ap, "updated", 0); } else { - ap_add_remove (self, FALSE, ap, TRUE); + ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE); schedule_ap_list_dump (self); } } @@ -2121,7 +2289,7 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, current_bss = nm_supplicant_interface_get_current_bss (iface); if (current_bss) - new_ap = nm_wifi_aps_find_by_supplicant_path (&priv->aps_lst_head, current_bss); + new_ap = get_ap_by_supplicant_path (self, current_bss); if (new_ap != priv->current_ap) { const char *new_bssid = NULL; @@ -2329,7 +2497,6 @@ build_supplicant_config (NMDeviceWifi *self, NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; NMSettingWirelessSecurityPmf pmf; - NMSettingWirelessSecurityFils fils; gs_free char *value = NULL; g_return_val_if_fail (priv->sup_iface, NULL); @@ -2337,9 +2504,7 @@ build_supplicant_config (NMDeviceWifi *self, s_wireless = nm_connection_get_setting_wireless (connection); g_return_val_if_fail (s_wireless != NULL, NULL); - config = nm_supplicant_config_new ( - nm_supplicant_interface_get_pmf_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_YES, - nm_supplicant_interface_get_fils_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_YES); + config = nm_supplicant_config_new (); /* Warn if AP mode may not be supported */ if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 @@ -2381,16 +2546,24 @@ build_supplicant_config (NMDeviceWifi *self, NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL); } - /* Configure FILS (802.11ai) */ - fils = nm_setting_wireless_security_get_fils (s_wireless_sec); - if (fils == NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT) { - value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, - "wifi-sec.fils", - NM_DEVICE (self)); - fils = _nm_utils_ascii_str_to_int64 (value, 10, - NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE, - NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED, - NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL); + /* Don't try to enable PMF on non-WPA networks */ + if (!NM_IN_STRSET (nm_setting_wireless_security_get_key_mgmt (s_wireless_sec), + "wpa-eap", + "wpa-psk")) + pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; + + /* Check if we actually support PMF */ + if (nm_supplicant_interface_get_pmf_support (priv->sup_iface) != NM_SUPPLICANT_FEATURE_YES) { + if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) { + g_set_error_literal (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, + "Supplicant does not support PMF"); + goto error; + } else if (pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL) { + /* To be on the safe side, assume no support if we can't determine + * capabilities. + */ + pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; + } } s_8021x = nm_connection_get_setting_802_1x (connection); @@ -2400,7 +2573,6 @@ build_supplicant_config (NMDeviceWifi *self, con_uuid, mtu, pmf, - fils, error)) { g_prefix_error (error, "802-11-wireless-security: "); goto error; @@ -2482,16 +2654,16 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) /* AP mode never uses a specific object or existing scanned AP */ if (priv->mode != NM_802_11_MODE_AP) { ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL; + ap = ap_path ? get_ap_by_path (self, ap_path) : NULL; if (ap) goto done; - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); + ap = find_first_compatible_ap (self, connection, FALSE); } if (ap) { nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))); goto done; } @@ -2508,11 +2680,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) nm_wifi_ap_set_address (ap, nm_device_get_hw_address (device)); g_object_freeze_notify (G_OBJECT (self)); - ap_add_remove (self, TRUE, ap, TRUE); + ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); g_object_thaw_notify (G_OBJECT (self)); set_current_ap (self, ap, FALSE); nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))); return NM_ACT_STAGE_RETURN_SUCCESS; done: @@ -2883,10 +3055,13 @@ activation_success_handler (NMDevice *device) NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (device); NMActRequest *req; + NMConnection *applied_connection; req = nm_device_get_act_request (device); g_assert (req); + applied_connection = nm_act_request_get_applied_connection (req); + /* Clear any critical protocol notification in the wifi stack */ nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), ifindex, FALSE); @@ -2924,7 +3099,7 @@ activation_success_handler (NMDevice *device) } nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->current_ap))); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->current_ap))); } periodic_update (self); @@ -3102,7 +3277,8 @@ get_property (GObject *object, guint prop_id, { NMDeviceWifi *self = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - const char **list; + gsize i; + char **list; switch (prop_id) { case PROP_MODE: @@ -3115,11 +3291,13 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->capabilities); break; case PROP_ACCESS_POINTS: - list = nm_wifi_aps_get_paths (&priv->aps_lst_head, TRUE); - g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list)); + list = (char **) ap_list_get_sorted_paths (self, TRUE); + for (i = 0; list[i]; i++) + list[i] = g_strdup (list[i]); + g_value_take_boxed (value, list); break; case PROP_ACTIVE_ACCESS_POINT: - nm_dbus_utils_g_value_set_object_path (value, priv->current_ap); + nm_utils_g_value_set_object_path (value, priv->current_ap); break; case PROP_SCANNING: g_value_set_boolean (value, priv->is_scanning); @@ -3155,9 +3333,8 @@ nm_device_wifi_init (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - c_list_init (&priv->aps_lst_head); - priv->mode = NM_802_11_MODE_INFRA; + priv->aps = g_hash_table_new (nm_str_hash, g_str_equal); } static void @@ -3215,7 +3392,9 @@ finalize (GObject *object) NMDeviceWifi *self = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - nm_assert (c_list_is_empty (&priv->aps_lst_head)); + nm_assert (g_hash_table_size (priv->aps) == 0); + + g_hash_table_unref (priv->aps); G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } @@ -3224,7 +3403,6 @@ static void nm_device_wifi_class_init (NMDeviceWifiClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI) @@ -3235,8 +3413,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&nm_interface_info_device_wireless); - parent_class->can_auto_connect = can_auto_connect; parent_class->get_autoconnect_allowed = get_autoconnect_allowed; parent_class->is_available = is_available; @@ -3303,6 +3479,24 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + signals[ACCESS_POINT_ADDED] = + g_signal_new (NM_DEVICE_WIFI_ACCESS_POINT_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_WIFI_AP); + + signals[ACCESS_POINT_REMOVED] = + g_signal_new (NM_DEVICE_WIFI_ACCESS_POINT_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_WIFI_AP); + signals[SCANNING_PROHIBITED] = g_signal_new (NM_DEVICE_WIFI_SCANNING_PROHIBITED, G_OBJECT_CLASS_TYPE (object_class), @@ -3310,4 +3504,13 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_prohibited), NULL, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_WIFI_SKELETON, + "GetAccessPoints", impl_device_wifi_get_access_points, + "GetAllAccessPoints", impl_device_wifi_get_all_access_points, + "RequestScan", impl_device_wifi_request_scan, + NULL); } + + diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h index c13b00de..09707d4f 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -23,6 +23,7 @@ #define __NETWORKMANAGER_DEVICE_WIFI_H__ #include "devices/nm-device.h" +#include "nm-wifi-ap.h" #define NM_TYPE_DEVICE_WIFI (nm_device_wifi_get_type ()) #define NM_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi)) @@ -38,6 +39,11 @@ #define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities" #define NM_DEVICE_WIFI_SCANNING "scanning" +/* signals */ +#define NM_DEVICE_WIFI_ACCESS_POINT_ADDED "access-point-added" +#define NM_DEVICE_WIFI_ACCESS_POINT_REMOVED "access-point-removed" + +/* internal signals */ #define NM_DEVICE_WIFI_SCANNING_PROHIBITED "scanning-prohibited" typedef struct _NMDeviceWifi NMDeviceWifi; @@ -47,10 +53,4 @@ GType nm_device_wifi_get_type (void); NMDevice * nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities); -const CList *_nm_device_wifi_get_aps (NMDeviceWifi *self); - -void _nm_device_wifi_request_scan (NMDeviceWifi *self, - GVariant *options, - GDBusMethodInvocation *invocation); - #endif /* __NETWORKMANAGER_DEVICE_WIFI_H__ */ diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c deleted file mode 100644 index 450009f0..00000000 --- a/src/devices/wifi/nm-iwd-manager.c +++ /dev/null @@ -1,694 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * 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. - * - * Copyright (C) 2017 Intel Corporation - */ - -#include "nm-default.h" - -#include "nm-iwd-manager.h" - -#include <string.h> -#include <net/if.h> - -#include "nm-logging.h" -#include "nm-core-internal.h" -#include "nm-manager.h" -#include "nm-device-iwd.h" -#include "nm-utils/nm-random-utils.h" - -/*****************************************************************************/ - -typedef struct { - gchar *name; - NMIwdNetworkSecurity security; -} KnownNetworkData; - -typedef struct { - NMManager *manager; - GCancellable *cancellable; - gboolean running; - GDBusObjectManager *object_manager; - guint agent_id; - gchar *agent_path; - GSList *known_networks; -} NMIwdManagerPrivate; - -struct _NMIwdManager { - GObject parent; - NMIwdManagerPrivate _priv; -}; - -struct _NMIwdManagerClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE (NMIwdManager, nm_iwd_manager, G_TYPE_OBJECT) - -#define NM_IWD_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMIwdManager, NM_IS_IWD_MANAGER) - -/*****************************************************************************/ - -#define _NMLOG_PREFIX_NAME "iwd-manager" -#define _NMLOG_DOMAIN LOGD_WIFI - -#define _NMLOG(level, ...) \ - G_STMT_START { \ - if (nm_logging_enabled (level, _NMLOG_DOMAIN)) { \ - char __prefix[32]; \ - \ - if (self) \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", ""_NMLOG_PREFIX_NAME"", (self)); \ - else \ - g_strlcpy (__prefix, _NMLOG_PREFIX_NAME, sizeof (__prefix)); \ - _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } G_STMT_END - -/*****************************************************************************/ - -static void -psk_agent_dbus_method_cb (GDBusConnection *connection, - const gchar *sender, const gchar *object_path, - const gchar *interface_name, const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - NMIwdManager *self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GDBusObjectManagerClient *omc = G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager); - const gchar *network_path, *device_path, *ifname; - gs_unref_object GDBusInterface *network = NULL, *device_obj = NULL; - gs_unref_variant GVariant *value = NULL; - gint ifindex; - NMDevice *device; - - /* Be paranoid and check the sender address */ - if (!nm_streq0 (g_dbus_object_manager_client_get_name_owner (omc), sender)) - goto return_error; - - g_variant_get (parameters, "(&o)", &network_path); - - network = g_dbus_object_manager_get_interface (priv->object_manager, - network_path, - NM_IWD_NETWORK_INTERFACE); - value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (network), "Device"); - device_path = g_variant_get_string (value, NULL); - - if (!device_path) { - _LOGE ("Device not cached for network %s in IWD Agent request", - network_path); - goto return_error; - } - - device_obj = g_dbus_object_manager_get_interface (priv->object_manager, - device_path, - NM_IWD_DEVICE_INTERFACE); - g_variant_unref (value); - value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (device_obj), "Name"); - ifname = g_variant_get_string (value, NULL); - - if (!ifname) { - _LOGE ("Name not cached for device %s in IWD Agent request", - device_path); - goto return_error; - } - - ifindex = if_nametoindex (ifname); - if (!ifindex) { - _LOGE ("if_nametoindex failed for Name %s for Device at %s: %i", - ifname, device_path, errno); - goto return_error; - } - - device = nm_manager_get_device_by_ifindex (priv->manager, ifindex); - if (!NM_IS_DEVICE_IWD (device)) { - _LOGE ("IWD device named %s is not a Wifi device in IWD Agent request", - ifname); - goto return_error; - } - - if (nm_device_iwd_agent_psk_query (NM_DEVICE_IWD (device), invocation)) - return; - - _LOGE ("Device %s did not handle the IWD Agent request", ifname); - -return_error: - /* IWD doesn't look at the specific error */ - g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "No PSK available for this connection"); -} - - -static guint -psk_agent_export (GDBusConnection *connection, gpointer user_data, - gchar **agent_path, GError **error) -{ - static const GDBusArgInfo request_passphrase_arg_network = { - -1, - (gchar *) "network", - (gchar *) "o", - NULL, - }; - static const GDBusArgInfo *const request_passphrase_in_args[] = { - &request_passphrase_arg_network, - NULL, - }; - static const GDBusArgInfo request_passphrase_arg_passphrase = { - -1, - (gchar *) "passphrase", - (gchar *) "s", - NULL, - }; - static const GDBusArgInfo *const request_passphrase_out_args[] = { - &request_passphrase_arg_passphrase, - NULL, - }; - static const GDBusMethodInfo request_passphrase_info = { - -1, - (gchar *) "RequestPassphrase", - (GDBusArgInfo **) &request_passphrase_in_args, - (GDBusArgInfo **) &request_passphrase_out_args, - NULL, - }; - static const GDBusMethodInfo *const method_info[] = { - &request_passphrase_info, - NULL, - }; - static GDBusInterfaceInfo interface_info = { - -1, - (gchar *) "net.connman.iwd.Agent", - (GDBusMethodInfo **) &method_info, - NULL, - NULL, - NULL, - }; - static GDBusInterfaceVTable vtable = { - psk_agent_dbus_method_cb, - NULL, - NULL, - }; - - gchar path[50]; - unsigned int rnd; - guint id; - - if (!nm_utils_random_bytes (&rnd, sizeof (rnd))) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_FAILED, - "Can't read urandom."); - return 0; - } - - nm_sprintf_buf (path, "/agent/%u", rnd); - - id = g_dbus_connection_register_object (connection, path, - &interface_info, &vtable, - user_data, NULL, error); - - if (id) - *agent_path = g_strdup (path); - return id; -} - -static void -register_agent (NMIwdManager *self) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GDBusInterface *agent_manager; - - agent_manager = g_dbus_object_manager_get_interface (priv->object_manager, - "/", - NM_IWD_AGENT_MANAGER_INTERFACE); - - /* Register our agent */ - g_dbus_proxy_call (G_DBUS_PROXY (agent_manager), - "RegisterAgent", - g_variant_new ("(o)", priv->agent_path), - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, NULL, NULL); - - g_object_unref (agent_manager); -} - -/*****************************************************************************/ - -static void -set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface, - GDBusObject *object) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GDBusProxy *proxy; - GVariant *value; - const char *ifname; - gint ifindex; - NMDevice *device; - - if (!priv->running) - return; - - g_return_if_fail (G_IS_DBUS_PROXY (interface)); - - proxy = G_DBUS_PROXY (interface); - - if (strcmp (g_dbus_proxy_get_interface_name (proxy), - NM_IWD_DEVICE_INTERFACE)) - return; - - value = g_dbus_proxy_get_cached_property (proxy, "Name"); - if (!value) { - _LOGE ("Name not cached for Device at %s", - g_dbus_proxy_get_object_path (proxy)); - return; - } - - ifname = g_variant_get_string (value, NULL); - ifindex = if_nametoindex (ifname); - g_variant_unref (value); - - if (!ifindex) { - _LOGE ("if_nametoindex failed for Name %s for Device at %s: %i", - ifname, g_dbus_proxy_get_object_path (proxy), errno); - return; - } - - device = nm_manager_get_device_by_ifindex (priv->manager, ifindex); - if (!NM_IS_DEVICE_IWD (device)) { - _LOGE ("IWD device named %s is not a Wifi device", ifname); - return; - } - - nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object); -} - -static void -interface_added (GDBusObjectManager *object_manager, GDBusObject *object, - GDBusInterface *interface, gpointer user_data) -{ - NMIwdManager *self = user_data; - - set_device_dbus_object (self, interface, object); -} - -static void -interface_removed (GDBusObjectManager *object_manager, GDBusObject *object, - GDBusInterface *interface, gpointer user_data) -{ - NMIwdManager *self = user_data; - - /* - * TODO: we may need to save the GDBusInterface or GDBusObject - * pointer in the hash table because we may be no longer able to - * access the Name property or map the name to ifindex with - * if_nametoindex at this point. - */ - - set_device_dbus_object (self, interface, NULL); -} - -static gboolean -_om_has_name_owner (GDBusObjectManager *object_manager) -{ - gs_free char *name_owner = NULL; - - nm_assert (G_IS_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); - - name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); - return !!name_owner; -} - -static void -object_added (NMIwdManager *self, GDBusObject *object) -{ - GList *interfaces, *iter; - - interfaces = g_dbus_object_get_interfaces (object); - for (iter = interfaces; iter; iter = iter->next) { - GDBusInterface *interface = G_DBUS_INTERFACE (iter->data); - - set_device_dbus_object (self, interface, object); - } - - g_list_free_full (interfaces, g_object_unref); -} - -static void -known_network_free (KnownNetworkData *network) -{ - g_free (network->name); - g_free (network); -} - -static void -list_known_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data) -{ - NMIwdManager *self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *variant = NULL; - GVariantIter *networks, *props; - - variant = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, - G_VARIANT_TYPE ("(aa{sv})"), - &error); - if (!variant) { - _LOGE ("ListKnownNetworks() failed: %s", error->message); - return; - } - - g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free); - priv->known_networks = NULL; - - g_variant_get (variant, "(aa{sv})", &networks); - - while (g_variant_iter_next (networks, "a{sv}", &props)) { - const gchar *key; - const gchar *name = NULL; - const gchar *type = NULL; - GVariant *val; - KnownNetworkData *network_data; - - while (g_variant_iter_next (props, "{&sv}", &key, &val)) { - if (!strcmp (key, "Name")) - name = g_variant_get_string (val, NULL); - - if (!strcmp (key, "Type")) - type = g_variant_get_string (val, NULL); - - g_variant_unref (val); - } - - if (!name || !type) - goto next; - - network_data = g_new (KnownNetworkData, 1); - network_data->name = g_strdup (name); - if (!strcmp (type, "open")) - network_data->security = NM_IWD_NETWORK_SECURITY_NONE; - else if (!strcmp (type, "psk")) - network_data->security = NM_IWD_NETWORK_SECURITY_PSK; - else if (!strcmp (type, "8021x")) - network_data->security = NM_IWD_NETWORK_SECURITY_8021X; - - priv->known_networks = g_slist_append (priv->known_networks, - network_data); - -next: - g_variant_iter_free (props); - } - - g_variant_iter_free (networks); - - /* For completness we may want to call nm_device_emit_recheck_auto_activate - * and nm_device_recheck_available_connections for all affected devices - * now but the ListKnownNetworks call should have been really fast, - * faster than any scan on any newly created devices could have happened. - */ -} - -static void -update_known_networks (NMIwdManager *self) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GDBusInterface *known_networks_if; - - known_networks_if = g_dbus_object_manager_get_interface (priv->object_manager, - "/", - NM_IWD_KNOWN_NETWORKS_INTERFACE); - - g_dbus_proxy_call (G_DBUS_PROXY (known_networks_if), - "ListKnownNetworks", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, -1, - priv->cancellable, list_known_networks_cb, self); - - g_object_unref (known_networks_if); -} - -static void prepare_object_manager (NMIwdManager *self); - -static void -name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - NMIwdManager *self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GDBusObjectManager *object_manager = G_DBUS_OBJECT_MANAGER (object); - - nm_assert (object_manager == priv->object_manager); - - if (_om_has_name_owner (object_manager)) { - g_signal_handlers_disconnect_by_data (object_manager, self); - g_clear_object (&priv->object_manager); - prepare_object_manager (self); - } else { - const CList *tmp_lst; - NMDevice *device; - - if (!priv->running) - return; - - priv->running = false; - - nm_manager_for_each_device (priv->manager, device, tmp_lst) { - if (NM_IS_DEVICE_IWD (device)) { - nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), - NULL); - } - } - } -} - -static void -device_added (NMManager *manager, NMDevice *device, gpointer user_data) -{ - NMIwdManager *self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GList *objects, *iter; - - if (!NM_IS_DEVICE_IWD (device)) - return; - - if (!priv->running) - return; - - objects = g_dbus_object_manager_get_objects (priv->object_manager); - for (iter = objects; iter; iter = iter->next) { - GDBusObject *object = G_DBUS_OBJECT (iter->data); - GDBusInterface *interface; - GDBusProxy *proxy; - GVariant *value; - const char *obj_ifname; - - interface = g_dbus_object_get_interface (object, - NM_IWD_DEVICE_INTERFACE); - if (!interface) - continue; - - proxy = G_DBUS_PROXY (interface); - value = g_dbus_proxy_get_cached_property (proxy, "Name"); - if (!value) { - g_object_unref (interface); - continue; - } - - obj_ifname = g_variant_get_string (value, NULL); - g_variant_unref (value); - g_object_unref (interface); - - if (strcmp (nm_device_get_iface (device), obj_ifname)) - continue; - - nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object); - break; - } - - g_list_free_full (objects, g_object_unref); -} - -static void -got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data) -{ - NMIwdManager *self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - GDBusObjectManager *object_manager; - GDBusConnection *connection; - - object_manager = g_dbus_object_manager_client_new_for_bus_finish (result, &error); - if (object_manager == NULL) { - _LOGE ("failed to acquire IWD Object Manager: Wi-Fi will not be available (%s)", - NM_G_ERROR_MSG (error)); - g_clear_error (&error); - return; - } - - priv->object_manager = object_manager; - - g_signal_connect (priv->object_manager, "notify::name-owner", - G_CALLBACK (name_owner_changed), self); - - nm_assert (G_IS_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); - - connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); - - priv->agent_id = psk_agent_export (connection, self, - &priv->agent_path, &error); - if (!priv->agent_id) { - _LOGE ("failed to export the IWD Agent: PSK/8021x WiFi networks will not work: %s", - NM_G_ERROR_MSG (error)); - g_clear_error (&error); - } - - if (_om_has_name_owner (object_manager)) { - GList *objects, *iter; - - priv->running = true; - - g_signal_connect (priv->object_manager, "interface-added", - G_CALLBACK (interface_added), self); - g_signal_connect (priv->object_manager, "interface-removed", - G_CALLBACK (interface_removed), self); - - objects = g_dbus_object_manager_get_objects (object_manager); - for (iter = objects; iter; iter = iter->next) - object_added (self, G_DBUS_OBJECT (iter->data)); - - g_list_free_full (objects, g_object_unref); - - if (priv->agent_id) - register_agent (self); - - update_known_networks (self); - } -} - -static void -prepare_object_manager (NMIwdManager *self) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - - g_dbus_object_manager_client_new_for_bus (NM_IWD_BUS_TYPE, - G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, - NM_IWD_SERVICE, "/", - NULL, NULL, NULL, - priv->cancellable, - got_object_manager, self); -} - -gboolean -nm_iwd_manager_is_known_network (NMIwdManager *self, const gchar *name, - NMIwdNetworkSecurity security) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - const GSList *iter; - - for (iter = priv->known_networks; iter; iter = g_slist_next (iter)) { - const KnownNetworkData *network = iter->data; - - if (!strcmp (network->name, name) && network->security == security) - return true; - } - - return false; -} - -void -nm_iwd_manager_network_connected (NMIwdManager *self, const gchar *name, - NMIwdNetworkSecurity security) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - KnownNetworkData *network_data; - - if (nm_iwd_manager_is_known_network (self, name, security)) - return; - - network_data = g_new (KnownNetworkData, 1); - network_data->name = g_strdup (name); - network_data->security = security; - priv->known_networks = g_slist_append (priv->known_networks, network_data); -} - -/*****************************************************************************/ - -NM_DEFINE_SINGLETON_GETTER (NMIwdManager, nm_iwd_manager_get, - NM_TYPE_IWD_MANAGER); - -static void -nm_iwd_manager_init (NMIwdManager *self) -{ - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - - priv->manager = g_object_ref (nm_manager_get ()); - g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED, - G_CALLBACK (device_added), self); - - priv->cancellable = g_cancellable_new (); - - prepare_object_manager (self); -} - -static void -dispose (GObject *object) -{ - NMIwdManager *self = (NMIwdManager *) object; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - - if (priv->object_manager) { - if (priv->agent_id) { - GDBusConnection *connection; - GDBusObjectManagerClient *omc = G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager); - - /* No need to unregister the agent as IWD will detect - * our DBus connection being closed. - */ - - connection = g_dbus_object_manager_client_get_connection (omc); - - g_dbus_connection_unregister_object (connection, priv->agent_id); - priv->agent_id = 0; - } - - g_clear_object (&priv->object_manager); - } - - nm_clear_g_free (&priv->agent_path); - - nm_clear_g_cancellable (&priv->cancellable); - - g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free); - priv->known_networks = NULL; - - if (priv->manager) { - g_signal_handlers_disconnect_by_data (priv->manager, self); - g_clear_object (&priv->manager); - } - - G_OBJECT_CLASS (nm_iwd_manager_parent_class)->dispose (object); -} - -static void -nm_iwd_manager_class_init (NMIwdManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dispose; -} diff --git a/src/devices/wifi/nm-iwd-manager.h b/src/devices/wifi/nm-iwd-manager.h deleted file mode 100644 index 8e6b66ff..00000000 --- a/src/devices/wifi/nm-iwd-manager.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * 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. - * - * Copyright (C) 2017 Intel Corporation - */ - -#ifndef __NETWORKMANAGER_IWD_MANAGER_H__ -#define __NETWORKMANAGER_IWD_MANAGER_H__ - -#include "devices/nm-device.h" - -#define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM -#define NM_IWD_SERVICE "net.connman.iwd" - -#define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager" -#define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter" -#define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device" -#define NM_IWD_NETWORK_INTERFACE "net.connman.iwd.Network" -#define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent" -#define NM_IWD_WSC_INTERFACE \ - "net.connman.iwd.WiFiSimpleConfiguration" -#define NM_IWD_KNOWN_NETWORKS_INTERFACE "net.connman.iwd.KnownNetworks" -#define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent" - -typedef enum { - NM_IWD_NETWORK_SECURITY_NONE, - NM_IWD_NETWORK_SECURITY_WEP, - NM_IWD_NETWORK_SECURITY_PSK, - NM_IWD_NETWORK_SECURITY_8021X, -} NMIwdNetworkSecurity; - -#define NM_TYPE_IWD_MANAGER (nm_iwd_manager_get_type ()) -#define NM_IWD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IWD_MANAGER, NMIwdManager)) -#define NM_IWD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IWD_MANAGER, NMIwdManagerClass)) -#define NM_IS_IWD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IWD_MANAGER)) -#define NM_IS_IWD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IWD_MANAGER)) -#define NM_IWD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IWD_MANAGER, NMIwdManagerClass)) - -typedef struct _NMIwdManager NMIwdManager; -typedef struct _NMIwdManagerClass NMIwdManagerClass; - -GType nm_iwd_manager_get_type (void); - -NMIwdManager *nm_iwd_manager_get (void); - -gboolean nm_iwd_manager_is_known_network (NMIwdManager *self, const gchar *name, - NMIwdNetworkSecurity security); -void nm_iwd_manager_network_connected (NMIwdManager *self, const gchar *name, - NMIwdNetworkSecurity security); - -#endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */ diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index dd6d1deb..bc823af0 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -21,20 +21,19 @@ #include "nm-default.h" -#include "nm-wifi-ap.h" - #include <string.h> #include <stdlib.h> -#include "nm-setting-wireless.h" - +#include "nm-wifi-ap.h" #include "nm-wifi-utils.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-core-internal.h" #include "platform/nm-platform.h" -#include "devices/nm-device.h" -#include "nm-dbus-manager.h" + +#include "nm-setting-wireless.h" + +#include "introspection/org.freedesktop.NetworkManager.AccessPoint.h" #define PROTO_WPA "wpa" #define PROTO_RSN "rsn" @@ -54,7 +53,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMWifiAP, PROP_LAST_SEEN, ); -struct _NMWifiAPPrivate { +typedef struct { char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */ /* Scanned or cached values */ @@ -73,17 +72,20 @@ struct _NMWifiAPPrivate { bool fake:1; /* Whether or not the AP is from a scan */ bool hotspot:1; /* Whether the AP is a local device's hotspot network */ gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ -}; +} NMWifiAPPrivate; -typedef struct _NMWifiAPPrivate NMWifiAPPrivate; +struct _NMWifiAP { + NMExportedObject parent; + NMWifiAPPrivate _priv; +}; struct _NMWifiAPClass { - NMDBusObjectClass parent; + NMExportedObjectClass parent; }; -G_DEFINE_TYPE (NMWifiAP, nm_wifi_ap, NM_TYPE_DBUS_OBJECT) +G_DEFINE_TYPE (NMWifiAP, nm_wifi_ap, NM_TYPE_EXPORTED_OBJECT) -#define NM_WIFI_AP_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMWifiAP, NM_IS_WIFI_AP) +#define NM_WIFI_AP_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMWifiAP, NM_IS_WIFI_AP) /*****************************************************************************/ @@ -95,24 +97,30 @@ nm_wifi_ap_get_supplicant_path (NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE (ap)->supplicant_path; } -const GByteArray * -nm_wifi_ap_get_ssid (const NMWifiAP *ap) +guint64 +nm_wifi_ap_get_id (NMWifiAP *ap) { - g_return_val_if_fail (NM_IS_WIFI_AP (ap), NULL); + const char *path; + guint64 i; - return NM_WIFI_AP_GET_PRIVATE (ap)->ssid; + g_return_val_if_fail (NM_IS_WIFI_AP (ap), 0); + + path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)); + g_return_val_if_fail (path, 0); + + nm_assert (g_str_has_prefix (path, NM_DBUS_PATH_ACCESS_POINT"/")); + + i = _nm_utils_ascii_str_to_int64 (&path[NM_STRLEN (NM_DBUS_PATH_ACCESS_POINT"/")], 10, 1, G_MAXINT64, 0); + + nm_assert (i); + return i; } -static GVariant * -nm_wifi_ap_get_ssid_as_variant (const NMWifiAP *self) +const GByteArray * nm_wifi_ap_get_ssid (const NMWifiAP *ap) { - const NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (self); + g_return_val_if_fail (NM_IS_WIFI_AP (ap), NULL); - if (priv->ssid) { - return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - priv->ssid->data, priv->ssid->len, 1); - } else - return g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0); + return NM_WIFI_AP_GET_PRIVATE (ap)->ssid; } gboolean @@ -322,7 +330,7 @@ guint32 nm_wifi_ap_get_max_bitrate (NMWifiAP *ap) { g_return_val_if_fail (NM_IS_WIFI_AP (ap), 0); - g_return_val_if_fail (nm_dbus_object_is_exported (NM_DBUS_OBJECT (ap)), 0); + g_return_val_if_fail (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (ap)), 0); return NM_WIFI_AP_GET_PRIVATE (ap)->max_bitrate; } @@ -407,9 +415,7 @@ security_from_vardict (GVariant *security) && array) { if (g_strv_contains (array, "wpa-psk")) flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; - if (g_strv_contains (array, "wpa-eap") || - g_strv_contains (array, "wpa-fils-sha256") || - g_strv_contains (array, "wpa-fils-sha384")) + if (g_strv_contains (array, "wpa-eap")) flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X; g_free (array); } @@ -630,7 +636,7 @@ get_max_rate_vht_160_ss3 (int mcs) static gboolean get_max_rate_ht (const guint8 *bytes, guint len, guint32 *out_maxrate) { - guint32 i; + guint32 mcs, i; guint8 ht_cap_info; const guint8 *supported_mcs_set; guint32 rate; @@ -647,6 +653,7 @@ get_max_rate_ht (const guint8 *bytes, guint len, guint32 *out_maxrate) *out_maxrate = 0; /* Find the maximum supported mcs rate */ + mcs = -1; for (i = 0; i <= 76; i++) { unsigned int mcs_octet = i / 8; unsigned int MCS_RATE_BIT = 1 << i % 8; @@ -970,7 +977,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self, if (priv->supplicant_path) supplicant_id = strrchr (priv->supplicant_path, '/') ?: supplicant_id; - export_path = nm_dbus_object_get_path (NM_DBUS_OBJECT (self)); + export_path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (self)); if (export_path) export_path = strrchr (export_path, '/') ?: export_path; else @@ -1112,8 +1119,8 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMWifiAP *self = NM_WIFI_AP (object); - NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (self); + NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE ((NMWifiAP *) object); + GVariant *ssid; switch (prop_id) { case PROP_FLAGS: @@ -1126,7 +1133,12 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->rsn_flags); break; case PROP_SSID: - g_value_take_variant (value, nm_wifi_ap_get_ssid_as_variant (self)); + if (priv->ssid) { + ssid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + priv->ssid->data, priv->ssid->len, 1); + } else + ssid = g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0); + g_value_take_variant (value, ssid); break; case PROP_FREQUENCY: g_value_set_uint (value, priv->freq); @@ -1158,15 +1170,9 @@ get_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_wifi_ap_init (NMWifiAP *self) +nm_wifi_ap_init (NMWifiAP *ap) { - NMWifiAPPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_WIFI_AP, NMWifiAPPrivate); - - self->_priv = priv; - - c_list_init (&self->aps_lst); + NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (ap); priv->mode = NM_802_11_MODE_INFRA; priv->flags = NM_802_11_AP_FLAGS_NONE; @@ -1326,11 +1332,7 @@ error: static void finalize (GObject *object) { - NMWifiAP *self = NM_WIFI_AP (object); - NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (self); - - nm_assert (!self->wifi_device); - nm_assert (c_list_is_empty (&self->aps_lst)); + NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE ((NMWifiAP *) object); g_free (priv->supplicant_path); if (priv->ssid) @@ -1340,28 +1342,6 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_wifi_ap_parent_class)->finalize (object); } -static const NMDBusInterfaceInfoExtended interface_info_access_point = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_ACCESS_POINT, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Flags", "u", NM_WIFI_AP_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WpaFlags", "u", NM_WIFI_AP_WPA_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("RsnFlags", "u", NM_WIFI_AP_RSN_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ssid", "ay", NM_WIFI_AP_SSID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Frequency", "u", NM_WIFI_AP_FREQUENCY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_WIFI_AP_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "u", NM_WIFI_AP_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("MaxBitrate", "u", NM_WIFI_AP_MAX_BITRATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Strength", "y", NM_WIFI_AP_STRENGTH), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("LastSeen", "i", NM_WIFI_AP_LAST_SEEN), - ), - ), - .legacy_property_changed = TRUE, -}; - static void nm_wifi_ap_class_init (NMWifiAPClass *ap_class) { @@ -1379,12 +1359,9 @@ nm_wifi_ap_class_init (NMWifiAPClass *ap_class) | NM_802_11_AP_SEC_KEY_MGMT_802_1X ) GObjectClass *object_class = G_OBJECT_CLASS (ap_class); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (ap_class); - - g_type_class_add_private (object_class, sizeof (NMWifiAPPrivate)); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (ap_class); - dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH_ACCESS_POINT); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_access_point); + exported_object_class->export_path = NM_EXPORT_PATH_NUMBERED (NM_DBUS_PATH_ACCESS_POINT); object_class->get_property = get_property; object_class->finalize = finalize; @@ -1447,85 +1424,9 @@ nm_wifi_ap_class_init (NMWifiAPClass *ap_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} - -/*****************************************************************************/ -const char ** -nm_wifi_aps_get_paths (const CList *aps_lst_head, gboolean include_without_ssid) -{ - NMWifiAP *ap; - gsize i, n; - const char **list; - const char *path; - - n = c_list_length (aps_lst_head); - list = g_new (const char *, n + 1); - - i = 0; - if (n > 0) { - c_list_for_each_entry (ap, aps_lst_head, aps_lst) { - nm_assert (i < n); - if ( !include_without_ssid - && !nm_wifi_ap_get_ssid (ap)) - continue; - - path = nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)); - nm_assert (path); - - list[i++] = path; - } - nm_assert (i <= n); - nm_assert (!include_without_ssid || i == n); - } - list[i] = NULL; - return list; + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ap_class), + NMDBUS_TYPE_ACCESS_POINT_SKELETON, + NULL); } -NMWifiAP * -nm_wifi_aps_find_first_compatible (const CList *aps_lst_head, - NMConnection *connection) -{ - NMWifiAP *ap; - - g_return_val_if_fail (connection, NULL); - - c_list_for_each_entry (ap, aps_lst_head, aps_lst) { - if (nm_wifi_ap_check_compatible (ap, connection)) - return ap; - } - return NULL; -} - -NMWifiAP * -nm_wifi_aps_find_by_supplicant_path (const CList *aps_lst_head, const char *path) -{ - NMWifiAP *ap; - - g_return_val_if_fail (path != NULL, NULL); - - c_list_for_each_entry (ap, aps_lst_head, aps_lst) { - if (nm_streq0 (path, nm_wifi_ap_get_supplicant_path (ap))) - return ap; - } - return NULL; -} - -/*****************************************************************************/ - -NMWifiAP * -nm_wifi_ap_lookup_for_device (NMDevice *device, const char *exported_path) -{ - NMWifiAP *ap; - - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - - ap = (NMWifiAP *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (device)), - exported_path); - if ( !ap - || !NM_IS_WIFI_AP (ap) - || ap->wifi_device != device) - return NULL; - - return ap; -} diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 4fdeee93..dd5a4ad1 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -22,7 +22,7 @@ #ifndef __NM_WIFI_AP_H__ #define __NM_WIFI_AP_H__ -#include "nm-dbus-object.h" +#include "nm-exported-object.h" #include "nm-dbus-interface.h" #include "nm-connection.h" @@ -44,13 +44,7 @@ #define NM_WIFI_AP_STRENGTH "strength" #define NM_WIFI_AP_LAST_SEEN "last-seen" -typedef struct { - NMDBusObject parent; - NMDevice *wifi_device; - CList aps_lst; - struct _NMWifiAPPrivate *_priv; -} NMWifiAP; - +typedef struct _NMWifiAP NMWifiAP; typedef struct _NMWifiAPClass NMWifiAPClass; GType nm_wifi_ap_get_type (void); @@ -72,6 +66,7 @@ gboolean nm_wifi_ap_complete_connection (NMWifiAP *self, GError **error); const char * nm_wifi_ap_get_supplicant_path (NMWifiAP *ap); +guint64 nm_wifi_ap_get_id (NMWifiAP *ap); const GByteArray *nm_wifi_ap_get_ssid (const NMWifiAP *ap); gboolean nm_wifi_ap_set_ssid (NMWifiAP *ap, const guint8 *ssid, @@ -100,14 +95,4 @@ const char *nm_wifi_ap_to_string (const NMWifiAP *self, gulong buf_len, gint32 now_s); -const char **nm_wifi_aps_get_paths (const CList *aps_lst_head, - gboolean include_without_ssid); - -NMWifiAP *nm_wifi_aps_find_first_compatible (const CList *aps_lst_head, - NMConnection *connection); - -NMWifiAP *nm_wifi_aps_find_by_supplicant_path (const CList *aps_lst_head, const char *path); - -NMWifiAP *nm_wifi_ap_lookup_for_device (NMDevice *device, const char *exported_path); - #endif /* __NM_WIFI_AP_H__ */ diff --git a/src/devices/wifi/nm-wifi-common.c b/src/devices/wifi/nm-wifi-common.c deleted file mode 100644 index 47c0ce67..00000000 --- a/src/devices/wifi/nm-wifi-common.c +++ /dev/null @@ -1,205 +0,0 @@ -/*-*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-wifi-common.h" - -#include "devices/nm-device.h" -#include "nm-wifi-ap.h" -#include "nm-device-wifi.h" -#include "nm-dbus-manager.h" - -#if WITH_IWD -#include "nm-device-iwd.h" -#endif - -/*****************************************************************************/ - -void -nm_device_wifi_emit_signal_access_point (NMDevice *device, - NMWifiAP *ap, - gboolean is_added /* or else is_removed */) -{ - nm_dbus_object_emit_signal (NM_DBUS_OBJECT (device), - &nm_interface_info_device_wireless, - is_added - ? &nm_signal_info_wireless_access_point_added - : &nm_signal_info_wireless_access_point_removed, - "(o)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); -} - -/*****************************************************************************/ - -static const CList * -_dispatch_get_aps (NMDevice *device) -{ -#if WITH_IWD - if (NM_IS_DEVICE_IWD (device)) - return _nm_device_iwd_get_aps (NM_DEVICE_IWD (device)); -#endif - return _nm_device_wifi_get_aps (NM_DEVICE_WIFI (device)); -} - -static void -_dispatch_request_scan (NMDevice *device, - GVariant *options, - GDBusMethodInvocation *invocation) -{ -#if WITH_IWD - if (NM_IS_DEVICE_IWD (device)) { - _nm_device_iwd_request_scan (NM_DEVICE_IWD (device), - options, - invocation); - } -#endif - _nm_device_wifi_request_scan (NM_DEVICE_WIFI (device), - options, - invocation); -} - -static void -impl_device_wifi_get_access_points (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - gs_free const char **list = NULL; - GVariant *v; - const CList *all_aps; - - /* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */ - - all_aps = _dispatch_get_aps (NM_DEVICE (obj)); - list = nm_wifi_aps_get_paths (all_aps, FALSE); - v = g_variant_new_objv (list, -1); - g_dbus_method_invocation_return_value (invocation, - g_variant_new_tuple (&v, 1)); -} - -static void -impl_device_wifi_get_all_access_points (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - gs_free const char **list = NULL; - GVariant *v; - const CList *all_aps; - - /* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */ - - all_aps = _dispatch_get_aps (NM_DEVICE (obj)); - list = nm_wifi_aps_get_paths (all_aps, TRUE); - v = g_variant_new_objv (list, -1); - g_dbus_method_invocation_return_value (invocation, - g_variant_new_tuple (&v, 1)); -} - -static void -impl_device_wifi_request_scan (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - gs_unref_variant GVariant *options = NULL; - - /* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */ - - g_variant_get (parameters, "(@a{sv})", &options); - - _dispatch_request_scan (NM_DEVICE (obj), - options, - invocation); -} - -const GDBusSignalInfo nm_signal_info_wireless_access_point_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( - "AccessPointAdded", - .args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("access_point", "o"), - ), -); - -const GDBusSignalInfo nm_signal_info_wireless_access_point_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( - "AccessPointRemoved", - .args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("access_point", "o"), - ), -); - -const NMDBusInterfaceInfoExtended nm_interface_info_device_wireless = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_WIRELESS, - .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetAccessPoints", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("access_points", "ao"), - ), - ), - .handle = impl_device_wifi_get_access_points, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetAllAccessPoints", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("access_points", "ao"), - ), - ), - .handle = impl_device_wifi_get_all_access_points, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "RequestScan", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("options", "a{sv}"), - ), - ), - .handle = impl_device_wifi_request_scan, - ), - ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - &nm_signal_info_wireless_access_point_added, - &nm_signal_info_wireless_access_point_removed, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PermHwAddress", "s", NM_DEVICE_PERM_HW_ADDRESS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "u", NM_DEVICE_WIFI_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("BitRate", "u", NM_DEVICE_WIFI_BITRATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("AccessPoints", "ao", NM_DEVICE_WIFI_ACCESS_POINTS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ActiveAccessPoint", "o", NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WirelessCapabilities", "u", NM_DEVICE_WIFI_CAPABILITIES), - ), - ), - .legacy_property_changed = TRUE, -}; diff --git a/src/devices/wifi/nm-wifi-common.h b/src/devices/wifi/nm-wifi-common.h deleted file mode 100644 index 91cbeb55..00000000 --- a/src/devices/wifi/nm-wifi-common.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. - */ - -#ifndef __NM_WIFI_COMMON_H__ -#define __NM_WIFI_COMMON_H__ - -#include "nm-dbus-utils.h" -#include "nm-wifi-ap.h" - -/*****************************************************************************/ - -void nm_device_wifi_emit_signal_access_point (NMDevice *device, - NMWifiAP *ap, - gboolean is_added /* or else is_removed */); - -extern const NMDBusInterfaceInfoExtended nm_interface_info_device_wireless; -extern const GDBusSignalInfo nm_signal_info_wireless_access_point_added; -extern const GDBusSignalInfo nm_signal_info_wireless_access_point_removed; - -#endif /* __NM_WIFI_COMMON_H__ */ diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c index 6b8e5fb8..a1752634 100644 --- a/src/devices/wifi/nm-wifi-factory.c +++ b/src/devices/wifi/nm-wifi-factory.c @@ -27,10 +27,8 @@ #include "nm-setting-olpc-mesh.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" -#include "nm-device-iwd.h" #include "settings/nm-settings-connection.h" #include "platform/nm-platform.h" -#include "nm-config.h" /*****************************************************************************/ @@ -77,7 +75,6 @@ create_device (NMDeviceFactory *factory, { NMDeviceWifiCapabilities capabilities; NM80211Mode mode; - gs_free char *backend = NULL; g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (plink != NULL, NULL); @@ -101,30 +98,10 @@ create_device (NMDeviceFactory *factory, return NULL; } - if (plink->type != NM_LINK_TYPE_WIFI) - return nm_device_olpc_mesh_new (iface); - - backend = nm_config_data_get_device_config_by_pllink (NM_CONFIG_GET_DATA, - NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_BACKEND, - plink, - "wifi", - NULL); - nm_strstrip (backend); - - nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI, - "(%s) config: backend is %s%s%s%s", - iface, - NM_PRINT_FMT_QUOTE_STRING (backend), - WITH_IWD ? " (iwd support enabled)" : ""); - if (!backend || !strcasecmp (backend, "wpa_supplicant")) + if (plink->type == NM_LINK_TYPE_WIFI) return nm_device_wifi_new (iface, capabilities); -#if WITH_IWD - else if (!strcasecmp (backend, "iwd")) - return nm_device_iwd_new (iface, capabilities); -#endif - - nm_log_warn (LOGD_PLATFORM | LOGD_WIFI, "(%s) config: unknown or unsupported wifi-backend %s", iface, backend); - return NULL; + else + return nm_device_olpc_mesh_new (iface); } /*****************************************************************************/ diff --git a/src/devices/wifi/nm-wifi-utils.c b/src/devices/wifi/nm-wifi-utils.c index 044bd392..3ff82004 100644 --- a/src/devices/wifi/nm-wifi-utils.c +++ b/src/devices/wifi/nm-wifi-utils.c @@ -782,35 +782,3 @@ nm_wifi_utils_level_to_quality (gint val) return CLAMP (val, 0, 100); } -gboolean -nm_wifi_utils_is_manf_default_ssid (const GByteArray *ssid) -{ - int i; - /* - * List of manufacturer default SSIDs that are often unchanged by users. - * - * NOTE: this list should *not* contain networks that you would like to - * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot". - */ - static const char *manf_defaults[] = { - "linksys", - "linksys-a", - "linksys-g", - "default", - "belkin54g", - "NETGEAR", - "o2DSL", - "WLAN", - "ALICE-WLAN", - "Speedport W 501V", - "TURBONETT", - }; - - for (i = 0; i < G_N_ELEMENTS (manf_defaults); i++) { - if (ssid->len == strlen (manf_defaults[i])) { - if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0) - return TRUE; - } - } - return FALSE; -} diff --git a/src/devices/wifi/nm-wifi-utils.h b/src/devices/wifi/nm-wifi-utils.h index def64dd6..1b6c2f4b 100644 --- a/src/devices/wifi/nm-wifi-utils.h +++ b/src/devices/wifi/nm-wifi-utils.h @@ -39,6 +39,4 @@ gboolean nm_wifi_utils_complete_connection (const GByteArray *ssid, guint32 nm_wifi_utils_level_to_quality (gint val); -gboolean nm_wifi_utils_is_manf_default_ssid (const GByteArray *ssid); - #endif /* __NM_WIFI_UTILS_H__ */ diff --git a/src/devices/wifi/tests/meson.build b/src/devices/wifi/tests/meson.build deleted file mode 100644 index bb8f7c27..00000000 --- a/src/devices/wifi/tests/meson.build +++ /dev/null @@ -1,13 +0,0 @@ -test_unit = 'test-general' - -exe = executable( - 'wifi-' + test_unit, - [test_unit + '.c'] + common_sources, - dependencies: test_nm_dep -) - -test( - 'devices/wifi/' + test_unit, - test_script, - args: test_args + [exe.full_path()] -) diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index 70b954c5..6efcb03f 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -11,10 +11,10 @@ global: nm_modem_get_capabilities; nm_modem_get_configured_mtu; nm_modem_get_control_port; + nm_modem_get_data_port; nm_modem_get_driver; nm_modem_get_iid; nm_modem_get_path; - nm_modem_get_ip_ifindex; nm_modem_get_secrets; nm_modem_get_state; nm_modem_get_type; diff --git a/src/devices/wwan/meson.build b/src/devices/wwan/meson.build deleted file mode 100644 index 032b3585..00000000 --- a/src/devices/wwan/meson.build +++ /dev/null @@ -1,75 +0,0 @@ -sources = files( - 'nm-modem-broadband.c', - 'nm-modem.c', - 'nm-modem-manager.c' -) - -deps = [ - libsystemd_dep, - mm_glib_dep, - nm_dep -] - -if enable_ofono - sources += files('nm-modem-ofono.c') -endif - -linker_script = join_paths(meson.current_source_dir(), 'libnm-wwan.ver') - -libnm_wwan = shared_module( - 'nm-wwan', - sources: sources, - dependencies: deps, - link_args: [ - '-Wl,--version-script,@0@'.format(linker_script), - ], - link_depends: linker_script, - install: true, - install_dir: nm_pkglibdir -) - -libnm_wwan_dep = declare_dependency( - include_directories: include_directories('.'), - link_with: libnm_wwan -) - -core_plugins += libnm_wwan - -run_target( - 'check-wwan', - command: [check_exports, libnm_wwan.full_path(), linker_script], - depends: libnm_wwan -) - -sources = files( - 'nm-device-modem.c', - 'nm-wwan-factory.c' -) - -libnm_device_plugin_wwan = shared_module( - 'nm-device-plugin-wwan', - sources: sources, - dependencies: deps, - link_with: libnm_wwan, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_pkglibdir -) - -core_plugins += libnm_device_plugin_wwan - -run_target( - 'check-local-devices-wwan', - command: [check_exports, libnm_device_plugin_wwan.full_path(), linker_script_devices], - depends: libnm_device_plugin_wwan -) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-wwan: src/devices/wwan/libnm-device-plugin-wwan.la src/devices/wwan/libnm-wwan.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so) - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-wwan.so "$(srcdir)/src/devices/wwan/libnm-wwan.ver" - $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-wwan.so) -''' diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 2a3e9ebe..b79d145d 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -32,6 +32,8 @@ #include "NetworkManagerUtils.h" #include "nm-core-internal.h" +#include "introspection/org.freedesktop.NetworkManager.Device.Modem.h" + #include "devices/nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceModem); @@ -258,26 +260,21 @@ modem_ip6_config_result (NMModem *modem, } static void -ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); - - if (!nm_device_is_activating (device)) - return; + NMDevice *self = NM_DEVICE (user_data); + gboolean changed; - if (!nm_device_set_ip_ifindex (device, - nm_modem_get_ip_ifindex (modem))) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } + /* We set the IP iface in the device as soon as we know it, so that we + * properly ifup it if needed */ + changed = nm_device_set_ip_iface (self, nm_modem_get_data_port (modem)); /* Disable IPv6 immediately on the interface since NM handles IPv6 * internally, and leaving it enabled could allow the kernel's IPv6 * RA handling code to run before NM is ready. */ - nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); + if (changed) + nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); } static void @@ -434,7 +431,7 @@ static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); @@ -632,7 +629,11 @@ set_modem (NMDeviceModem *self, NMModem *modem) g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); - g_signal_connect (modem, "notify::" NM_MODEM_IP_IFINDEX, G_CALLBACK (ip_ifindex_changed_cb), self); + /* In the old ModemManager the data port is known from the very beginning; + * while in the new ModemManager the data port is set afterwards when the bearer gets + * created */ + g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); + g_signal_connect (modem, "notify::" NM_MODEM_DEVICE_ID, G_CALLBACK (ids_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_SIM_ID, G_CALLBACK (ids_changed_cb), self); g_signal_connect (modem, "notify::" NM_MODEM_SIM_OPERATOR_ID, G_CALLBACK (ids_changed_cb), self); @@ -707,23 +708,34 @@ nm_device_modem_new (NMModem *modem) { NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE; NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE; + NMDevice *device; + const char *data_port; g_return_val_if_fail (NM_IS_MODEM (modem), NULL); /* Load capabilities */ nm_modem_get_capabilities (modem, &caps, ¤t_caps); - return g_object_new (NM_TYPE_DEVICE_MODEM, - NM_DEVICE_UDI, nm_modem_get_path (modem), - NM_DEVICE_IFACE, nm_modem_get_uid (modem), - NM_DEVICE_DRIVER, nm_modem_get_driver (modem), - NM_DEVICE_TYPE_DESC, "Broadband", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, - NM_DEVICE_MODEM_MODEM, modem, - NM_DEVICE_MODEM_CAPABILITIES, caps, - NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, - NULL); + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_MODEM, + NM_DEVICE_UDI, nm_modem_get_path (modem), + NM_DEVICE_IFACE, nm_modem_get_uid (modem), + NM_DEVICE_DRIVER, nm_modem_get_driver (modem), + NM_DEVICE_TYPE_DESC, "Broadband", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WWAN, + NM_DEVICE_MODEM_MODEM, modem, + NM_DEVICE_MODEM_CAPABILITIES, caps, + NM_DEVICE_MODEM_CURRENT_CAPABILITIES, current_caps, + NULL); + + /* If the data port is known, set it as the IP interface immediately */ + data_port = nm_modem_get_data_port (modem); + if (data_port) { + nm_device_set_ip_iface (device, data_port); + nm_device_ipv6_sysctl_set (device, "disable_ipv6", "1"); + } + + return device; } static void @@ -731,41 +743,23 @@ dispose (GObject *object) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object); - if (priv->modem) { + if (priv->modem) g_signal_handlers_disconnect_by_data (priv->modem, NM_DEVICE_MODEM (object)); - g_clear_object (&priv->modem); - } + g_clear_object (&priv->modem); G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object); } -static const NMDBusInterfaceInfoExtended interface_info_device_modem = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DEVICE_MODEM, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ModemCapabilities", "u", NM_DEVICE_MODEM_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("CurrentCapabilities", "u", NM_DEVICE_MODEM_CURRENT_CAPABILITIES), - ), - ), - .legacy_property_changed = TRUE, -}; - static void -nm_device_modem_class_init (NMDeviceModemClass *klass) +nm_device_modem_class_init (NMDeviceModemClass *mclass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (mclass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (mclass); object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_modem); - device_class->get_generic_capabilities = get_generic_capabilities; device_class->get_type_description = get_type_description; device_class->check_connection_compatible = check_connection_compatible; @@ -808,4 +802,8 @@ nm_device_modem_class_init (NMDeviceModemClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (mclass), + NMDBUS_TYPE_DEVICE_MODEM_SKELETON, + NULL); } diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 9a3744db..dc0ce303 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -339,7 +339,7 @@ connect_context_clear (NMModemBroadband *self) ConnectContext *ctx = self->_priv.ctx; g_clear_error (&ctx->first_error); - g_clear_pointer (&ctx->ip_types, g_array_unref); + g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); nm_clear_g_cancellable (&ctx->cancellable); g_clear_object (&ctx->connection); g_clear_object (&ctx->connect_properties); @@ -385,10 +385,9 @@ connect_ready (MMModemSimple *simple_iface, g_dbus_error_strip_remote_error (error); ctx->first_error = error; } else - g_clear_error (&error); + g_error_free (error); - if ( ctx->ip_type_tries == 0 - && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) { + if (ctx->ip_type_tries == 0 && g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) { /* Try one more time */ ctx->ip_type_tries++; } else { @@ -411,20 +410,21 @@ connect_ready (MMModemSimple *simple_iface, if (self->_priv.ipv6_config) ip6_method = get_bearer_ip_method (self->_priv.ipv6_config); - if (!nm_modem_set_data_port (NM_MODEM (self), - NM_PLATFORM_GET, - mm_bearer_get_interface (self->_priv.bearer), - ip4_method, - ip6_method, - mm_bearer_get_ip_timeout (self->_priv.bearer), - &error)) { - _LOGW ("failed to connect modem: %s", error->message); - g_error_free (error); + if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && + ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { + _LOGW ("failed to connect modem: invalid bearer IP configuration"); nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); connect_context_clear (self); return; } + g_object_set (self, + NM_MODEM_DATA_PORT, mm_bearer_get_interface (self->_priv.bearer), + NM_MODEM_IP4_METHOD, ip4_method, + NM_MODEM_IP6_METHOD, ip6_method, + NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->_priv.bearer), + NULL); + ctx->step++; connect_context_step (self); } @@ -663,7 +663,7 @@ check_connection_compatible (NMModem *_self, NMConnection *connection) static gboolean complete_connection (NMModem *_self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); @@ -1409,34 +1409,35 @@ nm_modem_broadband_init (NMModemBroadband *self) NMModem * nm_modem_broadband_new (GObject *object, GError **error) { + NMModem *modem; MMObject *modem_object; MMModem *modem_iface; - const char *const*drivers; - gs_free char *driver = NULL; + gchar *drivers; g_return_val_if_fail (MM_IS_OBJECT (object), NULL); modem_object = MM_OBJECT (object); /* Ensure we have the 'Modem' interface and the primary port at least */ modem_iface = mm_object_peek_modem (modem_object); - g_return_val_if_fail (modem_iface, NULL); - g_return_val_if_fail (mm_modem_get_primary_port (modem_iface), NULL); + g_return_val_if_fail (!!modem_iface, NULL); + g_return_val_if_fail (!!mm_modem_get_primary_port (modem_iface), NULL); /* Build a single string with all drivers listed */ - drivers = mm_modem_get_drivers (modem_iface); - if (drivers) - driver = g_strjoinv (", ", (char **) drivers); - - return g_object_new (NM_TYPE_MODEM_BROADBAND, - NM_MODEM_PATH, mm_object_get_path (modem_object), - NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), - NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), - NM_MODEM_IP_TYPES, mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem_iface)), - NM_MODEM_STATE, (int) mm_state_to_nm (mm_modem_get_state (modem_iface)), - NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), - NM_MODEM_BROADBAND_MODEM, modem_object, - NM_MODEM_DRIVER, driver, - NULL); + drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers (modem_iface)); + + modem = g_object_new (NM_TYPE_MODEM_BROADBAND, + NM_MODEM_PATH, mm_object_get_path (modem_object), + NM_MODEM_UID, mm_modem_get_primary_port (modem_iface), + NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface), + NM_MODEM_DATA_PORT, NULL, /* We don't know it until bearer created */ + NM_MODEM_IP_TYPES, mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem_iface)), + NM_MODEM_STATE, (int) mm_state_to_nm (mm_modem_get_state (modem_iface)), + NM_MODEM_DEVICE_ID, mm_modem_get_device_identifier (modem_iface), + NM_MODEM_BROADBAND_MODEM, modem_object, + NM_MODEM_DRIVER, drivers, + NULL); + g_free (drivers); + return modem; } static void diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c index a1c6aef2..811c3afb 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/devices/wwan/nm-modem-ofono.c @@ -836,7 +836,6 @@ context_property_changed (GDBusProxy *proxy, guint32 address_network, gateway_network; guint32 ip4_route_table, ip4_route_metric; int ifindex; - GError *error = NULL; _LOGD ("PropertyChanged: %s", property); @@ -861,26 +860,27 @@ context_property_changed (GDBusProxy *proxy, _LOGW ("Settings 'Interface' missing"); goto out; } + if (!interface || !interface[0]) { + _LOGW ("Settings 'Interface'; empty"); + goto out; + } - _LOGD ("Interface: %s", interface); - if (!nm_modem_set_data_port (NM_MODEM (self), - NM_PLATFORM_GET, - interface, - NM_MODEM_IP_METHOD_STATIC, - NM_MODEM_IP_METHOD_UNKNOWN, - 0, - &error)) { - _LOGW ("failed to connect to modem: %s", error->message); - g_clear_error (&error); + ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, interface); + if (ifindex <= 0) { + _LOGW ("Interface \"%s\" not found", interface); goto out; } - ifindex = nm_modem_get_ip_ifindex (NM_MODEM (self)); - nm_assert (ifindex > 0); + _LOGD ("Interface: %s", interface); + g_object_set (self, + NM_MODEM_DATA_PORT, interface, + NM_MODEM_IP4_METHOD, NM_MODEM_IP_METHOD_STATIC, + NULL); /* TODO: verify handling of ip4_config; check other places it's used... */ g_clear_object (&priv->ip4_config); + priv->ip4_config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex); diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 61b7247e..010a2b60 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -44,10 +44,13 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMModem, PROP_CONTROL_PORT, - PROP_IP_IFINDEX, + PROP_DATA_PORT, PROP_PATH, PROP_UID, PROP_DRIVER, + PROP_IP4_METHOD, + PROP_IP6_METHOD, + PROP_IP_TIMEOUT, PROP_STATE, PROP_DEVICE_ID, PROP_SIM_ID, @@ -76,12 +79,7 @@ typedef struct _NMModemPrivate { char *driver; char *control_port; char *data_port; - - /* TODO: ip_iface is solely used for nm_modem_owns_port(). - * We should rework the code that it's not necessary */ - char *ip_iface; - - int ip_ifindex; + char *ppp_iface; NMModemIPMethod ip4_method; NMModemIPMethod ip6_method; NMUtilsIPv6IfaceId iid; @@ -98,7 +96,7 @@ typedef struct _NMModemPrivate { guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; - guint mm_ip_timeout; + guint32 mm_ip_timeout; guint32 ip4_route_table; guint32 ip4_route_metric; @@ -155,10 +153,6 @@ _nmlog_prefix (char *prefix, NMModem *self) } G_STMT_END /*****************************************************************************/ - -static void _set_ip_ifindex (NMModem *self, int ifindex, const char *ifname); - -/*****************************************************************************/ /* State/enabled/connected */ static const char *state_table[] = { @@ -456,28 +450,20 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -ppp_ifindex_set (NMPPPManager *ppp_manager, - int ifindex, - const char *iface, - gpointer user_data) +set_data_port (NMModem *self, const char *new_data_port) { - NMModem *self = NM_MODEM (user_data); - - nm_assert (ifindex >= 0); - nm_assert (NM_MODEM_GET_PRIVATE (self)->ppp_manager == ppp_manager); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - if (ifindex <= 0 && iface) { - /* this might happen, if the ifname was already deleted - * and we failed to resolve ifindex. - * - * Forget about the name. */ - iface = NULL; + if (g_strcmp0 (priv->data_port, new_data_port) != 0) { + g_free (priv->data_port); + priv->data_port = g_strdup (new_data_port); + _notify (self, PROP_DATA_PORT); } - _set_ip_ifindex (self, ifindex, iface); } static void ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, NMIP4Config *config, gpointer user_data) { @@ -489,6 +475,9 @@ ppp_ip4_config (NMPPPManager *ppp_manager, guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ gboolean dns_workaround = FALSE; + /* Notify about the new data port to use */ + set_data_port (self, iface); + /* Work around a PPP bug (#1732) which causes many mobile broadband * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. * Apparently fixed in ppp-2.4.5 but we've had some reports that this is @@ -530,12 +519,16 @@ ppp_ip4_config (NMPPPManager *ppp_manager, static void ppp_ip6_config (NMPPPManager *ppp_manager, + const char *iface, const NMUtilsIPv6IfaceId *iid, NMIP6Config *config, gpointer user_data) { NMModem *self = NM_MODEM (user_data); + /* Notify about the new data port to use */ + set_data_port (self, iface); + NM_MODEM_GET_PRIVATE (self)->iid = *iid; nm_modem_emit_ip6_config_result (self, config, NULL); @@ -564,18 +557,6 @@ port_speed_is_zero (const char *port) { struct termios options; nm_auto_close int fd = -1; - gs_free char *path = NULL; - - nm_assert (port); - - if (port[0] != '/') { - if ( !port[0] - || strchr (port, '/') - || NM_IN_STRSET (port, ".", "..")) - return FALSE; - path = g_build_path ("/sys/class/tty", port, NULL); - port = path; - } fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC); if (fd < 0) @@ -617,12 +598,6 @@ ppp_stage3_ip_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_FAILURE; } - if (!priv->data_port) { - _LOGE ("error starting PPP (no data port)"); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, * use the default one (30s) */ if (priv->mm_ip_timeout > 0) { @@ -654,7 +629,9 @@ ppp_stage3_ip_config_start (NMModem *self, ip_timeout, baud_override, &error)) { _LOGE ("error starting PPP: %s", error->message); g_error_free (error); + g_clear_object (&priv->ppp_manager); + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -662,9 +639,6 @@ ppp_stage3_ip_config_start (NMModem *self, g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK (ppp_ifindex_set), - self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -1091,20 +1065,12 @@ nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { - NMModemClass *klass; - - klass = NM_MODEM_GET_CLASS (self); - if (!klass->complete_connection) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, - "Modem class %s had no complete_connection method", - G_OBJECT_TYPE_NAME (self)); - return FALSE; - } - - return klass->complete_connection (self, connection, existing_connections, error); + if (NM_MODEM_GET_CLASS (self)->complete_connection) + return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); + return FALSE; } /*****************************************************************************/ @@ -1129,10 +1095,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - if (priv->ppp_manager) { - g_signal_handlers_disconnect_by_data (priv->ppp_manager, self); - g_clear_object (&priv->ppp_manager); - } + g_clear_object (&priv->ppp_manager); if (device) { g_return_if_fail (NM_IS_DEVICE (device)); @@ -1151,12 +1114,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device) } } } - - nm_clear_g_free (&priv->data_port); - priv->mm_ip_timeout = 0; priv->ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; priv->ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - _set_ip_ifindex (self, -1, NULL); + + g_free (priv->ppp_iface); + priv->ppp_iface = NULL; } /*****************************************************************************/ @@ -1407,117 +1369,17 @@ nm_modem_get_control_port (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->control_port; } -int -nm_modem_get_ip_ifindex (NMModem *self) -{ - NMModemPrivate *priv; - - g_return_val_if_fail (NM_IS_MODEM (self), 0); - - priv = NM_MODEM_GET_PRIVATE (self); - - /* internally we track an unset ip_ifindex as -1. - * For the caller of nm_modem_get_ip_ifindex(), this - * shall be zero too. */ - return priv->ip_ifindex != -1 ? priv->ip_ifindex : 0; -} - -static void -_set_ip_ifindex (NMModem *self, int ifindex, const char *ifname) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - nm_assert (ifindex >= -1); - nm_assert ((ifindex > 0) == !!ifname); - - if (!nm_streq0 (priv->ip_iface, ifname)) { - g_free (priv->ip_iface); - priv->ip_iface = g_strdup (ifname); - } - - if (priv->ip_ifindex != ifindex) { - priv->ip_ifindex = ifindex; - _notify (self, PROP_IP_IFINDEX); - } -} - -gboolean -nm_modem_set_data_port (NMModem *self, - NMPlatform *platform, - const char *data_port, - NMModemIPMethod ip4_method, - NMModemIPMethod ip6_method, - guint timeout, - GError **error) +const char * +nm_modem_get_data_port (NMModem *self) { - NMModemPrivate *priv; - gboolean is_ppp; - int ifindex = -1; - - g_return_val_if_fail (NM_IS_MODEM (self), FALSE); - g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); - g_return_val_if_fail (!error || !*error, FALSE); - - priv = NM_MODEM_GET_PRIVATE (self); - - if ( priv->ppp_manager - || priv->data_port - || priv->ip_ifindex != -1) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot set data port in activated state"); - /* this really shouldn't happen. Assert. */ - g_return_val_if_reached (FALSE); - } - - if (!data_port) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "missing data port"); - return FALSE; - } - - is_ppp = (ip4_method == NM_MODEM_IP_METHOD_PPP) - || (ip6_method == NM_MODEM_IP_METHOD_PPP); - if (is_ppp) { - if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP) - || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "conflicting ip methods"); - return FALSE; - } - } else if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) - || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) - || ( ip4_method == NM_MODEM_IP_METHOD_UNKNOWN - && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "invalid ip methods"); - return FALSE; - } - - if (!is_ppp) { - ifindex = nm_platform_if_nametoindex (platform, data_port); - if (ifindex <= 0) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot find network interface %s", data_port); - return FALSE; - } - if (!nm_platform_process_events_ensure_link (platform, ifindex, data_port)) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot find network interface %s in platform cache", data_port); - return FALSE; - } - } + g_return_val_if_fail (NM_IS_MODEM (self), NULL); - priv->mm_ip_timeout = timeout; - priv->ip4_method = ip4_method; - priv->ip6_method = ip6_method; - if (is_ppp) { - priv->data_port = g_strdup (data_port); - _set_ip_ifindex (self, -1, NULL); - } else { - priv->data_port = NULL; - _set_ip_ifindex (self, ifindex, data_port); - } - return TRUE; + /* The ppp_iface takes precedence over the data interface when PPP is used, + * since data_iface is the TTY over which PPP is run, and that TTY can't + * do IP. The caller really wants the thing that's doing IP. + */ + return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? + NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; } gboolean @@ -1530,10 +1392,15 @@ nm_modem_owns_port (NMModem *self, const char *iface) if (NM_MODEM_GET_CLASS (self)->owns_port) return NM_MODEM_GET_CLASS (self)->owns_port (self, iface); - return NM_IN_STRSET (iface, - priv->ip_iface, - priv->data_port, - priv->control_port); + /* Fall back to data/control ports */ + if (priv->ppp_iface && (strcmp (priv->ppp_iface, iface) == 0)) + return TRUE; + if (priv->data_port && (strcmp (priv->data_port, iface) == 0)) + return TRUE; + if (priv->control_port && (strcmp (priv->control_port, iface) == 0)) + return TRUE; + + return FALSE; } gboolean @@ -1633,8 +1500,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModem *self = NM_MODEM (object); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE ((NMModem *) object); switch (prop_id) { case PROP_PATH: @@ -1646,12 +1512,21 @@ get_property (GObject *object, guint prop_id, case PROP_CONTROL_PORT: g_value_set_string (value, priv->control_port); break; - case PROP_IP_IFINDEX: - g_value_set_int (value, nm_modem_get_ip_ifindex (self)); + case PROP_DATA_PORT: + g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); break; case PROP_UID: g_value_set_string (value, priv->uid); break; + case PROP_IP4_METHOD: + g_value_set_uint (value, priv->ip4_method); + break; + case PROP_IP6_METHOD: + g_value_set_uint (value, priv->ip6_method); + break; + case PROP_IP_TIMEOUT: + g_value_set_uint (value, priv->mm_ip_timeout); + break; case PROP_STATE: g_value_set_int (value, priv->state); break; @@ -1694,10 +1569,23 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->control_port = g_value_dup_string (value); break; + case PROP_DATA_PORT: + g_free (priv->data_port); + priv->data_port = g_value_dup_string (value); + break; case PROP_UID: /* construct-only */ priv->uid = g_value_dup_string (value); break; + case PROP_IP4_METHOD: + priv->ip4_method = g_value_get_uint (value); + break; + case PROP_IP6_METHOD: + priv->ip6_method = g_value_get_uint (value); + break; + case PROP_IP_TIMEOUT: + priv->mm_ip_timeout = g_value_get_uint (value); + break; case PROP_STATE: /* construct-only */ priv->state = g_value_get_int (value); @@ -1735,7 +1623,6 @@ nm_modem_init (NMModem *self) self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate); priv = self->_priv; - priv->ip_ifindex = -1; priv->ip4_route_table = RT_TABLE_MAIN; priv->ip4_route_metric = 700; priv->ip6_route_table = RT_TABLE_MAIN; @@ -1751,7 +1638,7 @@ constructed (GObject *object) priv = NM_MODEM_GET_PRIVATE (NM_MODEM (object)); - g_return_if_fail (priv->control_port); + g_return_if_fail (priv->data_port || priv->control_port); } /*****************************************************************************/ @@ -1776,7 +1663,6 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->control_port); g_free (priv->data_port); - g_free (priv->ip_iface); g_free (priv->device_id); g_free (priv->sim_id); g_free (priv->sim_operator_id); @@ -1825,11 +1711,33 @@ nm_modem_class_init (NMModemClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IP_IFINDEX] = - g_param_spec_int (NM_MODEM_IP_IFINDEX, "", "", - 0, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DATA_PORT] = + g_param_spec_string (NM_MODEM_DATA_PORT, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP4_METHOD] = + g_param_spec_uint (NM_MODEM_IP4_METHOD, "", "", + NM_MODEM_IP_METHOD_UNKNOWN, + NM_MODEM_IP_METHOD_AUTO, + NM_MODEM_IP_METHOD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP6_METHOD] = + g_param_spec_uint (NM_MODEM_IP6_METHOD, "", "", + NM_MODEM_IP_METHOD_UNKNOWN, + NM_MODEM_IP_METHOD_AUTO, + NM_MODEM_IP_METHOD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP_TIMEOUT] = + g_param_spec_uint (NM_MODEM_IP_TIMEOUT, "", "", + 0, 360, 20, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATE] = g_param_spec_int (NM_MODEM_STATE, "", "", diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index 3e281c0c..9546e4a1 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -37,7 +37,10 @@ #define NM_MODEM_PATH "path" #define NM_MODEM_DRIVER "driver" #define NM_MODEM_CONTROL_PORT "control-port" -#define NM_MODEM_IP_IFINDEX "ip-ifindex" +#define NM_MODEM_DATA_PORT "data-port" +#define NM_MODEM_IP4_METHOD "ip4-method" +#define NM_MODEM_IP6_METHOD "ip6-method" +#define NM_MODEM_IP_TIMEOUT "ip-timeout" #define NM_MODEM_STATE "state" #define NM_MODEM_DEVICE_ID "device-id" #define NM_MODEM_SIM_ID "sim-id" @@ -126,7 +129,7 @@ typedef struct { gboolean (*complete_connection) (NMModem *modem, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error); NMActStageReturn (*act_stage1_prepare) (NMModem *modem, @@ -164,21 +167,13 @@ GType nm_modem_get_type (void); const char *nm_modem_get_path (NMModem *modem); const char *nm_modem_get_uid (NMModem *modem); const char *nm_modem_get_control_port (NMModem *modem); -int nm_modem_get_ip_ifindex (NMModem *modem); +const char *nm_modem_get_data_port (NMModem *modem); const char *nm_modem_get_driver (NMModem *modem); const char *nm_modem_get_device_id (NMModem *modem); const char *nm_modem_get_sim_id (NMModem *modem); const char *nm_modem_get_sim_operator_id (NMModem *modem); gboolean nm_modem_get_iid (NMModem *modem, NMUtilsIPv6IfaceId *out_iid); -gboolean nm_modem_set_data_port (NMModem *self, - NMPlatform *platform, - const char *data_port, - NMModemIPMethod ip4_method, - NMModemIPMethod ip6_method, - guint timeout, - GError **error); - gboolean nm_modem_owns_port (NMModem *modem, const char *iface); void nm_modem_get_capabilities (NMModem *self, @@ -189,7 +184,7 @@ gboolean nm_modem_check_connection_compatible (NMModem *self, NMConnection *conn gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error); void nm_modem_get_route_parameters (NMModem *self, diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index f0aae040..663102de 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -80,7 +80,7 @@ modem_added_cb (NMModemManager *manager, { NMWwanFactory *self = NM_WWAN_FACTORY (user_data); NMDevice *device; - const char *driver; + const char *driver, *port; /* Do nothing if the modem was consumed by some other plugin */ if (nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (self), G_OBJECT (modem))) @@ -93,8 +93,10 @@ modem_added_cb (NMModemManager *manager, * by the Bluetooth code during the connection process. */ if (driver && strstr (driver, "bluetooth")) { - nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", - nm_modem_get_control_port (modem)); + port = nm_modem_get_data_port (modem); + if (!port) + port = nm_modem_get_control_port (modem); + nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", port); return; } |