diff options
Diffstat (limited to 'src/devices')
50 files changed, 2612 insertions, 1481 deletions
diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index d3f1423f..a3fa4901 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -18,13 +18,12 @@ * Copyright (C) 2009 - 2013 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <gudev/gudev.h> #include <gmodule.h> -#include "nm-default.h" #include "nm-atm-manager.h" #include "nm-setting-adsl.h" #include "nm-device-adsl.h" diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index dd9a1203..e7a91e0a 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -18,7 +18,7 @@ * Pantelis Koukousoulas <pktoss@gmail.com> */ -#include "config.h" +#include "nm-default.h" #include <sys/socket.h> #include <linux/atmdev.h> @@ -32,7 +32,6 @@ #include <stdlib.h> #include <string.h> -#include "nm-default.h" #include "nm-device-adsl.h" #include "nm-device-private.h" #include "nm-enum-types.h" @@ -449,7 +448,6 @@ act_stage3_ip4_config_start (NMDevice *device, { NMDeviceAdsl *self = NM_DEVICE_ADSL (device); NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); - NMConnection *connection; NMSettingAdsl *s_adsl; NMActRequest *req; GError *err = NULL; @@ -458,11 +456,7 @@ act_stage3_ip4_config_start (NMDevice *device, req = nm_device_get_act_request (device); g_assert (req); - - connection = nm_act_request_get_applied_connection (req); - g_assert (req); - - s_adsl = nm_connection_get_setting_adsl (connection); + s_adsl = (NMSettingAdsl *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_ADSL); g_assert (s_adsl); /* PPPoE uses the NAS interface, not the ATM interface */ diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/devices/bluetooth/nm-bluez-common.h index 4262fa76..67810b94 100644 --- a/src/devices/bluetooth/nm-bluez-common.h +++ b/src/devices/bluetooth/nm-bluez-common.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_BLUEZ_COMMON_H__ #define __NETWORKMANAGER_BLUEZ_COMMON_H__ -#include "config.h" - #define BLUETOOTH_CONNECT_DUN "dun" #define BLUETOOTH_CONNECT_NAP "nap" diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index b7032143..71226813 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -19,11 +19,10 @@ * Copyright (C) 2013 Intel Corporation. */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include "nm-default.h" #include "nm-core-internal.h" #include "nm-bt-error.h" @@ -1014,7 +1013,7 @@ nm_bluez_device_new (const char *path, const char *interface_name = NULL; g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (provider != NULL, NULL); + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (provider), NULL); g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL); self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, @@ -1028,7 +1027,7 @@ nm_bluez_device_new (const char *path, priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); priv->bluez_version = bluez_version; - priv->provider = provider; + priv->provider = g_object_ref (provider); g_return_val_if_fail (bluez_version == 5 || (bluez_version == 4 && adapter_address), NULL); if (adapter_address) set_adapter_address (self, adapter_address); @@ -1102,9 +1101,11 @@ dispose (GObject *object) } #endif - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); + if (priv->provider) { + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); + } g_slist_free_full (priv->connections, g_object_unref); priv->connections = NULL; @@ -1120,6 +1121,8 @@ dispose (GObject *object) nm_settings_connection_delete (NM_SETTINGS_CONNECTION (to_delete), NULL, NULL); g_object_unref (to_delete); } + + g_clear_object (&priv->provider); } static void diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h index 0e54fcb0..c9560540 100644 --- a/src/devices/bluetooth/nm-bluez-device.h +++ b/src/devices/bluetooth/nm-bluez-device.h @@ -21,9 +21,6 @@ #ifndef __NETWORKMANAGER_BLUEZ_DEVICE_H__ #define __NETWORKMANAGER_BLUEZ_DEVICE_H__ - -#include "config.h" -#include "nm-default.h" #include "nm-connection.h" #include "nm-connection-provider.h" diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index 6903356c..f66b5abe 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -18,14 +18,13 @@ * Copyright (C) 2013 - 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <signal.h> #include <string.h> #include <stdlib.h> #include <gmodule.h> -#include "nm-default.h" #include "nm-bluez-manager.h" #include "nm-device-factory.h" #include "nm-setting-bluetooth.h" @@ -397,6 +396,10 @@ dispose (GObject *object) cleanup_checking (self, TRUE); priv->bluez_version = 0; + + g_clear_object (&priv->provider); + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); } static void @@ -404,8 +407,7 @@ nm_bluez_manager_init (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - priv->provider = nm_connection_provider_get (); - g_assert (priv->provider); + priv->provider = g_object_ref (nm_connection_provider_get ()); } static NMDevice * diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index 04ae833a..deeebcb6 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -18,11 +18,10 @@ * Copyright (C) 2009 - 2012 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include "nm-default.h" #include "nm-dbus-interface.h" #include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c index c5ba120c..146612a8 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -19,13 +19,12 @@ * Copyright (C) 2007 - 2013 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <signal.h> #include <string.h> #include <stdlib.h> -#include "nm-default.h" #include "nm-bluez-manager.h" #include "nm-bluez4-manager.h" #include "nm-bluez4-adapter.h" diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c index 875a662f..4c93feba 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.c +++ b/src/devices/bluetooth/nm-bluez5-dun.c @@ -18,7 +18,7 @@ * Copyright (C) 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <sys/socket.h> #include <bluetooth/sdp.h> @@ -32,7 +32,6 @@ #include "nm-bluez5-dun.h" #include "nm-bt-error.h" -#include "nm-default.h" #include "NetworkManagerUtils.h" struct _NMBluez5DunContext { diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index c9f5828d..e44e87d8 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -20,13 +20,12 @@ * Copyright (C) 2013 Intel Corporation. */ -#include "config.h" +#include "nm-default.h" #include <signal.h> #include <string.h> #include <stdlib.h> -#include "nm-default.h" #include "nm-bluez-manager.h" #include "nm-bluez5-manager.h" #include "nm-bluez-device.h" diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/devices/bluetooth/nm-bt-error.c index 9c35d8b6..18391187 100644 --- a/src/devices/bluetooth/nm-bt-error.c +++ b/src/devices/bluetooth/nm-bt-error.c @@ -18,9 +18,8 @@ * Copyright (C) 2014 Red Hat, Inc. */ -#include "config.h" - #include "nm-default.h" + #include "nm-bt-error.h" GQuark diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 1e3f9cdc..e151b795 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -18,12 +18,11 @@ * Copyright (C) 2009 - 2011 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <stdio.h> #include <string.h> -#include "nm-default.h" #include "nm-bluez-common.h" #include "nm-bluez-device.h" #include "nm-device-bt.h" diff --git a/src/devices/nm-arping-manager.c b/src/devices/nm-arping-manager.c new file mode 100644 index 00000000..dfb20b4b --- /dev/null +++ b/src/devices/nm-arping-manager.c @@ -0,0 +1,449 @@ +/* -*- 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 <netinet/in.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "nm-arping-manager.h" +#include "nm-platform.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" + +typedef enum { + STATE_INIT, + STATE_PROBING, + STATE_PROBE_DONE, + STATE_ANNOUNCING, +} State; + +typedef struct { + int ifindex; + State state; + GHashTable *addresses; + guint completed; + guint timer; + guint round2_id; +} NMArpingManagerPrivate; + +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 }; + +G_DEFINE_TYPE (NMArpingManager, nm_arping_manager, G_TYPE_OBJECT) + +#define NM_ARPING_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ARPING_MANAGER, NMArpingManagerPrivate)) + +#define _NMLOG_DOMAIN LOGD_IP4 +#define _NMLOG_PREFIX_NAME "arping" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + char _sbuf[64]; \ + \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + self ? nm_sprintf_buf (_sbuf, "[%p,%d]", \ + self, \ + NM_ARPING_MANAGER_GET_PRIVATE (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 on success, %FALSE on failure + */ +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; + + 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; + gboolean success; + + argv[9] = 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 | + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, &info->pid, NULL); + + info->watch = g_child_watch_add (info->pid, arping_watch_cb, info); + } + + priv->timer = g_timeout_add (timeout, arping_timeout_cb, self); + priv->state = STATE_PROBING; + + return TRUE; +} + +/** + * 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 (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 +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_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 +nm_arping_manager_class_init (NMArpingManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMArpingManagerPrivate)); + + 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..4a4f8d4b --- /dev/null +++ b/src/devices/nm-arping-manager.h @@ -0,0 +1,53 @@ +/* -*- 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> + +G_BEGIN_DECLS + +#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" + +struct _NMArpingManager { + GObject parent; +}; + +typedef struct { + GObjectClass parent; +} 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); + +G_END_DECLS + +#endif /* __NM_ARPING_MANAGER__ */ diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index dfd1de6d..cef104e6 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -18,12 +18,11 @@ * Copyright 2011 - 2012 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <errno.h> #include <stdlib.h> -#include "nm-default.h" #include "nm-device-bond.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" @@ -75,7 +74,6 @@ check_connection_available (NMDevice *device, static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { - const char *iface; NMSettingBond *s_bond; if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->check_connection_compatible (device, connection)) @@ -85,11 +83,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_bond || !nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) return FALSE; - /* Bond connections must specify the virtual interface name */ - iface = nm_connection_get_interface_name (connection); - if (!iface || strcmp (nm_device_get_iface (device), iface)) - return FALSE; - /* FIXME: match bond properties like mode, etc? */ return TRUE; @@ -457,7 +450,7 @@ create_and_realize (NMDevice *device, g_assert (iface); plerr = nm_platform_link_bond_add (NM_PLATFORM_GET, iface, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create bond interface '%s' for '%s': %s", iface, diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 843c5be4..cc72b003 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -18,11 +18,10 @@ * Copyright 2011 - 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <stdlib.h> -#include "nm-default.h" #include "nm-device-bridge.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" @@ -73,7 +72,6 @@ check_connection_available (NMDevice *device, static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { - const char *iface; NMSettingBridge *s_bridge; const char *mac_address; @@ -84,11 +82,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_bridge || !nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) return FALSE; - /* Bridge connections must specify the virtual interface name */ - iface = nm_connection_get_interface_name (connection); - if (!iface || strcmp (nm_device_get_iface (device), iface)) - return FALSE; - mac_address = nm_setting_bridge_get_mac_address (s_bridge); if (mac_address && nm_device_is_real (device)) { const char *hw_addr; @@ -405,7 +398,7 @@ create_and_realize (NMDevice *device, hwaddr ? mac_address : NULL, hwaddr ? ETH_ALEN : 0, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create bridge interface '%s' for '%s': %s", iface, diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c index 9165de31..d034ddfc 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/devices/nm-device-ethernet-utils.c @@ -16,12 +16,12 @@ * (C) Copyright 2011 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include <nm-connection.h> -#include "nm-default.h" +#include "nm-connection.h" + #include "nm-device-ethernet-utils.h" char * diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index a2396ec8..2fb84276 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -19,7 +19,7 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "config.h" +#include "nm-default.h" #include <netinet/in.h> #include <string.h> @@ -29,7 +29,6 @@ #include <gudev/gudev.h> -#include "nm-default.h" #include "nm-device-ethernet.h" #include "nm-device-private.h" #include "nm-activation-request.h" @@ -64,8 +63,6 @@ G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) #define PPPOE_RECONNECT_DELAY 7 #define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */ -static NMSetting *device_get_setting (NMDevice *device, GType setting_type); - typedef struct Supplicant { NMSupplicantManager *mgr; NMSupplicantInterface *iface; @@ -429,52 +426,18 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return TRUE; } -/* FIXME: Move it to nm-device.c and then get rid of all foo_device_get_setting() all around. - It's here now to keep the patch short. */ -static NMSetting * -device_get_setting (NMDevice *device, GType setting_type) -{ - NMActRequest *req; - NMSetting *setting = NULL; - - req = nm_device_get_act_request (device); - if (req) { - NMConnection *connection; - - connection = nm_act_request_get_applied_connection (req); - if (connection) - setting = nm_connection_get_setting (connection, setting_type); - } - - return setting; -} - /*****************************************************************************/ /* 802.1X */ static void -remove_supplicant_timeouts (NMDeviceEthernet *self) +supplicant_interface_clear_handlers (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - nm_clear_g_source (&priv->supplicant.con_timeout_id); nm_clear_g_source (&priv->supplicant_timeout_id); -} - -static void -remove_supplicant_interface_error_handler (NMDeviceEthernet *self) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - if (priv->supplicant.iface_error_id != 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id); - priv->supplicant.iface_error_id = 0; - } - - if (priv->supplicant.iface_con_error_cb_id > 0) { - g_source_remove (priv->supplicant.iface_con_error_cb_id); - priv->supplicant.iface_con_error_cb_id = 0; - } + nm_clear_g_source (&priv->supplicant.con_timeout_id); + nm_clear_g_source (&priv->supplicant.iface_con_error_cb_id); + nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_error_id); } static void @@ -482,18 +445,13 @@ supplicant_interface_release (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - remove_supplicant_timeouts (self); - remove_supplicant_interface_error_handler (self); + supplicant_interface_clear_handlers (self); - if (priv->supplicant.iface_state_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id); - priv->supplicant.iface_state_id = 0; - } + nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id); if (priv->supplicant.iface) { nm_supplicant_interface_disconnect (priv->supplicant.iface); - nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); - priv->supplicant.iface = NULL; + g_clear_object (&priv->supplicant.iface); } } @@ -656,8 +614,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, } break; case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - remove_supplicant_interface_error_handler (self); - remove_supplicant_timeouts (self); + supplicant_interface_clear_handlers (self); /* If this is the initial association during device activation, * schedule the next activation stage. @@ -677,7 +634,6 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, break; case NM_SUPPLICANT_INTERFACE_STATE_DOWN: supplicant_interface_release (self); - remove_supplicant_timeouts (self); if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { nm_device_state_changed (device, @@ -804,14 +760,15 @@ supplicant_interface_init (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - /* Create supplicant interface */ - priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, - nm_device_get_iface (NM_DEVICE (self)), - FALSE); + supplicant_interface_release (self); + + priv->supplicant.iface = nm_supplicant_manager_create_interface (priv->supplicant.mgr, + nm_device_get_iface (NM_DEVICE (self)), + FALSE); + if (!priv->supplicant.iface) { _LOGE (LOGD_DEVICE | LOGD_ETHER, "Couldn't initialize supplicant interface"); - supplicant_interface_release (self); return FALSE; } @@ -850,7 +807,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMActRequest *req; NMSettingWired *s_wired; const char *cloned_mac; NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; @@ -859,15 +815,11 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason); if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wired = (NMSettingWired *) device_get_setting (dev, NM_TYPE_SETTING_WIRED); + s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED); if (s_wired) { /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) - nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_ETHER); + nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_ETHER); } /* If we're re-activating a PPPoE connection a short while after @@ -878,7 +830,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (priv->last_pppoe_time) { gint32 delay = nm_utils_get_monotonic_timestamp_s () - priv->last_pppoe_time; - if (delay < PPPOE_RECONNECT_DELAY && device_get_setting (dev, NM_TYPE_SETTING_PPPOE)) { + if ( delay < PPPOE_RECONNECT_DELAY + && nm_device_get_applied_setting (dev, NM_TYPE_SETTING_PPPOE)) { _LOGI (LOGD_DEVICE, "delaying PPPoE reconnect for %d seconds to ensure peer is ready...", delay); g_assert (!priv->pppoe_wait_id); @@ -980,7 +933,6 @@ static NMActStageReturn pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reason) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMConnection *connection; NMSettingPppoe *s_pppoe; NMActRequest *req; GError *err = NULL; @@ -989,10 +941,7 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas req = nm_device_get_act_request (NM_DEVICE (self)); g_assert (req); - connection = nm_act_request_get_applied_connection (req); - g_assert (req); - - s_pppoe = nm_connection_get_setting_pppoe (connection); + s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting (self, NM_TYPE_SETTING_PPPOE); g_assert (s_pppoe); priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self))); @@ -1064,7 +1013,7 @@ dcb_configure (NMDevice *device) dcb_timeout_cleanup (device); - s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); + s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); g_assert (s_dcb); if (!nm_dcb_setup (nm_device_get_iface (device), s_dcb, &error)) { _LOGW (LOGD_DCB, "Activation: (ethernet) failed to enable DCB/FCoE: %s", @@ -1210,7 +1159,7 @@ wake_on_lan_enable (NMDevice *device) const char *password = NULL; gs_free char *value = NULL; - s_wired = (NMSettingWired *) device_get_setting (device, NM_TYPE_SETTING_WIRED); + s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); if (s_wired) { wol = nm_setting_wired_get_wake_on_lan (s_wired); password = nm_setting_wired_get_wake_on_lan_password (s_wired); @@ -1255,7 +1204,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION)); + s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (device, + NM_TYPE_SETTING_CONNECTION)); g_assert (s_con); dcb_timeout_cleanup (device); @@ -1268,7 +1218,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) { NMSetting8021x *security; - security = (NMSetting8021x *) device_get_setting (device, NM_TYPE_SETTING_802_1X); + security = (NMSetting8021x *) nm_device_get_applied_setting (device, + NM_TYPE_SETTING_802_1X); if (security) { /* FIXME: for now 802.1x is mutually exclusive with DCB */ return nm_8021x_stage2_config (self, reason); @@ -1278,7 +1229,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) wake_on_lan_enable (device); /* DCB and FCoE setup */ - s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); + s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); if (s_dcb) { /* lldpad really really wants the carrier to be up */ if (nm_platform_link_is_connected (NM_PLATFORM_GET, nm_device_get_ifindex (device))) { @@ -1307,7 +1258,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NM_SETTING_PPPOE_SETTING_NAME)) { NMSettingPpp *s_ppp; - s_ppp = (NMSettingPpp *) device_get_setting (device, NM_TYPE_SETTING_PPP); + s_ppp = (NMSettingPpp *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPP); if (s_ppp) { guint32 mtu = 0, mru = 0, mxu; @@ -1337,7 +1288,7 @@ act_stage3_ip4_config_start (NMDevice *device, g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - s_con = NM_SETTING_CONNECTION (device_get_setting (device, NM_TYPE_SETTING_CONNECTION)); + s_con = NM_SETTING_CONNECTION (nm_device_get_applied_setting (device, NM_TYPE_SETTING_CONNECTION)); g_assert (s_con); connection_type = nm_setting_connection_get_connection_type (s_con); @@ -1396,7 +1347,7 @@ deactivate (NMDevice *device) dcb_carrier_cleanup (device); /* Tear down DCB/FCoE if it was enabled */ - s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); + s_dcb = (NMSettingDcb *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_DCB); if (s_dcb) { if (!nm_dcb_cleanup (nm_device_get_iface (device), &error)) { _LOGW (LOGD_DEVICE | LOGD_HW, "failed to disable DCB/FCoE: %s", @@ -1406,7 +1357,7 @@ deactivate (NMDevice *device) } /* Set last PPPoE connection time */ - if (device_get_setting (device, NM_TYPE_SETTING_PPPOE)) + if (nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPPOE)) NM_DEVICE_ETHERNET_GET_PRIVATE (device)->last_pppoe_time = nm_utils_get_monotonic_timestamp_s (); /* Reset MAC address back to initial address */ @@ -1653,6 +1604,8 @@ dispose (GObject *object) NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + supplicant_interface_release (self); + nm_clear_g_source (&priv->pppoe_wait_id); dcb_timeout_cleanup (NM_DEVICE (self)); diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index 75731b14..bd0ec002 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -18,17 +18,16 @@ * Copyright (C) 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <string.h> - #include <gmodule.h> #include "nm-device-factory.h" -#include "nm-default.h" #include "nm-platform.h" +#include "nm-utils.h" const NMLinkType _nm_device_factory_no_default_links[] = { NM_LINK_TYPE_NONE }; const char *_nm_device_factory_no_default_settings[] = { NULL }; @@ -156,35 +155,46 @@ nm_device_factory_get_connection_parent (NMDeviceFactory *factory, return NULL; } -static char * -get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) -{ - const char *iface; - - /* For any other virtual connection, NMSettingConnection:interface-name is - * the virtual device name. - */ - iface = nm_connection_get_interface_name (connection); - g_return_val_if_fail (iface != NULL, NULL); - return g_strdup (iface); -} - char * -nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) +nm_device_factory_get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface, + GError **error) { + NMDeviceFactoryInterface *klass; + char *ifname; + g_return_val_if_fail (factory != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (!error || !*error, NULL); - if (!nm_connection_is_virtual (connection)) + klass = NM_DEVICE_FACTORY_GET_INTERFACE (factory); + + if (klass->get_connection_iface) + ifname = klass->get_connection_iface (factory, connection, parent_iface); + else + ifname = g_strdup (nm_connection_get_interface_name (connection)); + + if (!ifname) { + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "failed to determine interface name: error determine name for %s", + nm_connection_get_connection_type (connection)); return NULL; + } - if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_virtual_iface_name) - return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_virtual_iface_name (factory, connection, parent_iface); - return NULL; + if (!nm_utils_iface_valid_name (ifname)) { + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "failed to determine interface name: name \"%s\" is invalid", + ifname); + g_free (ifname); + return NULL; + } + + return ifname; } /*******************************************************************/ @@ -192,8 +202,6 @@ nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, static void nm_device_factory_default_init (NMDeviceFactoryInterface *factory_iface) { - factory_iface->get_virtual_iface_name = get_virtual_iface_name; - /* Signals */ signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED, NM_TYPE_DEVICE_FACTORY, diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h index 9b7cb35a..ae78968a 100644 --- a/src/devices/nm-device-factory.h +++ b/src/devices/nm-device-factory.h @@ -101,19 +101,19 @@ typedef struct { NMConnection *connection); /** - * get_virtual_iface_name: + * get_connection_iface: * @factory: the #NMDeviceFactory - * @connection: the #NMConnection to return the virtual interface name for - * @parent_iface: parent interface name + * @connection: the #NMConnection to return the interface name for + * @parent_iface: optional parent interface name for virtual devices * * Given a connection, returns the interface name that a device activating * that connection would have. * * Returns: the interface name, or %NULL */ - char * (*get_virtual_iface_name) (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface); + char * (*get_connection_iface) (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface); /** * create_device: @@ -175,9 +175,10 @@ void nm_device_factory_get_supported_types (NMDeviceFactory *factory, const char *nm_device_factory_get_connection_parent (NMDeviceFactory *factory, NMConnection *connection); -char * nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface); +char * nm_device_factory_get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface, + GError **error); void nm_device_factory_start (NMDeviceFactory *factory); diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 2e9c134a..d90840d2 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -18,7 +18,7 @@ * Copyright 2013 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include "nm-device-generic.h" #include "nm-device-private.h" @@ -138,7 +138,7 @@ constructor (GType type, n_construct_params, construct_params); - nm_device_set_unmanaged_flags_initial (NM_DEVICE (object), NM_UNMANAGED_DEFAULT, TRUE); + nm_device_set_unmanaged_flags ((NMDevice *) object, NM_UNMANAGED_BY_DEFAULT, TRUE); return object; } diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 45df49fe..79bcb57c 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -18,11 +18,10 @@ * Copyright 2011 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <linux/if_infiniband.h> -#include "nm-default.h" #include "nm-device-infiniband.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" @@ -69,8 +68,6 @@ static NMActStageReturn act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { NMActStageReturn ret; - NMActRequest *req; - NMConnection *connection; NMSettingInfiniband *s_infiniband; const char *transport_mode; char *mode_path; @@ -82,12 +79,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - req = nm_device_get_act_request (dev); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); - g_assert (connection); - s_infiniband = nm_connection_get_setting_infiniband (connection); + s_infiniband = (NMSettingInfiniband *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_INFINIBAND); g_assert (s_infiniband); transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); @@ -272,7 +264,7 @@ create_and_realize (NMDevice *device, } plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, parent_ifindex, p_key, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create InfiniBand P_Key interface '%s' for '%s': %s", nm_device_get_iface (device), @@ -406,9 +398,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) } static char * -get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) +get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) { NMSettingInfiniband *s_infiniband; @@ -430,6 +422,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (INFINIBAND, Infiniband, infiniband, NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_INFINIBAND_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; - factory_iface->get_virtual_iface_name = get_virtual_iface_name; + factory_iface->get_connection_iface = get_connection_iface; ) diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 6d0df059..0ba813eb 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -18,7 +18,7 @@ * Copyright 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <netinet/in.h> @@ -28,7 +28,6 @@ #include "nm-device-ip-tunnel.h" #include "nm-device-private.h" -#include "nm-default.h" #include "nm-manager.h" #include "nm-platform.h" #include "nm-device-factory.h" @@ -554,13 +553,13 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link) else if (lnk->proto == IPPROTO_IPV6) return NM_IP_TUNNEL_MODE_IP6IP6; else - return NM_IP_TUNNEL_MODE_UKNOWN; + return NM_IP_TUNNEL_MODE_UNKNOWN; case NM_LINK_TYPE_IPIP: return NM_IP_TUNNEL_MODE_IPIP; case NM_LINK_TYPE_SIT: return NM_IP_TUNNEL_MODE_SIT; default: - g_return_val_if_reached (NM_IP_TUNNEL_MODE_UKNOWN); + g_return_val_if_reached (NM_IP_TUNNEL_MODE_UNKNOWN); } } @@ -661,7 +660,7 @@ create_and_realize (NMDevice *device, } plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create GRE interface '%s' for '%s': %s", iface, @@ -687,7 +686,7 @@ create_and_realize (NMDevice *device, lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create SIT interface '%s' for '%s': %s", iface, @@ -713,7 +712,7 @@ create_and_realize (NMDevice *device, lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IPIP interface '%s' for '%s': %s", iface, @@ -742,7 +741,7 @@ create_and_realize (NMDevice *device, lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6; plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IPIP interface '%s' for '%s': %s", iface, @@ -997,7 +996,7 @@ create_device (NMDeviceFactory *factory, mode = platform_link_to_tunnel_mode (plink); } - if (mode == NM_IP_TUNNEL_MODE_UKNOWN) + if (mode == NM_IP_TUNNEL_MODE_UNKNOWN) return NULL; return (NMDevice *) g_object_new (NM_TYPE_DEVICE_IP_TUNNEL, @@ -1023,9 +1022,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) } static char * -get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) +get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) { const char *ifname; NMSettingIPTunnel *s_ip_tunnel; @@ -1048,5 +1047,5 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; - factory_iface->get_virtual_iface_name = get_virtual_iface_name; + factory_iface->get_connection_iface = get_connection_iface; ) diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 8123a793..2dc9d4f6 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -18,11 +18,10 @@ * Copyright 2013 - 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include "nm-default.h" #include "nm-device-macvlan.h" #include "nm-device-private.h" #include "nm-connection-provider.h" @@ -127,7 +126,7 @@ parent_state_changed (NMDevice *parent, if (reason == NM_DEVICE_STATE_REASON_CARRIER) return; - nm_device_set_unmanaged_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason); + nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason); } static void @@ -139,8 +138,7 @@ nm_device_macvlan_set_parent (NMDeviceMacvlan *self, NMDevice *parent) if (parent == priv->parent) return; - if (priv->parent_state_id) - nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id); + nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id); g_clear_object (&priv->parent); @@ -152,10 +150,10 @@ nm_device_macvlan_set_parent (NMDeviceMacvlan *self, NMDevice *parent) device); /* Set parent-dependent unmanaged flag */ - nm_device_set_unmanaged_flags (device, - NM_UNMANAGED_PARENT, - !nm_device_get_managed (parent), - NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); + nm_device_set_unmanaged_by_flags (device, + NM_UNMANAGED_PARENT, + !nm_device_get_managed (parent, FALSE), + NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); } /* Recheck availability now that the parent has changed */ @@ -239,7 +237,7 @@ create_and_realize (NMDevice *device, lnk.tap = nm_setting_macvlan_get_tap (s_macvlan); plerr = nm_platform_link_macvlan_add (NM_PLATFORM_GET, iface, parent_ifindex, &lnk, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create %s interface '%s' for '%s': %s", lnk.tap ? "macvtap" : "macvlan", @@ -377,7 +375,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); NMSettingMacvlan *s_macvlan; - const char *parent, *iface = NULL; + const char *parent = NULL; if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection)) return FALSE; @@ -410,13 +408,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) } } - /* Ensure the interface name matches */ - iface = nm_connection_get_interface_name (connection); - if (iface) { - if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) - return FALSE; - } - return TRUE; } @@ -503,8 +494,6 @@ update_connection (NMDevice *device, NMConnection *connection) static NMActStageReturn act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { - NMActRequest *req; - NMConnection *connection; NMSettingWired *s_wired; const char *cloned_mac; NMActStageReturn ret; @@ -515,18 +504,11 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - req = nm_device_get_act_request (dev); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wired = nm_connection_get_setting_wired (connection); + s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED); if (s_wired) { /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) - nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW); + nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW); } return TRUE; @@ -621,6 +603,14 @@ set_property (GObject *object, guint prop_id, } static void +dispose (GObject *object) +{ + nm_device_macvlan_set_parent (NM_DEVICE_MACVLAN (object), NULL); + + G_OBJECT_CLASS (nm_device_macvlan_parent_class)->dispose (object); +} + +static void nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -630,6 +620,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP) + object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; @@ -744,9 +735,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) } static char * -get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) +get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) { NMSettingMacvlan *s_macvlan; const char *ifname; @@ -768,6 +759,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (MACVLAN, Macvlan, macvlan, NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_MACVLAN_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; - factory_iface->get_virtual_iface_name = get_virtual_iface_name; + factory_iface->get_connection_iface = get_connection_iface; ) diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 5010e906..602c2c85 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -95,7 +95,6 @@ void nm_device_master_check_slave_physical_port (NMDevice *self, NMDevice *slave void nm_device_set_carrier (NMDevice *self, gboolean carrier); -void nm_device_emit_recheck_auto_activate (NMDevice *device); void nm_device_queue_recheck_assume (NMDevice *device); void nm_device_queue_recheck_available (NMDevice *device, NMDeviceStateReason available_reason, diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index 91ef8fe7..a8ae3edc 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -18,13 +18,12 @@ * Copyright 2013 - 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <stdlib.h> #include <string.h> #include <sys/types.h> -#include "nm-default.h" #include "nm-activation-request.h" #include "nm-device-tun.h" #include "nm-device-private.h" @@ -222,7 +221,7 @@ create_and_realize (NMDevice *device, nm_setting_tun_get_vnet_hdr (s_tun), nm_setting_tun_get_multi_queue (s_tun), out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + 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", iface, @@ -285,8 +284,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); - NMActRequest *req; - NMConnection *connection; NMSettingWired *s_wired; const char *cloned_mac; NMActStageReturn ret; @@ -301,18 +298,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) if (g_strcmp0 (priv->mode, "tap")) return NM_ACT_STAGE_RETURN_SUCCESS; - req = nm_device_get_act_request (device); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wired = nm_connection_get_setting_wired (connection); + s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); if (s_wired) { /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) - nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); + nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); } return NM_ACT_STAGE_RETURN_SUCCESS; diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index a1bf0d21..ff198a7d 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -18,7 +18,7 @@ * Copyright 2013 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <errno.h> #include <stdlib.h> @@ -29,7 +29,6 @@ #include "nm-device-veth.h" #include "nm-device-private.h" -#include "nm-default.h" #include "nm-manager.h" #include "nm-platform.h" #include "nm-device-factory.h" @@ -188,7 +187,7 @@ create_device (NMDeviceFactory *factory, return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH, NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Veth", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VETH, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_VETH, NULL); } diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index f8710412..e6e3708b 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -18,11 +18,10 @@ * Copyright 2011 - 2012 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <sys/socket.h> -#include "nm-default.h" #include "nm-device-vlan.h" #include "nm-manager.h" #include "nm-utils.h" @@ -77,7 +76,7 @@ parent_state_changed (NMDevice *parent, if (reason == NM_DEVICE_STATE_REASON_CARRIER) return; - nm_device_set_unmanaged_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason); + nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason); } static void @@ -115,7 +114,8 @@ parent_hwaddr_changed (NMDevice *parent, * removing the IPv6 configuration; reapply it. */ s_ip6 = nm_connection_get_setting_ip6_config (connection); - nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6); + if (s_ip6) + nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6); } } } @@ -144,10 +144,10 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent) G_CALLBACK (parent_hwaddr_changed), device); /* Set parent-dependent unmanaged flag */ - nm_device_set_unmanaged_flags (device, - NM_UNMANAGED_PARENT, - !nm_device_get_managed (parent), - NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); + nm_device_set_unmanaged_by_flags (device, + NM_UNMANAGED_PARENT, + !nm_device_get_managed (parent, FALSE), + NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); } /* Recheck availability now that the parent has changed */ @@ -237,7 +237,7 @@ create_and_realize (NMDevice *device, vlan_id, nm_setting_vlan_get_flags (s_vlan), out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create VLAN interface '%s' for '%s': %s", iface, @@ -389,7 +389,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); NMSettingVlan *s_vlan; - const char *parent, *iface = NULL; + const char *parent = NULL; if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection)) return FALSE; @@ -415,16 +415,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) } } - /* Ensure the interface name matches. If not specified we assume a match - * since both the parent interface and the VLAN ID matched by the time we - * get here. - */ - iface = nm_connection_get_interface_name (connection); - if (iface) { - if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) - return FALSE; - } - return TRUE; } @@ -546,8 +536,6 @@ update_connection (NMDevice *device, NMConnection *connection) static NMActStageReturn act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { - NMActRequest *req; - NMConnection *connection; NMSettingVlan *s_vlan; NMSettingWired *s_wired; const char *cloned_mac; @@ -559,21 +547,14 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - req = nm_device_get_act_request (dev); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wired = nm_connection_get_setting_wired (connection); + s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED); if (s_wired) { /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) - nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN); + nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN); } - s_vlan = nm_connection_get_setting_vlan (connection); + s_vlan = (NMSettingVlan *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_VLAN); if (s_vlan) { gs_free NMVlanQosMapping *ingress_map = NULL; gs_free NMVlanQosMapping *egress_map = NULL; @@ -765,9 +746,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) } static char * -get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) +get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) { const char *ifname; NMSettingVlan *s_vlan; @@ -796,6 +777,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (VLAN, Vlan, vlan, NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VLAN_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; - factory_iface->get_virtual_iface_name = get_virtual_iface_name; + factory_iface->get_connection_iface = get_connection_iface; ) diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index aab90539..79942458 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -18,11 +18,10 @@ * Copyright 2013 - 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include "nm-default.h" #include "nm-device-vxlan.h" #include "nm-device-private.h" #include "nm-manager.h" @@ -224,7 +223,7 @@ create_and_realize (NMDevice *device, props.l3miss = nm_setting_vxlan_get_l3_miss (s_vxlan); plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, iface, &props, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create VXLAN interface '%s' for '%s': %s", iface, @@ -296,7 +295,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); NMSettingVxlan *s_vxlan; - const char *iface, *parent; + const char *parent; if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->check_connection_compatible (device, connection)) return FALSE; @@ -305,12 +304,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_vxlan) return FALSE; - iface = nm_connection_get_interface_name (connection); - if (iface) { - if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) - return FALSE; - } - if (nm_device_is_real (device)) { parent = nm_setting_vxlan_get_parent (s_vxlan); if ( parent @@ -510,8 +503,6 @@ update_connection (NMDevice *device, NMConnection *connection) static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { - NMActRequest *req; - NMConnection *connection; NMSettingWired *s_wired; const char *cloned_mac; NMActStageReturn ret; @@ -522,18 +513,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - req = nm_device_get_act_request (device); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); - g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - s_wired = nm_connection_get_setting_wired (connection); + s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); if (s_wired) { /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) - nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); + nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); } return NM_ACT_STAGE_RETURN_SUCCESS; @@ -818,9 +802,9 @@ get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) } static char * -get_virtual_iface_name (NMDeviceFactory *factory, - NMConnection *connection, - const char *parent_iface) +get_connection_iface (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) { const char *ifname; NMSettingVxlan *s_vxlan; @@ -842,6 +826,6 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL (VXLAN, Vxlan, vxlan, NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VXLAN_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; - factory_iface->get_virtual_iface_name = get_virtual_iface_name; + factory_iface->get_connection_iface = get_connection_iface; ) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 93782a45..cdd3f7cb 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -19,7 +19,7 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "config.h" +#include "nm-default.h" #include <netinet/in.h> #include <string.h> @@ -34,7 +34,6 @@ #include <netlink/route/addr.h> #include <linux/if_addr.h> -#include "nm-default.h" #include "nm-device.h" #include "nm-device-private.h" #include "NetworkManagerUtils.h" @@ -64,6 +63,7 @@ #include "nm-lldp-listener.h" #include "sd-ipv4ll.h" #include "nm-audit-manager.h" +#include "nm-arping-manager.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF (NMDevice); @@ -94,8 +94,7 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, PROP_UDI, PROP_IFACE, PROP_IP_IFACE, @@ -132,8 +131,7 @@ enum { PROP_LLDP_NEIGHBORS, PROP_REAL, PROP_SLAVES, - LAST_PROP -}; +); #define DEFAULT_AUTOCONNECT TRUE @@ -193,10 +191,16 @@ typedef struct { int ifindex; } DeleteOnDeactivateData; +typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean); + +typedef struct { + ArpingCallback callback; + NMDevice *device; + NMIP4Config **configs; +} ArpingData; + typedef struct _NMDevicePrivate { gboolean in_state_changed; - gboolean initialized; - gboolean platform_link_initialized; guint device_link_changed_id; guint device_ip_link_changed_id; @@ -234,7 +238,7 @@ typedef struct _NMDevicePrivate { char * physical_port_id; guint dev_id; - gboolean managed_touched_by_user; + NMUnmanagedFlags unmanaged_mask; NMUnmanagedFlags unmanaged_flags; gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ @@ -300,7 +304,6 @@ typedef struct _NMDevicePrivate { NMDhcp4Config * dhcp4_config; guint dhcp4_restart_id; - guint arp_round2_id; PingInfo gw_ping; /* dnsmasq stuff for shared connections */ @@ -315,12 +318,19 @@ typedef struct _NMDevicePrivate { sd_ipv4ll * ipv4ll; guint ipv4ll_timeout; + /* IPv4 DAD stuff */ + struct { + GSList * dad_list; + NMArpingManager * announcing; + } arping; + /* IP6 configuration info */ NMIP6Config * ip6_config; IpState ip6_state; 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 */ gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ guint32 ip6_mtu; @@ -390,13 +400,10 @@ static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success); static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason); static gboolean addrconf6_start_with_link_ready (NMDevice *self); -static gboolean dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection); static NMActStageReturn linklocal6_start (NMDevice *self); static void _carrier_wait_check_queued_act_request (NMDevice *self); -static gboolean nm_device_get_default_unmanaged (NMDevice *self); - static const char *_activation_func_to_string (ActivationHandleFunc func); static void activation_source_handle_cb (NMDevice *self, int family); @@ -408,10 +415,6 @@ static void _set_state_full (NMDevice *self, static gboolean queued_ip4_config_change (gpointer user_data); static gboolean queued_ip6_config_change (gpointer user_data); -static void _set_unmanaged_flags (NMDevice *self, - NMUnmanagedFlags flags, - gboolean unmanaged); - /***********************************************************/ #define QUEUED_PREFIX "queued state change to " @@ -446,74 +449,75 @@ state_to_string (NMDeviceState state) return queued_state_to_string (state) + strlen (QUEUED_PREFIX); } -NM_UTILS_STRING_LOOKUP_TABLE_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, NULL, - [NM_DEVICE_STATE_REASON_UNKNOWN] = "unknown", - [NM_DEVICE_STATE_REASON_NONE] = "none", - [NM_DEVICE_STATE_REASON_NOW_MANAGED] = "managed", - [NM_DEVICE_STATE_REASON_NOW_UNMANAGED] = "unmanaged", - [NM_DEVICE_STATE_REASON_CONFIG_FAILED] = "config-failed", - [NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE] = "ip-config-unavailable", - [NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED] = "ip-config-expired", - [NM_DEVICE_STATE_REASON_NO_SECRETS] = "no-secrets", - [NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT] = "supplicant-disconnect", - [NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED] = "supplicant-config-failed", - [NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED] = "supplicant-failed", - [NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT] = "supplicant-timeout", - [NM_DEVICE_STATE_REASON_PPP_START_FAILED] = "ppp-start-failed", - [NM_DEVICE_STATE_REASON_PPP_DISCONNECT] = "ppp-disconnect", - [NM_DEVICE_STATE_REASON_PPP_FAILED] = "ppp-failed", - [NM_DEVICE_STATE_REASON_DHCP_START_FAILED] = "dhcp-start-failed", - [NM_DEVICE_STATE_REASON_DHCP_ERROR] = "dhcp-error", - [NM_DEVICE_STATE_REASON_DHCP_FAILED] = "dhcp-failed", - [NM_DEVICE_STATE_REASON_SHARED_START_FAILED] = "sharing-start-failed", - [NM_DEVICE_STATE_REASON_SHARED_FAILED] = "sharing-failed", - [NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED] = "autoip-start-failed", - [NM_DEVICE_STATE_REASON_AUTOIP_ERROR] = "autoip-error", - [NM_DEVICE_STATE_REASON_AUTOIP_FAILED] = "autoip-failed", - [NM_DEVICE_STATE_REASON_MODEM_BUSY] = "modem-busy", - [NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE] = "modem-no-dialtone", - [NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER] = "modem-no-carrier", - [NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT] = "modem-dial-timeout", - [NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED] = "modem-dial-failed", - [NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED] = "modem-init-failed", - [NM_DEVICE_STATE_REASON_GSM_APN_FAILED] = "gsm-apn-failed", - [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING] = "gsm-registration-idle", - [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED] = "gsm-registration-denied", - [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT] = "gsm-registration-timeout", - [NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED] = "gsm-registration-failed", - [NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED] = "gsm-pin-check-failed", - [NM_DEVICE_STATE_REASON_FIRMWARE_MISSING] = "firmware-missing", - [NM_DEVICE_STATE_REASON_REMOVED] = "removed", - [NM_DEVICE_STATE_REASON_SLEEPING] = "sleeping", - [NM_DEVICE_STATE_REASON_CONNECTION_REMOVED] = "connection-removed", - [NM_DEVICE_STATE_REASON_USER_REQUESTED] = "user-requested", - [NM_DEVICE_STATE_REASON_CARRIER] = "carrier-changed", - [NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED] = "connection-assumed", - [NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE] = "supplicant-available", - [NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND] = "modem-not-found", - [NM_DEVICE_STATE_REASON_BT_FAILED] = "bluetooth-failed", - [NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED] = "gsm-sim-not-inserted", - [NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED] = "gsm-sim-pin-required", - [NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED] = "gsm-sim-puk-required", - [NM_DEVICE_STATE_REASON_GSM_SIM_WRONG] = "gsm-sim-wrong", - [NM_DEVICE_STATE_REASON_INFINIBAND_MODE] = "infiniband-mode", - [NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED] = "dependency-failed", - [NM_DEVICE_STATE_REASON_BR2684_FAILED] = "br2684-bridge-failed", - [NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE] = "modem-manager-unavailable", - [NM_DEVICE_STATE_REASON_SSID_NOT_FOUND] = "ssid-not-found", - [NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED] = "secondary-connection-failed", - [NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED] = "dcb-fcoe-failed", - [NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED] = "teamd-control-failed", - [NM_DEVICE_STATE_REASON_MODEM_FAILED] = "modem-failed", - [NM_DEVICE_STATE_REASON_MODEM_AVAILABLE] = "modem-available", - [NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT] = "sim-pin-incorrect", - [NM_DEVICE_STATE_REASON_NEW_ACTIVATION] = "new-activation", - [NM_DEVICE_STATE_REASON_PARENT_CHANGED] = "parent-changed", - [NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED] = "parent-managed-changed", +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, + NM_UTILS_LOOKUP_DEFAULT (NULL), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_MANAGED, "managed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_UNMANAGED, "unmanaged"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONFIG_FAILED, "config-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, "ip-config-unavailable"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, "ip-config-expired"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NO_SECRETS, "no-secrets"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, "supplicant-disconnect"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED, "supplicant-config-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, "supplicant-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, "supplicant-timeout"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_START_FAILED, "ppp-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_DISCONNECT, "ppp-disconnect"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_FAILED, "ppp-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_START_FAILED, "dhcp-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_ERROR, "dhcp-error"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_FAILED, "dhcp-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_START_FAILED, "sharing-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_FAILED, "sharing-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, "autoip-start-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_ERROR, "autoip-error"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_FAILED, "autoip-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_BUSY, "modem-busy"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, "modem-no-dialtone"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, "modem-no-carrier"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, "modem-dial-timeout"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, "modem-dial-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, "modem-init-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_APN_FAILED, "gsm-apn-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, "gsm-registration-idle"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED, "gsm-registration-denied"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT, "gsm-registration-timeout"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, "gsm-registration-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, "gsm-pin-check-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, "firmware-missing"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_REMOVED, "removed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SLEEPING, "sleeping"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, "connection-removed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_USER_REQUESTED, "user-requested"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CARRIER, "carrier-changed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, "connection-assumed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, "supplicant-available"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, "modem-not-found"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BT_FAILED, "bluetooth-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, "gsm-sim-not-inserted"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, "gsm-sim-pin-required"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, "gsm-sim-puk-required"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, "gsm-sim-wrong"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_INFINIBAND_MODE, "infiniband-mode"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, "dependency-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BR2684_FAILED, "br2684-bridge-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE, "modem-manager-unavailable"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, "ssid-not-found"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED, "secondary-connection-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, "dcb-fcoe-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, "teamd-control-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_FAILED, "modem-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, "modem-available"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, "sim-pin-incorrect"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NEW_ACTIVATION, "new-activation"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED, "parent-changed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, "parent-managed-changed"), ); #define reason_to_string(reason) \ - NM_UTILS_STRING_LOOKUP_TABLE (_reason_to_string, reason) + NM_UTILS_LOOKUP_STR (_reason_to_string, reason) /***********************************************************/ @@ -649,7 +653,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) /* Emit change notification */ if (g_strcmp0 (old_ip_iface, priv->ip_iface)) - g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); + _notify (self, PROP_IP_IFACE); g_free (old_ip_iface); } @@ -772,6 +776,7 @@ nm_device_get_priority (NMDevice *self) switch (nm_device_get_device_type (self)) { /* 50 is reserved for VPN (NM_VPN_ROUTE_METRIC_DEFAULT) */ case NM_DEVICE_TYPE_ETHERNET: + case NM_DEVICE_TYPE_VETH: return 100; case NM_DEVICE_TYPE_INFINIBAND: return 150; @@ -981,6 +986,26 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags); } +NMSetting * +nm_device_get_applied_setting (NMDevice *device, GType setting_type) +{ + NMActRequest *req; + NMSetting *setting = NULL; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + req = nm_device_get_act_request (device); + if (req) { + NMConnection *connection; + + connection = nm_act_request_get_applied_connection (req); + if (connection) + setting = nm_connection_get_setting (connection, setting_type); + } + + return setting; +} + RfKillType nm_device_get_rfkill_type (NMDevice *self) { @@ -1158,6 +1183,7 @@ nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean co * when slaves change. */ nm_device_update_hw_address (self); + nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, NM_UNMAN_FLAG_OP_FORGET, NM_DEVICE_STATE_REASON_REMOVED); } /** @@ -1173,54 +1199,6 @@ can_unmanaged_external_down (NMDevice *self) return nm_device_is_software (self) && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; } -/** - * nm_device_finish_init: - * @self: the master device - * - * Whatever needs to be done post-initialization, when the device has a DBus - * object name. - */ -void -nm_device_finish_init (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - g_assert (priv->initialized == FALSE); - - /* Do not manage externally created software devices until they are IFF_UP */ - if ( NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self) - && priv->ifindex > 0 - && ( !priv->up - || !priv->platform_link_initialized)) - nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); - - if (priv->master) - nm_device_master_enslave_slave (priv->master, self, NULL); - - if (priv->ifindex > 0) { - if (priv->ifindex == 1) { - /* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag. - * Later we might want to manage 'lo' too. Currently that doesn't work because - * NetworkManager might down the interface or remove the 127.0.0.1 address. */ - nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_LOOPBACK, TRUE); - } else if (priv->platform_link_initialized || (priv->is_nm_owned && nm_device_is_software (self))) { - gboolean platform_unmanaged = FALSE; - - if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) - nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_DEFAULT, platform_unmanaged); - } else { - /* Hardware and externally-created software links stay unmanaged - * until they are fully initialized by the platform. NM created - * links must be available for activation immediately and thus - * do not get the PLATFORM_INIT unmanaged flag set. - */ - nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_PLATFORM_INIT, TRUE); - } - } - - priv->initialized = TRUE; -} - static void update_dynamic_ip_setup (NMDevice *self) { @@ -1272,7 +1250,7 @@ carrier_changed (NMDevice *self, gboolean carrier) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (!nm_device_get_managed (self)) + if (priv->state <= NM_DEVICE_STATE_UNMANAGED) return; nm_device_recheck_available_connections (self); @@ -1304,8 +1282,6 @@ carrier_changed (NMDevice *self, gboolean carrier) } if (carrier) { - g_warn_if_fail (priv->state >= NM_DEVICE_STATE_UNAVAILABLE); - if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); @@ -1324,8 +1300,6 @@ carrier_changed (NMDevice *self, gboolean carrier) update_dynamic_ip_setup (self); } } else { - g_return_if_fail (priv->state >= NM_DEVICE_STATE_UNAVAILABLE); - if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { if (nm_device_queued_state_peek (self) >= NM_DEVICE_STATE_DISCONNECTED) nm_device_queued_state_clear (self); @@ -1378,7 +1352,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier) return; priv->carrier = carrier; - g_object_notify (G_OBJECT (self), NM_DEVICE_CARRIER); + _notify (self, PROP_CARRIER); if (priv->carrier) { _LOGI (LOGD_DEVICE, "link connected"); @@ -1450,7 +1424,6 @@ device_link_changed (NMDevice *self) NMPlatformLink info; const NMPlatformLink *pllink; int ifindex; - gboolean just_initialized = FALSE; gboolean was_up; priv->device_link_changed_id = 0; @@ -1467,26 +1440,26 @@ device_link_changed (NMDevice *self) /* Update UDI to what udev gives us */ g_free (priv->udi); priv->udi = g_strdup (udi); - g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + _notify (self, PROP_UDI); } if (g_strcmp0 (info.driver, priv->driver)) { /* Update driver to what udev gives us */ g_free (priv->driver); priv->driver = g_strdup (info.driver); - g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER); + _notify (self, PROP_DRIVER); } /* Update MTU if it has changed. */ if (priv->mtu != info.mtu) { priv->mtu = info.mtu; - g_object_notify (G_OBJECT (self), NM_DEVICE_MTU); + _notify (self, PROP_MTU); } if (info.driver && g_strcmp0 (priv->driver, info.driver) != 0) { g_free (priv->driver); priv->driver = g_strdup (info.driver); - g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER); + _notify (self, PROP_DRIVER); } if (info.name[0] && strcmp (priv->iface, info.name) != 0) { @@ -1498,9 +1471,9 @@ device_link_changed (NMDevice *self) /* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */ ip_ifname_changed = !priv->ip_iface; - g_object_notify (G_OBJECT (self), NM_DEVICE_IFACE); + _notify (self, PROP_IFACE); if (ip_ifname_changed) - g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); + _notify (self, PROP_IP_IFACE); /* Re-match available connections against the new interface name */ nm_device_recheck_available_connections (self); @@ -1524,71 +1497,62 @@ device_link_changed (NMDevice *self) if (ip_ifname_changed) update_dynamic_ip_setup (self); - if (priv->ifindex > 0 && !priv->platform_link_initialized && info.initialized) { - gboolean platform_unmanaged = FALSE; - - priv->platform_link_initialized = TRUE; - - if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) { - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_DEFAULT, - platform_unmanaged, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } - - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_PLATFORM_INIT, - FALSE, - NM_DEVICE_STATE_REASON_NOW_MANAGED); - - just_initialized = TRUE; - } - was_up = priv->up; - priv->up = NM_FLAGS_HAS (info.flags, IFF_UP); + priv->up = NM_FLAGS_HAS (info.n_ifi_flags, IFF_UP); + + if ( priv->ifindex > 0 + && info.initialized + && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { + NMDeviceStateReason reason; + + nm_device_set_unmanaged_by_user_udev (self); + + /* If the devices that need an external IFF_UP go managed below, + * it means they're already up. In that case we should use an "assumed" + * reason to prevent the cleanup sequence from being run on transition + * from "unmanaged" to "unavailable". */ + if ( priv->up + && !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN) + && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) { + /* Ensure the assume check is queued before any queued state changes + * from the transition to UNAVAILABLE. + */ + nm_device_queue_recheck_assume (self); + reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; + } else + reason = NM_DEVICE_STATE_REASON_NOW_MANAGED; - if ( priv->platform_link_initialized - && ( just_initialized - || priv->up != was_up)) { + nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); + } + if ( priv->ifindex > 0 + && priv->up != was_up + && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) { /* Manage externally-created software interfaces only when they are IFF_UP */ - g_assert (priv->ifindex > 0); - if (NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) { - gboolean external_down = !!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN); - - if (external_down && NM_FLAGS_HAS (info.flags, IFF_UP)) { - if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED) { - /* Ensure the assume check is queued before any queued state changes - * from the transition to UNAVAILABLE. - */ - nm_device_queue_recheck_assume (self); - - /* Resetting the EXTERNAL_DOWN flag may change the device's state - * to UNAVAILABLE. To ensure that the state change doesn't touch - * the device before assumption occurs, pass - * NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED as the reason. - */ - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_EXTERNAL_DOWN, - FALSE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - } else { - /* Don't trigger a state change; if the device is in a - * state higher than UNAVAILABLE, it is already IFF_UP - * or an explicit activation request was received. - */ - _set_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN, FALSE); - } - } else if (!external_down && !NM_FLAGS_HAS (info.flags, IFF_UP) && nm_device_get_state (self) <= NM_DEVICE_STATE_DISCONNECTED) { - /* If the device is already disconnected and is set !IFF_UP, - * unmanage it. - */ - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_EXTERNAL_DOWN, - TRUE, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } + if ( priv->up + && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) { + /* Ensure the assume check is queued before any queued state changes + * from the transition to UNAVAILABLE. + */ + nm_device_queue_recheck_assume (self); } + + /* In case of @priv->up, resetting the EXTERNAL_DOWN flag may change the device's + * state to UNAVAILABLE. To ensure that the state change doesn't touch + * the device before assumption occurs, pass NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED + * as the reason. + * + * In case of !@priv->up, and the device is already unmanaged for other reasons, the + * state-change-reason has no effect. + * If the device is managed for an explict user-request, the state-change-reason + * also has no effect, because the device stays managed. + * + * The state-change-reason only has effect if the device was assumed + * and is now to be unmanaged. */ + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_EXTERNAL_DOWN, + !priv->up, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } device_recheck_slave_status (self, &info); @@ -1617,7 +1581,7 @@ device_ip_link_changed (NMDevice *self) g_free (priv->ip_iface); priv->ip_iface = g_strdup (pllink->name); - g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); + _notify (self, PROP_IP_IFACE); update_dynamic_ip_setup (self); } return G_SOURCE_REMOVE; @@ -1782,7 +1746,11 @@ nm_device_create_and_realize (NMDevice *self, realize_start_setup (self, plink); nm_device_realize_finish (self, plink); - g_return_val_if_fail (nm_device_check_connection_compatible (self, connection), TRUE); + if (nm_device_get_managed (self, FALSE)) { + nm_device_state_changed (self, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NOW_MANAGED); + } return TRUE; } @@ -1798,25 +1766,24 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink) if (udi && !g_strcmp0 (udi, priv->udi)) { g_free (priv->udi); priv->udi = g_strdup (udi); - g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + _notify (self, PROP_UDI); } if (!g_strcmp0 (plink->name, priv->iface)) { g_free (priv->iface); priv->iface = g_strdup (plink->name); - g_object_notify (G_OBJECT (self), NM_DEVICE_IFACE); + _notify (self, PROP_IFACE); } priv->ifindex = plink->ifindex; - g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX); + _notify (self, PROP_IFINDEX); - priv->up = NM_FLAGS_HAS (plink->flags, IFF_UP); + priv->up = NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP); if (plink->driver && g_strcmp0 (plink->driver, priv->driver) != 0) { g_free (priv->driver); priv->driver = g_strdup (plink->driver); - g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER); + _notify (self, PROP_DRIVER); } - priv->platform_link_initialized = plink->initialized; } static void @@ -1874,6 +1841,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) /* The device should not be realized */ g_return_if_fail (!priv->real); + 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); @@ -1891,7 +1859,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) if (priv->ifindex > 0) { priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex); - g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID); + _notify (self, PROP_PHYSICAL_PORT_ID); priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex); @@ -1899,7 +1867,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex); - g_object_notify (G_OBJECT (self), NM_DEVICE_MTU); + _notify (self, PROP_MTU); nm_platform_link_get_driver_info (NM_PLATFORM_GET, priv->ifindex, @@ -1907,9 +1875,9 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) &priv->driver_version, &priv->firmware_version); if (priv->driver_version) - g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION); + _notify (self, PROP_DRIVER_VERSION); if (priv->firmware_version) - g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION); + _notify (self, PROP_FIRMWARE_VERSION); if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ifindex); @@ -1921,7 +1889,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) if (!priv->udi) { /* Use a placeholder UDI until we get a real one */ priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++); - g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + _notify (self, PROP_UDI); } /* trigger initial ip config change to initialize ip-config */ @@ -1951,9 +1919,26 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->carrier = TRUE; } - g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES); + _notify (self, PROP_CAPABILITIES); klass->realize_start_notify (self, plink); + + /* Do not manage externally created software devices until they are IFF_UP */ + if ( priv->ifindex > 0 + && plink + && !priv->up + && NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) + nm_device_set_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); + + /* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag. + * Later we might want to manage 'lo' too. Currently that doesn't work because + * NetworkManager might down the interface or remove the 127.0.0.1 address. */ + nm_device_set_unmanaged_flags (self, NM_UNMANAGED_LOOPBACK, priv->ifindex == 1); + + nm_device_set_unmanaged_by_user_udev (self); + + nm_device_set_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT, + plink && !plink->initialized); } /** @@ -1977,17 +1962,15 @@ nm_device_realize_finish (NMDevice *self, const NMPlatformLink *plink) g_return_if_fail (!priv->real); - if (plink) { - update_device_from_platform_link (self, plink); + if (plink) device_recheck_slave_status (self, plink); - } priv->real = TRUE; - g_object_notify (G_OBJECT (self), NM_DEVICE_REAL); + _notify (self, PROP_REAL); nm_device_recheck_available_connections (self); - /* Balanced by a freeze in realize_start_setup() */ + /* Balanced by a freeze in realize_start_setup(). */ g_object_thaw_notify (G_OBJECT (self)); } @@ -2000,7 +1983,7 @@ unrealize_notify (NMDevice *self) } static gboolean -available_connection_check_delete_unrealized_on_idle (gpointer user_data) +available_connections_check_delete_unrealized_on_idle (gpointer user_data) { NMDevice *self = user_data; NMDevicePrivate *priv; @@ -2019,7 +2002,7 @@ available_connection_check_delete_unrealized_on_idle (gpointer user_data) } static void -available_connection_check_delete_unrealized (NMDevice *self) +available_connections_check_delete_unrealized (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -2028,7 +2011,7 @@ available_connection_check_delete_unrealized (NMDevice *self) if ( g_hash_table_size (priv->available_connections) == 0 && !nm_device_is_real (self)) - priv->check_delete_unrealized_id = g_idle_add (available_connection_check_delete_unrealized_on_idle, self); + priv->check_delete_unrealized_id = g_idle_add (available_connections_check_delete_unrealized_on_idle, self); } /** @@ -2078,32 +2061,32 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) if (priv->ifindex > 0) { priv->ifindex = 0; - g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX); + _notify (self, PROP_IFINDEX); } priv->ip_ifindex = 0; if (priv->ip_iface) { g_clear_pointer (&priv->ip_iface, g_free); - g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); + _notify (self, PROP_IP_IFACE); } if (priv->driver_version) { g_clear_pointer (&priv->driver_version, g_free); - g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION); + _notify (self, PROP_DRIVER_VERSION); } if (priv->firmware_version) { g_clear_pointer (&priv->firmware_version, g_free); - g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION); + _notify (self, PROP_FIRMWARE_VERSION); } if (priv->udi) { g_clear_pointer (&priv->udi, g_free); - g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + _notify (self, PROP_UDI); } if (priv->hw_addr) { g_clear_pointer (&priv->hw_addr, g_free); - g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS); + _notify (self, PROP_HW_ADDRESS); } if (priv->physical_port_id) { g_clear_pointer (&priv->physical_port_id, g_free); - g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID); + _notify (self, PROP_PHYSICAL_PORT_ID); } g_clear_pointer (&priv->perm_hw_addr, g_free); @@ -2112,15 +2095,27 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); - g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES); + _notify (self, PROP_CAPABILITIES); priv->real = FALSE; - g_object_notify (G_OBJECT (self), NM_DEVICE_REAL); + _notify (self, PROP_REAL); nm_device_set_autoconnect (self, DEFAULT_AUTOCONNECT); g_object_thaw_notify (G_OBJECT (self)); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_PLATFORM_INIT, + TRUE); + + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_PARENT | + NM_UNMANAGED_LOOPBACK | + NM_UNMANAGED_USER_UDEV | + NM_UNMANAGED_EXTERNAL_DOWN | + NM_UNMANAGED_IS_SLAVE, + NM_UNMAN_FLAG_OP_FORGET); + nm_device_state_changed (self, NM_DEVICE_STATE_UNMANAGED, remove_resources ? @@ -2295,10 +2290,13 @@ nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) /* no need to emit * - * g_object_notify (G_OBJECT (slave), NM_DEVICE_MASTER); + * _notify (slave, PROP_MASTER); * * because slave_priv->is_enslaved is not true, thus the value * didn't change yet. */ + + g_warn_if_fail (!NM_FLAGS_HAS (slave_priv->unmanaged_mask, NM_UNMANAGED_IS_SLAVE)); + nm_device_set_unmanaged_by_flags (slave, NM_UNMANAGED_IS_SLAVE, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } else g_return_if_fail (slave_priv->master == self); @@ -2476,8 +2474,8 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success) _LOGI (LOGD_DEVICE, "enslaved to %s", nm_device_get_iface (priv->master)); priv->is_enslaved = TRUE; - g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); - g_object_notify (G_OBJECT (priv->master), NM_DEVICE_SLAVES); + _notify (self, PROP_MASTER); + _notify (priv->master, PROP_SLAVES); } else if (activating) { _LOGW (LOGD_DEVICE, "Activation: connection '%s' could not be enslaved", nm_connection_get_id (connection)); @@ -2535,8 +2533,8 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) if (priv->is_enslaved) { priv->is_enslaved = FALSE; - g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); - g_object_notify (G_OBJECT (priv->master), NM_DEVICE_SLAVES); + _notify (self, PROP_MASTER); + _notify (priv->master, PROP_SLAVES); } } @@ -2662,19 +2660,12 @@ nm_device_set_autoconnect (NMDevice *self, gboolean autoconnect) g_return_if_fail (NM_IS_DEVICE (self)); - priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->autoconnect == autoconnect) - return; + autoconnect = !!autoconnect; - if (autoconnect) { - /* Default-unmanaged devices never autoconnect */ - if (!nm_device_get_default_unmanaged (self)) { - priv->autoconnect = TRUE; - g_object_notify (G_OBJECT (self), NM_DEVICE_AUTOCONNECT); - } - } else { - priv->autoconnect = FALSE; - g_object_notify (G_OBJECT (self), NM_DEVICE_AUTOCONNECT); + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->autoconnect != autoconnect) { + priv->autoconnect = autoconnect; + _notify (self, PROP_AUTOCONNECT); } } @@ -2980,15 +2971,18 @@ nm_device_complete_connection (NMDevice *self, static gboolean check_connection_compatible (NMDevice *self, NMConnection *connection) { - NMSettingConnection *s_con; - const char *config_iface, *device_iface; + const char *device_iface = nm_device_get_iface (self); + gs_free char *conn_iface = nm_manager_get_connection_iface (nm_manager_get (), + connection, + NULL, NULL); - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); + /* We always need a interface name for virtual devices, but for + * physical ones a connection without interface name is fine for + * any device. */ + if (!conn_iface) + return !nm_connection_is_virtual (connection); - config_iface = nm_setting_connection_get_interface_name (s_con); - device_iface = nm_device_get_iface (self); - if (config_iface && strcmp (config_iface, device_iface) != 0) + if (strcmp (conn_iface, device_iface) != 0) return FALSE; return TRUE; @@ -3401,7 +3395,7 @@ lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, { NMDevice *self = NM_DEVICE (user_data); - g_object_notify (G_OBJECT (self), NM_DEVICE_LLDP_NEIGHBORS); + _notify (self, PROP_LLDP_NEIGHBORS); } static gboolean @@ -3457,7 +3451,7 @@ activate_stage1_device_prepare (NMDevice *self) priv->ip4_state = priv->ip6_state = IP_NONE; /* Notify the new ActiveConnection along with the state change */ - g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); + _notify (self, PROP_ACTIVE_CONNECTION); nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); @@ -3629,12 +3623,12 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self) } /* - * nm_device_check_ip_failed + * check_ip_failed * * Progress the device to appropriate state if both IPv4 and IPv6 failed */ static void -nm_device_check_ip_failed (NMDevice *self, gboolean may_fail) +check_ip_failed (NMDevice *self, gboolean may_fail) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMDeviceState state; @@ -3664,6 +3658,212 @@ nm_device_check_ip_failed (NMDevice *self, gboolean may_fail) NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } +/* + * check_ip_done + * + * Progress the device to ip connectivity check state if IPv4 or IPv6 succeeded + */ +static void +check_ip_done (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (nm_device_get_state (self) != NM_DEVICE_STATE_IP_CONFIG) + return; + + if (priv->ip4_state != IP_DONE && !get_ip_config_may_fail (self, AF_INET)) + return; + + if (priv->ip6_state != IP_DONE && !get_ip_config_may_fail (self, AF_INET6)) + return; + + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); +} + +/*********************************************/ +/* IPv4 DAD stuff */ + +static guint +get_ipv4_dad_timeout (NMDevice *self) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip4 = NULL; + gs_free char *value = NULL; + gint ret = 0; + + connection = nm_device_get_applied_connection (self); + if (connection) + s_ip4 = nm_connection_get_setting_ip4_config (connection); + + if (s_ip4) { + ret = nm_setting_ip_config_get_dad_timeout (s_ip4); + + if (ret < 0) { + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ipv4.dad-timeout", self); + ret = _nm_utils_ascii_str_to_int64 (value, 10, -1, + NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, + -1); + ret = ret < 0 ? 0 : ret; + } + } + + return ret; +} + +static void +arping_data_destroy (gpointer ptr, GClosure *closure) +{ + ArpingData *data = ptr; + int i; + + if (data) { + for (i = 0; data->configs && data->configs[i]; i++) + g_object_unref (data->configs[i]); + g_free (data->configs); + g_slice_free (ArpingData, data); + } +} + +static void +ipv4_manual_method_apply (NMDevice *self, NMIP4Config **configs, gboolean success) +{ + NMIP4Config *empty; + + if (success) { + empty = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); + nm_device_activate_schedule_ip4_config_result (self, empty); + g_object_unref (empty); + } else { + nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } +} + +static void +arping_manager_probe_terminated (NMArpingManager *arping_manager, ArpingData *data) +{ + NMDevice *self; + NMDevicePrivate *priv; + const NMPlatformIP4Address *address; + gboolean result, success = TRUE; + int i, j; + + g_assert (data); + self = data->device; + priv = NM_DEVICE_GET_PRIVATE (self); + + for (i = 0; data->configs && data->configs[i]; i++) { + for (j = 0; j < nm_ip4_config_get_num_addresses (data->configs[i]); j++) { + address = nm_ip4_config_get_address (data->configs[i], j); + result = nm_arping_manager_check_address (arping_manager, address->address); + success &= result; + + _NMLOG (result ? LOGL_DEBUG : LOGL_WARN, + LOGD_DEVICE, + "IPv4 DAD result: address %s is %s", + nm_utils_inet4_ntop (address->address, NULL), + result ? "unique" : "duplicate"); + } + } + + data->callback (self, data->configs, success); + + priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager); + nm_arping_manager_destroy (arping_manager); +} + +/** + * ipv4_dad_start: + * @self: device instance + * @configs: NULL-terminated array of IPv4 configurations + * @cb: callback function + * + * Start IPv4 DAD on device @self, check addresses in @configs and call @cb + * when the procedure ends. @cb will be called in any case, even if DAD can't + * be started. @configs will be unreferenced after @cb has been called. + */ +static void +ipv4_dad_start (NMDevice *self, NMIP4Config **configs, ArpingCallback cb) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMArpingManager *arping_manager; + const NMPlatformIP4Address *address; + ArpingData *data; + guint timeout; + gboolean ret, addr_found; + const guint8 *hw_addr; + size_t hw_addr_len = 0; + GError *error = NULL; + guint i, j; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (configs); + g_return_if_fail (cb); + + for (i = 0, addr_found = FALSE; configs[i]; i++) { + if (nm_ip4_config_get_num_addresses (configs[i]) > 0) { + addr_found = TRUE; + break; + } + } + + timeout = get_ipv4_dad_timeout (self); + hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (self), + &hw_addr_len); + + if ( !timeout + || !hw_addr + || !hw_addr_len + || !addr_found + || nm_device_uses_assumed_connection (self)) { + + /* DAD not needed, signal success */ + cb (self, configs, TRUE); + + for (i = 0; configs[i]; i++) + g_object_unref (configs[i]); + g_free (configs); + + return; + } + + /* don't take additional references of @arping_manager that outlive @self. + * Otherwise, the callback can be invoked on a dangling pointer as we don't + * disconnect the handler. */ + arping_manager = nm_arping_manager_new (nm_device_get_ip_ifindex (self)); + priv->arping.dad_list = g_slist_append (priv->arping.dad_list, arping_manager); + + data = g_slice_new0 (ArpingData); + data->configs = configs; + data->callback = cb; + data->device = self; + + for (i = 0; configs[i]; i++) { + for (j = 0; j < nm_ip4_config_get_num_addresses (configs[i]); j++) { + address = nm_ip4_config_get_address (configs[i], j); + nm_arping_manager_add_address (arping_manager, address->address); + } + } + + g_signal_connect_data (arping_manager, NM_ARPING_MANAGER_PROBE_TERMINATED, + G_CALLBACK (arping_manager_probe_terminated), data, + arping_data_destroy, 0); + + ret = nm_arping_manager_start_probe (arping_manager, timeout, &error); + + if (!ret) { + _LOGW (LOGD_DEVICE, "arping probe failed: %s", error->message); + + /* DAD could not be started, signal success */ + cb (self, configs, TRUE); + + priv->arping.dad_list = g_slist_remove (priv->arping.dad_list, arping_manager); + nm_arping_manager_destroy (arping_manager); + } +} + /*********************************************/ /* IPv4LL stuff */ @@ -3738,14 +3938,14 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) if (r < 0) { _LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r); priv->ip4_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); return; } if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { _LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr); priv->ip4_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); return; } @@ -3753,7 +3953,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) if (config == NULL) { _LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config"); priv->ip4_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); return; } @@ -3764,7 +3964,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) if (!ip4_config_merge_and_apply (self, config, TRUE, NULL)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); priv->ip4_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); } } else g_assert_not_reached (); @@ -3774,7 +3974,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) default: _LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event); priv->ip4_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); } } @@ -3985,7 +4185,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) if (priv->dhcp4_config) { nm_exported_object_clear_and_unexport (&priv->dhcp4_config); - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); + _notify (self, PROP_DHCP4_CONFIG); } } @@ -4156,6 +4356,8 @@ END_ADD_DEFAULT_ROUTE: priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4); } + nm_ip4_config_addresses_sort (composite); + /* Allow setting MTU etc */ if (commit) { if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) @@ -4253,6 +4455,17 @@ dhcp4_fail (NMDevice *self, gboolean timeout) } static void +dhcp4_dad_cb (NMDevice *self, NMIP4Config **configs, gboolean success) +{ + if (success) + nm_device_activate_schedule_ip4_config_result (self, configs[1]); + else { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } +} + +static void dhcp4_state_changed (NMDhcpClient *client, NMDhcpState state, NMIP4Config *ip4_config, @@ -4262,6 +4475,8 @@ dhcp4_state_changed (NMDhcpClient *client, { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMIP4Config *manual, **configs; + NMConnection *connection; g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE); g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config)); @@ -4279,11 +4494,23 @@ dhcp4_state_changed (NMDhcpClient *client, } nm_dhcp4_config_set_options (priv->dhcp4_config, options); - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); + _notify (self, PROP_DHCP4_CONFIG); - if (priv->ip4_state == IP_CONF) - nm_device_activate_schedule_ip4_config_result (self, ip4_config); - else if (priv->ip4_state == IP_DONE) { + if (priv->ip4_state == IP_CONF) { + connection = nm_device_get_applied_connection (self); + g_assert (connection); + + manual = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); + nm_ip4_config_merge_setting (manual, + nm_connection_get_setting_ip4_config (connection), + nm_device_get_ip4_route_metric (self)); + + configs = g_new0 (NMIP4Config *, 3); + configs[0] = manual; + configs[1] = g_object_ref (ip4_config); + + ipv4_dad_start (self, configs, dhcp4_dad_cb); + } else if (priv->ip4_state == IP_DONE) { dhcp4_lease_change (self, ip4_config); nm_device_update_metered (self); } @@ -4312,7 +4539,7 @@ dhcp4_get_timeout (NMDevice *self, NMSettingIP4Config *s_ip4) gs_free char *value = NULL; int timeout; - timeout = nm_setting_ip4_config_get_dhcp_timeout (s_ip4); + timeout = nm_setting_ip_config_get_dhcp_timeout (NM_SETTING_IP_CONFIG (s_ip4)); if (timeout) return timeout; @@ -4629,10 +4856,17 @@ act_stage3_ip4_config_start (NMDevice *self, else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) ret = ipv4ll_start (self, reason); else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { - /* Use only IPv4 config from the connection data */ - *out_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); - g_assert (*out_config); - ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMIP4Config **configs, *config; + + config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); + nm_ip4_config_merge_setting (config, + nm_connection_get_setting_ip4_config (connection), + nm_device_get_ip4_route_metric (self)); + + configs = g_new0 (NMIP4Config *, 2); + configs[0] = config; + ipv4_dad_start (self, configs, ipv4_manual_method_apply); + ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { *out_config = shared4_new_config (self, connection, reason); if (*out_config) { @@ -4676,7 +4910,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) if (priv->dhcp6_config) { nm_exported_object_clear_and_unexport (&priv->dhcp6_config); - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); + _notify (self, PROP_DHCP6_CONFIG); } } @@ -5011,7 +5245,7 @@ dhcp6_state_changed (NMDhcpClient *client, 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); - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); + _notify (self, PROP_DHCP6_CONFIG); } } @@ -5057,9 +5291,7 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) GByteArray *tmp = NULL; const guint8 *hw_addr; size_t hw_addr_len = 0; - const struct in6_addr *ll_addr = NULL; - NMIP6Config *ip6_config; - int i; + const NMPlatformIP6Address *ll_addr = NULL; g_assert (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -5071,22 +5303,16 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) g_byte_array_append (tmp, hw_addr, hw_addr_len); } - ip6_config = priv->ext_ip6_config; - for (i = 0; ip6_config && i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i); + if (priv->ext_ip6_config_captured) + ll_addr = nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE); - if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) { - ll_addr = &addr->address; - break; - } - } g_return_val_if_fail (ll_addr, FALSE); priv->dhcp6_client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), tmp, - ll_addr, + &ll_addr->address, nm_connection_get_uuid (connection), nm_device_get_ip6_route_metric (self), nm_setting_ip_config_get_dhcp_send_hostname (s_ip6), @@ -5169,27 +5395,6 @@ nm_device_dhcp6_renew (NMDevice *self, gboolean release) /******************************************/ -static gboolean -have_ip6_address (const NMIP6Config *ip6_config, gboolean linklocal) -{ - guint i; - - if (!ip6_config) - return FALSE; - - linklocal = !!linklocal; - - for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i); - - if ((IN6_IS_ADDR_LINKLOCAL (&addr->address) == linklocal) && - !(addr->flags & IFA_F_TENTATIVE)) - return TRUE; - } - - return FALSE; -} - static void linklocal6_cleanup (NMDevice *self) { @@ -5223,7 +5428,7 @@ linklocal6_complete (NMDevice *self) const char *method; g_assert (priv->linklocal6_timeout_id); - g_assert (have_ip6_address (priv->ip6_config, TRUE)); + g_assert (nm_ip6_config_get_address_first_nontentative (priv->ip6_config, TRUE)); linklocal6_cleanup (self); @@ -5271,7 +5476,7 @@ check_and_add_ipv6ll_addr (NMDevice *self) addr = nm_ip6_config_get_address (priv->ip6_config, i); if ( IN6_IS_ADDR_LINKLOCAL (&addr->address) - && !(addr->flags & IFA_F_DADFAILED)) { + && !(addr->n_ifa_flags & IFA_F_DADFAILED)) { /* Already have an LL address, nothing to do */ return; } @@ -5288,9 +5493,9 @@ check_and_add_ipv6ll_addr (NMDevice *self) if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { if (!nm_utils_ipv6_addr_set_stable_privacy (&lladdr, nm_device_get_iface (self), - nm_connection_get_uuid (connection), + nm_connection_get_uuid (connection), priv->linklocal6_dad_counter++, - &error)) { + &error)) { _LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); g_clear_error (&error); linklocal6_failed (self); @@ -5340,7 +5545,8 @@ linklocal6_start (NMDevice *self) linklocal6_cleanup (self); - if (have_ip6_address (priv->ip6_config, TRUE)) + if ( priv->ip6_config + && nm_ip6_config_get_address_first_nontentative (priv->ip6_config, TRUE)) return NM_ACT_STAGE_RETURN_FINISH; connection = nm_device_get_applied_connection (self); @@ -5421,7 +5627,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int i; int system_support; - guint ifa_flags = 0x00; + guint32 ifa_flags = 0x00; /* * Check, whether kernel is recent enough to help user space handling RA. @@ -5477,7 +5683,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) if (address.preferred > address.lifetime) address.preferred = address.lifetime; address.source = NM_IP_CONFIG_SOURCE_RDISC; - address.flags = ifa_flags; + address.n_ifa_flags = ifa_flags; nm_ip6_config_add_address (priv->ac_ip6_config, &address); } @@ -5575,7 +5781,8 @@ rdisc_ra_timeout (NMRDisc *rdisc, NMDevice *self) * IPv6 configuration, like manual IPv6 addresses or external IPv6 * config, consider that sufficient for IPv6 success. */ - if (have_ip6_address (priv->ip6_config, FALSE)) + 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); @@ -5769,7 +5976,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) if (enable) { /* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */ - value = nm_platform_sysctl_get (NM_PLATFORM_GET, + value = nm_platform_sysctl_get (NM_PLATFORM_GET, nm_utils_ip6_property_path (nm_device_get_ip_iface (self), "disable_ipv6")); if (g_strcmp0 (value, "0") == 0) nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); @@ -6054,8 +6261,7 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) } else if (ret == NM_ACT_STAGE_RETURN_FINISH) { /* Early finish, nothing more to do */ priv->ip6_state = IP_DONE; - if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + check_ip_done (self); } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { /* Wait for something to try IP config again */ priv->ip6_state = IP_WAIT; @@ -6116,7 +6322,7 @@ activate_stage3_ip_config_start (NMDevice *self) && !nm_device_activate_stage3_ip6_start (self)) return; - nm_device_check_ip_failed (self, TRUE); + check_ip_failed (self, TRUE); } static gboolean @@ -6251,7 +6457,7 @@ activate_stage4_ip4_config_timeout (NMDevice *self) priv->ip4_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); } @@ -6311,7 +6517,7 @@ activate_stage4_ip6_config_timeout (NMDevice *self) priv->ip6_state = IP_FAIL; - nm_device_check_ip_failed (self, FALSE); + check_ip_failed (self, FALSE); } @@ -6410,16 +6616,16 @@ start_sharing (NMDevice *self, NMIP4Config *config) req = nm_device_get_act_request (self); g_assert (req); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface); - add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface); - add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface); - add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface); - add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface); - add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface); add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask); + add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface); + add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface); + add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface); + add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface); + add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface); + add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface); nm_act_request_set_shared (req, TRUE); @@ -6438,77 +6644,14 @@ start_sharing (NMDevice *self, NMIP4Config *config) } static void -send_arps (NMDevice *self, const char *mode_arg) -{ - const char *argv[] = { NULL, mode_arg, "-q", "-I", nm_device_get_ip_iface (self), "-c", "1", NULL, NULL }; - int ip_arg = G_N_ELEMENTS (argv) - 2; - NMConnection *connection; - NMSettingIPConfig *s_ip4; - int i, num; - NMIPAddress *addr; - GError *error = NULL; - - connection = nm_device_get_applied_connection (self); - if (!connection) - return; - s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (!s_ip4) - return; - num = nm_setting_ip_config_get_num_addresses (s_ip4); - if (num == 0) - return; - - argv[0] = nm_utils_find_helper ("arping", NULL, NULL); - if (!argv[0]) { - _LOGW (LOGD_DEVICE | LOGD_IP4, "arping could not be found; no ARPs will be sent"); - return; - } - - for (i = 0; i < num; i++) { - gs_free char *tmp_str = NULL; - gboolean success; - - addr = nm_setting_ip_config_get_address (s_ip4, i); - argv[ip_arg] = nm_ip_address_get_address (addr); - - _LOGD (LOGD_DEVICE | LOGD_IP4, - "arping: 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 (LOGD_DEVICE | LOGD_IP4, - "arping: could not send ARP for local address %s: %s", - argv[ip_arg], error->message); - g_clear_error (&error); - } - } -} - -static gboolean -arp_announce_round2 (gpointer user_data) -{ - NMDevice *self = user_data; - NMDevicePrivate *priv; - - g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); - - priv = NM_DEVICE_GET_PRIVATE (self); - priv->arp_round2_id = 0; - - if ( priv->state >= NM_DEVICE_STATE_IP_CONFIG - && priv->state <= NM_DEVICE_STATE_ACTIVATED) - send_arps (self, "-U"); - - return G_SOURCE_REMOVE; -} - -static void arp_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - nm_clear_g_source (&priv->arp_round2_id); + if (priv->arping.announcing) { + nm_arping_manager_destroy (priv->arping.announcing); + priv->arping.announcing = NULL; + } } static void @@ -6517,10 +6660,19 @@ arp_announce (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; NMSettingIPConfig *s_ip4; - int num; + guint num, i; + const guint8 *hw_addr; + size_t hw_addr_len = 0; arp_cleanup (self); + hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (self), + &hw_addr_len); + + if (!hw_addr_len || !hw_addr) + return; + /* We only care about manually-configured addresses; DHCP- and autoip-configured * ones should already have been seen on the network at this point. */ @@ -6534,8 +6686,19 @@ arp_announce (NMDevice *self) if (num == 0) return; - send_arps (self, "-A"); - priv->arp_round2_id = g_timeout_add_seconds (2, arp_announce_round2, self); + priv->arping.announcing = nm_arping_manager_new (nm_device_get_ip_ifindex (self)); + + for (i = 0; i < num; i++) { + NMIPAddress *ip = nm_setting_ip_config_get_address (s_ip4, i); + in_addr_t addr; + + if (inet_pton (AF_INET, nm_ip_address_get_address (ip), &addr) == 1) + nm_arping_manager_add_address (priv->arping.announcing, addr); + else + g_warn_if_reached (); + } + + nm_arping_manager_announce_addresses (priv->arping.announcing); } static void @@ -6597,13 +6760,11 @@ activate_stage5_ip4_config_commit (NMDevice *self) arp_announce (self); - /* Enter the IP_CHECK state if this is the first method to complete */ - priv->ip4_state = IP_DONE; - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); - if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + /* Enter the IP_CHECK state if this is the first method to complete */ + priv->ip4_state = IP_DONE; + check_ip_done (self); } static void @@ -6690,26 +6851,24 @@ activate_stage5_ip6_config_commit (NMDevice *self) * then ensure dispatcher scripts get the DHCP lease information. */ nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), + self, + NULL, + NULL, + NULL); } else { /* still waiting for first dhcp6 lease. */ return; } } - /* Enter the IP_CHECK state if this is the first method to complete */ - priv->ip6_state = IP_DONE; - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE); - if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) - nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + /* Enter the IP_CHECK state if this is the first method to complete */ + priv->ip6_state = IP_DONE; + check_ip_done (self); } else { _LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed"); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); @@ -6760,7 +6919,7 @@ clear_act_request (NMDevice *self) nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id); g_clear_object (&priv->act_request); - g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); + _notify (self, PROP_ACTIVE_CONNECTION); } static void @@ -6792,7 +6951,7 @@ _update_ip4_address (NMDevice *self) addr = nm_ip4_config_get_address (priv->ip4_config, 0)->address; if (addr != priv->ip4_address) { priv->ip4_address = addr; - g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS); + _notify (self, PROP_IP4_ADDRESS); } } } @@ -6911,25 +7070,23 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) addrconf6_cleanup (self); } -G_GNUC_NULL_TERMINATED static gboolean -_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **error, ...) +_hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GError **error, const char **argv) { - va_list ap; - const char *key; guint found_keys = 0; + guint i; + + nm_assert (argv && argv[0]); #if NM_MORE_ASSERTS > 10 /* Assert that the keys are unique. */ { gs_unref_hashtable GHashTable *check_dups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); - va_start (ap, error); - while ((key = va_arg (ap, const char *))) { - if (!g_hash_table_add (check_dups, (char *) key)) + for (i = 0; argv[i]; i++) { + if (!g_hash_table_add (check_dups, (char *) argv[i])) nm_assert (FALSE); } - va_end (ap); nm_assert (g_hash_table_size (check_dups) > 0); } #endif @@ -6937,12 +7094,10 @@ _hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **e if (!hash || g_hash_table_size (hash) == 0) return TRUE; - va_start (ap, error); - while ((key = va_arg (ap, const char *))) { - if (g_hash_table_contains (hash, key)) + for (i = 0; argv[i]; i++) { + if (g_hash_table_contains (hash, argv[i])) found_keys++; } - va_end (ap); if (found_keys != g_hash_table_size (hash)) { GHashTableIter iter; @@ -6954,14 +7109,12 @@ _hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **e g_hash_table_iter_init (&iter, hash); while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) { - va_start (ap, error); - while ((key = va_arg (ap, const char *))) { - if (!strcmp (key, k)) { + for (i = 0; argv[i]; i++) { + if (!strcmp (argv[i], k)) { first_invalid_key = k; break; } } - va_end (ap); if (first_invalid_key) break; } @@ -6978,6 +7131,7 @@ _hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **e return TRUE; } +#define _hash_check_invalid_keys(hash, setting_name, error, ...) _hash_check_invalid_keys_impl (hash, setting_name, error, ((const char *[]) { __VA_ARGS__, NULL })) void nm_device_reactivate_ip4_config (NMDevice *self, @@ -7002,8 +7156,10 @@ nm_device_reactivate_ip4_config (NMDevice *self, priv->ip4_state = IP_WAIT; if (!nm_device_activate_stage3_ip4_start (self)) _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); - } else - ip4_config_merge_and_apply (self, NULL, TRUE, NULL); + } else { + if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) + _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); + } } } @@ -7030,8 +7186,10 @@ nm_device_reactivate_ip6_config (NMDevice *self, priv->ip6_state = IP_WAIT; if (!nm_device_activate_stage3_ip6_start (self)) _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); - } else - ip6_config_merge_and_apply (self, TRUE, NULL); + } else { + if (!ip6_config_merge_and_apply (self, TRUE, NULL)) + _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); + } } } @@ -7039,6 +7197,8 @@ nm_device_reactivate_ip6_config (NMDevice *self, /* reapply_connection: * @connection: the new connection settings to be applied or %NULL to reapply * the current settings connection + * @version_id: either zero, or the current version id for the applied + * connection. * @error: the error if %FALSE is returned * * Change configuration of an already configured device if possible. @@ -7049,6 +7209,7 @@ nm_device_reactivate_ip6_config (NMDevice *self, static gboolean reapply_connection (NMDevice *self, NMConnection *connection, + guint64 version_id, GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -7079,24 +7240,36 @@ reapply_connection (NMDevice *self, if (!_hash_check_invalid_keys (diffs, NULL, error, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_SETTING_NAME, - NM_SETTING_CONNECTION_SETTING_NAME, - NULL)) + NM_SETTING_CONNECTION_SETTING_NAME)) return FALSE; if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL, NM_SETTING_CONNECTION_SETTING_NAME, error, NM_SETTING_CONNECTION_ZONE, - NM_SETTING_CONNECTION_METERED, - NULL)) + NM_SETTING_CONNECTION_METERED)) return FALSE; - _LOGD (LOGD_DEVICE, "reapply"); + if ( version_id != 0 + && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_VERSION_ID_MISMATCH, + "Reapply failed because device changed in the meantime and the version-id mismatches"); + return FALSE; + } /************************************************************************** * Update applied connection *************************************************************************/ + if (diffs) + nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request); + + _LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)", + (long long unsigned) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)), + diffs ? "" : " (unmodified)"); + if (diffs) { con_old = applied_clone = nm_simple_connection_new_clone (applied); con_new = applied; @@ -7122,6 +7295,11 @@ reapply_connection (NMDevice *self, return TRUE; } +typedef struct { + NMConnection *connection; + guint64 version_id; +} ReapplyData; + static void reapply_cb (NMDevice *self, GDBusMethodInvocation *context, @@ -7129,9 +7307,17 @@ reapply_cb (NMDevice *self, GError *error, gpointer user_data) { - gs_unref_object NMConnection *connection = NM_CONNECTION (user_data); + ReapplyData *reapply_data = user_data; + guint64 version_id = 0; + gs_unref_object NMConnection *connection = NULL; GError *local = NULL; + if (reapply_data) { + connection = reapply_data->connection; + version_id = reapply_data->version_id; + g_slice_free (ReapplyData, reapply_data); + } + if (error) { nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, error->message); g_dbus_method_invocation_return_gerror (context, error); @@ -7140,6 +7326,7 @@ reapply_cb (NMDevice *self, if (!reapply_connection (self, connection ? : (NMConnection *) nm_device_get_settings_connection (self), + version_id, &local)) { nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, local->message); g_dbus_method_invocation_take_error (context, local); @@ -7154,17 +7341,19 @@ static void impl_device_reapply (NMDevice *self, GDBusMethodInvocation *context, GVariant *settings, - guint flags) + guint64 version_id, + guint32 flags) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; NMConnection *connection = NULL; GError *error = NULL; + ReapplyData *reapply_data; /* No flags supported as of now. */ if (flags != 0) { error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ACTIVE, + NM_DEVICE_ERROR_FAILED, "Invalid flags specified"); nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); g_dbus_method_invocation_take_error (context, error); @@ -7195,6 +7384,13 @@ impl_device_reapply (NMDevice *self, nm_connection_clear_secrets (connection); } + if (connection || version_id) { + reapply_data = g_slice_new (ReapplyData); + reapply_data->connection = connection; + reapply_data->version_id = version_id; + } else + reapply_data = NULL; + /* Ask the manager to authenticate this request for us */ g_signal_emit (self, signals[AUTH_REQUEST], 0, context, @@ -7202,10 +7398,104 @@ impl_device_reapply (NMDevice *self, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, reapply_cb, - connection); + reapply_data); +} + +/*****************************************************************************/ + +static void +get_applied_connection_cb (NMDevice *self, + GDBusMethodInvocation *context, + NMAuthSubject *subject, + GError *error, + gpointer user_data /* possibly dangling pointer */) +{ + NMDevicePrivate *priv; + NMConnection *applied_connection; + GVariant *settings; + + g_return_if_fail (NM_IS_DEVICE (self)); + + if (error) { + g_dbus_method_invocation_return_gerror (context, error); + return; + } + + priv = NM_DEVICE_GET_PRIVATE (self); + + applied_connection = nm_device_get_applied_connection (self); + + if (!applied_connection) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not activated"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + if (applied_connection != user_data) { + /* The applied connection changed due to a race. Reauthenticate. */ + g_signal_emit (self, signals[AUTH_REQUEST], 0, + context, + applied_connection, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + get_applied_connection_cb, + applied_connection /* no need take a ref. We will not dereference this pointer. */); + return; + } + + settings = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); + if (!settings) + settings = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); + + g_dbus_method_invocation_return_value (context, + g_variant_new ("(@a{sa{sv}}t)", + settings, + nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request))); } static void +impl_device_get_applied_connection (NMDevice *self, + GDBusMethodInvocation *context, + guint32 flags) +{ + NMConnection *applied_connection; + GError *error = NULL; + + g_return_if_fail (NM_IS_DEVICE (self)); + + /* No flags supported as of now. */ + if (flags != 0) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "Invalid flags specified"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + applied_connection = nm_device_get_applied_connection (self); + if (!applied_connection) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not activated"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + /* Ask the manager to authenticate this request for us */ + g_signal_emit (self, signals[AUTH_REQUEST], 0, + context, + applied_connection, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + get_applied_connection_cb, + applied_connection /* no need take a ref. We will not dereference this pointer. */); +} + +/*****************************************************************************/ + +static void disconnect_cb (NMDevice *self, GDBusMethodInvocation *context, NMAuthSubject *subject, @@ -7329,6 +7619,7 @@ _device_activate (NMDevice *self, NMActRequest *req) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE); + g_return_val_if_fail (nm_device_get_managed (self, FALSE), FALSE); /* Ensure the activation request is still valid; the master may have * already failed in which case activation of this device should not proceed. @@ -7347,13 +7638,6 @@ _device_activate (NMDevice *self, NMActRequest *req) delete_on_deactivate_unschedule (self); - /* Move default unmanaged devices to DISCONNECTED state here */ - if (nm_device_get_default_unmanaged (self) && priv->state == NM_DEVICE_STATE_UNMANAGED) { - nm_device_state_changed (self, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NOW_MANAGED); - } - /* note: don't notify D-Bus of the new AC here, but do it later when * changing state to PREPARE so that the two properties change together. */ @@ -7602,7 +7886,7 @@ nm_device_set_ip4_config (NMDevice *self, _update_ip4_address (self); if (old_config != priv->ip4_config) - g_object_notify (G_OBJECT (self), NM_DEVICE_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->ip4_config) @@ -7769,7 +8053,7 @@ nm_device_set_ip6_config (NMDevice *self, if (has_changes) { if (old_config != priv->ip6_config) - g_object_notify (G_OBJECT (self), NM_DEVICE_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) @@ -8275,7 +8559,7 @@ nm_device_set_firmware_missing (NMDevice *self, gboolean new_missing) priv = NM_DEVICE_GET_PRIVATE (self); if (priv->firmware_missing != new_missing) { priv->firmware_missing = new_missing; - g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_MISSING); + _notify (self, PROP_FIRMWARE_MISSING); } } @@ -8295,7 +8579,7 @@ nm_device_set_nm_plugin_missing (NMDevice *self, gboolean new_missing) priv = NM_DEVICE_GET_PRIVATE (self); if (priv->nm_plugin_missing != new_missing) { priv->nm_plugin_missing = new_missing; - g_object_notify (G_OBJECT (self), NM_DEVICE_NM_PLUGIN_MISSING); + _notify (self, PROP_NM_PLUGIN_MISSING); } } @@ -8507,7 +8791,6 @@ update_ip6_config (NMDevice *self, gboolean initial) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; - gboolean linklocal6_just_completed = FALSE; gboolean capture_resolv_conf; NMDnsManagerResolvConfMode resolv_conf_mode; @@ -8520,12 +8803,11 @@ update_ip6_config (NMDevice *self, gboolean initial) /* IPv6 */ g_clear_object (&priv->ext_ip6_config); - priv->ext_ip6_config = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - if (priv->ext_ip6_config) { + g_clear_object (&priv->ext_ip6_config_captured); + priv->ext_ip6_config_captured = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + if (priv->ext_ip6_config_captured) { - /* Check this before modifying ext_ip6_config */ - linklocal6_just_completed = priv->linklocal6_timeout_id && - have_ip6_address (priv->ext_ip6_config, TRUE); + priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); /* This function was called upon external changes. Remove the configuration * (addresses,routes) that is no longer present externally from the internal @@ -8557,7 +8839,9 @@ update_ip6_config (NMDevice *self, gboolean initial) ip6_config_merge_and_apply (self, FALSE, NULL); } - if (linklocal6_just_completed) { + if ( 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. */ @@ -8673,8 +8957,8 @@ device_ipx_changed (NMPlatform *platform, if ( priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING - && ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED) - || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->flags & IFA_F_TENTATIVE))) { + && ( (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))); } @@ -8690,119 +8974,319 @@ device_ipx_changed (NMPlatform *platform, } } +/*****************************************************************************/ + +NM_UTILS_FLAGS2STR_DEFINE (nm_unmanaged_flags2str, NMUnmanagedFlags, + NM_UTILS_FLAGS2STR (NM_UNMANAGED_SLEEPING, "sleeping"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_QUITTING, "quitting"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_PARENT, "parent"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_LOOPBACK, "loopback"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_PLATFORM_INIT, "platform-init"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_EXPLICIT, "user-explicit"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_BY_DEFAULT, "by-default"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_SETTINGS, "user-settings"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_USER_UDEV, "user-udev"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_EXTERNAL_DOWN, "external-down"), + NM_UTILS_FLAGS2STR (NM_UNMANAGED_IS_SLAVE, "is-slave"), +); + +static const char * +_unmanaged_flags2str (NMUnmanagedFlags flags, NMUnmanagedFlags mask, char *buf, gsize len) +{ + char buf2[512]; + char *b; + char *tmp, *tmp2; + gsize l; + + nm_utils_to_string_buffer_init (&buf, &len); + if (!len) + return buf; + + b = buf; + + mask |= flags; + + nm_unmanaged_flags2str (flags, b, len); + l = strlen (b); + b += l; + len -= l; + + nm_unmanaged_flags2str (mask & ~flags, buf2, sizeof (buf2)); + if (buf2[0]) { + gboolean add_separator = l > 0; + + tmp = buf2; + while (TRUE) { + if (add_separator) + nm_utils_strbuf_append_c (&b, &len, ','); + add_separator = TRUE; + + tmp2 = strchr (tmp, ','); + if (tmp2) + tmp2[0] = '\0'; + + nm_utils_strbuf_append_c (&b, &len, '!'); + nm_utils_strbuf_append_str (&b, &len, tmp); + if (!tmp2) + break; + + tmp = &tmp2[1]; + } + } + + return buf; +} + +static gboolean +_get_managed_by_flags(NMUnmanagedFlags flags, NMUnmanagedFlags mask, gboolean for_user_request) +{ + /* Evaluate the managed state based on the unmanaged flags. + * + * Some flags are authoritative, meaning they always cause + * the device to be unmanaged (e.g. @NM_UNMANAGED_PLATFORM_INIT). + * + * OTOH, some flags can be overwritten. For example NM_UNMANAGED_USER_SETTINGS + * is ignored once NM_UNMANAGED_USER_EXPLICIT is set. The idea is that + * the flag from the configuration has no effect once the user explicitly + * touches the unmanaged flags. */ + + if (for_user_request) { + + /* @for_user_request can make the result only ~more~ managed. + * If the flags already indicate a managed state for a non-user-request, + * then it is also managed for an explict user-request. + * + * Effectively, this check is redundant, as the code below already + * already ensures that. Still, express this invariant explictly here. */ + if (_get_managed_by_flags (flags, mask, FALSE)) + return TRUE; + + /* A for-user-request, is effectively the same as pretending + * that user-dbus flag is cleared. */ + mask |= NM_UNMANAGED_USER_EXPLICIT; + flags &= ~NM_UNMANAGED_USER_EXPLICIT; + } + + if ( NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_SETTINGS) + && !NM_FLAGS_ANY (flags, NM_UNMANAGED_USER_SETTINGS)) { + /* NM_UNMANAGED_USER_SETTINGS can only explicitly unmanage a device. It cannot + * *manage* it. Having NM_UNMANAGED_USER_SETTINGS explicitly not set, is the + * same as having it not set at all. */ + mask &= ~NM_UNMANAGED_USER_SETTINGS; + } + + if (NM_FLAGS_ANY (mask, NM_UNMANAGED_USER_UDEV)) { + /* configuration from udev or nm-config overwrites the by-default flag + * which is based on the device type. */ + flags &= ~NM_UNMANAGED_BY_DEFAULT; + } + + if ( NM_FLAGS_HAS (mask, NM_UNMANAGED_IS_SLAVE) + && !NM_FLAGS_HAS (flags, NM_UNMANAGED_IS_SLAVE)) { + /* for an enslaved device, by-default doesn't matter */ + flags &= ~NM_UNMANAGED_BY_DEFAULT; + } + + if (NM_FLAGS_HAS (mask, NM_UNMANAGED_USER_EXPLICIT)) { + /* if the device is managed by user-decision, certain other flags + * are ignored. */ + + flags &= ~( NM_UNMANAGED_BY_DEFAULT + | NM_UNMANAGED_USER_UDEV + | NM_UNMANAGED_EXTERNAL_DOWN); + } + + return flags == NM_UNMANAGED_NONE; +} + /** - * nm_device_get_managed(): + * nm_device_get_managed: * @self: the #NMDevice + * @for_user_request: whether to check the flags for an explict user-request + * + * Whether the device is unmanaged according to the unmanaged flags. * - * Returns: %TRUE if the device is managed + * Returns: %TRUE if the device is unmanaged because of the flags. */ gboolean -nm_device_get_managed (NMDevice *self) +nm_device_get_managed (NMDevice *self, gboolean for_user_request) { NMDevicePrivate *priv; - gboolean managed; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - priv = NM_DEVICE_GET_PRIVATE (self); + if (!nm_device_is_real (self)) { + /* a unrealized device is always considered unmanaged. */ + return FALSE; + } - /* Return the composite of all managed flags. However, if the device - * is a default-unmanaged device, and would be managed except for the - * default-unmanaged flag (eg, only NM_UNMANAGED_DEFAULT is set) then - * the device is managed whenever it's not in the UNMANAGED state. - */ - managed = !NM_FLAGS_ANY (priv->unmanaged_flags, ~NM_UNMANAGED_DEFAULT); - if (managed && NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_DEFAULT)) - managed = (priv->state > NM_DEVICE_STATE_UNMANAGED); + priv = NM_DEVICE_GET_PRIVATE (self); - return managed; + return _get_managed_by_flags (priv->unmanaged_flags, priv->unmanaged_mask, for_user_request); } /** - * nm_device_get_unmanaged_flags(): + * nm_device_get_unmanaged_flags: * @self: the #NMDevice - * @flag: return only the selected flags + * @flag: the unmanaged flags to check. + * + * Return the unmanaged flags of the device. * - * Returns: the unmanage flags of the device (filtered with @flag) + * Returns: the flags of the device ( & @flag) */ NMUnmanagedFlags nm_device_get_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flag) { + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (flag != NM_UNMANAGED_NONE, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags & flag; } /** - * nm_device_get_default_unmanaged(): - * @self: the #NMDevice + * _set_unmanaged_flags: + * @self: the #NMDevice instance + * @flags: which #NMUnmanagedFlags to set. + * @set_op: whether to set/clear/forget the flags. You can also pass + * boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED + * and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively. + * @allow_state_transition: if %FALSE, setting flags never triggers a device + * state change. If %TRUE, the device can change state, if it is real and + * switches from managed to unmanaged (or vice versa). + * @reason: the device state reason passed to nm_device_state_changed() if + * the device becomes managed/unmanaged. This is only relevant if the + * device switches state and if @allow_state_transition is %TRUE. * - * Returns: %TRUE if the device is by default unmanaged - */ -static gboolean -nm_device_get_default_unmanaged (NMDevice *self) -{ - return !!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_DEFAULT); -} - + * Set the unmanaged flags of the device. + **/ static void _set_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flags, - gboolean unmanaged) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - if (unmanaged) { - if (!NM_FLAGS_ALL (priv->unmanaged_flags, flags)) { - _LOGD (LOGD_DEVICE, "unmanaged: flags set to 0x%0llx (was 0x%0llx, %s 0x%0llx)", - (long long unsigned) (priv->unmanaged_flags | flags), - (long long unsigned) priv->unmanaged_flags, - "set", - (long long unsigned) flags); - priv->unmanaged_flags |= flags; - } - } else { - if (NM_FLAGS_ANY (priv->unmanaged_flags, flags)) { - _LOGD (LOGD_DEVICE, "unmanaged: flags set to 0x%0llx (was 0x%0llx, %s 0x%0llx)", - (long long unsigned) (priv->unmanaged_flags & (~flags)), - (long long unsigned) priv->unmanaged_flags, - "clear", - (long long unsigned) flags); - priv->unmanaged_flags &= ~flags; - } - } -} - -void -nm_device_set_unmanaged_flags (NMDevice *self, - NMUnmanagedFlags flag, - gboolean unmanaged, - NMDeviceStateReason reason) + NMUnmanFlagOp set_op, + gboolean allow_state_transition, + NMDeviceStateReason reason) { NMDevicePrivate *priv; - gboolean was_managed, now_managed; + gboolean was_managed, transition_state; + NMUnmanagedFlags old_flags, old_mask; + const char *operation = NULL; + char str1[512]; + char str2[512]; g_return_if_fail (NM_IS_DEVICE (self)); - g_return_if_fail (flag <= NM_UNMANAGED_LAST); + g_return_if_fail (flags); priv = NM_DEVICE_GET_PRIVATE (self); - was_managed = nm_device_get_managed (self); - _set_unmanaged_flags (self, flag, unmanaged); - now_managed = nm_device_get_managed (self); + if (!priv->real) + allow_state_transition = FALSE; + was_managed = allow_state_transition && nm_device_get_managed (self, FALSE); + + old_flags = priv->unmanaged_flags; + old_mask = priv->unmanaged_mask; - if (was_managed != now_managed) { - _LOGD (LOGD_DEVICE, "now %s", unmanaged ? "unmanaged" : "managed"); + switch (set_op) { + case NM_UNMAN_FLAG_OP_FORGET: + priv->unmanaged_mask &= ~flags; + priv->unmanaged_flags &= ~flags; + operation = "forget"; + break; + case NM_UNMAN_FLAG_OP_SET_UNMANAGED: + priv->unmanaged_mask |= flags; + priv->unmanaged_flags |= flags; + operation = "set-unmanaged"; + break; + case NM_UNMAN_FLAG_OP_SET_MANAGED: + priv->unmanaged_mask |= flags; + priv->unmanaged_flags &= ~flags; + operation = "set-managed"; + break; + default: + g_return_if_reached (); + } - g_object_notify (G_OBJECT (self), NM_DEVICE_MANAGED); + if ( old_flags == priv->unmanaged_flags + && old_mask == priv->unmanaged_mask) + return; - if (unmanaged) + transition_state = allow_state_transition + && was_managed != nm_device_get_managed (self, FALSE) + && ( was_managed + || ( !was_managed + && nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)); + +#define _FMTX "[%s%s0x%0x/0x%x/%s" +#define _FMT(flags, mask, str) \ + _unmanaged_flags2str ((flags), (mask), str, sizeof (str)), \ + ((flags) | (mask)) ? "=" : "", \ + (flags), \ + (mask), \ + (_get_managed_by_flags (flags, mask, FALSE) \ + ? "managed" \ + : (_get_managed_by_flags (flags, mask, TRUE) \ + ? "manageable" \ + : "unmanaged")) + _LOGD (LOGD_DEVICE, "unmanaged: flags set to "_FMTX"%s, %s [%s=0x%0x]%s%s%s)", + _FMT (priv->unmanaged_flags, priv->unmanaged_mask, str1), + priv->real ? "" : "/unrealized", + operation, + nm_unmanaged_flags2str (flags, str2, sizeof (str2)), + flags, + NM_PRINT_FMT_QUOTED (allow_state_transition, + ", reason ", + reason_to_string (reason), + transition_state ? ", transition-state" : "", + "")); +#undef _FMT + + if (transition_state) { + if (was_managed) nm_device_state_changed (self, NM_DEVICE_STATE_UNMANAGED, reason); - else if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED) + else nm_device_state_changed (self, NM_DEVICE_STATE_UNAVAILABLE, reason); } } +/** + * @self: the #NMDevice instance + * @flags: which #NMUnmanagedFlags to set. + * @set_op: whether to set/clear/forget the flags. You can also pass + * boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED + * and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively. + * + * Set the unmanaged flags of the device (does not trigger a state change). + **/ +void +nm_device_set_unmanaged_flags (NMDevice *self, + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op) +{ + _set_unmanaged_flags (self, flags, set_op, FALSE, NM_DEVICE_STATE_REASON_NONE); +} + +/** + * nm_device_set_unmanaged_by_flags: + * @self: the #NMDevice instance + * @flags: which #NMUnmanagedFlags to set. + * @set_op: whether to set/clear/forget the flags. You can also pass + * boolean values %TRUE and %FALSE, which mean %NM_UNMAN_FLAG_OP_SET_UNMANAGED + * and %NM_UNMAN_FLAG_OP_SET_MANAGED, respectively. + * @reason: the device state reason passed to nm_device_state_changed() if + * the device becomes managed/unmanaged. + * + * Set the unmanaged flags of the device and possibly trigger a state change. + **/ +void +nm_device_set_unmanaged_by_flags (NMDevice *self, + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op, + NMDeviceStateReason reason) +{ + _set_unmanaged_flags (self, flags, set_op, TRUE, reason); +} + void -nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unmanaged_specs) +nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs) { NMDevicePrivate *priv; gboolean unmanaged; @@ -8811,46 +9295,36 @@ nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unma priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->managed_touched_by_user) - return; - unmanaged = nm_device_spec_match_list (self, unmanaged_specs); - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_USER, - unmanaged, - unmanaged - ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED - : NM_DEVICE_STATE_REASON_NOW_MANAGED); + + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_USER_SETTINGS, + unmanaged, + unmanaged + ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED + : NM_DEVICE_STATE_REASON_NOW_MANAGED); } -/** - * nm_device_set_unmanaged_flags_initial(): - * @self: the #NMDevice - * @flag: an #NMUnmanagedFlag - * @unmanaged: %TRUE or %FALSE to set or clear @flag - * - * Like nm_device_set_unmanaged_flags(), but must be set before the device is - * initialized by nm_device_finish_init(), and does not trigger state changes. - * Should only be used when initializing a device. - */ void -nm_device_set_unmanaged_flags_initial (NMDevice *self, - NMUnmanagedFlags flag, - gboolean unmanaged) +nm_device_set_unmanaged_by_user_udev (NMDevice *self) { - NMDevicePrivate *priv; + int ifindex; + gboolean platform_unmanaged = FALSE; - g_return_if_fail (NM_IS_DEVICE (self)); - g_return_if_fail (flag <= NM_UNMANAGED_LAST); + ifindex = self->priv->ifindex; - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->initialized == FALSE); + if ( ifindex <= 0 + || !nm_platform_link_get_unmanaged (NM_PLATFORM_GET, ifindex, &platform_unmanaged)) + return; - _set_unmanaged_flags (self, flag, unmanaged); + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_USER_UDEV, + platform_unmanaged, + NM_DEVICE_STATE_REASON_USER_REQUESTED); } void -nm_device_set_unmanaged_quitting (NMDevice *self) +nm_device_set_unmanaged_by_quitting (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean need_deactivate = nm_device_is_activating (self) || @@ -8860,11 +9334,11 @@ nm_device_set_unmanaged_quitting (NMDevice *self) if (need_deactivate) _set_state_full (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_NOW_UNMANAGED, TRUE); - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_INTERNAL, - TRUE, - need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED - : NM_DEVICE_STATE_REASON_NOW_UNMANAGED); + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_QUITTING, + TRUE, + need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED + : NM_DEVICE_STATE_REASON_NOW_UNMANAGED); } /*****************************************************************************/ @@ -8901,6 +9375,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) NMSettingConnection *s_con_applied; const char *zone; NMMetered metered; + guint64 version_id; g_return_if_fail (NM_IS_DEVICE (self)); @@ -8923,7 +9398,8 @@ 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) { - _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s", NM_PRINT_FMT_QUOTE_STRING (zone)); + 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), (long long unsigned) version_id); g_object_set (G_OBJECT (s_con_applied), NM_SETTING_CONNECTION_ZONE, zone, @@ -8934,7 +9410,8 @@ 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)) { - _LOGD (LOGD_DEVICE, "reapply setting: metered = %d", (int) metered); + 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, (long long unsigned) version_id); g_object_set (G_OBJECT (s_con_applied), NM_SETTING_CONNECTION_METERED, metered, @@ -9017,7 +9494,7 @@ nm_device_update_metered (NMDevice *self) if (value != priv->metered) { _LOGD (LOGD_DEVICE, "set metered value %d", value); priv->metered = value; - g_object_notify (G_OBJECT (self), NM_DEVICE_METERED); + _notify (self, PROP_METERED); } } @@ -9029,11 +9506,21 @@ _nm_device_check_connection_available (NMDevice *self, { NMDeviceState state; + /* an unrealized software device is always available, hardware devices never. */ + if (!nm_device_is_real (self)) { + if (nm_device_is_software (self)) + return nm_device_check_connection_compatible (self, connection); + return FALSE; + } + state = nm_device_get_state (self); if (state < NM_DEVICE_STATE_UNMANAGED) return FALSE; if ( state < NM_DEVICE_STATE_UNAVAILABLE - && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT)) + && ( ( !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST) + && !nm_device_get_managed (self, FALSE)) + || ( NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST) + && !nm_device_get_managed (self, TRUE)))) return FALSE; if ( state < NM_DEVICE_STATE_DISCONNECTED && !nm_device_is_software (self) @@ -9100,34 +9587,30 @@ nm_device_check_connection_available (NMDevice *self, } static void -_signal_available_connections_changed (NMDevice *self) +available_connections_notify (NMDevice *self) { - g_object_notify (G_OBJECT (self), NM_DEVICE_AVAILABLE_CONNECTIONS); + _notify (self, PROP_AVAILABLE_CONNECTIONS); } -static void -_clear_available_connections (NMDevice *self, gboolean do_signal) +static gboolean +available_connections_del_all (NMDevice *self) { - g_hash_table_remove_all (NM_DEVICE_GET_PRIVATE (self)->available_connections); - if (do_signal == TRUE) - _signal_available_connections_changed (self); + if (g_hash_table_size (self->priv->available_connections) == 0) + return FALSE; + g_hash_table_remove_all (self->priv->available_connections); + return TRUE; } static gboolean -_try_add_available_connection (NMDevice *self, NMConnection *connection) +available_connections_add (NMDevice *self, NMConnection *connection) { - if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL)) { - g_hash_table_add (NM_DEVICE_GET_PRIVATE (self)->available_connections, - g_object_ref (connection)); - return TRUE; - } - return FALSE; + return nm_g_hash_table_add (self->priv->available_connections, g_object_ref (connection)); } static gboolean -_del_available_connection (NMDevice *self, NMConnection *connection) +available_connections_del (NMDevice *self, NMConnection *connection) { - return g_hash_table_remove (NM_DEVICE_GET_PRIVATE (self)->available_connections, connection); + return g_hash_table_remove (self->priv->available_connections, connection); } static gboolean @@ -9162,22 +9645,55 @@ nm_device_recheck_available_connections (NMDevice *self) { NMDevicePrivate *priv; const GSList *connections, *iter; + gboolean changed = FALSE; + GHashTableIter h_iter; + NMConnection *connection; g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE(self); if (priv->con_provider) { - _clear_available_connections (self, FALSE); + gs_unref_hashtable GHashTable *prune_list = NULL; + + if (g_hash_table_size (priv->available_connections) > 0) { + prune_list = g_hash_table_new (g_direct_hash, g_direct_equal); + g_hash_table_iter_init (&h_iter, priv->available_connections); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) + g_hash_table_add (prune_list, connection); + } connections = nm_connection_provider_get_connections (priv->con_provider); - for (iter = connections; iter; iter = g_slist_next (iter)) - _try_add_available_connection (self, NM_CONNECTION (iter->data)); + for (iter = connections; iter; iter = g_slist_next (iter)) { + connection = NM_CONNECTION (iter->data); + + if (nm_device_check_connection_available (self, + connection, + NM_DEVICE_CHECK_CON_AVAILABLE_NONE, + NULL)) { + if (available_connections_add (self, connection)) + changed = TRUE; + } else { + if (prune_list && g_hash_table_remove (prune_list, connection)) + changed = TRUE; + } + } - _signal_available_connections_changed (self); + if (prune_list) { + g_hash_table_iter_init (&h_iter, prune_list); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) { + if (available_connections_del (self, connection)) + changed = TRUE; + } + } + } else { + if (available_connections_del_all (self)) + changed = TRUE; } - available_connection_check_delete_unrealized (self); + if (changed) + available_connections_notify (self); + available_connections_check_delete_unrealized (self); } /** @@ -9209,7 +9725,7 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object * compatible with it. */ if ( !specific_object /* << Optimization: we know that the connection is available without @specific_object. */ - || nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, specific_object)) + || nm_device_check_connection_available (self, connection, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, specific_object)) g_ptr_array_add (array, connection); } } @@ -9217,45 +9733,38 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object } static void -cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { + gboolean changed; NMDevice *self = user_data; g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); - if (_try_add_available_connection (self, connection)) - _signal_available_connections_changed (self); -} - -static void -cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) -{ - NMDevice *self = user_data; - - g_return_if_fail (NM_IS_DEVICE (self)); + if (nm_device_check_connection_available (self, + connection, + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + NULL)) + changed = available_connections_add (self, connection); + else + changed = available_connections_del (self, connection); - if (_del_available_connection (self, connection)) { - _signal_available_connections_changed (self); - available_connection_check_delete_unrealized (self); + if (changed) { + available_connections_notify (self); + available_connections_check_delete_unrealized (self); } } static void -cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { NMDevice *self = user_data; - gboolean added, deleted; g_return_if_fail (NM_IS_DEVICE (self)); - /* FIXME: don't remove it from the hash if it's just going to get re-added */ - deleted = _del_available_connection (self, connection); - added = _try_add_available_connection (self, connection); - - /* Only signal if the connection was removed OR added, but not both */ - if (added != deleted) { - _signal_available_connections_changed (self); - available_connection_check_delete_unrealized (self); + if (available_connections_del (self, connection)) { + available_connections_notify (self); + available_connections_check_delete_unrealized (self); } } @@ -9309,7 +9818,7 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser _LOGD (LOGD_DEVICE, "add_pending_action (%d): '%s'", count, action); if (count == 1) - g_object_notify (G_OBJECT (self), NM_DEVICE_HAS_PENDING_ACTION); + _notify (self, PROP_HAS_PENDING_ACTION); return TRUE; } @@ -9344,7 +9853,7 @@ nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean as g_free (iter->data); priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter); if (priv->pending_actions == NULL) - g_object_notify (G_OBJECT (self), NM_DEVICE_HAS_PENDING_ACTION); + _notify (self, PROP_HAS_PENDING_ACTION); return TRUE; } count++; @@ -9453,6 +9962,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) 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); g_clear_object (&priv->wwan_ip6_config); g_clear_object (&priv->ip6_config); @@ -9466,7 +9976,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) /* Clear legacy IPv4 address property */ if (priv->ip4_address) { priv->ip4_address = 0; - g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS); + _notify (self, PROP_IP4_ADDRESS); } if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) { @@ -9733,11 +10243,11 @@ ip_config_valid (NMDeviceState state) static void notify_ip_properties (NMDevice *self) { - g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); - g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG); - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); - g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG); - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); + _notify (self, PROP_IP_IFACE); + _notify (self, PROP_IP4_CONFIG); + _notify (self, PROP_DHCP4_CONFIG); + _notify (self, PROP_IP6_CONFIG); + _notify (self, PROP_DHCP6_CONFIG); } static void @@ -9840,14 +10350,16 @@ _set_state_full (NMDevice *self, * can retry device initialization. */ if ( (priv->state == state) - && !(state == NM_DEVICE_STATE_UNAVAILABLE && priv->firmware_missing)) { - _LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d] (skip due to missing firmware)", + && ( state != NM_DEVICE_STATE_UNAVAILABLE + || !priv->firmware_missing)) { + _LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]%s", state_to_string (old_state), state_to_string (state), reason_to_string (reason), old_state, state, - reason); + reason, + priv->firmware_missing ? " (missing firmware)" : ""); return; } @@ -9875,13 +10387,13 @@ _set_state_full (NMDevice *self, req = priv->act_request ? g_object_ref (priv->act_request) : NULL; if (state <= NM_DEVICE_STATE_UNAVAILABLE) { - _clear_available_connections (self, TRUE); + if (available_connections_del_all (self)) + available_connections_notify (self); _clear_queued_act_request (priv); } /* Update the available connections list when a device first becomes available */ - if ( (state >= NM_DEVICE_STATE_DISCONNECTED && old_state < NM_DEVICE_STATE_DISCONNECTED) - || nm_device_get_default_unmanaged (self)) + if (state >= NM_DEVICE_STATE_DISCONNECTED && old_state < NM_DEVICE_STATE_DISCONNECTED) nm_device_recheck_available_connections (self); /* Handle the new state here; but anything that could trigger @@ -9963,8 +10475,8 @@ _set_state_full (NMDevice *self, && state <= NM_DEVICE_STATE_ACTIVATED) nm_device_set_autoconnect (self, TRUE); - g_object_notify (G_OBJECT (self), NM_DEVICE_STATE); - g_object_notify (G_OBJECT (self), NM_DEVICE_STATE_REASON); + _notify (self, PROP_STATE); + _notify (self, PROP_STATE_REASON); g_signal_emit_by_name (self, NM_DEVICE_STATE_CHANGED, state, old_state, reason); /* Post-process the event after internal notification */ @@ -9982,11 +10494,7 @@ _set_state_full (NMDevice *self, NM_DEVICE_STATE_REASON_NONE, NM_DEVICE_STATE_REASON_NONE); } else { - if (old_state == NM_DEVICE_STATE_UNMANAGED) - _LOGD (LOGD_DEVICE, "device not yet available for transition to DISCONNECTED"); - else if ( old_state > NM_DEVICE_STATE_UNAVAILABLE - && nm_device_get_default_unmanaged (self)) - nm_device_queue_state (self, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE); + _LOGD (LOGD_DEVICE, "device not yet available for transition to DISCONNECTED"); } break; case NM_DEVICE_STATE_DEACTIVATING: @@ -10032,9 +10540,6 @@ _set_state_full (NMDevice *self, break; /* fall through */ } - if ( old_state > NM_DEVICE_STATE_DISCONNECTED - && nm_device_get_default_unmanaged (self)) - nm_device_queue_state (self, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_NONE); break; case NM_DEVICE_STATE_ACTIVATED: _LOGI (LOGD_DEVICE, "Activation: successful, device activated."); @@ -10149,6 +10654,9 @@ _set_state_full (NMDevice *self, g_object_unref (req); priv->in_state_changed = FALSE; + + if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED)) + _notify (self, PROP_MANAGED); } void @@ -10297,7 +10805,7 @@ nm_device_update_hw_address (NMDevice *self) priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); _LOGD (LOGD_HW | LOGD_DEVICE, "hardware address now %s", priv->hw_addr); - g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS); + _notify (self, PROP_HW_ADDRESS); } } else { /* Invalid or no hardware address */ @@ -10306,7 +10814,7 @@ nm_device_update_hw_address (NMDevice *self) priv->hw_addr_len = 0; _LOGD (LOGD_HW | LOGD_DEVICE, "previous hardware address is no longer valid"); - g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS); + _notify (self, PROP_HW_ADDRESS); } } } @@ -10347,7 +10855,11 @@ nm_device_set_hw_addr (NMDevice *self, const char *addr, const char *cur_addr = nm_device_get_hw_address (self); guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX]; - g_return_val_if_fail (addr != NULL, FALSE); + /* Fall back to the permanent address */ + if (!addr) + addr = priv->perm_hw_addr; + if (!addr) + return FALSE; /* Do nothing if current MAC is same */ if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) { @@ -10498,7 +11010,8 @@ nm_device_init (NMDevice *self) priv->dhcp_timeout = 0; priv->rfkill_type = RFKILL_TYPE_UNKNOWN; priv->autoconnect = DEFAULT_AUTOCONNECT; - priv->unmanaged_flags = NM_UNMANAGED_INTERNAL; + priv->unmanaged_flags = NM_UNMANAGED_PLATFORM_INIT; + priv->unmanaged_mask = priv->unmanaged_flags; 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 (g_str_hash, g_str_equal, NULL, g_free); @@ -10533,7 +11046,7 @@ constructor (GType type, if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) { priv->ifindex = pllink->ifindex; - priv->up = NM_FLAGS_HAS (pllink->flags, IFF_UP); + priv->up = NM_FLAGS_HAS (pllink->n_ifi_flags, IFF_UP); } } @@ -10563,7 +11076,7 @@ constructed (GObject *object) g_assert (priv->con_provider); g_signal_connect (priv->con_provider, NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added), + G_CALLBACK (cp_connection_added_or_updated), self); g_signal_connect (priv->con_provider, @@ -10573,18 +11086,9 @@ constructed (GObject *object) g_signal_connect (priv->con_provider, NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_updated), + G_CALLBACK (cp_connection_added_or_updated), self); - /* Update default-unmanaged device available connections immediately, - * since they don't transition from UNMANAGED (and thus the state handler - * doesn't run and update them) until something external happens. - */ - if (nm_device_get_default_unmanaged (self)) { - nm_device_set_autoconnect (self, FALSE); - nm_device_recheck_available_connections (self); - } - G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); _LOGD (LOGD_DEVICE, "constructed (%s)", G_OBJECT_TYPE_NAME (self)); @@ -10599,6 +11103,11 @@ dispose (GObject *object) _LOGD (LOGD_DEVICE, "disposing"); + g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy); + priv->arping.dad_list = NULL; + + arp_cleanup (self); + g_signal_handlers_disconnect_by_func (nm_config_get (), config_changed_update_ignore_carrier, self); dispatcher_cleanup (self); @@ -10623,13 +11132,12 @@ dispose (GObject *object) link_disconnect_action_cancel (self); if (priv->con_provider) { - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added_or_updated, self); g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_updated, self); priv->con_provider = NULL; } - g_hash_table_remove_all (priv->available_connections); + available_connections_del_all (self); nm_clear_g_source (&priv->carrier_wait_id); @@ -10698,7 +11206,6 @@ set_property (GObject *object, guint prop_id, NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *hw_addr, *p; guint count; - gboolean val_bool; switch (prop_id) { case PROP_UDI: @@ -10732,18 +11239,26 @@ set_property (GObject *object, guint prop_id, case PROP_IP4_ADDRESS: priv->ip4_address = g_value_get_uint (value); break; - case PROP_MANAGED: - val_bool = g_value_get_boolean (value); - priv->managed_touched_by_user = TRUE; - nm_device_set_unmanaged_flags (self, - NM_UNMANAGED_USER | (val_bool ? NM_UNMANAGED_DEFAULT : NM_UNMANAGED_NONE), - !val_bool, - NM_DEVICE_STATE_REASON_USER_REQUESTED); + case PROP_MANAGED: { + gboolean managed; + NMDeviceStateReason reason; + + managed = g_value_get_boolean (value); + if (managed) + reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; + else + reason = NM_DEVICE_STATE_REASON_REMOVED; + nm_device_set_unmanaged_by_flags (self, + NM_UNMANAGED_USER_EXPLICIT, + !managed, + reason); break; + } case PROP_AUTOCONNECT: nm_device_set_autoconnect (self, g_value_get_boolean (value)); break; case PROP_FIRMWARE_MISSING: + /* construct only */ priv->firmware_missing = g_value_get_boolean (value); break; case PROP_NM_PLUGIN_MISSING: @@ -10878,7 +11393,8 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->link_type); break; case PROP_MANAGED: - g_value_set_boolean (value, nm_device_get_managed (self)); + /* The managed state exposed on D-Bus only depends on the current device state alone. */ + g_value_set_boolean (value, nm_device_get_state (self) > NM_DEVICE_STATE_UNMANAGED); break; case PROP_AUTOCONNECT: g_value_set_boolean (value, priv->autoconnect); @@ -11002,232 +11518,169 @@ nm_device_class_init (NMDeviceClass *klass) klass->get_ip_iface_identifier = get_ip_iface_identifier; /* Properties */ - g_object_class_install_property - (object_class, PROP_UDI, - g_param_spec_string (NM_DEVICE_UDI, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IFACE, - g_param_spec_string (NM_DEVICE_IFACE, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IP_IFACE, - g_param_spec_string (NM_DEVICE_IP_IFACE, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DRIVER, - g_param_spec_string (NM_DEVICE_DRIVER, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DRIVER_VERSION, - g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_FIRMWARE_VERSION, - g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_CAPABILITIES, "", "", - 0, G_MAXUINT32, NM_DEVICE_CAP_NONE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CARRIER, - g_param_spec_boolean (NM_DEVICE_CARRIER, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MTU, - g_param_spec_uint (NM_DEVICE_MTU, "", "", - 0, G_MAXUINT32, 1500, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IP4_ADDRESS, - g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, "", "", - 0, G_MAXUINT32, 0, /* FIXME */ - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IP4_CONFIG, - g_param_spec_string (NM_DEVICE_IP4_CONFIG, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DHCP4_CONFIG, - g_param_spec_string (NM_DEVICE_DHCP4_CONFIG, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IP6_CONFIG, - g_param_spec_string (NM_DEVICE_IP6_CONFIG, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DHCP6_CONFIG, - g_param_spec_string (NM_DEVICE_DHCP6_CONFIG, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_STATE, - g_param_spec_uint (NM_DEVICE_STATE, "", "", - 0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_STATE_REASON, - g_param_spec_variant (NM_DEVICE_STATE_REASON, "", "", - G_VARIANT_TYPE ("(uu)"), - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_ACTIVE_CONNECTION, - g_param_spec_string (NM_DEVICE_ACTIVE_CONNECTION, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_DEVICE_TYPE, - g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, "", "", - 0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LINK_TYPE, - g_param_spec_uint (NM_DEVICE_LINK_TYPE, "", "", - 0, G_MAXUINT32, NM_LINK_TYPE_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MANAGED, - g_param_spec_boolean (NM_DEVICE_MANAGED, "", "", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_AUTOCONNECT, - g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "", - DEFAULT_AUTOCONNECT, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_FIRMWARE_MISSING, - g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_NM_PLUGIN_MISSING, - g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TYPE_DESC, - g_param_spec_string (NM_DEVICE_TYPE_DESC, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_RFKILL_TYPE, - g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, "", "", - RFKILL_TYPE_WLAN, - RFKILL_TYPE_MAX, - RFKILL_TYPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IFINDEX, - g_param_spec_int (NM_DEVICE_IFINDEX, "", "", - 0, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_AVAILABLE_CONNECTIONS, - g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_PHYSICAL_PORT_ID, - g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_IS_MASTER, - g_param_spec_boolean (NM_DEVICE_IS_MASTER, "", "", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MASTER, - g_param_spec_object (NM_DEVICE_MASTER, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_HAS_PENDING_ACTION, - g_param_spec_boolean (NM_DEVICE_HAS_PENDING_ACTION, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_UDI] = + g_param_spec_string (NM_DEVICE_UDI, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IFACE] = + g_param_spec_string (NM_DEVICE_IFACE, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IP_IFACE] = + g_param_spec_string (NM_DEVICE_IP_IFACE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DRIVER] = + g_param_spec_string (NM_DEVICE_DRIVER, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DRIVER_VERSION] = + g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_FIRMWARE_VERSION] = + g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_CAPABILITIES] = + g_param_spec_uint (NM_DEVICE_CAPABILITIES, "", "", + 0, G_MAXUINT32, NM_DEVICE_CAP_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_CARRIER] = + g_param_spec_boolean (NM_DEVICE_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_MTU] = + g_param_spec_uint (NM_DEVICE_MTU, "", "", + 0, G_MAXUINT32, 1500, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IP4_ADDRESS] = + g_param_spec_uint (NM_DEVICE_IP4_ADDRESS, "", "", + 0, G_MAXUINT32, 0, /* FIXME */ + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IP4_CONFIG] = + g_param_spec_string (NM_DEVICE_IP4_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DHCP4_CONFIG] = + g_param_spec_string (NM_DEVICE_DHCP4_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IP6_CONFIG] = + g_param_spec_string (NM_DEVICE_IP6_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DHCP6_CONFIG] = + g_param_spec_string (NM_DEVICE_DHCP6_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_STATE] = + g_param_spec_uint (NM_DEVICE_STATE, "", "", + 0, G_MAXUINT32, NM_DEVICE_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_STATE_REASON] = + g_param_spec_variant (NM_DEVICE_STATE_REASON, "", "", + G_VARIANT_TYPE ("(uu)"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ACTIVE_CONNECTION] = + g_param_spec_string (NM_DEVICE_ACTIVE_CONNECTION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEVICE_TYPE] = + g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, "", "", + 0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_LINK_TYPE] = + g_param_spec_uint (NM_DEVICE_LINK_TYPE, "", "", + 0, G_MAXUINT32, NM_LINK_TYPE_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_MANAGED] = + g_param_spec_boolean (NM_DEVICE_MANAGED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_AUTOCONNECT] = + g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "", + DEFAULT_AUTOCONNECT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_FIRMWARE_MISSING] = + g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_NM_PLUGIN_MISSING] = + g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_TYPE_DESC] = + g_param_spec_string (NM_DEVICE_TYPE_DESC, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_RFKILL_TYPE] = + g_param_spec_uint (NM_DEVICE_RFKILL_TYPE, "", "", + RFKILL_TYPE_WLAN, + RFKILL_TYPE_MAX, + RFKILL_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IFINDEX] = + g_param_spec_int (NM_DEVICE_IFINDEX, "", "", + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_AVAILABLE_CONNECTIONS] = + g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_PHYSICAL_PORT_ID] = + g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IS_MASTER] = + g_param_spec_boolean (NM_DEVICE_IS_MASTER, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_MASTER] = + g_param_spec_object (NM_DEVICE_MASTER, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_HW_ADDRESS] = + g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_HAS_PENDING_ACTION] = + g_param_spec_boolean (NM_DEVICE_HAS_PENDING_ACTION, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); /** * NMDevice:metered: @@ -11236,99 +11689,95 @@ nm_device_class_init (NMDeviceClass *klass) * * Since: 1.2 **/ - g_object_class_install_property - (object_class, PROP_METERED, - g_param_spec_uint (NM_DEVICE_METERED, "", "", - 0, G_MAXUINT32, NM_METERED_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LLDP_NEIGHBORS, - g_param_spec_variant (NM_DEVICE_LLDP_NEIGHBORS, "", "", - G_VARIANT_TYPE ("aa{sv}"), - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_REAL, - g_param_spec_boolean (NM_DEVICE_REAL, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SLAVES, - g_param_spec_boxed (NM_DEVICE_SLAVES, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_METERED] = + g_param_spec_uint (NM_DEVICE_METERED, "", "", + 0, G_MAXUINT32, NM_METERED_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_LLDP_NEIGHBORS] = + g_param_spec_variant (NM_DEVICE_LLDP_NEIGHBORS, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_REAL] = + g_param_spec_boolean (NM_DEVICE_REAL, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SLAVES] = + g_param_spec_boxed (NM_DEVICE_SLAVES, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); /* Signals */ signals[STATE_CHANGED] = - g_signal_new (NM_DEVICE_STATE_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceClass, state_changed), - NULL, NULL, NULL, - G_TYPE_NONE, 3, - G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); + g_signal_new (NM_DEVICE_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMDeviceClass, state_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 3, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); signals[AUTOCONNECT_ALLOWED] = - g_signal_new ("autoconnect-allowed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - autoconnect_allowed_accumulator, NULL, NULL, - G_TYPE_BOOLEAN, 0); + g_signal_new ("autoconnect-allowed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + autoconnect_allowed_accumulator, NULL, NULL, + G_TYPE_BOOLEAN, 0); signals[AUTH_REQUEST] = - g_signal_new (NM_DEVICE_AUTH_REQUEST, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - /* context, connection, permission, allow_interaction, callback, user_data */ - G_TYPE_NONE, 6, G_TYPE_DBUS_METHOD_INVOCATION, NM_TYPE_CONNECTION, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); + g_signal_new (NM_DEVICE_AUTH_REQUEST, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + /* context, connection, permission, allow_interaction, callback, user_data */ + G_TYPE_NONE, 6, G_TYPE_DBUS_METHOD_INVOCATION, NM_TYPE_CONNECTION, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); signals[IP4_CONFIG_CHANGED] = - g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); signals[IP6_CONFIG_CHANGED] = - g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); signals[REMOVED] = - g_signal_new (NM_DEVICE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); + g_signal_new (NM_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); signals[RECHECK_AUTO_ACTIVATE] = - g_signal_new (NM_DEVICE_RECHECK_AUTO_ACTIVATE, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); + g_signal_new (NM_DEVICE_RECHECK_AUTO_ACTIVATE, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); signals[RECHECK_ASSUME] = - g_signal_new (NM_DEVICE_RECHECK_ASSUME, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); + g_signal_new (NM_DEVICE_RECHECK_ASSUME, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); 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); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index e173b2db..9b9edda4 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -103,12 +103,14 @@ typedef enum NMActStageReturn NMActStageReturn; typedef enum { /*< skip >*/ NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0, - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 0), - _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 1), - NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = (1L << 0), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 1), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 2), + NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST + | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP, - NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 2) - 1, + NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 3) - 1, } NMDeviceCheckConAvailableFlags; struct _NMDevicePrivate; @@ -324,8 +326,6 @@ typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, GType nm_device_get_type (void); -void nm_device_finish_init (NMDevice *device); - const char * nm_device_get_udi (NMDevice *dev); const char * nm_device_get_iface (NMDevice *dev); int nm_device_get_ifindex (NMDevice *dev); @@ -375,6 +375,7 @@ NMSettingsConnection * nm_device_get_settings_connection (NMDevice *dev); NMConnection * nm_device_get_applied_connection (NMDevice *dev); gboolean nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFlags compare_flags); +NMSetting * nm_device_get_applied_setting (NMDevice *dev, GType setting_type); void nm_device_removed (NMDevice *dev); @@ -421,45 +422,67 @@ RfKillType nm_device_get_rfkill_type (NMDevice *device); /** * NMUnmanagedFlags: * @NM_UNMANAGED_NONE: placeholder value - * @NM_UNMANAGED_INTERNAL: %TRUE when unmanaged by internal decision (ie, - * because NM is sleeping or not managed for some other reason) + * @NM_UNMANAGED_SLEEPING: %TRUE when unmanaged because NM is sleeping. + * @NM_UNMANAGED_QUITTING: %TRUE when unmanaged because NM is shutting down. * @NM_UNMANAGED_PARENT: %TRUE when unmanaged due to parent device being unmanaged * @NM_UNMANAGED_LOOPBACK: %TRUE for unmanaging loopback device * @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not - * yet initialized - * @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs) - * @NM_UNMANAGED_DEFAULT: %TRUE when unmanaged by default (ie, Generic devices) + * yet initialized. Unrealized device are also unmanaged for this reason. + * @NM_UNMANAGED_USER_EXPLICIT: %TRUE when unmanaged by explicit user decision + * (e.g. via a D-Bus command) + * @NM_UNMANAGED_USER_SETTINGS: %TRUE when unmanaged by user decision via + * the settings plugin (for example keyfile.unmanaged-devices or ifcfg-rh's + * NM_CONTROLLED=no) + * @NM_UNMANAGED_BY_DEFAULT: %TRUE for certain device types where we unmanage + * them by default + * @NM_UNMANAGED_USER_UDEV: %TRUE when unmanaged by user decision (via UDev rule) * @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM + * @NM_UNMANAGED_IS_SLAVE: indicates that the device is enslaved. Note that + * setting the NM_UNMANAGED_IS_SLAVE to %TRUE makes no sense, this flag has only + * meaning to set a slave device as managed if the parent is managed too. */ typedef enum { /*< skip >*/ NM_UNMANAGED_NONE = 0, - NM_UNMANAGED_INTERNAL = (1LL << 0), - NM_UNMANAGED_PARENT = (1LL << 1), - NM_UNMANAGED_LOOPBACK = (1LL << 2), - NM_UNMANAGED_PLATFORM_INIT = (1LL << 3), - NM_UNMANAGED_USER = (1LL << 4), - - NM_UNMANAGED_DEFAULT = (1LL << 8), + /* these flags are authorative. If one of them is set, + * the device cannot be managed. */ + NM_UNMANAGED_SLEEPING = (1LL << 0), + NM_UNMANAGED_QUITTING = (1LL << 1), + NM_UNMANAGED_PARENT = (1LL << 2), + NM_UNMANAGED_LOOPBACK = (1LL << 3), + NM_UNMANAGED_PLATFORM_INIT = (1LL << 4), + NM_UNMANAGED_USER_EXPLICIT = (1LL << 5), + NM_UNMANAGED_USER_SETTINGS = (1LL << 6), + + /* These flags can be non-effective and be overwritten + * by other flags. */ + NM_UNMANAGED_BY_DEFAULT = (1LL << 8), + NM_UNMANAGED_USER_UDEV = (1LL << 10), NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 11), + NM_UNMANAGED_IS_SLAVE = (1LL << 12), - /* Boundary value */ - __NM_UNMANAGED_LAST, - NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1, - NM_UNMANAGED_ALL = ((NM_UNMANAGED_LAST << 1) - 1), } NMUnmanagedFlags; -gboolean nm_device_get_managed (NMDevice *device); +typedef enum { + NM_UNMAN_FLAG_OP_SET_MANAGED = FALSE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED = TRUE, + NM_UNMAN_FLAG_OP_FORGET = 2, +} NMUnmanFlagOp; + +const char *nm_unmanaged_flags2str (NMUnmanagedFlags flags, char *buf, gsize len); + +gboolean nm_device_get_managed (NMDevice *device, gboolean for_user_request); NMUnmanagedFlags nm_device_get_unmanaged_flags (NMDevice *device, NMUnmanagedFlags flag); void nm_device_set_unmanaged_flags (NMDevice *device, - NMUnmanagedFlags flag, - gboolean unmanaged, - NMDeviceStateReason reason); -void nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unmanaged_specs); -void nm_device_set_unmanaged_flags_initial (NMDevice *device, - NMUnmanagedFlags flag, - gboolean unmanaged); -void nm_device_set_unmanaged_quitting (NMDevice *device); + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op); +void nm_device_set_unmanaged_by_flags (NMDevice *device, + NMUnmanagedFlags flags, + NMUnmanFlagOp set_op, + NMDeviceStateReason reason); +void nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs); +void nm_device_set_unmanaged_by_user_udev (NMDevice *self); +void nm_device_set_unmanaged_by_quitting (NMDevice *device); gboolean nm_device_get_is_nm_owned (NMDevice *device); @@ -481,6 +504,7 @@ gboolean nm_device_unrealize (NMDevice *device, gboolean nm_device_get_autoconnect (NMDevice *device); void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect); +void nm_device_emit_recheck_auto_activate (NMDevice *device); void nm_device_state_changed (NMDevice *device, NMDeviceState state, diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 91181292..81827817 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -18,7 +18,7 @@ * Copyright (C) 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <net/ethernet.h> @@ -65,6 +65,32 @@ typedef struct { static void process_lldp_neighbors (NMLldpListener *self); +/*****************************************************************************/ + +#define _NMLOG_PREFIX_NAME "lldp" +#define _NMLOG_DOMAIN LOGD_DEVICE +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \ + char _sbuf[64]; \ + int _ifindex = (self) ? NM_LLDP_LISTENER_GET_PRIVATE (self)->ifindex : 0; \ + \ + _nm_log (_level, _NMLOG_DOMAIN, 0, \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((_ifindex > 0) \ + ? nm_sprintf_buf (_sbuf, "[%p,%d]", (self), _ifindex) \ + : ((self) \ + ? nm_sprintf_buf (_sbuf, "[%p]", (self)) \ + : "")) \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END \ + +/*****************************************************************************/ + static void gvalue_destroy (gpointer data) { @@ -100,11 +126,13 @@ static guint lldp_neighbor_id_hash (gconstpointer ptr) { const LLDPNeighbor *neigh = ptr; + guint hash; - return g_str_hash (neigh->chassis_id) ^ - g_str_hash (neigh->port_id) ^ - neigh->chassis_id_type ^ - (neigh->port_id_type * 33); + hash = 23423423u + ((guint) (neigh->chassis_id ? g_str_hash (neigh->chassis_id) : 12321u)); + hash = (hash * 33u) + ((guint) (neigh->port_id ? g_str_hash (neigh->port_id) : 34342343u)); + hash = (hash * 33u) + ((guint) neigh->chassis_id_type); + hash = (hash * 33u) + ((guint) neigh->port_id_type); + return hash; } static gboolean @@ -119,18 +147,22 @@ lldp_neighbor_id_equal (gconstpointer a, gconstpointer b) } static void -lldp_neighbor_free (gpointer data) +lldp_neighbor_free (LLDPNeighbor *neighbor) { - LLDPNeighbor *neighbor = data; - if (neighbor) { g_free (neighbor->chassis_id); g_free (neighbor->port_id); g_hash_table_unref (neighbor->tlvs); - g_free (neighbor); + g_slice_free (LLDPNeighbor, neighbor); } } +static void +lldp_neighbor_freep (LLDPNeighbor **ptr) +{ + lldp_neighbor_free (*ptr); +} + static gboolean lldp_neighbor_equal (LLDPNeighbor *a, LLDPNeighbor *b) { @@ -207,8 +239,12 @@ lldp_hash_table_equal (GHashTable *a, GHashTable *b) static gboolean lldp_timeout (gpointer user_data) { - NMLldpListener *self = NM_LLDP_LISTENER (user_data); - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + NMLldpListener *self = user_data; + NMLldpListenerPrivate *priv; + + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), G_SOURCE_REMOVE); + + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); priv->timer = 0; @@ -222,24 +258,26 @@ static void process_lldp_neighbors (NMLldpListener *self) { NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - sd_lldp_packet **packets = NULL; + nm_auto_free sd_lldp_packet **packets = NULL; GHashTable *hash; int num, i; + g_return_if_fail (priv->lldp_handle); + num = sd_lldp_get_packets (priv->lldp_handle, &packets); if (num < 0) { - nm_log_dbg (LOGD_DEVICE, "LLDP: error %d retrieving neighbor packets for %s", - num, priv->iface); + _LOGD ("process: error %d retrieving neighbor packets for %s", + num, priv->iface); return; } hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal, - lldp_neighbor_free, NULL); + (GDestroyNotify) lldp_neighbor_free, NULL); for (i = 0; packets && i < num; i++) { + nm_auto (lldp_neighbor_freep) LLDPNeighbor *neigh = NULL; uint8_t chassis_id_type, port_id_type, *chassis_id, *port_id, data8; uint16_t chassis_id_len, port_id_len, len, data16; - LLDPNeighbor *neigh; GValue *value; char *str; int r; @@ -257,37 +295,32 @@ process_lldp_neighbors (NMLldpListener *self) if (r < 0) goto next_packet; - neigh = g_malloc0 (sizeof (LLDPNeighbor)); + neigh = g_slice_new0 (LLDPNeighbor); neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); neigh->chassis_id_type = chassis_id_type; neigh->port_id_type = port_id_type; sd_lldp_packet_get_destination_type (packets[i], &neigh->dest); - if (chassis_id_len < 1) { - lldp_neighbor_free (neigh); + if (chassis_id_len < 1) goto next_packet; - } switch (chassis_id_type) { case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: - neigh->chassis_id = strndup ((char *) chassis_id, chassis_id_len); + neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); break; case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); break; default: - nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported chassis ID type %d", chassis_id_type); - lldp_neighbor_free (neigh); + _LOGD ("process: unsupported chassis ID type %d", chassis_id_type); goto next_packet; } - if (port_id_len < 1) { - lldp_neighbor_free (neigh); + if (port_id_len < 1) goto next_packet; - } switch (port_id_type) { case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: @@ -300,8 +333,7 @@ process_lldp_neighbors (NMLldpListener *self) neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); break; default: - nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported port ID type %d", port_id_type); - lldp_neighbor_free (neigh); + _LOGD ("process: unsupported port ID type %d", port_id_type); goto next_packet; } @@ -346,16 +378,15 @@ process_lldp_neighbors (NMLldpListener *self) g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, value); } - nm_log_dbg (LOGD_DEVICE, "LLDP: new neigh: CHASSIS='%s' PORT='%s'", - neigh->chassis_id, neigh->port_id); + _LOGD ("process: new neigh: CHASSIS='%s' PORT='%s'", + neigh->chassis_id, neigh->port_id); g_hash_table_add (hash, neigh); + neigh = NULL; next_packet: sd_lldp_packet_unref (packets[i]); } - g_free (packets); - if (lldp_hash_table_equal (priv->lldp_neighbors, hash)) { g_hash_table_destroy (hash); } else { @@ -380,6 +411,7 @@ lldp_event_handler (sd_lldp *lldp, int event, void *userdata) NMLldpListenerPrivate *priv; g_return_if_fail (NM_IS_LLDP_LISTENER (self)); + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); if (priv->timer > 0) { @@ -446,6 +478,7 @@ nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, priv->ifindex = ifindex; priv->iface = strdup (iface); + _LOGD ("start"); return TRUE; err: @@ -466,6 +499,7 @@ nm_lldp_listener_stop (NMLldpListener *self) priv = NM_LLDP_LISTENER_GET_PRIVATE (self); if (priv->lldp_handle) { + _LOGD ("stop"); sd_lldp_stop (priv->lldp_handle); sd_lldp_detach_event (priv->lldp_handle); sd_lldp_unref (priv->lldp_handle); @@ -481,6 +515,7 @@ nm_lldp_listener_stop (NMLldpListener *self) } nm_clear_g_source (&priv->timer); + priv->ifindex = 0; } gboolean @@ -595,7 +630,9 @@ nm_lldp_listener_init (NMLldpListener *self) priv->lldp_neighbors = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal, - lldp_neighbor_free, NULL); + (GDestroyNotify) lldp_neighbor_free, NULL); + + _LOGT ("lldp listener created"); } NMLldpListener * @@ -623,6 +660,8 @@ finalize (GObject *object) nm_clear_g_variant (&priv->variant); + _LOGT ("lldp listener destroyed"); + G_OBJECT_CLASS (nm_lldp_listener_parent_class)->finalize (object); } diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h index 492752c1..10c43e7c 100644 --- a/src/devices/nm-lldp-listener.h +++ b/src/devices/nm-lldp-listener.h @@ -21,9 +21,6 @@ #ifndef __NM_LLDP_LISTENER__ #define __NM_LLDP_LISTENER__ -#include "nm-glib.h" -#include "nm-types.h" - G_BEGIN_DECLS #define NM_TYPE_LLDP_LISTENER (nm_lldp_listener_get_type ()) diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index c0b83b84..c3d48b41 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -18,7 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include "nm-default.h" #include <sys/types.h> #include <unistd.h> @@ -27,7 +27,6 @@ #include <teamdctl.h> #include <stdlib.h> -#include "nm-default.h" #include "nm-device-team.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" @@ -85,7 +84,6 @@ check_connection_available (NMDevice *device, static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { - const char *iface; NMSettingTeam *s_team; if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->check_connection_compatible (device, connection)) @@ -95,11 +93,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_team || !nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) return FALSE; - /* Team connections must specify the virtual interface name */ - iface = nm_connection_get_interface_name (connection); - if (!iface || strcmp (nm_device_get_iface (device), iface)) - return FALSE; - /* FIXME: match team properties like mode, etc? */ return TRUE; @@ -218,6 +211,7 @@ master_update_slave_connection (NMDevice *self, err = teamdctl_port_config_get_raw_direct (tdc, iface_slave, (char **)&team_port_config); port_config = g_strdup (team_port_config); + teamdctl_disconnect (tdc); teamdctl_free (tdc); if (err) { g_set_error (error, @@ -501,7 +495,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; gs_free_error GError *error = NULL; - NMConnection *connection; NMSettingTeam *s_team; const char *cfg; @@ -511,9 +504,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - connection = nm_device_get_applied_connection (device); - g_assert (connection); - s_team = nm_connection_get_setting_team (connection); + s_team = (NMSettingTeam *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_TEAM); g_assert (s_team); if (priv->tdc) { @@ -673,7 +664,7 @@ create_and_realize (NMDevice *device, NMPlatformError plerr; plerr = nm_platform_link_team_add (NM_PLATFORM_GET, iface, out_plink); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create team master interface '%s' for '%s': %s", iface, diff --git a/src/devices/team/nm-team-factory.c b/src/devices/team/nm-team-factory.c index 5f9e142a..971efe87 100644 --- a/src/devices/team/nm-team-factory.c +++ b/src/devices/team/nm-team-factory.c @@ -18,7 +18,7 @@ * Copyright (C) 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <gmodule.h> @@ -26,7 +26,6 @@ #include "nm-device-factory.h" #include "nm-team-factory.h" #include "nm-device-team.h" -#include "nm-default.h" #include "nm-platform.h" #include "nm-core-internal.h" diff --git a/src/devices/tests/Makefile.am b/src/devices/tests/Makefile.am index 330377b0..e4f4d3fe 100644 --- a/src/devices/tests/Makefile.am +++ b/src/devices/tests/Makefile.am @@ -23,7 +23,8 @@ DEVICES_LDADD = \ @GNOME_CODE_COVERAGE_RULES@ noinst_PROGRAMS = \ - test-lldp + test-lldp \ + test-arping test_lldp_SOURCES = \ test-lldp.c \ @@ -37,6 +38,19 @@ test_lldp_CPPFLAGS = \ test_lldp_LDADD = $(DEVICES_LDADD) +test_arping_SOURCES = \ + test-arping.c \ + ../nm-arping-manager.c \ + $(top_srcdir)/src/platform/tests/test-common.c + +test_arping_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir)/src/platform/tests \ + -DSETUP=nm_linux_platform_setup + +test_arping_LDADD = $(DEVICES_LDADD) + @VALGRIND_RULES@ TESTS = \ - test-lldp + test-lldp \ + test-arping diff --git a/src/devices/tests/Makefile.in b/src/devices/tests/Makefile.in index 1cfe46b6..1cb73d28 100644 --- a/src/devices/tests/Makefile.in +++ b/src/devices/tests/Makefile.in @@ -88,8 +88,8 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -noinst_PROGRAMS = test-lldp$(EXEEXT) -TESTS = test-lldp$(EXEEXT) +noinst_PROGRAMS = test-lldp$(EXEEXT) test-arping$(EXEEXT) +TESTS = test-lldp$(EXEEXT) test-arping$(EXEEXT) subdir = src/devices/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ @@ -113,15 +113,20 @@ CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) +am_test_arping_OBJECTS = test_arping-test-arping.$(OBJEXT) \ + test_arping-nm-arping-manager.$(OBJEXT) \ + test_arping-test-common.$(OBJEXT) +test_arping_OBJECTS = $(am_test_arping_OBJECTS) +test_arping_DEPENDENCIES = $(DEVICES_LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = am_test_lldp_OBJECTS = test_lldp-test-lldp.$(OBJEXT) \ test_lldp-nm-lldp-listener.$(OBJEXT) \ test_lldp-test-common.$(OBJEXT) test_lldp_OBJECTS = $(am_test_lldp_OBJECTS) test_lldp_DEPENDENCIES = $(DEVICES_LDADD) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -156,8 +161,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(test_lldp_SOURCES) -DIST_SOURCES = $(test_lldp_SOURCES) +SOURCES = $(test_arping_SOURCES) $(test_lldp_SOURCES) +DIST_SOURCES = $(test_arping_SOURCES) $(test_lldp_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -685,6 +690,17 @@ test_lldp_CPPFLAGS = \ -DSETUP=nm_linux_platform_setup test_lldp_LDADD = $(DEVICES_LDADD) +test_arping_SOURCES = \ + test-arping.c \ + ../nm-arping-manager.c \ + $(top_srcdir)/src/platform/tests/test-common.c + +test_arping_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir)/src/platform/tests \ + -DSETUP=nm_linux_platform_setup + +test_arping_LDADD = $(DEVICES_LDADD) all: all-am .SUFFIXES: @@ -728,6 +744,10 @@ clean-noinstPROGRAMS: echo " rm -f" $$list; \ rm -f $$list +test-arping$(EXEEXT): $(test_arping_OBJECTS) $(test_arping_DEPENDENCIES) $(EXTRA_test_arping_DEPENDENCIES) + @rm -f test-arping$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_arping_OBJECTS) $(test_arping_LDADD) $(LIBS) + test-lldp$(EXEEXT): $(test_lldp_OBJECTS) $(test_lldp_DEPENDENCIES) $(EXTRA_test_lldp_DEPENDENCIES) @rm -f test-lldp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_lldp_OBJECTS) $(test_lldp_LDADD) $(LIBS) @@ -738,6 +758,9 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping-nm-arping-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping-test-arping.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping-test-common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-nm-lldp-listener.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-test-common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-test-lldp.Po@am__quote@ @@ -763,6 +786,48 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +test_arping-test-arping.o: test-arping.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-arping.o -MD -MP -MF $(DEPDIR)/test_arping-test-arping.Tpo -c -o test_arping-test-arping.o `test -f 'test-arping.c' || echo '$(srcdir)/'`test-arping.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-arping.Tpo $(DEPDIR)/test_arping-test-arping.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-arping.c' object='test_arping-test-arping.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-arping.o `test -f 'test-arping.c' || echo '$(srcdir)/'`test-arping.c + +test_arping-test-arping.obj: test-arping.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-arping.obj -MD -MP -MF $(DEPDIR)/test_arping-test-arping.Tpo -c -o test_arping-test-arping.obj `if test -f 'test-arping.c'; then $(CYGPATH_W) 'test-arping.c'; else $(CYGPATH_W) '$(srcdir)/test-arping.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-arping.Tpo $(DEPDIR)/test_arping-test-arping.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-arping.c' object='test_arping-test-arping.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-arping.obj `if test -f 'test-arping.c'; then $(CYGPATH_W) 'test-arping.c'; else $(CYGPATH_W) '$(srcdir)/test-arping.c'; fi` + +test_arping-nm-arping-manager.o: ../nm-arping-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-nm-arping-manager.o -MD -MP -MF $(DEPDIR)/test_arping-nm-arping-manager.Tpo -c -o test_arping-nm-arping-manager.o `test -f '../nm-arping-manager.c' || echo '$(srcdir)/'`../nm-arping-manager.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-nm-arping-manager.Tpo $(DEPDIR)/test_arping-nm-arping-manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-arping-manager.c' object='test_arping-nm-arping-manager.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-nm-arping-manager.o `test -f '../nm-arping-manager.c' || echo '$(srcdir)/'`../nm-arping-manager.c + +test_arping-nm-arping-manager.obj: ../nm-arping-manager.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-nm-arping-manager.obj -MD -MP -MF $(DEPDIR)/test_arping-nm-arping-manager.Tpo -c -o test_arping-nm-arping-manager.obj `if test -f '../nm-arping-manager.c'; then $(CYGPATH_W) '../nm-arping-manager.c'; else $(CYGPATH_W) '$(srcdir)/../nm-arping-manager.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-nm-arping-manager.Tpo $(DEPDIR)/test_arping-nm-arping-manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-arping-manager.c' object='test_arping-nm-arping-manager.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-nm-arping-manager.obj `if test -f '../nm-arping-manager.c'; then $(CYGPATH_W) '../nm-arping-manager.c'; else $(CYGPATH_W) '$(srcdir)/../nm-arping-manager.c'; fi` + +test_arping-test-common.o: $(top_srcdir)/src/platform/tests/test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-common.o -MD -MP -MF $(DEPDIR)/test_arping-test-common.Tpo -c -o test_arping-test-common.o `test -f '$(top_srcdir)/src/platform/tests/test-common.c' || echo '$(srcdir)/'`$(top_srcdir)/src/platform/tests/test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-common.Tpo $(DEPDIR)/test_arping-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/platform/tests/test-common.c' object='test_arping-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-common.o `test -f '$(top_srcdir)/src/platform/tests/test-common.c' || echo '$(srcdir)/'`$(top_srcdir)/src/platform/tests/test-common.c + +test_arping-test-common.obj: $(top_srcdir)/src/platform/tests/test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_arping-test-common.obj -MD -MP -MF $(DEPDIR)/test_arping-test-common.Tpo -c -o test_arping-test-common.obj `if test -f '$(top_srcdir)/src/platform/tests/test-common.c'; then $(CYGPATH_W) '$(top_srcdir)/src/platform/tests/test-common.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/platform/tests/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_arping-test-common.Tpo $(DEPDIR)/test_arping-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/platform/tests/test-common.c' object='test_arping-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_arping_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_arping-test-common.obj `if test -f '$(top_srcdir)/src/platform/tests/test-common.c'; then $(CYGPATH_W) '$(top_srcdir)/src/platform/tests/test-common.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/platform/tests/test-common.c'; fi` + test_lldp-test-lldp.o: test-lldp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-test-lldp.o -MD -MP -MF $(DEPDIR)/test_lldp-test-lldp.Tpo -c -o test_lldp-test-lldp.o `test -f 'test-lldp.c' || echo '$(srcdir)/'`test-lldp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-test-lldp.Tpo $(DEPDIR)/test_lldp-test-lldp.Po @@ -1011,6 +1076,13 @@ test-lldp.log: test-lldp$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +test-arping.log: test-arping$(EXEEXT) + @p='test-arping$(EXEEXT)'; \ + b='test-arping'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c new file mode 100644 index 00000000..36e17631 --- /dev/null +++ b/src/devices/tests/test-arping.c @@ -0,0 +1,139 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * 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, 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) 2015 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-arping-manager.h" +#include "test-common.h" + +#define IFACE_VETH0 "nm-test-veth0" +#define IFACE_VETH1 "nm-test-veth1" + +#define ADDR1 0x01010101 +#define ADDR2 0x02020202 +#define ADDR3 0x03030303 +#define ADDR4 0x04040404 + +typedef struct { + int ifindex0; + int ifindex1; +} test_fixture; + +static void +fixture_setup (test_fixture *fixture, gconstpointer user_data) +{ + /* create veth pair. */ + nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1); + fixture->ifindex0 = nmtstp_assert_wait_for_link (IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; + fixture->ifindex1 = nmtstp_assert_wait_for_link (IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; + + 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)); +} + +typedef struct { + in_addr_t addresses[8]; + in_addr_t peer_addresses[8]; + gboolean expected_result[8]; +} TestInfo; + +static void +arping_manager_probe_terminated (NMArpingManager *arping_manager, GMainLoop *loop) +{ + g_main_loop_quit (loop); +} + +static void +test_arping_common (test_fixture *fixture, TestInfo *info) +{ + gs_unref_object NMArpingManager *manager = NULL; + GMainLoop *loop; + int i; + + if (!nm_utils_find_helper ("arping", NULL, NULL)) { + g_test_skip ("arping binary is missing"); + return; + } + + manager = nm_arping_manager_new (fixture->ifindex0); + g_assert (manager != NULL); + + for (i = 0; info->addresses[i]; i++) + g_assert (nm_arping_manager_add_address (manager, info->addresses[i])); + + for (i = 0; info->peer_addresses[i]; i++) { + nmtstp_ip4_address_add (FALSE, fixture->ifindex1, info->peer_addresses[i], + 24, 0, 3600, 1800, NULL); + } + + loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (manager, NM_ARPING_MANAGER_PROBE_TERMINATED, + G_CALLBACK (arping_manager_probe_terminated), loop); + g_assert (nm_arping_manager_start_probe (manager, 100, NULL)); + g_assert (nmtst_main_loop_run (loop, 1000)); + + for (i = 0; info->addresses[i]; i++) { + g_assert_cmpint (nm_arping_manager_check_address (manager, info->addresses[i]), + ==, + info->expected_result[i]); + } + + g_main_loop_unref (loop); +} + +static void +test_arping_1 (test_fixture *fixture, gconstpointer user_data) +{ + TestInfo info = { .addresses = { ADDR1, ADDR2, ADDR3 }, + .peer_addresses = { ADDR4 }, + .expected_result = { TRUE, TRUE, TRUE } }; + + test_arping_common (fixture, &info); +} + +static void +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_arping_common (fixture, &info); +} + +static void +fixture_teardown (test_fixture *fixture, gconstpointer user_data) +{ + nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex0); + nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex1); +} + +void +init_tests (int *argc, char ***argv) +{ + nmtst_init_with_logging (argc, argv, NULL, "ALL"); +} + +void +setup_tests (void) +{ + 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 c339d9ca..dfae58b1 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -18,7 +18,7 @@ * Copyright (C) 2015 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <fcntl.h> #include <linux/if_tun.h> @@ -26,7 +26,6 @@ #include <sys/stat.h> #include <sys/types.h> -#include "nm-default.h" #include "nm-lldp-listener.h" #include "test-common.h" @@ -95,7 +94,6 @@ get_lldp_neighbor_attribute (GVariant *neighbors, GVariantIter iter, attrs_iter; GVariant *variant, *attr_variant; const char *attr_name; - GVariant *chassis_v, *port_v, *attr_v; g_return_val_if_fail (g_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")), @@ -103,31 +101,34 @@ get_lldp_neighbor_attribute (GVariant *neighbors, g_variant_iter_init (&iter, neighbors); while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { - g_variant_iter_init (&attrs_iter, variant); - chassis_v = NULL; - port_v = NULL; - attr_v = NULL; + gs_unref_variant GVariant *chassis_v = NULL; + gs_unref_variant GVariant *port_v = NULL; + gs_unref_variant GVariant *attr_v = NULL; + g_variant_iter_init (&attrs_iter, variant); while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) { - if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) + if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) { + g_assert (!chassis_v); chassis_v = attr_variant; - else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) + } else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) { + g_assert (!port_v); port_v = attr_variant; - else if (!g_strcmp0 (attr_name, name)) + } else if (!g_strcmp0 (attr_name, name)) { + g_assert (!attr_v); attr_v = attr_variant; + } else + g_variant_unref (attr_variant); } - if ( g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING) + g_variant_unref (variant); + + if ( chassis_v + && port_v + && g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING) && g_variant_is_of_type (port_v, G_VARIANT_TYPE_STRING) && !g_strcmp0 (chassis, g_variant_get_string (chassis_v, NULL)) - && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) { - - g_variant_ref (attr_v); - g_variant_unref (variant); - - return attr_v; - } - g_variant_unref (variant); + && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) + return g_variant_ref (attr_v); } /* neighbor not found */ @@ -137,7 +138,7 @@ get_lldp_neighbor_attribute (GVariant *neighbors, static void test_receive_frame (test_fixture *fixture, gconstpointer user_data) { - NMLldpListener *listener; + gs_unref_object NMLldpListener *listener = NULL; GMainLoop *loop; TestInfo info = { }; GVariant *neighbors, *attr; @@ -182,6 +183,7 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data) g_assert (attr != NULL); g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); + nm_clear_g_variant (&attr); /* Check system name */ attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", @@ -189,6 +191,7 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data) g_assert (attr != NULL); g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); + nm_clear_g_variant (&attr); /* Check destination */ attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", @@ -197,6 +200,7 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data) g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + nm_clear_g_variant (&attr); g_clear_pointer (&loop, g_main_loop_unref); } diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 23ebd9c8..11da011e 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -24,7 +24,7 @@ * (C) Copyright 2009 One Laptop per Child */ -#include "config.h" +#include "nm-default.h" #include <netinet/in.h> #include <string.h> @@ -35,7 +35,6 @@ #include <sys/ioctl.h> #include <errno.h> -#include "nm-default.h" #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 64da03e1..da2a0f4a 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -19,14 +19,13 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "config.h" +#include "nm-default.h" #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <errno.h> -#include "nm-default.h" #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-private.h" @@ -125,8 +124,6 @@ static gboolean check_scanning_allowed (NMDeviceWifi *self); static void schedule_scan (NMDeviceWifi *self, gboolean backoff); -static void cancel_pending_scan (NMDeviceWifi *self); - static void cleanup_association_attempt (NMDeviceWifi * self, gboolean disconnect); @@ -194,13 +191,12 @@ supplicant_interface_acquire (NMDeviceWifi *self) NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); g_return_val_if_fail (self != NULL, FALSE); - /* interface already acquired? */ - g_return_val_if_fail (priv->sup_iface == NULL, TRUE); + g_return_val_if_fail (!priv->sup_iface, TRUE); - priv->sup_iface = nm_supplicant_manager_iface_get (priv->sup_mgr, - nm_device_get_iface (NM_DEVICE (self)), - TRUE); - if (priv->sup_iface == NULL) { + priv->sup_iface = nm_supplicant_manager_create_interface (priv->sup_mgr, + nm_device_get_iface (NM_DEVICE (self)), + TRUE); + if (!priv->sup_iface) { _LOGE (LOGD_WIFI, "Couldn't initialize supplicant interface"); return FALSE; } @@ -249,7 +245,7 @@ supplicant_interface_release (NMDeviceWifi *self) priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - cancel_pending_scan (self); + nm_clear_g_source (&priv->pending_scan_id); /* Reset the scan interval to be pretty frequent when disconnected */ priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP; @@ -259,16 +255,13 @@ supplicant_interface_release (NMDeviceWifi *self) nm_clear_g_source (&priv->ap_dump_id); if (priv->sup_iface) { - remove_supplicant_interface_error_handler (self); - /* Clear supplicant interface signal handlers */ g_signal_handlers_disconnect_by_data (priv->sup_iface, self); /* Tell the supplicant to disconnect from the current AP */ nm_supplicant_interface_disconnect (priv->sup_iface); - nm_supplicant_manager_iface_release (priv->sup_mgr, priv->sup_iface); - priv->sup_iface = NULL; + g_clear_object (&priv->sup_iface); } } @@ -495,8 +488,6 @@ deactivate (NMDevice *device) if (nm_device_get_initial_hw_address (device)) nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI); - nm_platform_wifi_set_powersave (NM_PLATFORM_GET, ifindex, 0); - /* Ensure we're in infrastructure mode after deactivation; some devices * (usually older ones) don't scan well in adhoc mode. */ @@ -513,7 +504,7 @@ deactivate (NMDevice *device) /* Ensure we trigger a scan after deactivating a Hotspot */ if (old_mode == NM_802_11_MODE_AP) { - cancel_pending_scan (self); + nm_clear_g_source (&priv->pending_scan_id); request_wireless_scan (self, NULL); } } @@ -926,13 +917,26 @@ can_auto_connect (NMDevice *device, char **specific_object) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMSettingWireless *s_wifi; NMAccessPoint *ap; - const char *method = NULL; + const char *method, *mode; guint64 timestamp = 0; if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->can_auto_connect (device, connection, specific_object)) return FALSE; + s_wifi = nm_connection_get_setting_wireless (connection); + g_return_val_if_fail (s_wifi, FALSE); + + /* Always allow autoconnect for AP and non-autoconf Ad-Hoc */ + method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + mode = nm_setting_wireless_get_mode (s_wifi); + if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) + return TRUE; + else if ( g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0 + && g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) != 0) + return TRUE; + /* 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. @@ -942,11 +946,6 @@ can_auto_connect (NMDevice *device, return FALSE; } - /* Use the connection if it's a shared connection */ - method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) - return TRUE; - ap = find_first_compatible_ap (self, connection, FALSE); if (ap) { /* All good; connection is usable */ @@ -1027,6 +1026,7 @@ request_scan_cb (NMDevice *device, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv; gs_unref_variant GVariant *new_scan_options = user_data; if (error) { @@ -1042,7 +1042,9 @@ request_scan_cb (NMDevice *device, return; } - cancel_pending_scan (self); + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + nm_clear_g_source (&priv->pending_scan_id); request_wireless_scan (self, new_scan_options); g_dbus_method_invocation_return_value (context, NULL); } @@ -1366,7 +1368,7 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff) /* Cancel the pending scan if it would happen later than (now + the scan_interval) */ if (priv->pending_scan_id) { if (now + priv->scan_interval < priv->scheduled_scan_time) - cancel_pending_scan (self); + nm_clear_g_source (&priv->pending_scan_id); } if (!priv->pending_scan_id) { @@ -1399,15 +1401,6 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff) } } - -static void -cancel_pending_scan (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - nm_clear_g_source (&priv->pending_scan_id); -} - static void supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, gboolean success, @@ -2205,7 +2198,7 @@ build_supplicant_config (NMDeviceWifi *self, NMSettingMacRandomization mac_randomization_fallback; gs_free char *svalue = NULL; - g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (priv->sup_iface, NULL); s_wireless = nm_connection_get_setting_wireless (connection); g_return_val_if_fail (s_wireless != NULL, NULL); @@ -2323,8 +2316,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) /* Set spoof MAC to the interface */ cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); - if (cloned_mac) - nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI); + nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI); /* AP mode never uses a specific object or existing scanned AP */ if (priv->mode != NM_802_11_MODE_AP) { @@ -2393,6 +2385,38 @@ ensure_hotspot_frequency (NMDeviceWifi *self, nm_ap_set_freq (ap, freq); } +static void +set_powersave (NMDevice *device) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMSettingWireless *s_wireless; + NMSettingWirelessPowersave powersave; + gs_free char *value = NULL; + + s_wireless = (NMSettingWireless *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRELESS); + g_return_if_fail (s_wireless); + + powersave = nm_setting_wireless_get_powersave (s_wireless); + if (powersave == NM_SETTING_WIRELESS_POWERSAVE_DEFAULT) { + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi.powersave", + device); + powersave = _nm_utils_ascii_str_to_int64 (value, 10, + NM_SETTING_WIRELESS_POWERSAVE_IGNORE, + NM_SETTING_WIRELESS_POWERSAVE_ENABLE, + NM_SETTING_WIRELESS_POWERSAVE_IGNORE); + } + + _LOGT (LOGD_WIFI, "powersave is set to %u", (unsigned int) powersave); + + if (powersave == NM_SETTING_WIRELESS_POWERSAVE_IGNORE) + return; + + nm_platform_wifi_set_powersave (NM_PLATFORM_GET, + nm_device_get_ifindex (device), + powersave == NM_SETTING_WIRELESS_POWERSAVE_ENABLE); +} + static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { @@ -2459,11 +2483,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap)) ensure_hotspot_frequency (self, s_wireless, ap); - if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) { - nm_platform_wifi_set_powersave (NM_PLATFORM_GET, - nm_device_get_ifindex (device), - nm_setting_wireless_get_powersave (s_wireless)); - } + if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) + set_powersave (device); /* Build up the supplicant configuration */ config = build_supplicant_config (self, connection, nm_ap_get_freq (ap), &error); @@ -2817,7 +2838,7 @@ device_state_changed (NMDevice *device, case NM_DEVICE_STATE_DISCONNECTED: /* Kick off a scan to get latest results */ priv->scan_interval = SCAN_INTERVAL_MIN; - cancel_pending_scan (self); + nm_clear_g_source (&priv->pending_scan_id); request_wireless_scan (self, NULL); break; default: diff --git a/src/devices/wifi/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c index d7916aa0..bcf439da 100644 --- a/src/devices/wifi/nm-wifi-ap-utils.c +++ b/src/devices/wifi/nm-wifi-ap-utils.c @@ -18,12 +18,11 @@ * (C) Copyright 2011 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <stdlib.h> -#include "nm-default.h" #include "nm-wifi-ap-utils.h" #include "nm-utils.h" @@ -162,7 +161,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec, g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a connection using '%s' authentication cannot specific WPA protocols"), + _("a connection using '%s' authentication cannot specify WPA protocols"), tag); g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PROTO); @@ -178,7 +177,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec, g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a connection using '%s' authentication cannot specific WPA ciphers"), + _("a connection using '%s' authentication cannot specify WPA ciphers"), tag); g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PAIRWISE); @@ -195,7 +194,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec, g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a connection using '%s' authentication cannot specific WPA ciphers"), + _("a connection using '%s' authentication cannot specify WPA ciphers"), tag); g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_GROUP); @@ -207,7 +206,7 @@ verify_no_wpa (NMSettingWirelessSecurity *s_wsec, g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("a connection using '%s' authentication cannot specific a WPA password"), + _("a connection using '%s' authentication cannot specify a WPA password"), tag); g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PSK); diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 771d6704..307825c6 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -19,12 +19,11 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <stdlib.h> -#include "nm-default.h" #include "nm-wifi-ap.h" #include "nm-wifi-ap-utils.h" #include "NetworkManagerUtils.h" diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c index 7f56dc74..2d5f8faf 100644 --- a/src/devices/wifi/nm-wifi-factory.c +++ b/src/devices/wifi/nm-wifi-factory.c @@ -18,7 +18,7 @@ * Copyright (C) 2011 - 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <gmodule.h> @@ -66,6 +66,7 @@ create_device (NMDeviceFactory *factory, gboolean *out_ignore) { NMDeviceWifiCapabilities capabilities; + NM80211Mode mode; g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (plink != NULL, NULL); @@ -79,6 +80,16 @@ create_device (NMDeviceFactory *factory, return NULL; } + /* Ignore monitor-mode and other unhandled interface types. + * FIXME: keep TYPE_MONITOR devices in UNAVAILABLE state and manage + * them if/when they change to a handled type. + */ + mode = nm_platform_wifi_get_mode (NM_PLATFORM_GET, plink->ifindex); + if (mode == NM_802_11_MODE_UNKNOWN) { + *out_ignore = TRUE; + return NULL; + } + if (plink->type == NM_LINK_TYPE_WIFI) return nm_device_wifi_new (iface, capabilities); else diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c index b5642fe2..01990bee 100644 --- a/src/devices/wifi/tests/test-wifi-ap-utils.c +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -18,11 +18,10 @@ * */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include "nm-default.h" #include "nm-wifi-ap-utils.h" #include "nm-core-internal.h" @@ -594,7 +593,7 @@ wpa_flags_for_idx (guint32 idx) return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK; else if (idx == IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP) return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_PSK; - else if (IDX_WPA_RSN_PSK_PCCMP_GCCMP) + else if (NM_IN_SET (idx, IDX_WPA_PSK_PTKIP_PCCMP_GTKIP, IDX_WPA_RSN_PSK_PCCMP_GCCMP)) return NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_CCMP | NM_802_11_AP_SEC_KEY_MGMT_PSK; else if (idx == IDX_WPA_8021X) return NM_802_11_AP_SEC_PAIR_TKIP | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_KEY_MGMT_802_1X; diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index edecd24d..e9c4f02e 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -18,11 +18,10 @@ * Copyright (C) 2009 - 2011 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> -#include "nm-default.h" #include "nm-device-modem.h" #include "nm-modem.h" #include "nm-device-private.h" diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 427f3ed6..6343416c 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -18,7 +18,7 @@ * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <arpa/inet.h> @@ -26,7 +26,6 @@ #include "nm-modem-broadband.h" #include "nm-core-internal.h" -#include "nm-default.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-platform.h" @@ -52,6 +51,7 @@ typedef struct { MMSimpleConnectProperties *connect_properties; GArray *ip_types; guint ip_types_i; + guint ip_type_tries; GError *first_error; } ConnectContext; @@ -331,11 +331,17 @@ connect_ready (MMModemSimple *simple_iface, } else g_error_free (error); - /* If the modem/provider lies and the IP type we tried isn't supported, - * retry with the next one, if any. - */ - ctx->ip_types_i++; - connect_context_clear (self); + 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 { + /* If the modem/provider lies and the IP type we tried isn't supported, + * retry with the next one, if any. + */ + ctx->ip_types_i++; + ctx->ip_type_tries = 0; + } + connect_context_step (self); return; } @@ -485,9 +491,10 @@ connect_context_step (NMModemBroadband *self) else g_assert_not_reached (); - nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s'", + nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s' (try %d)", nm_modem_get_uid (NM_MODEM (self)), - nm_modem_ip_type_to_string (current)); + nm_modem_ip_type_to_string (current), + ctx->ip_type_tries + 1); mm_modem_simple_connect (self->priv->simple_iface, ctx->connect_properties, diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index c28d86ad..79082c41 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -20,14 +20,13 @@ * Copyright (C) 2009 Canonical Ltd. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <libmm-glib.h> #include "nm-modem-manager.h" -#include "nm-default.h" #include "nm-dbus-compat.h" #include "nm-modem.h" #include "nm-modem-broadband.h" diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 15104307..c1736ecf 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -19,20 +19,19 @@ * Copyright (C) 2009 Novell, Inc. */ -#include "config.h" +#include "nm-default.h" + +#include "nm-modem.h" #include <string.h> -#include "nm-modem.h" #include "nm-core-internal.h" #include "nm-platform.h" #include "nm-setting-connection.h" -#include "nm-default.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-modem-enum-types.h" #include "nm-route-manager.h" -#include "gsystem-local-alloc.h" G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index 2fd9e0bd..805aea69 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -18,7 +18,7 @@ * Copyright (C) 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <gmodule.h> @@ -29,7 +29,6 @@ #include "nm-setting-cdma.h" #include "nm-modem-manager.h" #include "nm-device-modem.h" -#include "nm-default.h" #include "nm-platform.h" static GType nm_wwan_factory_get_type (void); |