diff options
| author | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
| commit | 28028b26b3371756811e95d894f709f4b1207c00 (patch) | |
| tree | 6fe7316fd743b51042db47601a8ef8814b3134ac /src | |
| parent | e22609983008e1a669196ad64ba3a59ae8c76e0d (diff) | |
New upstream version 1.22.0 upstream/1.22.0
Diffstat (limited to 'src')
440 files changed, 12078 insertions, 13821 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index c33f36ec..3f2f44d3 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -1,21 +1,7 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2004 - 2016 Red Hat, Inc. - * Copyright 2005 - 2008 Novell, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2004 - 2016 Red Hat, Inc. + * Copyright (C) 2005 - 2008 Novell, Inc. */ #include "nm-default.h" @@ -960,9 +946,10 @@ nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule, struct _NMShutdownWaitObjHandle { CList lst; - GObject *watched_obj; + gpointer watched_obj; char *msg_reason; bool free_msg_reason:1; + bool is_cancellable:1; }; static CList _shutdown_waitobj_lst_head; @@ -981,7 +968,7 @@ _shutdown_waitobj_unregister (NMShutdownWaitObjHandle *handle) static void _shutdown_waitobj_cb (gpointer user_data, - GObject *where_the_object_was) + GObject *where_the_object_was) { NMShutdownWaitObjHandle *handle = user_data; @@ -994,6 +981,9 @@ _shutdown_waitobj_cb (gpointer user_data, * nm_shutdown_wait_obj_register_full: * @watched_obj: the object to watch. Takes a weak reference on the object * to be notified when it gets destroyed. + * If wait_type is %NM_SHUTDOWN_WAIT_TYPE_HANDLE, this must be %NULL. + * @wait_type: whether @watched_obj is just a plain GObject or a GCancellable + * that should be cancelled. * @msg_reason: a reason message, for debugging and logging purposes. * @free_msg_reason: if %TRUE, then ownership of @msg_reason will be taken * and the string will be freed with g_free() afterwards. If %FALSE, @@ -1007,21 +997,43 @@ _shutdown_waitobj_cb (gpointer user_data, * the reference-counter of @watched_obj as signal, that the object * is still used. * + * If @wait_type is %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, then during shutdown + * (after %NM_SHUTDOWN_TIMEOUT_MS), the cancellable will be cancelled to notify + * the source of the shutdown. Note that otherwise, in this mode also @watched_obj + * is only tracked with a weak-pointer. Especially, it does not register to the + * "cancelled" signal to automatically unregister (otherwise, you would never + * know whether the returned NMShutdownWaitObjHandle is still valid. + * * FIXME(shutdown): proper shutdown is not yet implemented, and registering * an object (currently) has no effect. * + * FIXME(shutdown): during shutdown, after %NM_SHUTDOWN_TIMEOUT_MS timeout, cancel + * all remaining %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE instances. Also, when somebody + * enqueues a cancellable after that point, cancel it right away on an idle handler. + * * Returns: a handle to unregister the object. The caller may choose to ignore * the handle, in which case, the object will be automatically unregistered, * once it gets destroyed. + * Note that the handle is only valid as long as @watched_obj exists. If + * you plan to use it, ensure that you take care of not using it after + * destroying @watched_obj. */ NMShutdownWaitObjHandle * -nm_shutdown_wait_obj_register_full (GObject *watched_obj, +nm_shutdown_wait_obj_register_full (gpointer watched_obj, + NMShutdownWaitType wait_type, char *msg_reason, gboolean free_msg_reason) { NMShutdownWaitObjHandle *handle; - g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL); + if (wait_type == NM_SHUTDOWN_WAIT_TYPE_OBJECT) + g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL); + else if (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE) + g_return_val_if_fail (G_IS_CANCELLABLE (watched_obj), NULL); + else if (wait_type == NM_SHUTDOWN_WAIT_TYPE_HANDLE) + g_return_val_if_fail (!watched_obj, NULL); + else + g_return_val_if_reached (NULL); if (G_UNLIKELY (!_shutdown_waitobj_lst_head.next)) c_list_init (&_shutdown_waitobj_lst_head); @@ -1034,9 +1046,11 @@ nm_shutdown_wait_obj_register_full (GObject *watched_obj, .watched_obj = watched_obj, .msg_reason = msg_reason, .free_msg_reason = free_msg_reason, + .is_cancellable = (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE), }; c_list_link_tail (&_shutdown_waitobj_lst_head, &handle->lst); - g_object_weak_ref (watched_obj, _shutdown_waitobj_cb, handle); + if (watched_obj) + g_object_weak_ref (watched_obj, _shutdown_waitobj_cb, handle); return handle; } @@ -1045,10 +1059,11 @@ nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle) { g_return_if_fail (handle); - nm_assert (G_IS_OBJECT (handle->watched_obj)); + nm_assert (!handle->watched_obj || G_IS_OBJECT (handle->watched_obj)); nm_assert (nm_c_list_contains_entry (&_shutdown_waitobj_lst_head, handle, lst)); - g_object_weak_unref (handle->watched_obj, _shutdown_waitobj_cb, handle); + if (handle->watched_obj) + g_object_weak_unref (handle->watched_obj, _shutdown_waitobj_cb, handle); _shutdown_waitobj_unregister (handle); } diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 778dc001..558a262b 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -1,21 +1,7 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2004 - 2016 Red Hat, Inc. - * Copyright 2005 - 2008 Novell, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2004 - 2016 Red Hat, Inc. + * Copyright (C) 2005 - 2008 Novell, Inc. */ #ifndef __NETWORKMANAGER_UTILS_H__ @@ -87,13 +73,56 @@ NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *ru #define NM_SHUTDOWN_TIMEOUT_MS 1500 #define NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG 500 +typedef enum { + /* There is no watched_obj argument, and the shutdown is delayed until the user + * explicitly calls unregister on the returned handle. */ + NM_SHUTDOWN_WAIT_TYPE_HANDLE, + + /* The watched_obj argument is a GObject, and shutdown is delayed until the object + * gets destroyed (or unregistered). */ + NM_SHUTDOWN_WAIT_TYPE_OBJECT, + + /* The watched_obj argument is a GCancellable, and shutdown is delayed until the object + * gets destroyed (or unregistered). Note that after NM_SHUTDOWN_TIMEOUT_MS, the + * cancellable will be cancelled to notify listeners about the shutdown. */ + NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, +} NMShutdownWaitType; + typedef struct _NMShutdownWaitObjHandle NMShutdownWaitObjHandle; -NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full (GObject *watched_obj, +NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full (gpointer watched_obj, + NMShutdownWaitType wait_type, char *msg_reason, gboolean free_msg_reason); -#define nm_shutdown_wait_obj_register(watched_obj, msg_reason) nm_shutdown_wait_obj_register_full((watched_obj), (""msg_reason""), FALSE) +static inline NMShutdownWaitObjHandle * +nm_shutdown_wait_obj_register_object_full (gpointer watched_obj, + char *msg_reason, + gboolean free_msg_reason) +{ + return nm_shutdown_wait_obj_register_full (watched_obj, NM_SHUTDOWN_WAIT_TYPE_OBJECT, msg_reason, free_msg_reason); +} + +#define nm_shutdown_wait_obj_register_object(watched_obj, msg_reason) nm_shutdown_wait_obj_register_object_full((watched_obj), (""msg_reason""), FALSE) + +static inline NMShutdownWaitObjHandle * +nm_shutdown_wait_obj_register_handle_full (char *msg_reason, + gboolean free_msg_reason) +{ + return nm_shutdown_wait_obj_register_full (NULL, NM_SHUTDOWN_WAIT_TYPE_HANDLE, msg_reason, free_msg_reason); +} + +#define nm_shutdown_wait_obj_register_handle(msg_reason) nm_shutdown_wait_obj_register_handle_full((""msg_reason""), FALSE) + +static inline NMShutdownWaitObjHandle * +nm_shutdown_wait_obj_register_cancellable_full (GCancellable *watched_obj, + char *msg_reason, + gboolean free_msg_reason) +{ + return nm_shutdown_wait_obj_register_full (watched_obj, NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, msg_reason, free_msg_reason); +} + +#define nm_shutdown_wait_obj_register_cancellable(watched_obj, msg_reason) nm_shutdown_wait_obj_register_cancellable_full((watched_obj), (""msg_reason""), FALSE) void nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle); diff --git a/src/devices/adsl/meson.build b/src/devices/adsl/meson.build index f92e809c..a5d1c4b4 100644 --- a/src/devices/adsl/meson.build +++ b/src/devices/adsl/meson.build @@ -3,15 +3,11 @@ sources = files( 'nm-device-adsl.c', ) -deps = [ - libudev_dep, - nm_dep, -] - libnm_device_plugin_adsl = shared_module( 'nm-device-plugin-adsl', sources: sources, - dependencies: deps, + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, @@ -25,10 +21,3 @@ test( check_exports, args: [libnm_device_plugin_adsl.full_path(), linker_script_devices], ) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-adsl: src/devices/adsl/libnm-device-plugin-adsl.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/adsl/.libs/libnm-device-plugin-adsl.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/adsl/.libs/libnm-device-plugin-adsl.so) -''' diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index bc0bf5c6..487011ff 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2013 Red Hat, Inc. */ diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index 34efdb01..7c2b3e20 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Pantelis Koukousoulas <pktoss@gmail.com> */ diff --git a/src/devices/adsl/nm-device-adsl.h b/src/devices/adsl/nm-device-adsl.h index 2d3a9fc7..84176fae 100644 --- a/src/devices/adsl/nm-device-adsl.h +++ b/src/devices/adsl/nm-device-adsl.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Author: Pantelis Koukousoulas <pktoss@gmail.com> * Copyright (C) 2009 - 2011 Red Hat Inc. */ diff --git a/src/devices/bluetooth/meson.build b/src/devices/bluetooth/meson.build index b2f67ceb..f0507c23 100644 --- a/src/devices/bluetooth/meson.build +++ b/src/devices/bluetooth/meson.build @@ -1,16 +1,12 @@ sources = files( - 'nm-bluez-device.c', 'nm-bluez-manager.c', - 'nm-bluez4-adapter.c', - 'nm-bluez4-manager.c', - 'nm-bluez5-manager.c', 'nm-bt-error.c', 'nm-device-bt.c', ) deps = [ + daemon_nm_default_dep, libnm_wwan_dep, - nm_dep, ] if enable_bluez5_dun @@ -19,9 +15,21 @@ if enable_bluez5_dun deps += bluez5_dep endif +libnm_device_plugin_bluetooth_static = static_library( + 'nm-device-plugin-bluetooth-static', + sources: sources, + dependencies: deps, + c_args: daemon_c_flags, +) + +libnm_device_plugin_bluetooth_static_dep = declare_dependency( + link_whole: libnm_device_plugin_bluetooth_static, +) + +deps += libnm_device_plugin_bluetooth_static_dep + libnm_device_plugin_bluetooth = shared_module( 'nm-device-plugin-bluetooth', - sources: sources, dependencies: deps, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, @@ -38,9 +46,13 @@ test( args: [libnm_device_plugin_bluetooth.full_path(), linker_script_devices], ) -# FIXME: check_so_symbols replacement -''' -check-local-devices-bluetooth: src/devices/bluetooth/libnm-device-plugin-bluetooth.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/bluetooth/.libs/libnm-device-plugin-bluetooth.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/bluetooth/.libs/libnm-device-plugin-bluetooth.so) -''' +if enable_tests + test_unit = 'nm-bt-test' + + executable( + test_unit, + 'tests/' + test_unit + '.c', + dependencies: [ libnetwork_manager_test_dep, deps ], + c_args: test_c_flags, + ) +endif diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/devices/bluetooth/nm-bluez-common.h index 956375bb..ade4434b 100644 --- a/src/devices/bluetooth/nm-bluez-common.h +++ b/src/devices/bluetooth/nm-bluez-common.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ @@ -26,19 +12,12 @@ #define NM_BLUEZ_SERVICE "org.bluez" #define NM_BLUEZ_MANAGER_PATH "/" -#define NM_OBJECT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" #define NM_BLUEZ5_ADAPTER_INTERFACE "org.bluez.Adapter1" #define NM_BLUEZ5_DEVICE_INTERFACE "org.bluez.Device1" #define NM_BLUEZ5_NETWORK_INTERFACE "org.bluez.Network1" #define NM_BLUEZ5_NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1" -#define NM_BLUEZ4_MANAGER_INTERFACE "org.bluez.Manager" -#define NM_BLUEZ4_ADAPTER_INTERFACE "org.bluez.Adapter" -#define NM_BLUEZ4_DEVICE_INTERFACE "org.bluez.Device" -#define NM_BLUEZ4_SERIAL_INTERFACE "org.bluez.Serial" -#define NM_BLUEZ4_NETWORK_INTERFACE "org.bluez.Network" - #define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" #define NM_BLUEZ_MANAGER_NETWORK_SERVER_ADDED "network-server-added" diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c deleted file mode 100644 index fb0a72c4..00000000 --- a/src/devices/bluetooth/nm-bluez-device.c +++ /dev/null @@ -1,1320 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - * Copyright (C) 2013 Intel Corporation. - */ - -#include "nm-default.h" - -#include "nm-bluez-device.h" - -#include "nm-core-internal.h" -#include "nm-bt-error.h" -#include "nm-bluez-common.h" -#include "settings/nm-settings.h" -#include "settings/nm-settings-connection.h" -#include "NetworkManagerUtils.h" - -#if WITH_BLUEZ5_DUN -#include "nm-bluez5-dun.h" -#endif - -/*****************************************************************************/ - -#define VARIANT_IS_OF_TYPE_BOOLEAN(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_BOOLEAN) )) -#define VARIANT_IS_OF_TYPE_STRING(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING) )) -#define VARIANT_IS_OF_TYPE_OBJECT_PATH(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_OBJECT_PATH) )) -#define VARIANT_IS_OF_TYPE_STRING_ARRAY(v) ((v) != NULL && ( g_variant_is_of_type ((v), G_VARIANT_TYPE_STRING_ARRAY) )) - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE (NMBluezDevice, - PROP_PATH, - PROP_ADDRESS, - PROP_NAME, - PROP_CAPABILITIES, - PROP_USABLE, - PROP_CONNECTED, -); - -enum { - INITIALIZED, - REMOVED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct { - char *path; - GDBusConnection *dbus_connection; - - GDBusProxy *proxy; - - GDBusProxy *adapter5; - gboolean adapter_powered; - - int bluez_version; - - gboolean initialized; - gboolean usable; - NMBluetoothCapabilities connection_bt_type; - - guint check_emit_usable_id; - - char *adapter_address; - char *address; - char *name; - guint32 capabilities; - gboolean connected; - gboolean paired; - - char *b4_iface; -#if WITH_BLUEZ5_DUN - NMBluez5DunContext *b5_dun_context; -#endif - - NMSettings *settings; - GSList *connections; - - NMSettingsConnection *pan_connection; - gboolean pan_connection_no_autocreate; -} NMBluezDevicePrivate; - -struct _NMBluezDevice { - GObject parent; - NMBluezDevicePrivate _priv; -}; - -struct _NMBluezDeviceClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT) - -#define NM_BLUEZ_DEVICE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMBluezDevice, NM_IS_BLUEZ_DEVICE) - -/*****************************************************************************/ - -static void cp_connection_added (NMSettings *settings, - NMSettingsConnection *sett_conn, - NMBluezDevice *self); -static gboolean connection_compatible (NMBluezDevice *self, NMSettingsConnection *sett_conn); - -/*****************************************************************************/ - -const char * -nm_bluez_device_get_path (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->path; -} - -const char * -nm_bluez_device_get_address (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->address; -} - -gboolean -nm_bluez_device_get_initialized (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->initialized; -} - -gboolean -nm_bluez_device_get_usable (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->usable; -} - -const char * -nm_bluez_device_get_name (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), NULL); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->name; -} - -guint32 -nm_bluez_device_get_capabilities (NMBluezDevice *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), 0); - - return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->capabilities; -} - -gboolean -nm_bluez_device_get_connected (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv; - - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE); - - priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - return priv->connected; -} - -static void -pan_connection_check_create (NMBluezDevice *self) -{ - gs_unref_object NMConnection *connection = NULL; - NMSettingsConnection *added; - NMSetting *setting; - gs_free char *id = NULL; - char uuid[37]; - GError *error = NULL; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_return_if_fail (priv->capabilities & NM_BT_CAPABILITY_NAP); - g_return_if_fail (priv->connections == NULL); - g_return_if_fail (priv->name); - - if (priv->pan_connection || priv->pan_connection_no_autocreate) { - /* already have a connection or we don't want to create one, nothing to do. */ - return; - } - - /* Only try once to create a connection. If it does not succeed, we do not try again. Also, - * if the connection gets deleted later, do not create another one for this device. */ - priv->pan_connection_no_autocreate = TRUE; - - /* create a new connection */ - - connection = nm_simple_connection_new (); - - /* Setting: Connection */ - nm_utils_uuid_generate_buf (uuid); - id = g_strdup_printf (_("%s Network"), priv->name); - setting = nm_setting_connection_new (); - g_object_set (setting, - NM_SETTING_CONNECTION_ID, id, - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, - NULL); - nm_connection_add_setting (connection, setting); - - /* Setting: Bluetooth */ - setting = nm_setting_bluetooth_new (); - g_object_set (G_OBJECT (setting), - NM_SETTING_BLUETOOTH_BDADDR, priv->address, - NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, - NULL); - nm_connection_add_setting (connection, setting); - - if (!nm_connection_normalize (connection, NULL, NULL, &error)) { - nm_log_err (LOGD_BT, "bluez[%s] couldn't generate a connection for NAP device: %s", - priv->path, error->message); - g_error_free (error); - g_return_if_reached (); - } - - /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) - * which then already finds the suitable connection in priv->connections. This is confusing, - * so block the signal. check_emit_usable will succeed after this function call returns. */ - g_signal_handlers_block_by_func (priv->settings, cp_connection_added, self); - nm_settings_add_connection (priv->settings, - connection, - NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, - NM_SETTINGS_CONNECTION_ADD_REASON_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED, - &added, - &error); - g_signal_handlers_unblock_by_func (priv->settings, cp_connection_added, self); - - if (added) { - nm_assert (!g_slist_find (priv->connections, added)); - nm_assert (connection_compatible (self, added)); - priv->connections = g_slist_prepend (priv->connections, g_object_ref (added)); - priv->pan_connection = added; - nm_log_dbg (LOGD_BT, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid); - } else { - nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %s", - priv->path, id, uuid, error->message); - g_clear_error (&error); - } -} - -static gboolean -check_emit_usable (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - gboolean new_usable; - - /* only expect the supported capabilities set. */ - nm_assert ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE ); - - new_usable = ( priv->initialized && priv->capabilities - && priv->name && priv->paired - && ( (priv->bluez_version == 4) - || (priv->bluez_version == 5 && priv->adapter5 && priv->adapter_powered)) - && priv->dbus_connection && priv->address && priv->adapter_address); - - if (!new_usable) - goto END; - - if (priv->connections) - goto END; - - if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { - /* non NAP devices are only usable, if they already have a connection. */ - new_usable = FALSE; - goto END; - } - - pan_connection_check_create (self); - new_usable = !!priv->pan_connection; - -END: - if (new_usable != priv->usable) { - priv->usable = new_usable; - _notify (self, PROP_USABLE); - } - - return G_SOURCE_REMOVE; -} - -static void -check_emit_usable_schedule (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (priv->check_emit_usable_id == 0) - priv->check_emit_usable_id = g_idle_add ((GSourceFunc) check_emit_usable, self); -} - -/*****************************************************************************/ - -static gboolean -connection_compatible (NMBluezDevice *self, NMSettingsConnection *sett_conn) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - NMConnection *connection = nm_settings_connection_get_connection (sett_conn); - NMSettingBluetooth *s_bt; - const char *bt_type; - const char *bdaddr; - - if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) - return FALSE; - - s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) - return FALSE; - - if (!priv->address) - return FALSE; - - bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); - if (!bdaddr) - return FALSE; - if (!nm_utils_hwaddr_matches (bdaddr, -1, priv->address, -1)) - return FALSE; - - bt_type = nm_setting_bluetooth_get_connection_type (s_bt); - - if (nm_streq (bt_type, NM_SETTING_BLUETOOTH_TYPE_NAP)) - return FALSE; - - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) - && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) - return FALSE; - - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) - && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) - return FALSE; - - return TRUE; -} - -static gboolean -_internal_track_connection (NMBluezDevice *self, - NMSettingsConnection *sett_conn, - gboolean tracked) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - gboolean was_tracked; - - was_tracked = !!g_slist_find (priv->connections, sett_conn); - if (was_tracked == !!tracked) - return FALSE; - - if (tracked) - priv->connections = g_slist_prepend (priv->connections, g_object_ref (sett_conn)); - else { - priv->connections = g_slist_remove (priv->connections, sett_conn); - if (priv->pan_connection == sett_conn) - priv->pan_connection = NULL; - g_object_unref (sett_conn); - } - - return TRUE; -} - -static void -cp_connection_added (NMSettings *settings, - NMSettingsConnection *sett_conn, - NMBluezDevice *self) -{ - if (connection_compatible (self, sett_conn)) { - if (_internal_track_connection (self, sett_conn, TRUE)) - check_emit_usable (self); - } -} - -static void -cp_connection_removed (NMSettings *settings, - NMSettingsConnection *sett_conn, - NMBluezDevice *self) -{ - if (_internal_track_connection (self, sett_conn, FALSE)) - check_emit_usable (self); -} - -static void -cp_connection_updated (NMSettings *settings, - NMSettingsConnection *sett_conn, - guint update_reason_u, - NMBluezDevice *self) -{ - if (_internal_track_connection (self, sett_conn, - connection_compatible (self, sett_conn))) - check_emit_usable_schedule (self); -} - -static void -load_connections (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - NMSettingsConnection *const*connections; - guint i; - gboolean changed = FALSE; - - connections = nm_settings_get_connections (priv->settings, NULL); - for (i = 0; connections[i]; i++) { - if (connection_compatible (self, connections[i])) - changed |= _internal_track_connection (self, connections[i], TRUE); - } - if (changed) - check_emit_usable (self); -} - -/*****************************************************************************/ - -static void -bluez_disconnect_cb (GDBusConnection *dbus_connection, - GAsyncResult *res, - gpointer user_data) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE ((NMBluezDevice *) user_data); - GError *error = NULL; - GVariant *variant; - - variant = g_dbus_connection_call_finish (dbus_connection, res, &error); - if (!variant) { - if (!strstr (error->message, "org.bluez.Error.NotConnected")) - nm_log_warn (LOGD_BT, "bluez[%s]: failed to disconnect: %s", priv->path, error->message); - g_error_free (error); - } else - g_variant_unref (variant); - - g_object_unref (NM_BLUEZ_DEVICE (user_data)); -} - -void -nm_bluez_device_disconnect (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *args = NULL; - const char *dbus_iface = NULL; - - g_return_if_fail (priv->dbus_connection); - - /* FIXME: if we are in the process of connecting and cancel the - * connection attempt, we must complete the pending connect request. - * However, we must also ensure that we don't leave a connected device. */ - if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) { - if (priv->bluez_version == 4) { - /* Can't pass a NULL interface name through dbus to bluez, so just - * ignore the disconnect if the interface isn't known. - */ - if (!priv->b4_iface) - goto out; - args = g_variant_new ("(s)", priv->b4_iface), - dbus_iface = NM_BLUEZ4_SERIAL_INTERFACE; - } else if (priv->bluez_version == 5) { -#if WITH_BLUEZ5_DUN - nm_bluez5_dun_cleanup (priv->b5_dun_context); -#endif - priv->connected = FALSE; - goto out; - } - } else if (priv->connection_bt_type == NM_BT_CAPABILITY_NAP) { - if (priv->bluez_version == 4) - dbus_iface = NM_BLUEZ4_NETWORK_INTERFACE; - else if (priv->bluez_version == 5) - dbus_iface = NM_BLUEZ5_NETWORK_INTERFACE; - else - g_assert_not_reached (); - } else - g_assert_not_reached (); - - g_dbus_connection_call (priv->dbus_connection, - NM_BLUEZ_SERVICE, - priv->path, - dbus_iface, - "Disconnect", - args ?: g_variant_new("()"), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 10000, - NULL, - (GAsyncReadyCallback) bluez_disconnect_cb, - g_object_ref (self)); - -out: - g_clear_pointer (&priv->b4_iface, g_free); - priv->connection_bt_type = NM_BT_CAPABILITY_NONE; -} - -static void -_connect_complete (NMBluezDevice *self, - const char *device, - NMBluezDeviceConnectCallback callback, - gpointer callback_user_data, - GError *error) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - nm_assert ((device || error) && !(device && error)); - - if ( device - && priv->bluez_version == 5) { - priv->connected = TRUE; - _notify (self, PROP_CONNECTED); - } - - if (callback) - callback (self, device, error, callback_user_data); -} - -static void -_connect_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - gs_unref_object NMBluezDevice *self = NULL; - NMBluezDevicePrivate *priv; - NMBluezDeviceConnectCallback callback; - gpointer callback_user_data; - gs_free_error GError *error = NULL; - char *device = NULL; - gs_unref_variant GVariant *variant = NULL; - - nm_utils_user_data_unpack (user_data, &self, &callback, &callback_user_data); - - priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - variant = _nm_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, G_VARIANT_TYPE ("(s)"), &error); - if (variant) { - g_variant_get (variant, "(s)", &device); - priv->b4_iface = device; - } - - _connect_complete (self, device, callback, callback_user_data, error); -} - -#if WITH_BLUEZ5_DUN -static void -_connect_cb_bluez5_dun (NMBluez5DunContext *context, - const char *device, - GError *error, - gpointer user_data) -{ - gs_unref_object NMBluezDevice *self = NULL; - gs_unref_object GCancellable *cancellable = NULL; - NMBluezDeviceConnectCallback callback; - gpointer callback_user_data; - gs_free_error GError *cancelled_error = NULL; - - nm_utils_user_data_unpack (user_data, &self, &cancellable, &callback, &callback_user_data); - - /* FIXME(shutdown): the async operation nm_bluez5_dun_connect() should be cancellable. - * Fake it here. */ - if (g_cancellable_set_error_if_cancelled (cancellable, &cancelled_error)) - error = cancelled_error; - - _connect_complete (self, device, callback, callback_user_data, error); -} -#else /* WITH_BLUEZ5_DUN */ -static void -_connect_cb_bluez5_dun_idle_no_b5 (gpointer user_data, - GCancellable *cancellable) -{ - gs_unref_object NMBluezDevice *self = NULL; - NMBluezDeviceConnectCallback callback; - gpointer callback_user_data; - gs_free_error GError *error = NULL; - - nm_utils_user_data_unpack (user_data, &self, &callback, &callback_user_data); - - if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) { - g_set_error (&error, - NM_BT_ERROR, - NM_BT_ERROR_DUN_CONNECT_FAILED, - "NetworkManager built without support for Bluez 5"); - } - callback (self, NULL, error, callback_user_data); -} -#endif /* WITH_BLUEZ5_DUN */ - -void -nm_bluez_device_connect_async (NMBluezDevice *self, - NMBluetoothCapabilities connection_bt_type, - GCancellable *cancellable, - NMBluezDeviceConnectCallback callback, - gpointer callback_user_data) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const char *dbus_iface = NULL; - const char *connect_type = NULL; - - g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); - - priv->connection_bt_type = connection_bt_type; - - if (connection_bt_type == NM_BT_CAPABILITY_NAP) { - connect_type = BLUETOOTH_CONNECT_NAP; - if (priv->bluez_version == 4) - dbus_iface = NM_BLUEZ4_NETWORK_INTERFACE; - else if (priv->bluez_version == 5) - dbus_iface = NM_BLUEZ5_NETWORK_INTERFACE; - } else if (connection_bt_type == NM_BT_CAPABILITY_DUN) { - connect_type = BLUETOOTH_CONNECT_DUN; - if (priv->bluez_version == 4) - dbus_iface = NM_BLUEZ4_SERIAL_INTERFACE; - else if (priv->bluez_version == 5) { -#if WITH_BLUEZ5_DUN - if (priv->b5_dun_context == NULL) - priv->b5_dun_context = nm_bluez5_dun_new (priv->adapter_address, priv->address); - nm_bluez5_dun_connect (priv->b5_dun_context, - _connect_cb_bluez5_dun, - nm_utils_user_data_pack (g_object_ref (self), - nm_g_object_ref (cancellable), - callback, - callback_user_data)); -#else - if (callback) { - nm_utils_invoke_on_idle (_connect_cb_bluez5_dun_idle_no_b5, - nm_utils_user_data_pack (g_object_ref (self), - callback, - callback_user_data), - cancellable); - } -#endif - return; - } - } else - g_return_if_reached (); - - /* FIXME: we need to remember that a connect is in progress. - * So, if the request gets cancelled, that we disconnect the - * connection that was established in the meantime. */ - g_dbus_connection_call (priv->dbus_connection, - NM_BLUEZ_SERVICE, - priv->path, - dbus_iface, - "Connect", - g_variant_new ("(s)", connect_type), - NULL, - G_DBUS_CALL_FLAGS_NONE, - 20000, - cancellable, - _connect_cb, - nm_utils_user_data_pack (g_object_ref (self), - callback, - callback_user_data)); -} - -/*****************************************************************************/ - -static void -set_adapter_address (NMBluezDevice *self, const char *address) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - g_return_if_fail (address); - - if (priv->adapter_address) - g_free (priv->adapter_address); - priv->adapter_address = g_strdup (address); -} - -static guint32 -convert_uuids_to_capabilities (const char **strings) -{ - const char **iter; - guint32 capabilities = 0; - - for (iter = strings; iter && *iter; iter++) { - char **parts; - - parts = g_strsplit (*iter, "-", -1); - if (parts && parts[0]) { - switch (g_ascii_strtoull (parts[0], NULL, 16)) { - case 0x1103: - capabilities |= NM_BT_CAPABILITY_DUN; - break; - case 0x1116: - capabilities |= NM_BT_CAPABILITY_NAP; - break; - default: - break; - } - } - g_strfreev (parts); - } - - return capabilities; -} - -static void -_set_property_capabilities (NMBluezDevice *self, const char **uuids) -{ - guint32 uint_val; - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - uint_val = convert_uuids_to_capabilities (uuids); - if (priv->capabilities != uint_val) { - if (priv->capabilities) { - /* changing (relevant) capabilities is not supported and ignored -- except setting initially */ - nm_log_warn (LOGD_BT, "bluez[%s] ignore change of capabilities for Bluetooth device from %u to %u", - priv->path, priv->capabilities, uint_val); - return; - } - nm_log_dbg (LOGD_BT, "bluez[%s] set capabilities for Bluetooth device: %s%s%s", priv->path, - uint_val & NM_BT_CAPABILITY_NAP ? "NAP" : "", - ((uint_val & NM_BT_CAPABILITY_DUN) && (uint_val &NM_BT_CAPABILITY_NAP)) ? " | " : "", - uint_val & NM_BT_CAPABILITY_DUN ? "DUN" : ""); - priv->capabilities = uint_val; - _notify (self, PROP_CAPABILITIES); - } -} - -/** - * priv->address can only be set one to a certain (non NULL) value. Every later attempt - * to reset it to another value will be ignored and a warning will be logged. - **/ -static void -_set_property_address (NMBluezDevice *self, const char *addr) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (g_strcmp0 (priv->address, addr) == 0) - return; - - if (!addr) { - nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to NULL", priv->path, priv->address); - return; - } - - if (priv->address != NULL) { - nm_log_warn (LOGD_BT, "bluez[%s] cannot reset address from '%s' to '%s'", priv->path, priv->address, addr); - return; - } - - if (!nm_utils_hwaddr_valid (addr, ETH_ALEN)) { - nm_log_warn (LOGD_BT, "bluez[%s] cannot set address to '%s' (invalid value)", priv->path, addr); - return; - } - - priv->address = g_strdup (addr); - _notify (self, PROP_ADDRESS); -} - -static void -_take_variant_property_address (NMBluezDevice *self, GVariant *v) -{ - _set_property_address (self, VARIANT_IS_OF_TYPE_STRING (v) ? g_variant_get_string (v, NULL) : NULL); - if (v) - g_variant_unref (v); -} - -static void -_take_variant_property_name (NMBluezDevice *self, GVariant *v) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const char *str; - - if (VARIANT_IS_OF_TYPE_STRING (v)) { - str = g_variant_get_string (v, NULL); - if (g_strcmp0 (priv->name, str)) { - g_free (priv->name); - priv->name = g_strdup (str); - _notify (self, PROP_NAME); - } - } - if (v) - g_variant_unref (v); -} - -static void -_take_variant_property_uuids (NMBluezDevice *self, GVariant *v) -{ - if (VARIANT_IS_OF_TYPE_STRING_ARRAY (v)) { - const char **uuids = g_variant_get_strv (v, NULL); - - _set_property_capabilities (self, uuids); - g_free (uuids); - } - if (v) - g_variant_unref (v); -} - -static void -_take_variant_property_connected (NMBluezDevice *self, GVariant *v) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (VARIANT_IS_OF_TYPE_BOOLEAN (v)) { - gboolean connected = g_variant_get_boolean (v); - - if (priv->connected != connected) { - priv->connected = connected; - _notify (self, PROP_CONNECTED); - } - } - if (v) - g_variant_unref (v); -} - -static void -_take_variant_property_paired (NMBluezDevice *self, GVariant *v) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - if (VARIANT_IS_OF_TYPE_BOOLEAN (v)) - priv->paired = g_variant_get_boolean (v); - - if (v) - g_variant_unref (v); -} - -static void -adapter5_on_properties_changed (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariantIter i; - const char *property; - GVariant *v; - - g_variant_iter_init (&i, changed_properties); - while (g_variant_iter_next (&i, "{&sv}", &property, &v)) { - if (!strcmp (property, "Powered") && VARIANT_IS_OF_TYPE_BOOLEAN (v)) { - gboolean powered = g_variant_get_boolean (v); - if (priv->adapter_powered != powered) - priv->adapter_powered = powered; - } - g_variant_unref (v); - } - - check_emit_usable (self); -} - -static void -adapter5_on_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - GVariant *v; - - priv->adapter5 = g_dbus_proxy_new_for_bus_finish (res, &error); - if (!priv->adapter5) { - nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire adapter proxy: %s.", priv->path, error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - } else { - g_signal_connect (priv->adapter5, "g-properties-changed", - G_CALLBACK (adapter5_on_properties_changed), self); - - /* Check adapter's powered state */ - v = g_dbus_proxy_get_cached_property (priv->adapter5, "Powered"); - priv->adapter_powered = VARIANT_IS_OF_TYPE_BOOLEAN (v) ? g_variant_get_boolean (v) : FALSE; - if (v) - g_variant_unref (v); - - v = g_dbus_proxy_get_cached_property (priv->adapter5, "Address"); - if (VARIANT_IS_OF_TYPE_STRING (v)) - set_adapter_address (self, g_variant_get_string (v, NULL)); - - priv->initialized = TRUE; - g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - - check_emit_usable (self); - } - - g_object_unref (self); -} - -static void -_take_one_variant_property (NMBluezDevice *self, const char *property, GVariant *v) -{ - if (v) { - if (!g_strcmp0 (property, "Address")) - _take_variant_property_address (self, v); - else if (!g_strcmp0 (property, "Connected")) - _take_variant_property_connected (self, v); - else if (!g_strcmp0 (property, "Paired")) - _take_variant_property_paired (self, v); - else if (!g_strcmp0 (property, "Name")) - _take_variant_property_name (self, v); - else if (!g_strcmp0 (property, "UUIDs")) - _take_variant_property_uuids (self, v); - else - g_variant_unref (v); - } -} - -static void -_set_properties (NMBluezDevice *self, GVariant *properties) -{ - GVariantIter i; - const char *property; - GVariant *v; - - g_object_freeze_notify (G_OBJECT (self)); - g_variant_iter_init (&i, properties); - while (g_variant_iter_next (&i, "{&sv}", &property, &v)) - _take_one_variant_property (self, property, v); - g_object_thaw_notify (G_OBJECT (self)); -} - -static void -properties_changed (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - - _set_properties (self, changed_properties); - check_emit_usable (self); -} - -static void -bluez4_property_changed (GDBusProxy *proxy, - const char *property, - GVariant *v, - gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - - _take_one_variant_property (self, property, v); - check_emit_usable (self); -} - -static void -get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_data) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *err = NULL; - GVariant *v_properties, *v_dict; - - v_properties = _nm_dbus_proxy_call_finish (priv->proxy, res, - G_VARIANT_TYPE ("(a{sv})"), - &err); - if (!v_properties) { - g_dbus_error_strip_remote_error (err); - nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s", - priv->path, err->message); - g_error_free (err); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - goto END; - } - - v_dict = g_variant_get_child_value (v_properties, 0); - _set_properties (self, v_dict); - g_variant_unref (v_dict); - g_variant_unref (v_properties); - - /* Check if any connections match this device */ - load_connections (self); - - priv->initialized = TRUE; - g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - - check_emit_usable (self); - -END: - g_object_unref (self); -} - -static void -query_properties (NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GVariant *v; - - switch (priv->bluez_version) { - case 4: - g_dbus_proxy_call (priv->proxy, "GetProperties", NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, 3000, - NULL, get_properties_cb_4, g_object_ref (self)); - break; - case 5: - g_object_freeze_notify (G_OBJECT (self)); - _take_variant_property_address (self, g_dbus_proxy_get_cached_property (priv->proxy, "Address")); - _take_variant_property_connected (self, g_dbus_proxy_get_cached_property (priv->proxy, "Connected")); - _take_variant_property_paired (self, g_dbus_proxy_get_cached_property (priv->proxy, "Paired")); - _take_variant_property_name (self, g_dbus_proxy_get_cached_property (priv->proxy, "Name")); - _take_variant_property_uuids (self, g_dbus_proxy_get_cached_property (priv->proxy, "UUIDs")); - g_object_thaw_notify (G_OBJECT (self)); - - v = g_dbus_proxy_get_cached_property (priv->proxy, "Adapter"); - if (VARIANT_IS_OF_TYPE_OBJECT_PATH (v)) { - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - NM_BLUEZ_SERVICE, - g_variant_get_string (v, NULL), - NM_BLUEZ5_ADAPTER_INTERFACE, - NULL, - (GAsyncReadyCallback) adapter5_on_acquired, - g_object_ref (self)); - g_variant_unref (v); - } else { - /* If the Adapter property is unset at this point, we won't try to acquire the adapter later on - * and the device stays unusable. This should not happen, but if it does, log a debug message. */ - nm_log_dbg (LOGD_BT, "bluez[%s] device has no adapter property and cannot be used.", priv->path); - } - - /* Check if any connections match this device */ - load_connections (self); - - break; - } -} - -static void -on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - - priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->proxy) { - nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire device proxy: %s.", priv->path, error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - } else { - g_signal_connect (priv->proxy, "g-properties-changed", - G_CALLBACK (properties_changed), self); - if (priv->bluez_version == 4) { - /* Watch for custom Bluez4 PropertyChanged signals */ - _nm_dbus_signal_connect (priv->proxy, "PropertyChanged", G_VARIANT_TYPE ("(sv)"), - G_CALLBACK (bluez4_property_changed), self); - } - - query_properties (self); - } - g_object_unref (self); -} - -static void -on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - - priv->dbus_connection = g_bus_get_finish (res, &error); - - if (!priv->dbus_connection) { - nm_log_warn (LOGD_BT, "bluez[%s] failed to acquire bus connection: %s.", priv->path, error->message); - g_clear_error (&error); - g_signal_emit (self, signals[INITIALIZED], 0, FALSE); - } else - check_emit_usable (self); - - g_object_unref (self); -} - -/*****************************************************************************/ - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE ((NMBluezDevice *) object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_ADDRESS: - g_value_set_string (value, priv->address); - break; - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - case PROP_CAPABILITIES: - g_value_set_uint (value, priv->capabilities); - break; - case PROP_USABLE: - g_value_set_boolean (value, priv->usable); - break; - case PROP_CONNECTED: - g_value_set_boolean (value, priv->connected); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE ((NMBluezDevice *) object); - - switch (prop_id) { - case PROP_PATH: - /* construct-only */ - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_bluez_device_init (NMBluezDevice *self) -{ -} - -NMBluezDevice * -nm_bluez_device_new (const char *path, - const char *adapter_address, - NMSettings *settings, - int bluez_version) -{ - NMBluezDevice *self; - NMBluezDevicePrivate *priv; - const char *interface_name = NULL; - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); - g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL); - - self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, - NM_BLUEZ_DEVICE_PATH, path, - NULL); - if (!self) - return NULL; - - nm_log_dbg (LOGD_BT, "bluez[%s] create NMBluezDevice", path); - - priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - - priv->bluez_version = bluez_version; - priv->settings = g_object_ref (settings); - g_return_val_if_fail (bluez_version == 5 || (bluez_version == 4 && adapter_address), NULL); - if (adapter_address) - set_adapter_address (self, adapter_address); - - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, G_CALLBACK (cp_connection_added), self); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, G_CALLBACK (cp_connection_removed), self); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (cp_connection_updated), self); - - g_bus_get (G_BUS_TYPE_SYSTEM, - NULL, - (GAsyncReadyCallback) on_bus_acquired, - g_object_ref (self)); - - switch (priv->bluez_version) { - case 4: - interface_name = NM_BLUEZ4_DEVICE_INTERFACE; - break; - case 5: - interface_name = NM_BLUEZ5_DEVICE_INTERFACE; - break; - } - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - NM_BLUEZ_SERVICE, - priv->path, - interface_name, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - g_object_ref (self)); - return self; -} - -static void -dispose (GObject *object) -{ - NMBluezDevice *self = NM_BLUEZ_DEVICE (object); - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - NMSettingsConnection *to_delete = NULL; - - nm_clear_g_source (&priv->check_emit_usable_id); - - if (priv->pan_connection) { - /* Check whether we want to remove the created connection. If so, we take a reference - * and delete it at the end of dispose(). */ - if (NM_FLAGS_HAS (nm_settings_connection_get_flags (priv->pan_connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) - to_delete = g_object_ref (priv->pan_connection); - - priv->pan_connection = NULL; - } - -#if WITH_BLUEZ5_DUN - if (priv->b5_dun_context) { - nm_bluez5_dun_free (priv->b5_dun_context); - priv->b5_dun_context = NULL; - } -#endif - - if (priv->settings) { - g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self); - g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self); - } - - g_slist_free_full (priv->connections, g_object_unref); - priv->connections = NULL; - - if (priv->adapter5) { - g_signal_handlers_disconnect_by_func (priv->adapter5, adapter5_on_properties_changed, self); - g_clear_object (&priv->adapter5); - } - - g_clear_object (&priv->dbus_connection); - - G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); - - if (to_delete) { - nm_log_dbg (LOGD_BT, "bluez[%s] removing Bluetooth connection for NAP device: '%s' (%s)", priv->path, - nm_settings_connection_get_id (to_delete), nm_settings_connection_get_uuid (to_delete)); - nm_settings_connection_delete (to_delete, FALSE); - g_object_unref (to_delete); - } - - g_clear_object (&priv->settings); -} - -static void -finalize (GObject *object) -{ - NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE ((NMBluezDevice *) object); - - nm_log_dbg (LOGD_BT, "bluez[%s]: finalize NMBluezDevice", priv->path); - - g_free (priv->path); - g_free (priv->adapter_address); - g_free (priv->address); - g_free (priv->name); - g_free (priv->b4_iface); - - if (priv->proxy) - g_signal_handlers_disconnect_by_data (priv->proxy, object); - g_clear_object (&priv->proxy); - - G_OBJECT_CLASS (nm_bluez_device_parent_class)->finalize (object); -} - -static void -nm_bluez_device_class_init (NMBluezDeviceClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (config_class); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - obj_properties[PROP_PATH] = - g_param_spec_string (NM_BLUEZ_DEVICE_PATH, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ADDRESS] = - g_param_spec_string (NM_BLUEZ_DEVICE_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_NAME] = - g_param_spec_string (NM_BLUEZ_DEVICE_NAME, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CAPABILITIES] = - g_param_spec_uint (NM_BLUEZ_DEVICE_CAPABILITIES, "", "", - 0, G_MAXUINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_USABLE] = - g_param_spec_boolean (NM_BLUEZ_DEVICE_USABLE, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTED] = - g_param_spec_boolean (NM_BLUEZ_DEVICE_CONNECTED, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[INITIALIZED] = g_signal_new (NM_BLUEZ_DEVICE_INITIALIZED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[REMOVED] = g_signal_new (NM_BLUEZ_DEVICE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h deleted file mode 100644 index e8dd2ced..00000000 --- a/src/devices/bluetooth/nm-bluez-device.h +++ /dev/null @@ -1,84 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2014 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_BLUEZ_DEVICE_H__ -#define __NETWORKMANAGER_BLUEZ_DEVICE_H__ - -#include "nm-connection.h" - -#define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) -#define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) -#define NM_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) -#define NM_IS_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_DEVICE)) -#define NM_IS_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_DEVICE)) -#define NM_BLUEZ_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) - -/* Properties */ -#define NM_BLUEZ_DEVICE_PATH "path" -#define NM_BLUEZ_DEVICE_ADDRESS "address" -#define NM_BLUEZ_DEVICE_NAME "name" -#define NM_BLUEZ_DEVICE_CAPABILITIES "capabilities" -#define NM_BLUEZ_DEVICE_USABLE "usable" -#define NM_BLUEZ_DEVICE_CONNECTED "connected" - -/* Signals */ -#define NM_BLUEZ_DEVICE_INITIALIZED "initialized" -#define NM_BLUEZ_DEVICE_REMOVED "removed" - -typedef struct _NMBluezDevice NMBluezDevice; -typedef struct _NMBluezDeviceClass NMBluezDeviceClass; - -GType nm_bluez_device_get_type (void); - -NMBluezDevice *nm_bluez_device_new (const char *path, - const char *adapter_address, - NMSettings *settings, - int bluez_version); - -const char *nm_bluez_device_get_path (NMBluezDevice *self); - -gboolean nm_bluez_device_get_initialized (NMBluezDevice *self); - -gboolean nm_bluez_device_get_usable (NMBluezDevice *self); - -const char *nm_bluez_device_get_address (NMBluezDevice *self); - -const char *nm_bluez_device_get_name (NMBluezDevice *self); - -guint32 nm_bluez_device_get_capabilities (NMBluezDevice *self); - -gboolean nm_bluez_device_get_connected (NMBluezDevice *self); - -typedef void (*NMBluezDeviceConnectCallback) (NMBluezDevice *self, - const char *device, - GError *error, - gpointer user_data); - -void -nm_bluez_device_connect_async (NMBluezDevice *self, - NMBluetoothCapabilities connection_bt_type, - GCancellable *cancellable, - NMBluezDeviceConnectCallback callback, - gpointer callback_user_data); - -void -nm_bluez_device_disconnect (NMBluezDevice *self); - -#endif /* __NETWORKMANAGER_BLUEZ_DEVICE_H__ */ - diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index 7577ab8b..ef087d83 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -1,73 +1,185 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 - 2014 Red Hat, Inc. */ #include "nm-default.h" +#include "nm-bluez-manager.h" + #include <signal.h> #include <stdlib.h> #include <gmodule.h> +#include "nm-glib-aux/nm-dbus-aux.h" +#include "nm-glib-aux/nm-c-list.h" +#include "nm-dbus-manager.h" #include "devices/nm-device-factory.h" #include "devices/nm-device-bridge.h" #include "nm-setting-bluetooth.h" #include "settings/nm-settings.h" -#include "nm-bluez4-manager.h" -#include "nm-bluez5-manager.h" -#include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-device-bt.h" +#include "nm-manager.h" +#include "nm-bluez5-dun.h" #include "nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-std-aux/nm-dbus-compat.h" /*****************************************************************************/ -#define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) -#define NM_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManager)) -#define NM_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) -#define NM_IS_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_MANAGER)) -#define NM_IS_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_MANAGER)) -#define NM_BLUEZ_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) +#if WITH_BLUEZ5_DUN +#define _NM_BT_CAPABILITY_SUPPORTED_DUN NM_BT_CAPABILITY_DUN +#else +#define _NM_BT_CAPABILITY_SUPPORTED_DUN NM_BT_CAPABILITY_NONE +#endif +#define _NM_BT_CAPABILITY_SUPPORTED (NM_BT_CAPABILITY_NAP | _NM_BT_CAPABILITY_SUPPORTED_DUN) + +typedef struct { + const char *bdaddr; + CList lst_head; + NMBluetoothCapabilities bt_type:8; + char bdaddr_data[]; +} ConnDataHead; + +typedef struct { + NMSettingsConnection *sett_conn; + ConnDataHead *cdata_hd; + CList lst; +} ConnDataElem; typedef struct { - int bluez_version; + GCancellable *ext_cancellable; + GCancellable *int_cancellable; + NMBtVTableRegisterCallback callback; + gpointer callback_user_data; + gulong ext_cancelled_id; +} NetworkServerRegisterReqData; + +typedef struct { + GCancellable *ext_cancellable; + GCancellable *int_cancellable; + NMBluezManagerConnectCb callback; + gpointer callback_user_data; + char *device_name; + gulong ext_cancelled_id; + guint timeout_id; + guint timeout_wait_connect_id; +} DeviceConnectReqData; + +typedef struct { + const char *object_path; + + NMBluezManager *self; + /* Fields name with "d_" prefix are purely cached values from BlueZ's + * ObjectManager D-Bus interface. There is no logic whatsoever about + * them. + */ + + CList process_change_lst; + + struct { + char *address; + } d_adapter; + + struct { + char *address; + char *name; + char *adapter; + } d_device; + + struct { + char *interface; + } d_network; + + struct { + CList lst; + char *adapter_address; + NMDevice *device_br; + NetworkServerRegisterReqData *r_req_data; + } x_network_server; + + struct { + NMSettingsConnection *panu_connection; + NMDeviceBt *device_bt; + DeviceConnectReqData *c_req_data; + NMBluez5DunContext *connect_dun_context; + gulong device_bt_signal_id; + } x_device; + + /* indicate whether the D-Bus object has the particular D-Bus interface. */ + bool d_has_adapter_iface:1; + bool d_has_device_iface:1; + bool d_has_network_iface:1; + bool d_has_network_server_iface:1; + + /* cached D-Bus properties for Device1 ("d_device*"). */ + NMBluetoothCapabilities d_device_capabilities:6; + bool d_device_connected:1; + bool d_device_paired:1; + + /* cached D-Bus properties for Network1 ("d_network*"). */ + bool d_network_connected:1; + + /* cached D-Bus properties for Adapter1 ("d_adapter*"). */ + bool d_adapter_powered:1; + + /* properties related to device ("x_device*"). */ + NMBluetoothCapabilities x_device_connect_bt_type:6; + bool x_device_is_usable:1; + bool x_device_is_connected:1; + + bool x_device_panu_connection_allow_create:1; + + /* flag to remember last time when we checked wether the object + * was a suitable adapter that is usable to a device. */ + bool was_usable_adapter_for_device_before:1; + + char _object_path_intern[]; +} BzDBusObj; + +typedef struct { + NMManager *manager; NMSettings *settings; - NMBluez4Manager *manager4; - NMBluez5Manager *manager5; - guint watch_name_id; + GDBusConnection *dbus_connection; + + NMBtVTableNetworkServer vtable_network_server; + + GCancellable *name_owner_get_cancellable; + GCancellable *get_managed_objects_cancellable; + + GHashTable *bzobjs; + + char *name_owner; + + GHashTable *conn_data_heads; + GHashTable *conn_data_elems; + + CList network_server_lst_head; + + CList process_change_lst_head; + + guint name_owner_changed_id; - GDBusProxy *introspect_proxy; - GCancellable *async_cancellable; + guint managed_objects_changed_id; + + guint properties_changed_id; + + guint process_change_idle_id; + + bool settings_registered:1; } NMBluezManagerPrivate; -typedef struct { +struct _NMBluezManager { NMDeviceFactory parent; NMBluezManagerPrivate _priv; -} NMBluezManager; +}; -typedef struct { +struct _NMBluezManagerClass { NMDeviceFactoryClass parent; -} NMBluezManagerClass; - -static GType nm_bluez_manager_get_type (void); +}; G_DEFINE_TYPE (NMBluezManager, nm_bluez_manager, NM_TYPE_DEVICE_FACTORY); @@ -93,313 +205,2583 @@ nm_device_factory_create (GError **error) /*****************************************************************************/ -static void check_bluez_and_try_setup (NMBluezManager *self); +static NMBluetoothCapabilities +convert_uuids_to_capabilities (const char *const*strv) +{ + NMBluetoothCapabilities capabilities = NM_BT_CAPABILITY_NONE; + + if (strv) { + for (; strv[0]; strv++) { + gs_free char *s_part1 = NULL; + const char *str = strv[0]; + const char *s; + + s = strchr (str, '-'); + if (!s) + continue; + + s_part1 = g_strndup (str, s - str); + switch (g_ascii_strtoull (s_part1, NULL, 16)) { + case 0x1103: + capabilities |= NM_BT_CAPABILITY_DUN; + break; + case 0x1116: + capabilities |= NM_BT_CAPABILITY_NAP; + break; + default: + break; + } + } + } + + return capabilities; +} + +/*****************************************************************************/ + +static void _cleanup_for_name_owner (NMBluezManager *self); +static void _connect_disconnect (NMBluezManager *self, + BzDBusObj *bzobj, + const char *reason); +static gboolean _bzobjs_network_server_is_usable (const BzDBusObj *bzobj, + gboolean require_powered); +static gboolean _bzobjs_is_dead (const BzDBusObj *bzobj); +static gboolean _bzobjs_device_is_usable (const BzDBusObj *bzobj, + BzDBusObj **out_adapter_bzobj, + gboolean *out_create_panu_connection); +static gboolean _bzobjs_adapter_is_usable_for_device (const BzDBusObj *bzobj); +static ConnDataHead *_conn_track_find_head (NMBluezManager *self, + NMBluetoothCapabilities bt_type, + const char *bdaddr); +static void _process_change_idle_schedule (NMBluezManager *self, + BzDBusObj *bzobj); +static void _network_server_unregister_bridge (NMBluezManager *self, + BzDBusObj *bzobj, + const char *reason); +static gboolean _connect_timeout_wait_connected_cb (gpointer user_data); /*****************************************************************************/ -struct AsyncData { +static void +_dbus_call_complete_cb_nop (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + /* we don't do anything at all. The only reason to register this + * callback is so that GDBusConnection keeps the cancellable alive + * long enough until the call completes. + * + * Note that this cancellable in turn is registered via + * nm_shutdown_wait_obj_register_*(), to block shutdown until + * we are done. */ +} + +/*****************************************************************************/ + +static void +_network_server_register_req_data_complete (NetworkServerRegisterReqData *r_req_data, + GError *error) +{ + nm_clear_g_signal_handler (r_req_data->ext_cancellable, &r_req_data->ext_cancelled_id); + + nm_clear_g_cancellable (&r_req_data->int_cancellable); + + if (r_req_data->callback) { + gs_free_error GError *error_cancelled = NULL; + + if (g_cancellable_set_error_if_cancelled (r_req_data->ext_cancellable, &error_cancelled)) + error = error_cancelled; + + r_req_data->callback (error, r_req_data->callback_user_data); + } + + g_object_unref (r_req_data->ext_cancellable); + nm_g_slice_free (r_req_data); +} + +static void +_device_connect_req_data_complete (DeviceConnectReqData *c_req_data, + NMBluezManager *self, + const char *device_name, + GError *error) +{ + nm_assert ((!!device_name) != (!!error)); + + nm_clear_g_signal_handler (c_req_data->ext_cancellable, &c_req_data->ext_cancelled_id); + + nm_clear_g_cancellable (&c_req_data->int_cancellable); + nm_clear_g_source (&c_req_data->timeout_id); + nm_clear_g_source (&c_req_data->timeout_wait_connect_id); + + if (c_req_data->callback) { + gs_free_error GError *error_cancelled = NULL; + + if (g_cancellable_set_error_if_cancelled (c_req_data->ext_cancellable, &error_cancelled)) { + error = error_cancelled; + device_name = NULL; + } + + c_req_data->callback (self, TRUE, device_name, error, c_req_data->callback_user_data); + } + + g_object_unref (c_req_data->ext_cancellable); + nm_clear_g_free (&c_req_data->device_name); + nm_g_slice_free (c_req_data); +} + +/*****************************************************************************/ + +static BzDBusObj * +_bz_dbus_obj_new (NMBluezManager *self, + const char *object_path) +{ + BzDBusObj *bzobj; + gsize l; + + nm_assert (NM_IS_BLUEZ_MANAGER (self)); + + l = strlen (object_path) + 1; + + bzobj = g_malloc (sizeof (BzDBusObj) + l); + *bzobj = (BzDBusObj) { + .object_path = bzobj->_object_path_intern, + .self = self, + .x_network_server.lst = C_LIST_INIT (bzobj->x_network_server.lst), + .process_change_lst = C_LIST_INIT (bzobj->process_change_lst), + .x_device_panu_connection_allow_create = TRUE, + }; + memcpy (bzobj->_object_path_intern, object_path, l); + + return bzobj; +} + +static void +_bz_dbus_obj_free (BzDBusObj *bzobj) +{ + nm_assert (bzobj); + nm_assert (NM_IS_BLUEZ_MANAGER (bzobj->self)); + nm_assert (!bzobj->x_network_server.device_br); + nm_assert (!bzobj->x_network_server.r_req_data); + nm_assert (!bzobj->x_device.c_req_data); + + c_list_unlink_stale (&bzobj->process_change_lst); + c_list_unlink_stale (&bzobj->x_network_server.lst); + g_free (bzobj->x_network_server.adapter_address); + g_free (bzobj->d_adapter.address); + g_free (bzobj->d_network.interface); + g_free (bzobj->d_device.address); + g_free (bzobj->d_device.name); + g_free (bzobj->d_device.adapter); + g_free (bzobj); +} + +/*****************************************************************************/ + +static const char * +_bzobj_to_string (const BzDBusObj *bzobj, char *buf, gsize len) +{ + char *buf0 = buf; + const char *prefix = ""; + gboolean device_is_usable; + gboolean create_panu_connection = FALSE; + gboolean network_server_is_usable; + char sbuf_cap[100]; + + if (len > 0) + buf[0] = '\0'; + + if (bzobj->d_has_adapter_iface) { + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + nm_utils_strbuf_append_str (&buf, &len, "Adapter1 {"); + if (bzobj->d_adapter.address) { + nm_utils_strbuf_append (&buf, &len, " d.address: \"%s\"", bzobj->d_adapter.address); + if (bzobj->d_adapter_powered) + nm_utils_strbuf_append_str (&buf, &len, ","); + } + if (bzobj->d_adapter_powered) + nm_utils_strbuf_append (&buf, &len, " d.powered: 1"); + nm_utils_strbuf_append_str (&buf, &len, " }"); + } + + if (bzobj->d_has_device_iface) { + const char *prefix1 = ""; + + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + nm_utils_strbuf_append_str (&buf, &len, "Device1 {"); + if (bzobj->d_device.address) { + nm_utils_strbuf_append (&buf, &len, "%s d.address: \"%s\"", prefix1, bzobj->d_device.address); + prefix1 = ","; + } + if (bzobj->d_device.name) { + nm_utils_strbuf_append (&buf, &len, "%s d.name: \"%s\"", prefix1, bzobj->d_device.name); + prefix1 = ","; + } + if (bzobj->d_device.adapter) { + nm_utils_strbuf_append (&buf, &len, "%s d.adapter: \"%s\"", prefix1, bzobj->d_device.adapter); + prefix1 = ","; + } + if (bzobj->d_device_capabilities != NM_BT_CAPABILITY_NONE) { + nm_utils_strbuf_append (&buf, &len, "%s d.capabilities: \"%s\"", + prefix1, + nm_bluetooth_capability_to_string (bzobj->d_device_capabilities, sbuf_cap, sizeof (sbuf_cap))); + prefix1 = ","; + } + if (bzobj->d_device_connected) { + nm_utils_strbuf_append (&buf, &len, "%s d.connected: 1", prefix1); + prefix1 = ","; + } + if (bzobj->d_device_paired) { + nm_utils_strbuf_append (&buf, &len, "%s d.paired: 1", prefix1); + prefix1 = ","; + } + nm_utils_strbuf_append_str (&buf, &len, " }"); + } + + network_server_is_usable = _bzobjs_network_server_is_usable (bzobj, TRUE); + + if ( bzobj->d_has_network_server_iface + || network_server_is_usable != (!c_list_is_empty (&bzobj->x_network_server.lst)) + || !c_list_is_empty (&bzobj->x_network_server.lst) + || !nm_streq0 (bzobj->d_has_adapter_iface ? bzobj->d_adapter.address : NULL, bzobj->x_network_server.adapter_address) + || bzobj->x_network_server.device_br + || bzobj->x_network_server.r_req_data) { + + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + + nm_utils_strbuf_append (&buf, &len, "NetworkServer1 { "); + + if (!bzobj->d_has_network_server_iface) + nm_utils_strbuf_append (&buf, &len, " has-d-iface: 0, "); + + if (network_server_is_usable != (!c_list_is_empty (&bzobj->x_network_server.lst))) + nm_utils_strbuf_append (&buf, &len, "usable: %d, used: %d", !!network_server_is_usable, !network_server_is_usable); + else if (network_server_is_usable) + nm_utils_strbuf_append (&buf, &len, "used: 1"); + else + nm_utils_strbuf_append (&buf, &len, "usable: 0"); + + if (!nm_streq0 (bzobj->d_has_adapter_iface ? bzobj->d_adapter.address : NULL, bzobj->x_network_server.adapter_address)) { + if (bzobj->x_network_server.adapter_address) + nm_utils_strbuf_append (&buf, &len, ", adapter-address: \"%s\"", bzobj->x_network_server.adapter_address); + else + nm_utils_strbuf_append (&buf, &len, ", adapter-address: <NULL>"); + } + + if (bzobj->x_network_server.device_br) + nm_utils_strbuf_append (&buf, &len, ", bridge-device: 1"); + + if (bzobj->x_network_server.r_req_data) + nm_utils_strbuf_append (&buf, &len, ", register-in-progress: 1"); + + nm_utils_strbuf_append_str (&buf, &len, " }"); + } + + device_is_usable = _bzobjs_device_is_usable (bzobj, NULL, &create_panu_connection); + + if ( bzobj->d_has_network_iface + || bzobj->d_network.interface + || bzobj->d_network_connected + || create_panu_connection + || bzobj->x_device.panu_connection + || device_is_usable != bzobj->x_device_is_usable + || bzobj->x_device.device_bt + || bzobj->x_device_connect_bt_type != NM_BT_CAPABILITY_NONE + || bzobj->x_device.connect_dun_context + || bzobj->x_device.c_req_data + || bzobj->x_device_is_connected != bzobj->d_network_connected) { + + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + nm_utils_strbuf_append_str (&buf, &len, "Network1 {"); + if (bzobj->d_network.interface) + nm_utils_strbuf_append (&buf, &len, " d.interface: \"%s\", ", bzobj->d_network.interface); + if (bzobj->d_network_connected) + nm_utils_strbuf_append (&buf, &len, " d.connected: %d, ", !!bzobj->d_network_connected); + if (!bzobj->d_has_network_iface) + nm_utils_strbuf_append (&buf, &len, " has-d-iface: 0, "); + if (device_is_usable != bzobj->x_device_is_usable) + nm_utils_strbuf_append (&buf, &len, " usable: %d, used: %d", !!device_is_usable, !device_is_usable); + else if (device_is_usable) + nm_utils_strbuf_append (&buf, &len, " used: 1"); + else + nm_utils_strbuf_append (&buf, &len, " usable: 0"); + + if (create_panu_connection) + nm_utils_strbuf_append (&buf, &len, ", create-panu-connection: 1"); + + if (bzobj->x_device.panu_connection) + nm_utils_strbuf_append (&buf, &len, ", has-panu-connection: 1"); + + if (bzobj->x_device.device_bt) + nm_utils_strbuf_append (&buf, &len, ", has-device: 1"); + + if ( bzobj->x_device_connect_bt_type != NM_BT_CAPABILITY_NONE + || bzobj->x_device.connect_dun_context) { + nm_utils_strbuf_append (&buf, &len, ", connect: %s%s", + nm_bluetooth_capability_to_string (bzobj->x_device_connect_bt_type, sbuf_cap, sizeof (sbuf_cap)), + bzobj->x_device.connect_dun_context ? ",with-dun-context" : ""); + } + + if (bzobj->x_device.c_req_data) + nm_utils_strbuf_append (&buf, &len, ", connecting: 1"); + + if (bzobj->x_device_is_connected != bzobj->d_network_connected) + nm_utils_strbuf_append (&buf, &len, ", connected: %d", !!bzobj->x_device_is_connected); + + nm_utils_strbuf_append_str (&buf, &len, " }"); + } + + if (_bzobjs_is_dead (bzobj)) { + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + nm_utils_strbuf_append_str (&buf, &len, "dead: 1"); + } + + if (!c_list_is_empty (&bzobj->process_change_lst)) { + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + nm_utils_strbuf_append (&buf, &len, "change-pending-on-idle: 1"); + } + + if (_bzobjs_adapter_is_usable_for_device (bzobj) != bzobj->was_usable_adapter_for_device_before) { + nm_utils_strbuf_append_str (&buf, &len, prefix); + prefix = ", "; + nm_utils_strbuf_append (&buf, &len, "change-usable-adapter-for-device: 1"); + } + + return buf0; +} + +#define _LOG_bzobj(bzobj, context) \ + G_STMT_START { \ + const BzDBusObj *const _bzobj = (bzobj); \ + char _buf[500]; \ + \ + _LOGT ("change %-21s %s : { %s }", \ + (context), \ + _bzobj->object_path, \ + _bzobj_to_string (_bzobj, _buf, sizeof (_buf))); \ + } G_STMT_END + +static gboolean +_bzobjs_is_dead (const BzDBusObj *bzobj) +{ + return !bzobj->d_has_adapter_iface + && !bzobj->d_has_device_iface + && !bzobj->d_has_network_iface + && !bzobj->d_has_network_server_iface + && c_list_is_empty (&bzobj->process_change_lst); +} + +static BzDBusObj * +_bzobjs_get (NMBluezManager *self, const char *object_path) +{ + return g_hash_table_lookup (NM_BLUEZ_MANAGER_GET_PRIVATE (self)->bzobjs, &object_path); +} + +static BzDBusObj * +_bzobjs_add (NMBluezManager *self, + const char *object_path) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + BzDBusObj *bzobj; + + bzobj = _bz_dbus_obj_new (self, object_path); + if (!g_hash_table_add (priv->bzobjs, bzobj)) + nm_assert_not_reached (); + return bzobj; +} + +static void +_bzobjs_del (BzDBusObj *bzobj) +{ + nm_assert (bzobj); + nm_assert (bzobj == _bzobjs_get (bzobj->self, bzobj->object_path)); + + if (!g_hash_table_remove (NM_BLUEZ_MANAGER_GET_PRIVATE (bzobj->self)->bzobjs, bzobj)) + nm_assert_not_reached (); +} + +static void +_bzobjs_del_if_dead (BzDBusObj *bzobj) +{ + if (_bzobjs_is_dead (bzobj)) + _bzobjs_del (bzobj); +} + +static BzDBusObj * +_bzobjs_init (NMBluezManager *self, BzDBusObj **inout, const char *object_path) +{ + nm_assert (NM_IS_BLUEZ_MANAGER (self)); + nm_assert (object_path); + nm_assert (inout); + + if (!*inout) { + *inout = _bzobjs_get (self, object_path); + if (!*inout) + *inout = _bzobjs_add (self, object_path); + } + + nm_assert (nm_streq ((*inout)->object_path, object_path)); + nm_assert (*inout == _bzobjs_get (self, object_path)); + return *inout; +} + +static gboolean +_bzobjs_adapter_is_usable_for_device (const BzDBusObj *bzobj) +{ + return bzobj->d_has_adapter_iface + && bzobj->d_adapter.address + && bzobj->d_adapter_powered; +} + +static gboolean +_bzobjs_device_is_usable (const BzDBusObj *bzobj, + BzDBusObj **out_adapter_bzobj, + gboolean *out_create_panu_connection) +{ NMBluezManager *self; - GCancellable *async_cancellable; -}; + NMBluezManagerPrivate *priv; + gboolean usable_dun = FALSE; + gboolean usable_nap = FALSE; + BzDBusObj *bzobj_adapter; + gboolean create_panu_connection = FALSE; + + if ( !bzobj->d_has_device_iface + || !NM_FLAGS_ANY ((NMBluetoothCapabilities) bzobj->d_device_capabilities, _NM_BT_CAPABILITY_SUPPORTED) + || !bzobj->d_device.name + || !bzobj->d_device.address + || !bzobj->d_device_paired + || !bzobj->d_device.adapter) + goto out_unusable; + + self = bzobj->self; + + priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + if (!priv->settings_registered) + goto out_unusable; + + bzobj_adapter = _bzobjs_get (self, bzobj->d_device.adapter); + if ( !bzobj_adapter + || !_bzobjs_adapter_is_usable_for_device (bzobj_adapter)) + goto out_unusable; + +#if WITH_BLUEZ5_DUN + if (NM_FLAGS_HAS (bzobj->d_device_capabilities, NM_BT_CAPABILITY_DUN)) { + if (_conn_track_find_head (self, NM_BT_CAPABILITY_DUN, bzobj->d_device.address)) + usable_dun = TRUE; + } +#endif + + if (NM_FLAGS_HAS (bzobj->d_device_capabilities, NM_BT_CAPABILITY_NAP)) { + if (!bzobj->d_has_network_iface) + usable_nap = FALSE; + else if (_conn_track_find_head (self, NM_BT_CAPABILITY_NAP, bzobj->d_device.address)) + usable_nap = TRUE; + else if (bzobj->x_device_panu_connection_allow_create) { + /* We didn't yet try to create a connection. Presume we are going to create + * it when the time comes... */ + usable_nap = TRUE; + create_panu_connection = TRUE; + } + } + + if ( !usable_dun + && !usable_nap) { + if ( bzobj->x_device.device_bt + && nm_device_get_state (NM_DEVICE (bzobj->x_device.device_bt)) > NM_DEVICE_STATE_DISCONNECTED) { + /* The device is still activated... the absence of a profile does not + * render it unusable (yet). But since there is no more profile, the + * device is probably about to disconnect. */ + } else + goto out_unusable; + } + + NM_SET_OUT (out_create_panu_connection, create_panu_connection); + NM_SET_OUT (out_adapter_bzobj, bzobj_adapter); + return TRUE; -static struct AsyncData * -async_data_pack (NMBluezManager *self) +out_unusable: + NM_SET_OUT (out_create_panu_connection, FALSE); + NM_SET_OUT (out_adapter_bzobj, NULL); + return FALSE; +} + +static gboolean +_bzobjs_device_is_connected (const BzDBusObj *bzobj) { - struct AsyncData *data = g_new (struct AsyncData, 1); + nm_assert (_bzobjs_device_is_usable (bzobj, NULL, NULL)); + + if ( !bzobj->d_has_device_iface + || !bzobj->d_device_connected) + return FALSE; + + if ( bzobj->d_has_network_iface + && bzobj->d_network_connected) + return TRUE; + if (bzobj->x_device.connect_dun_context) { + /* As long as we have a dun-context, we consider it connected. + * + * We require NMDeviceBt to try to connect to the modem, and if that fails, + * it will disconnect. */ + return TRUE; + } + return FALSE; +} - data->self = self; - data->async_cancellable = g_object_ref (NM_BLUEZ_MANAGER_GET_PRIVATE (self)->async_cancellable); - return data; +static gboolean +_bzobjs_network_server_is_usable (const BzDBusObj *bzobj, + gboolean require_powered) +{ + return bzobj->d_has_network_server_iface + && bzobj->d_has_adapter_iface + && bzobj->d_adapter.address + && ( !require_powered + || bzobj->d_adapter_powered); } -static NMBluezManager * -async_data_unpack (struct AsyncData *async_data) +/*****************************************************************************/ + +static ConnDataHead * +_conn_data_head_new (NMBluetoothCapabilities bt_type, + const char *bdaddr) { - NMBluezManager *self = g_cancellable_is_cancelled (async_data->async_cancellable) - ? NULL : async_data->self; + ConnDataHead *cdata_hd; + gsize l; - g_object_unref (async_data->async_cancellable); - g_free (async_data); - return self; + nm_assert (NM_IN_SET (bt_type, NM_BT_CAPABILITY_DUN, + NM_BT_CAPABILITY_NAP)); + nm_assert (bdaddr); + + l = strlen (bdaddr) + 1; + cdata_hd = g_malloc (sizeof (ConnDataHead) + l); + *cdata_hd = (ConnDataHead) { + .bdaddr = cdata_hd->bdaddr_data, + .lst_head = C_LIST_INIT (cdata_hd->lst_head), + .bt_type = bt_type, + }; + memcpy (cdata_hd->bdaddr_data, bdaddr, l); + + nm_assert (cdata_hd->bt_type == bt_type); + + return cdata_hd; +} + +static guint +_conn_data_head_hash (gconstpointer ptr) +{ + const ConnDataHead *cdata_hd = ptr; + NMHashState h; + + nm_hash_init (&h, 520317467u); + nm_hash_update_val (&h, (NMBluetoothCapabilities) cdata_hd->bt_type); + nm_hash_update_str (&h, cdata_hd->bdaddr); + return nm_hash_complete (&h); +} + +static gboolean +_conn_data_head_equal (gconstpointer a, gconstpointer b) +{ + const ConnDataHead *cdata_hd_a = a; + const ConnDataHead *cdata_hd_b = b; + + return cdata_hd_a->bt_type == cdata_hd_b->bt_type + && nm_streq (cdata_hd_a->bdaddr, cdata_hd_b->bdaddr); +} + +static ConnDataHead * +_conn_track_find_head (NMBluezManager *self, + NMBluetoothCapabilities bt_type, + const char *bdaddr) +{ + ConnDataHead cdata_hd = { + .bt_type = bt_type, + .bdaddr = bdaddr, + }; + + return g_hash_table_lookup (NM_BLUEZ_MANAGER_GET_PRIVATE (self)->conn_data_heads, &cdata_hd); +} + +static ConnDataElem * +_conn_track_find_elem (NMBluezManager *self, + NMSettingsConnection *sett_conn) +{ + G_STATIC_ASSERT (G_STRUCT_OFFSET (ConnDataElem, sett_conn) == 0); + + return g_hash_table_lookup (NM_BLUEZ_MANAGER_GET_PRIVATE (self)->conn_data_elems, &sett_conn); +} + +static gboolean +_conn_track_is_relevant_connection (NMConnection *connection, + NMBluetoothCapabilities *out_bt_type, + const char **out_bdaddr) +{ + NMSettingBluetooth *s_bt; + NMBluetoothCapabilities bt_type; + const char *bdaddr; + const char *b_type; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) + return FALSE; + + bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); + if (!bdaddr) + return FALSE; + + b_type = nm_setting_bluetooth_get_connection_type (s_bt); + + if (nm_streq (b_type, NM_SETTING_BLUETOOTH_TYPE_DUN)) + bt_type = NM_BT_CAPABILITY_DUN; + else if (nm_streq (b_type, NM_SETTING_BLUETOOTH_TYPE_PANU)) + bt_type = NM_BT_CAPABILITY_NAP; + else + return FALSE; + + NM_SET_OUT (out_bt_type, bt_type); + NM_SET_OUT (out_bdaddr, bdaddr); + return TRUE; +} + +static gboolean +_conn_track_is_relevant_sett_conn (NMSettingsConnection *sett_conn, + NMBluetoothCapabilities *out_bt_type, + const char **out_bdaddr) +{ + NMConnection *connection; + + connection = nm_settings_connection_get_connection (sett_conn); + if (!connection) + return FALSE; + + return _conn_track_is_relevant_connection (connection, out_bt_type, out_bdaddr); +} + +static gboolean +_conn_track_is_relevant_for_sett_conn (NMSettingsConnection *sett_conn, + NMBluetoothCapabilities bt_type, + const char *bdaddr) +{ + NMBluetoothCapabilities x_bt_type; + const char *x_bdaddr; + + return bdaddr + && _conn_track_is_relevant_sett_conn (sett_conn, &x_bt_type, &x_bdaddr) + && x_bt_type == bt_type + && nm_streq (x_bdaddr, bdaddr); +} + +static void +_conn_track_schedule_notify (NMBluezManager *self, + NMBluetoothCapabilities bt_type, + const char *bdaddr) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + BzDBusObj *bzobj; + + g_hash_table_iter_init (&iter, priv->bzobjs); + while (g_hash_table_iter_next (&iter, (gpointer *) &bzobj, NULL)) { + gboolean device_is_usable; + + device_is_usable = _bzobjs_device_is_usable (bzobj, NULL, NULL); + if (bzobj->x_device_is_usable != device_is_usable) + _process_change_idle_schedule (self, bzobj); + } } -/** - * Cancel any current attempt to detect the version and cleanup - * the related fields. - **/ static void -cleanup_checking (NMBluezManager *self, gboolean do_unwatch_name) +_conn_track_update (NMBluezManager *self, + NMSettingsConnection *sett_conn, + gboolean track, + gboolean *out_changed, + gboolean *out_changed_usable, + ConnDataElem **out_conn_data_elem) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + ConnDataHead *cdata_hd; + ConnDataElem *cdata_el; + ConnDataElem *cdata_el_remove = NULL; + NMBluetoothCapabilities bt_type; + const char *bdaddr; + gboolean changed = FALSE; + gboolean changed_usable = FALSE; + char sbuf_cap[100]; + + nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn)); + + cdata_el = _conn_track_find_elem (self, sett_conn); + + if (track) + track = _conn_track_is_relevant_sett_conn (sett_conn, &bt_type, &bdaddr); - nm_clear_g_cancellable (&priv->async_cancellable); + if (!track) { + cdata_el_remove = g_steal_pointer (&cdata_el); + goto out_remove; + } + + if (cdata_el) { + cdata_hd = cdata_el->cdata_hd; + if ( cdata_hd->bt_type != bt_type + || !nm_streq (cdata_hd->bdaddr, bdaddr)) + cdata_el_remove = g_steal_pointer (&cdata_el); + } + + if (!cdata_el) { + _LOGT ("connecton: track for %s, %s: %s (%s)", + nm_bluetooth_capability_to_string (bt_type, sbuf_cap, sizeof (sbuf_cap)), + bdaddr, + nm_settings_connection_get_uuid (sett_conn), + nm_settings_connection_get_id (sett_conn)); + changed = TRUE; + cdata_hd = _conn_track_find_head (self, bt_type, bdaddr); + if (!cdata_hd) { + changed_usable = TRUE; + cdata_hd = _conn_data_head_new (bt_type, bdaddr); + if (!g_hash_table_add (priv->conn_data_heads, cdata_hd)) + nm_assert_not_reached (); + _conn_track_schedule_notify (self, bt_type, bdaddr); + } + cdata_el = g_slice_new (ConnDataElem); + cdata_el->sett_conn = sett_conn; + cdata_el->cdata_hd = cdata_hd; + c_list_link_tail (&cdata_hd->lst_head, &cdata_el->lst); + if (!g_hash_table_add (priv->conn_data_elems, cdata_el)) + nm_assert_not_reached (); + } - g_clear_object (&priv->introspect_proxy); +out_remove: + if (cdata_el_remove) { + GHashTableIter iter; + BzDBusObj *bzobj; + + _LOGT ("connecton: untrack for %s, %s: %s (%s)", + nm_bluetooth_capability_to_string (cdata_el_remove->cdata_hd->bt_type, sbuf_cap, sizeof (sbuf_cap)), + cdata_el_remove->cdata_hd->bdaddr, + nm_settings_connection_get_uuid (sett_conn), + nm_settings_connection_get_id (sett_conn)); + + g_hash_table_iter_init (&iter, priv->bzobjs); + while (g_hash_table_iter_next (&iter, (gpointer *) &bzobj, NULL)) { + if (bzobj->x_device.panu_connection == sett_conn) + bzobj->x_device.panu_connection = NULL; + } - if (do_unwatch_name && priv->watch_name_id) { - g_bus_unwatch_name (priv->watch_name_id); - priv->watch_name_id = 0; + changed = TRUE; + cdata_hd = cdata_el_remove->cdata_hd; + c_list_unlink_stale (&cdata_el_remove->lst); + if (!g_hash_table_remove (priv->conn_data_elems, cdata_el_remove)) + nm_assert_not_reached (); + if (c_list_is_empty (&cdata_hd->lst_head)) { + changed_usable = TRUE; + _conn_track_schedule_notify (self, cdata_hd->bt_type, cdata_hd->bdaddr); + if (!g_hash_table_remove (priv->conn_data_heads, cdata_hd)) + nm_assert_not_reached (); + } } + + NM_SET_OUT (out_changed, changed); + NM_SET_OUT (out_changed_usable, changed_usable); + NM_SET_OUT (out_conn_data_elem, cdata_el); +} + +/*****************************************************************************/ + +static void +cp_connection_added (NMSettings *settings, + NMSettingsConnection *sett_conn, + NMBluezManager *self) +{ + _conn_track_update (self, sett_conn, TRUE, NULL, NULL, NULL); } static void -manager_bdaddr_added_cb (GObject *manager, - NMBluezDevice *bt_device, - const char *bdaddr, - const char *name, - const char *object_path, - guint32 capabilities, - gpointer user_data) +cp_connection_updated (NMSettings *settings, + NMSettingsConnection *sett_conn, + guint update_reason_u, + NMBluezManager *self) { - NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); - NMDevice *device; - gboolean has_dun = (capabilities & NM_BT_CAPABILITY_DUN); - gboolean has_nap = (capabilities & NM_BT_CAPABILITY_NAP); + _conn_track_update (self, sett_conn, TRUE, NULL, NULL, NULL); +} - g_return_if_fail (bdaddr != NULL); - g_return_if_fail (name != NULL); - g_return_if_fail (object_path != NULL); - g_return_if_fail (capabilities != NM_BT_CAPABILITY_NONE); - g_return_if_fail (NM_IS_BLUEZ_DEVICE (bt_device)); +static void +cp_connection_removed (NMSettings *settings, + NMSettingsConnection *sett_conn, + NMBluezManager *self) +{ + _conn_track_update (self, sett_conn, FALSE, NULL, NULL, NULL); +} + +/*****************************************************************************/ - device = nm_device_bt_new (bt_device, object_path, bdaddr, name, capabilities); - if (!device) +static NMBluezManager * +_network_server_get_bluez_manager (const NMBtVTableNetworkServer *vtable_network_server) +{ + NMBluezManager *self; + + self = (NMBluezManager *) (((char *) vtable_network_server) - G_STRUCT_OFFSET (NMBluezManager, _priv.vtable_network_server)); + + g_return_val_if_fail (NM_IS_BLUEZ_MANAGER (self), NULL); + + return self; +} + +static BzDBusObj * +_network_server_find_has_device (NMBluezManagerPrivate *priv, + NMDevice *device) +{ + BzDBusObj *bzobj; + + c_list_for_each_entry (bzobj, &priv->network_server_lst_head, x_network_server.lst) { + if (bzobj->x_network_server.device_br == device) + return bzobj; + } + return NULL; +} + +static BzDBusObj * +_network_server_find_available (NMBluezManagerPrivate *priv, + const char *addr, + NMDevice *device_accept_busy) +{ + BzDBusObj *bzobj; + + c_list_for_each_entry (bzobj, &priv->network_server_lst_head, x_network_server.lst) { + if (bzobj->x_network_server.device_br) { + if (bzobj->x_network_server.device_br != device_accept_busy) + continue; + } + if ( addr + && !nm_streq (addr, bzobj->d_adapter.address)) + continue; + nm_assert (!bzobj->x_network_server.r_req_data); + return bzobj; + } + return NULL; +} + +static gboolean +_network_server_vt_is_available (const NMBtVTableNetworkServer *vtable, + const char *addr, + NMDevice *device_accept_busy) +{ + NMBluezManager *self = _network_server_get_bluez_manager (vtable); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + return !!_network_server_find_available (priv, addr, device_accept_busy); +} + +static void +_network_server_register_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + BzDBusObj *bzobj; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) return; - _LOGI ("BT device %s (%s) added (%s%s%s)", - name, - bdaddr, - has_dun ? "DUN" : "", - has_dun && has_nap ? " " : "", - has_nap ? "NAP" : ""); - g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); - g_object_unref (device); + bzobj = user_data; + + if (!ret) { + _LOGT ("NAP: [%s]: registering failed: %s", bzobj->object_path, error->message); + } else + _LOGT ("NAP: [%s]: registration successful", bzobj->object_path); + + g_clear_object (&bzobj->x_network_server.r_req_data->int_cancellable); + _network_server_register_req_data_complete (g_steal_pointer (&bzobj->x_network_server.r_req_data), error); +} + +static void +_network_server_register_cancelled_cb (GCancellable *cancellable, + BzDBusObj *bzobj) +{ + _network_server_unregister_bridge (bzobj->self, bzobj, "registration cancelled"); +} + +static gboolean +_network_server_vt_register_bridge (const NMBtVTableNetworkServer *vtable, + const char *addr, + NMDevice *device, + GCancellable *cancellable, + NMBtVTableRegisterCallback callback, + gpointer callback_user_data, + GError **error) +{ + NMBluezManager *self = _network_server_get_bluez_manager (vtable); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + NetworkServerRegisterReqData *r_req_data; + BzDBusObj *bzobj; + const char *ifname; + + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE); + + nm_assert (!g_cancellable_is_cancelled (cancellable)); + nm_assert (!_network_server_find_has_device (priv, device)); + + ifname = nm_device_get_iface (device); + g_return_val_if_fail (ifname, FALSE); + + g_return_val_if_fail (ifname, FALSE); + + bzobj = _network_server_find_available (priv, addr, NULL); + if (!bzobj) { + /* The device checked that a network server is available, before + * starting the activation, but for some reason it no longer is. + * Indicate that the activation should not proceed. */ + if (addr) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "adapter %s is not available for %s", + addr, ifname); + } else { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "no adapter available for %s", + ifname); + } + return FALSE; + } + + _LOGD ("NAP: [%s]: registering \"%s\" on adapter %s", + bzobj->object_path, + ifname, + bzobj->d_adapter.address); + + r_req_data = g_slice_new (NetworkServerRegisterReqData); + *r_req_data = (NetworkServerRegisterReqData) { + .int_cancellable = g_cancellable_new (), + .ext_cancellable = g_object_ref (cancellable), + .callback = callback, + .callback_user_data = callback_user_data, + .ext_cancelled_id = g_signal_connect (cancellable, + "cancelled", + G_CALLBACK (_network_server_register_cancelled_cb), + bzobj), + }; + + bzobj->x_network_server.device_br = g_object_ref (device); + bzobj->x_network_server.r_req_data = r_req_data; + + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + bzobj->object_path, + NM_BLUEZ5_NETWORK_SERVER_INTERFACE, + "Register", + g_variant_new ("(ss)", + BLUETOOTH_CONNECT_NAP, + ifname), + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + bzobj->x_network_server.r_req_data->int_cancellable, + _network_server_register_cb, + bzobj); + return TRUE; +} + +static void +_network_server_unregister_bridge_complete_on_idle_cb (gpointer user_data, + GCancellable *cancellable) +{ + gs_free_error GError *error = NULL; + gs_free char *reason = NULL; + NetworkServerRegisterReqData *r_req_data; + + nm_utils_user_data_unpack (user_data, &r_req_data, &reason); + + nm_utils_error_set (&error, NM_UTILS_ERROR_UNKNOWN, + "registration was aborted due to %s", + reason); + _network_server_register_req_data_complete (r_req_data, error); } static void -manager_network_server_added_cb (GObject *manager, - gpointer user_data) +_network_server_unregister_bridge (NMBluezManager *self, + BzDBusObj *bzobj, + const char *reason) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + _nm_unused gs_unref_object NMDevice *device = NULL; + NetworkServerRegisterReqData *r_req_data; + + nm_assert (NM_IS_DEVICE (bzobj->x_network_server.device_br)); + + _LOGD ("NAP: [%s]: unregistering \"%s\" (%s)", + bzobj->object_path, + nm_device_get_iface (bzobj->x_network_server.device_br), + reason); + + device = g_steal_pointer (&bzobj->x_network_server.device_br); + + r_req_data = g_steal_pointer (&bzobj->x_network_server.r_req_data); + + if (priv->name_owner) { + gs_unref_object GCancellable *cancellable = NULL; + + cancellable = g_cancellable_new (); + + nm_shutdown_wait_obj_register_cancellable_full (cancellable, + g_strdup_printf ("bt-unregister-nap[%s]", bzobj->object_path), + TRUE); + + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + bzobj->object_path, + NM_BLUEZ5_NETWORK_SERVER_INTERFACE, + "Unregister", + g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + cancellable, + _dbus_call_complete_cb_nop, + NULL); + } + + if (r_req_data) { + nm_clear_g_cancellable (&r_req_data->int_cancellable); + nm_utils_invoke_on_idle (_network_server_unregister_bridge_complete_on_idle_cb, + nm_utils_user_data_pack (r_req_data, g_strdup (reason)), + r_req_data->ext_cancellable); + } + + _nm_device_bridge_notify_unregister_bt_nap (device, reason); +} + +static gboolean +_network_server_vt_unregister_bridge (const NMBtVTableNetworkServer *vtable, + NMDevice *device) { - nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (user_data), NULL); + NMBluezManager *self = _network_server_get_bluez_manager (vtable); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + BzDBusObj *bzobj; + + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + bzobj = _network_server_find_has_device (priv, device); + if (bzobj) + _network_server_unregister_bridge (self, bzobj, "disconnecting"); + + return TRUE; } static void -setup_version_number (NMBluezManager *self, int bluez_version) +_network_server_process_change (BzDBusObj *bzobj, + gboolean *out_emit_device_availability_changed) { + NMBluezManager *self = bzobj->self; NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gboolean network_server_is_usable; + gboolean emit_device_availability_changed = FALSE; + + network_server_is_usable = _bzobjs_network_server_is_usable (bzobj, TRUE); - g_return_if_fail (!priv->bluez_version); + if (!network_server_is_usable) { - _LOGI ("use BlueZ version %d", bluez_version); + if (!c_list_is_empty (&bzobj->x_network_server.lst)) { + emit_device_availability_changed = TRUE; + c_list_unlink (&bzobj->x_network_server.lst); + } - priv->bluez_version = bluez_version; + nm_clear_g_free (&bzobj->x_network_server.adapter_address); + + if (bzobj->x_network_server.device_br) { + _network_server_unregister_bridge (self, + bzobj, + _bzobjs_network_server_is_usable (bzobj, FALSE) + ? "adapter disabled" + : "adapter disappeared"); + } + + } else { + + if (!nm_streq0 (bzobj->x_network_server.adapter_address, bzobj->d_adapter.address)) { + emit_device_availability_changed = TRUE; + g_free (bzobj->x_network_server.adapter_address); + bzobj->x_network_server.adapter_address = g_strdup (bzobj->d_adapter.address); + } - /* Just detected the version. Cleanup the ongoing checking/detection. */ - cleanup_checking (self, TRUE); + if (c_list_is_empty (&bzobj->x_network_server.lst)) { + emit_device_availability_changed = TRUE; + c_list_link_tail (&priv->network_server_lst_head, &bzobj->x_network_server.lst); + } + + } + + if (emit_device_availability_changed) + NM_SET_OUT (out_emit_device_availability_changed, TRUE); } +/*****************************************************************************/ + static void -setup_bluez4 (NMBluezManager *self) +_conn_create_panu_connection (NMBluezManager *self, + BzDBusObj *bzobj) { - NMBluez4Manager *manager; NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gs_unref_object NMConnection *connection = NULL; + NMSettingsConnection *added; + NMSetting *setting; + gs_free char *id = NULL; + char uuid[37]; + gs_free_error GError *error = NULL; + + nm_utils_uuid_generate_buf (uuid); + id = g_strdup_printf (_("%s Network"), bzobj->d_device.name); + + connection = nm_simple_connection_new (); + + setting = nm_setting_connection_new (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_SETTING_NAME, + NULL); + nm_connection_add_setting (connection, setting); + + setting = nm_setting_bluetooth_new (); + g_object_set (setting, + NM_SETTING_BLUETOOTH_BDADDR, bzobj->d_device.address, + NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU, + NULL); + nm_connection_add_setting (connection, setting); + + if (!nm_connection_normalize (connection, NULL, NULL, &error)) { + _LOGE ("connection: couldn't generate a connection for NAP device: %s", + error->message); + g_return_if_reached (); + } - g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); + nm_assert (_conn_track_is_relevant_connection (connection, NULL, NULL)); + + _LOGT ("connection: create in-memory PANU connection %s (%s) for device \"%s\" (%s)", + uuid, + id, + bzobj->d_device.name, + bzobj->d_device.address); + + nm_settings_add_connection (priv->settings, + connection, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, + NM_SETTINGS_CONNECTION_ADD_REASON_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED, + &added, + &error); + if (!added) { + _LOGW ("connection: couldn't add new Bluetooth connection for NAP device: '%s' (%s): %s", + id, uuid, error->message); + return; + } - setup_version_number (self, 4); - priv->manager4 = manager = nm_bluez4_manager_new (priv->settings); + if ( !_conn_track_is_relevant_for_sett_conn (added, NM_BT_CAPABILITY_NAP, bzobj->d_device.address) + || !_conn_track_find_elem (self, added) + || bzobj->x_device.panu_connection) { + _LOGE ("connection: something went wrong creating PANU connection %s (%s) for device '%s'", + uuid, id, bzobj->d_device.address); + g_return_if_reached (); + } - g_signal_connect (manager, - NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_CALLBACK (manager_bdaddr_added_cb), - self); + bzobj->x_device.panu_connection = added; +} + +/*****************************************************************************/ + +static void +_device_state_changed_cb (NMDevice *device, + guint new_state_u, + guint old_state_u, + guint reason_u, + gpointer user_data) +{ + BzDBusObj *bzobj = user_data; - nm_bluez4_manager_query_devices (manager); + if (!_bzobjs_device_is_usable (bzobj, NULL, NULL)) { + /* the device got unusable? Need to revisit it... */ + _process_change_idle_schedule (bzobj->self, bzobj); + } } static void -setup_bluez5 (NMBluezManager *self) +_device_process_change (BzDBusObj *bzobj) +{ + NMBluezManager *self = bzobj->self; + gs_unref_object NMDeviceBt *device_added = NULL; + gs_unref_object NMDeviceBt *device_deleted = NULL; + gboolean device_is_usable; + gboolean create_panu_connection = FALSE; + + device_is_usable = _bzobjs_device_is_usable (bzobj, NULL, &create_panu_connection); + + if (create_panu_connection) { + bzobj->x_device_panu_connection_allow_create = FALSE; + _conn_create_panu_connection (self, bzobj); + device_is_usable = _bzobjs_device_is_usable (bzobj, NULL, NULL); + } else { + if ( device_is_usable + && bzobj->x_device_panu_connection_allow_create + && NM_FLAGS_HAS (bzobj->d_device_capabilities, NM_BT_CAPABILITY_NAP) + && _conn_track_find_head (self, NM_BT_CAPABILITY_NAP, bzobj->d_device.address) ) { + /* We have a useable device and also a panu-connection. We block future attemps + * to generate a connection. */ + bzobj->x_device_panu_connection_allow_create = FALSE; + } + if (bzobj->x_device.panu_connection) { + if (!NM_FLAGS_HAS (nm_settings_connection_get_flags (bzobj->x_device.panu_connection), + NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) { + /* the connection that we generated earlier still exists, but it's not longer the same + * as it was when we created it. Forget about it, so that we don't delete the profile later... */ + bzobj->x_device.panu_connection = NULL; + } else { + if ( !device_is_usable + || !_conn_track_is_relevant_for_sett_conn (bzobj->x_device.panu_connection, + NM_BT_CAPABILITY_NAP, + bzobj->d_device.address)) { + _LOGT ("connection: delete in-memory PANU connection %s (%s) as device %s", + nm_settings_connection_get_uuid (bzobj->x_device.panu_connection), + nm_settings_connection_get_id (bzobj->x_device.panu_connection), + !device_is_usable ? "is now unusable" : "no longer matches"); + bzobj->x_device_panu_connection_allow_create = TRUE; + nm_settings_connection_delete (g_steal_pointer (&bzobj->x_device.panu_connection), FALSE); + } + } + } + } + + bzobj->x_device_is_connected = device_is_usable + && _bzobjs_device_is_connected (bzobj); + + bzobj->x_device_is_usable = device_is_usable; + + if (bzobj->x_device.device_bt) { + const char *device_to_delete_msg; + + if (!device_is_usable) + device_to_delete_msg = "device became unusable"; + else if (!_nm_device_bt_for_same_device (bzobj->x_device.device_bt, + bzobj->object_path, + bzobj->d_device.address, + NULL, + bzobj->d_device_capabilities)) + device_to_delete_msg = "device is no longer compatible"; + else + device_to_delete_msg = NULL; + + if (device_to_delete_msg) { + nm_clear_g_signal_handler (bzobj->x_device.device_bt, &bzobj->x_device.device_bt_signal_id); + + device_deleted = g_steal_pointer (&bzobj->x_device.device_bt); + + _LOGD ("[%s]: drop device because %s", + bzobj->object_path, + device_to_delete_msg); + + _connect_disconnect (self, bzobj, device_to_delete_msg); + } + } + + if (device_is_usable) { + if (!bzobj->x_device.device_bt) { + bzobj->x_device.device_bt = nm_device_bt_new (self, + bzobj->object_path, + bzobj->d_device.address, + bzobj->d_device.name, + bzobj->d_device_capabilities); + device_added = g_object_ref (bzobj->x_device.device_bt); + bzobj->x_device.device_bt_signal_id = g_signal_connect (device_added, + NM_DEVICE_STATE_CHANGED, + G_CALLBACK (_device_state_changed_cb), + bzobj); + } else + _nm_device_bt_notify_set_name (bzobj->x_device.device_bt, bzobj->d_device.name); + + _nm_device_bt_notify_set_connected (bzobj->x_device.device_bt, bzobj->x_device_is_connected); + } + + if ( bzobj->x_device.c_req_data + && !bzobj->x_device.c_req_data->int_cancellable + && bzobj->x_device_is_connected) { + gs_free char *device_name = g_steal_pointer (&bzobj->x_device.c_req_data->device_name); + + _device_connect_req_data_complete (g_steal_pointer (&bzobj->x_device.c_req_data), + self, + device_name, + NULL); + } + + if (device_added) + g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device_added); + + if (device_deleted) + _nm_device_bt_notify_removed (device_deleted); +} + +/*****************************************************************************/ + +static void +_process_change_idle_all (NMBluezManager *self, + gboolean *out_emit_device_availability_changed) { - NMBluez5Manager *manager; NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + BzDBusObj *bzobj; + + while ((bzobj = c_list_first_entry (&priv->process_change_lst_head, BzDBusObj, process_change_lst))) { + + c_list_unlink (&bzobj->process_change_lst); + + _LOG_bzobj (bzobj, "before-processing"); + + _device_process_change (bzobj); + + _network_server_process_change (bzobj, out_emit_device_availability_changed); + + _LOG_bzobj (bzobj, "after-processing"); + + _bzobjs_del_if_dead (bzobj); + } + + nm_clear_g_source (&priv->process_change_idle_id); +} - g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); +static gboolean +_process_change_idle_cb (gpointer user_data) +{ + NMBluezManager *self = user_data; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gboolean emit_device_availability_changed = FALSE; - setup_version_number (self, 5); - priv->manager5 = manager = nm_bluez5_manager_new (priv->settings); + _process_change_idle_all (self, &emit_device_availability_changed); - g_signal_connect (manager, - NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_CALLBACK (manager_bdaddr_added_cb), - self); - g_signal_connect (manager, - NM_BLUEZ_MANAGER_NETWORK_SERVER_ADDED, - G_CALLBACK (manager_network_server_added_cb), - self); + if (emit_device_availability_changed) + nm_manager_notify_device_availibility_maybe_changed (priv->manager); - nm_bluez5_manager_query_devices (manager); + return G_SOURCE_CONTINUE; } static void -watch_name_on_appeared (GDBusConnection *connection, - const char *name, - const char *name_owner, - gpointer user_data) +_process_change_idle_schedule (NMBluezManager *self, + BzDBusObj *bzobj) { - check_bluez_and_try_setup (NM_BLUEZ_MANAGER (user_data)); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + nm_c_list_move_tail (&priv->process_change_lst_head, &bzobj->process_change_lst); + if (priv->process_change_idle_id == 0) + priv->process_change_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1, _process_change_idle_cb, self, NULL); } static void -check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, const char *reason) +_dbus_process_changes (NMBluezManager *self, + BzDBusObj *bzobj, + const char *log_reason) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gboolean network_server_is_usable; + gboolean adapter_is_usable_for_device; + gboolean device_is_usable; + gboolean changes = FALSE; + gboolean recheck_devices_for_adapter = FALSE; + + nm_assert (bzobj); + + _LOG_bzobj (bzobj, log_reason); + + device_is_usable = _bzobjs_device_is_usable (bzobj, NULL, NULL); + + if (bzobj->x_device_is_usable != device_is_usable) + changes = TRUE; + else if (bzobj->x_device.device_bt) { + if (!device_is_usable) + changes = TRUE; + else { + if ( bzobj->x_device_is_connected != _bzobjs_device_is_connected (bzobj) + || !_nm_device_bt_for_same_device (bzobj->x_device.device_bt, + bzobj->object_path, + bzobj->d_device.address, + bzobj->d_device.name, + bzobj->d_device_capabilities)) + changes = TRUE; + } + } + + adapter_is_usable_for_device = _bzobjs_adapter_is_usable_for_device (bzobj); + if (adapter_is_usable_for_device != bzobj->was_usable_adapter_for_device_before) { + /* this function does not modify bzobj in any other cases except here. + * Usually changes are processed delayed, in the idle handler. + * + * But the bzobj->was_usable_adapter_for_device_before only exists to know whether + * we need to re-check device availability. It is correct to set the flag + * here, right before we checked. */ + bzobj->was_usable_adapter_for_device_before = adapter_is_usable_for_device; + recheck_devices_for_adapter = TRUE; + changes = TRUE; + } + + if (!changes) { + network_server_is_usable = _bzobjs_network_server_is_usable (bzobj, TRUE); + + if (network_server_is_usable != (!c_list_is_empty (&bzobj->x_network_server.lst))) + changes = TRUE; + else if ( bzobj->x_network_server.device_br + && !network_server_is_usable) + changes = TRUE; + else if (!nm_streq0 (bzobj->d_has_adapter_iface ? bzobj->d_adapter.address : NULL, + bzobj->x_network_server.adapter_address)) + changes = TRUE; + } + + if (changes) + _process_change_idle_schedule (self, bzobj); + + if (recheck_devices_for_adapter) { + GHashTableIter iter; + BzDBusObj *bzobj2; + + /* we got a change to the availability of an adapter. We might need to recheck + * all devices that use this adapter... */ + g_hash_table_iter_init (&iter, priv->bzobjs); + while (g_hash_table_iter_next (&iter, (gpointer *) &bzobj2, NULL)) { + if (bzobj2 == bzobj) + continue; + if (!nm_streq0 (bzobj2->d_device.adapter, bzobj->object_path)) + continue; + if (c_list_is_empty (&bzobj2->process_change_lst)) + _dbus_process_changes (self, bzobj2, "adapter-changed"); + else + nm_c_list_move_tail (&priv->process_change_lst_head, &bzobj2->process_change_lst); + } + } + + _bzobjs_del_if_dead (bzobj); +} + +/*****************************************************************************/ + +#define ALL_RELEVANT_INTERFACE_NAMES NM_MAKE_STRV (NM_BLUEZ5_ADAPTER_INTERFACE, \ + NM_BLUEZ5_DEVICE_INTERFACE, \ + NM_BLUEZ5_NETWORK_INTERFACE, \ + NM_BLUEZ5_NETWORK_SERVER_INTERFACE) + +static gboolean +_dbus_handle_properties_changed (NMBluezManager *self, + const char *object_path, + const char *interface_name, + GVariant *changed_properties, + const char *const*invalidated_properties, + BzDBusObj **inout_bzobj) +{ + BzDBusObj *bzobj = NULL; + gboolean changed = FALSE; + const char *property_name; + GVariant *property_value; + GVariantIter iter_prop; + gsize i; - g_return_if_fail (!priv->bluez_version); + if (!invalidated_properties) + invalidated_properties = NM_PTRARRAY_EMPTY (const char *); - switch (bluez_version) { - case 4: - setup_bluez4 (self); - break; - case 5: - setup_bluez5 (self); - break; - default: - _LOGD ("detecting BlueZ version failed: %s", reason); + nm_assert (g_variant_is_of_type (changed_properties, G_VARIANT_TYPE ("a{sv}"))); - /* cancel current attempts to detect the version. */ - cleanup_checking (self, FALSE); - if (!priv->watch_name_id) { - priv->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, - NM_BLUEZ_SERVICE, - G_BUS_NAME_WATCHER_FLAGS_NONE, - watch_name_on_appeared, - NULL, - self, - NULL); + if (inout_bzobj) { + bzobj = *inout_bzobj; + nm_assert (!bzobj || nm_streq (object_path, bzobj->object_path)); + } + + if (changed_properties) + g_variant_iter_init (&iter_prop, changed_properties); + + if (nm_streq (interface_name, NM_BLUEZ5_ADAPTER_INTERFACE)) { + _bzobjs_init (self, &bzobj, object_path); + if (!bzobj->d_has_adapter_iface) { + changed = TRUE; + bzobj->d_has_adapter_iface = TRUE; + } + + while ( changed_properties + && g_variant_iter_next (&iter_prop, "{&sv}", &property_name, &property_value)) { + _nm_unused gs_unref_variant GVariant *property_value_free = property_value; + + if (nm_streq (property_name, "Address")) { + gs_free char *s = g_variant_is_of_type (property_value, G_VARIANT_TYPE_STRING) + ? nm_utils_hwaddr_canonical (g_variant_get_string (property_value, NULL), ETH_ALEN) + : NULL; + + if (!nm_streq0 (bzobj->d_adapter.address, s)) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_adapter.address); + bzobj->d_adapter.address = g_steal_pointer (&s); + } + continue; + } + if (nm_streq (property_name, "Powered")) { + bool v = g_variant_is_of_type (property_value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean (property_value); + + if (bzobj->d_adapter_powered != v) { + changed = TRUE; + bzobj->d_adapter_powered = v; + } + continue; + } + } + + for (i = 0; (property_name = invalidated_properties[i]); i++) { + if (nm_streq (property_name, "Address")) { + if (bzobj->d_adapter.address) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_adapter.address); + } + continue; + } + if (nm_streq (property_name, "Powered")) { + if (bzobj->d_adapter_powered) { + changed = TRUE; + bzobj->d_adapter_powered = FALSE; + } + continue; + } + } + + } else if (nm_streq (interface_name, NM_BLUEZ5_DEVICE_INTERFACE)) { + _bzobjs_init (self, &bzobj, object_path); + if (!bzobj->d_has_device_iface) { + changed = TRUE; + bzobj->d_has_device_iface = TRUE; + } + + while ( changed_properties + && g_variant_iter_next (&iter_prop, "{&sv}", &property_name, &property_value)) { + _nm_unused gs_unref_variant GVariant *property_value_free = property_value; + + if (nm_streq (property_name, "Address")) { + gs_free char *s = g_variant_is_of_type (property_value, G_VARIANT_TYPE_STRING) + ? nm_utils_hwaddr_canonical (g_variant_get_string (property_value, NULL), ETH_ALEN) + : NULL; + + if (!nm_streq0 (bzobj->d_device.address, s)) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.address); + bzobj->d_device.address = g_steal_pointer (&s); + } + continue; + } + if (nm_streq (property_name, "Name")) { + const char *s = g_variant_is_of_type (property_value, G_VARIANT_TYPE_STRING) + ? g_variant_get_string (property_value, NULL) + : NULL; + + if (!nm_streq0 (bzobj->d_device.name, s)) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.name); + bzobj->d_device.name = g_strdup (s); + } + continue; + } + if (nm_streq (property_name, "Adapter")) { + const char *s = g_variant_is_of_type (property_value, G_VARIANT_TYPE_OBJECT_PATH) + ? g_variant_get_string (property_value, NULL) + : NULL; + + if (!nm_streq0 (bzobj->d_device.adapter, s)) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.adapter); + bzobj->d_device.adapter = g_strdup (s); + } + continue; + } + if (nm_streq (property_name, "UUIDs")) { + NMBluetoothCapabilities capabilities = NM_BT_CAPABILITY_NONE; + + if (g_variant_is_of_type (property_value, G_VARIANT_TYPE_STRING_ARRAY)) { + gs_free const char **s = g_variant_get_strv (property_value, NULL); + + capabilities = convert_uuids_to_capabilities (s); + } + if (bzobj->d_device_capabilities != capabilities) { + changed = TRUE; + bzobj->d_device_capabilities = capabilities; + nm_assert (bzobj->d_device_capabilities == capabilities); + } + continue; + } + if (nm_streq (property_name, "Connected")) { + bool v = g_variant_is_of_type (property_value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean (property_value); + + if (bzobj->d_device_connected != v) { + changed = TRUE; + bzobj->d_device_connected = v; + } + continue; + } + if (nm_streq (property_name, "Paired")) { + bool v = g_variant_is_of_type (property_value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean (property_value); + + if (bzobj->d_device_paired != v) { + changed = TRUE; + bzobj->d_device_paired = v; + } + continue; + } + } + + for (i = 0; (property_name = invalidated_properties[i]); i++) { + if (nm_streq (property_name, "Address")) { + if (bzobj->d_device.address) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.address); + } + continue; + } + if (nm_streq (property_name, "Name")) { + if (bzobj->d_device.name) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.name); + } + continue; + } + if (nm_streq (property_name, "Adapter")) { + if (bzobj->d_device.adapter) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.adapter); + } + continue; + } + if (nm_streq (property_name, "UUIDs")) { + if (bzobj->d_device_capabilities != NM_BT_CAPABILITY_NONE) { + changed = TRUE; + bzobj->d_device_capabilities = NM_BT_CAPABILITY_NONE; + } + continue; + } + if (nm_streq (property_name, "Connected")) { + if (bzobj->d_device_connected) { + changed = TRUE; + bzobj->d_device_connected = FALSE; + } + continue; + } + if (nm_streq (property_name, "Paired")) { + if (bzobj->d_device_paired) { + changed = TRUE; + bzobj->d_device_paired = FALSE; + } + continue; + } + } + + } else if (nm_streq (interface_name, NM_BLUEZ5_NETWORK_INTERFACE)) { + _bzobjs_init (self, &bzobj, object_path); + if (!bzobj->d_has_network_iface) { + changed = TRUE; + bzobj->d_has_network_iface = TRUE; + } + + while ( changed_properties + && g_variant_iter_next (&iter_prop, "{&sv}", &property_name, &property_value)) { + _nm_unused gs_unref_variant GVariant *property_value_free = property_value; + + if (nm_streq (property_name, "Interface")) { + const char *s = g_variant_is_of_type (property_value, G_VARIANT_TYPE_STRING) + ? g_variant_get_string (property_value, NULL) + : NULL; + + if (!nm_streq0 (bzobj->d_network.interface, s)) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_network.interface); + bzobj->d_network.interface = g_strdup (s); + } + continue; + } + if (nm_streq (property_name, "Connected")) { + bool v = g_variant_is_of_type (property_value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean (property_value); + + if (bzobj->d_network_connected != v) { + changed = TRUE; + bzobj->d_network_connected = v; + } + continue; + } + } + + for (i = 0; (property_name = invalidated_properties[i]); i++) { + if (nm_streq (property_name, "Interface")) { + if (bzobj->d_network.interface) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_network.interface); + } + continue; + } + if (nm_streq (property_name, "Connected")) { + if (bzobj->d_network_connected) { + changed = TRUE; + bzobj->d_network_connected = FALSE; + } + continue; + } + } + + } else if (nm_streq (interface_name, NM_BLUEZ5_NETWORK_SERVER_INTERFACE)) { + _bzobjs_init (self, &bzobj, object_path); + if (!bzobj->d_has_network_server_iface) { + changed = TRUE; + bzobj->d_has_network_server_iface = TRUE; } - break; } + + nm_assert (!changed || bzobj); + + if (inout_bzobj) + *inout_bzobj = bzobj; + + return changed; } static void -check_bluez_and_try_setup_do_introspect (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +_dbus_handle_interface_added (NMBluezManager *self, + const char *object_path, + GVariant *ifaces, + gboolean initial_get_managed_objects) +{ + BzDBusObj *bzobj = NULL; + gboolean changed = FALSE; + const char *interface_name; + GVariant *changed_properties; + GVariantIter iter_ifaces; + + nm_assert (g_variant_is_of_type (ifaces, G_VARIANT_TYPE ("a{sa{sv}}"))); + + g_variant_iter_init (&iter_ifaces, ifaces); + while (g_variant_iter_next (&iter_ifaces, "{&s@a{sv}}", &interface_name, &changed_properties)) { + _nm_unused gs_unref_variant GVariant *changed_properties_free = changed_properties; + + if (_dbus_handle_properties_changed (self, object_path, interface_name, changed_properties, NULL, &bzobj)) + changed = TRUE; + } + + if (changed) { + _dbus_process_changes (self, + bzobj, + initial_get_managed_objects + ? "dbus-init" + : "dbus-iface-added"); + } +} + +static gboolean +_dbus_handle_interface_removed (NMBluezManager *self, + const char *object_path, + BzDBusObj **inout_bzobj, + const char *const*removed_interfaces) { - NMBluezManager *self = async_data_unpack (user_data); + gboolean changed = FALSE; + BzDBusObj *bzobj; + gsize i; + + if ( inout_bzobj + && *inout_bzobj) { + bzobj = *inout_bzobj; + nm_assert (bzobj == _bzobjs_get (self, object_path)); + } else { + bzobj = _bzobjs_get (self, object_path); + if (!bzobj) + return FALSE; + NM_SET_OUT (inout_bzobj, bzobj); + } + + for (i = 0; removed_interfaces[i]; i++) { + const char *interface_name = removed_interfaces[i]; + + if (nm_streq (interface_name, NM_BLUEZ5_ADAPTER_INTERFACE)) { + if (bzobj->d_has_adapter_iface) { + changed = TRUE; + bzobj->d_has_adapter_iface = FALSE; + } + if (bzobj->d_adapter.address) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_adapter.address); + } + if (bzobj->d_adapter_powered) { + changed = TRUE; + bzobj->d_adapter_powered = FALSE; + } + } else if (nm_streq (interface_name, NM_BLUEZ5_DEVICE_INTERFACE)) { + if (bzobj->d_has_device_iface) { + changed = TRUE; + bzobj->d_has_device_iface = FALSE; + } + if (bzobj->d_device.address) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.address); + } + if (bzobj->d_device.name) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.name); + } + if (bzobj->d_device.adapter) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_device.adapter); + } + if (bzobj->d_device_capabilities != NM_BT_CAPABILITY_NONE) { + changed = TRUE; + bzobj->d_device_capabilities = NM_BT_CAPABILITY_NONE; + } + if (bzobj->d_device_connected) { + changed = TRUE; + bzobj->d_device_connected = FALSE; + } + if (bzobj->d_device_paired) { + changed = TRUE; + bzobj->d_device_paired = FALSE; + } + } else if (nm_streq (interface_name, NM_BLUEZ5_NETWORK_INTERFACE)) { + if (bzobj->d_has_network_iface) { + changed = TRUE; + bzobj->d_has_network_iface = FALSE; + } + if (bzobj->d_network.interface) { + changed = TRUE; + nm_clear_g_free (&bzobj->d_network.interface); + } + if (bzobj->d_network_connected) { + changed = TRUE; + bzobj->d_network_connected = FALSE; + } + } else if (nm_streq (interface_name, NM_BLUEZ5_NETWORK_SERVER_INTERFACE)) { + if (bzobj->d_has_network_server_iface) { + changed = TRUE; + bzobj->d_has_network_server_iface = FALSE; + } + } + } + + return changed; +} + +static void +_dbus_managed_objects_changed_cb (const char *object_path, + GVariant *added_interfaces_and_properties, + const char *const*removed_interfaces, + gpointer user_data) +{ + NMBluezManager *self = user_data; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + BzDBusObj *bzobj = NULL; + gboolean changed; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!added_interfaces_and_properties) { + changed = _dbus_handle_interface_removed (self, object_path, &bzobj, removed_interfaces); + if (changed) + _dbus_process_changes (self, bzobj, "dbus-iface-removed"); + } else + _dbus_handle_interface_added (self, object_path, added_interfaces_and_properties, FALSE); +} + +static void +_dbus_properties_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMBluezManager *self = user_data; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + const char *interface_name; + gs_unref_variant GVariant *changed_properties = NULL; + gs_free const char **invalidated_properties = NULL; + BzDBusObj *bzobj = NULL; + + if (priv->get_managed_objects_cancellable) { + /* we still wait for the initial GetManagedObjects(). Ignore the event. */ + return; + } + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)"))) + return; + + g_variant_get (parameters, + "(&s@a{sv}^a&s)", + &interface_name, + &changed_properties, + &invalidated_properties); + + if (_dbus_handle_properties_changed (self, object_path, interface_name, changed_properties, invalidated_properties, &bzobj)) + _dbus_process_changes (self, bzobj, "dbus-property-changed"); +} + +static void +_dbus_get_managed_objects_cb (GVariant *result, + GError *error, + gpointer user_data) +{ + NMBluezManager *self; NMBluezManagerPrivate *priv; - GError *error = NULL; - GVariant *result; - const char *xml_data; - int bluez_version = 0; - const char *reason = NULL; + GVariantIter iter; + const char *object_path; + GVariant *ifaces; - if (!self) + if ( !result + && nm_utils_error_is_cancelled (error, FALSE)) return; + self = user_data; priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - g_return_if_fail (priv->introspect_proxy); - g_return_if_fail (!g_cancellable_is_cancelled (priv->async_cancellable)); - g_return_if_fail (!priv->bluez_version); - - g_clear_object (&priv->async_cancellable); + g_clear_object (&priv->get_managed_objects_cancellable); - result = _nm_dbus_proxy_call_finish (priv->introspect_proxy, res, - G_VARIANT_TYPE ("(s)"), &error); if (!result) { - char *reason2; - - g_dbus_error_strip_remote_error (error); - reason2 = g_strdup_printf ("introspect failed with %s", error->message); - check_bluez_and_try_setup_final_step (self, 0, reason2); - g_error_free (error); - g_free (reason2); + _LOGT ("initial GetManagedObjects() call failed: %s", error->message); + _cleanup_for_name_owner (self); return; } - g_variant_get (result, "(&s)", &xml_data); + _LOGT ("initial GetManagedObjects call succeeded"); + + g_variant_iter_init (&iter, result); + while (g_variant_iter_next (&iter, "{&o@a{sa{sv}}}", &object_path, &ifaces)) { + _nm_unused gs_unref_variant GVariant *ifaces_free = ifaces; + + _dbus_handle_interface_added (self, object_path, ifaces, TRUE); + } +} + +/*****************************************************************************/ + +static void +_cleanup_for_name_owner (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + gboolean emit_device_availability_changed = FALSE; + GHashTableIter iter; + BzDBusObj *bzobj; + gboolean first = TRUE; + + nm_clear_g_cancellable (&priv->get_managed_objects_cancellable); + + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->managed_objects_changed_id); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->properties_changed_id); + + nm_clear_g_free (&priv->name_owner); + + g_hash_table_iter_init (&iter, priv->bzobjs); + while (g_hash_table_iter_next (&iter, (gpointer *) &bzobj, NULL)) { + if (first) { + first = FALSE; + _LOGT ("drop all objects form D-Bus cache..."); + } + _dbus_handle_interface_removed (self, + bzobj->object_path, + &bzobj, + ALL_RELEVANT_INTERFACE_NAMES); + nm_c_list_move_tail (&priv->process_change_lst_head, &bzobj->process_change_lst); + } + _process_change_idle_all (self, &emit_device_availability_changed); + nm_assert (g_hash_table_size (priv->bzobjs) == 0); + + if (emit_device_availability_changed) + nm_manager_notify_device_availibility_maybe_changed (priv->manager); +} - /* might not be the best approach to detect the version, but it's good enough in practice. */ - if (strstr (xml_data, "org.freedesktop.DBus.ObjectManager")) - bluez_version = 5; - else if (strstr (xml_data, NM_BLUEZ4_MANAGER_INTERFACE)) - bluez_version = 4; +static void +name_owner_changed (NMBluezManager *self, + const char *owner) +{ + _nm_unused gs_unref_object NMBluezManager *self_keep_alive = g_object_ref (self); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + owner = nm_str_not_empty (owner); + + if (!owner) + _LOGT ("D-Bus name for bluez has no owner"); else - reason = "unexpected introspect result"; + _LOGT ("D-Bus name for bluez has owner %s", owner); + + nm_clear_g_cancellable (&priv->name_owner_get_cancellable); + + if (nm_streq0 (priv->name_owner, owner)) + return; + + _cleanup_for_name_owner (self); - g_variant_unref (result); + if (!owner) + return; - check_bluez_and_try_setup_final_step (self, bluez_version, reason); + priv->name_owner = g_strdup (owner); + + priv->get_managed_objects_cancellable = g_cancellable_new (); + + priv->managed_objects_changed_id = nm_dbus_connection_signal_subscribe_object_manager (priv->dbus_connection, + priv->name_owner, + NM_BLUEZ_MANAGER_PATH, + _dbus_managed_objects_changed_cb, + self, + NULL); + + priv->properties_changed_id = nm_dbus_connection_signal_subscribe_properties_changed (priv->dbus_connection, + priv->name_owner, + NULL, + NULL, + _dbus_properties_changed_cb, + self, + NULL); + + nm_dbus_connection_call_get_managed_objects (priv->dbus_connection, + priv->name_owner, + NM_BLUEZ_MANAGER_PATH, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 20000, + priv->get_managed_objects_cancellable, + _dbus_get_managed_objects_cb, + self); } static void -check_bluez_and_try_setup_on_new_proxy (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) { - NMBluezManager *self = async_data_unpack (user_data); - NMBluezManagerPrivate *priv; - GError *error = NULL; + NMBluezManager *self = user_data; + const char *new_owner; - if (!self) + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) return; + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + + name_owner_changed (self, new_owner); +} + +static void +name_owner_get_cb (const char *name_owner, + GError *error, + gpointer user_data) +{ + if ( name_owner + || !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + name_owner_changed (user_data, name_owner); +} + +/*****************************************************************************/ + +static void +_cleanup_all (NMBluezManager *self) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + priv->settings_registered = FALSE; + + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self); + + g_hash_table_remove_all (priv->conn_data_elems); + g_hash_table_remove_all (priv->conn_data_heads); + + _cleanup_for_name_owner (self); + + nm_clear_g_cancellable (&priv->name_owner_get_cancellable); + + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); +} + +static void +start (NMDeviceFactory *factory) +{ + NMBluezManager *self; + NMBluezManagerPrivate *priv; + NMSettingsConnection *const*sett_conns; + guint n_sett_conns; + guint i; + + g_return_if_fail (NM_IS_BLUEZ_MANAGER (factory)); + + self = NM_BLUEZ_MANAGER (factory); priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - g_return_if_fail (!priv->introspect_proxy); - g_return_if_fail (!g_cancellable_is_cancelled (priv->async_cancellable)); - g_return_if_fail (!priv->bluez_version); + _cleanup_all (self); + + if (!priv->dbus_connection) { + _LOGI ("no D-Bus connection available"); + return; + } + + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, G_CALLBACK (cp_connection_added), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (cp_connection_updated), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, G_CALLBACK (cp_connection_removed), self); - priv->introspect_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + priv->settings_registered = TRUE; - if (!priv->introspect_proxy) { - char *reason = g_strdup_printf ("bluez error creating dbus proxy: %s", error->message); - check_bluez_and_try_setup_final_step (self, 0, reason); - g_error_free (error); - g_free (reason); + sett_conns = nm_settings_get_connections (priv->settings, &n_sett_conns); + for (i = 0; i < n_sett_conns; i++) + _conn_track_update (self, sett_conns[i], TRUE, NULL, NULL, NULL); + + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + NM_BLUEZ_SERVICE, + name_owner_changed_cb, + self, + NULL); + + priv->name_owner_get_cancellable = g_cancellable_new (); + + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + NM_BLUEZ_SERVICE, + 10000, + priv->name_owner_get_cancellable, + name_owner_get_cb, + self); +} + +/*****************************************************************************/ + +static void +_connect_returned (NMBluezManager *self, + BzDBusObj *bzobj, + NMBluetoothCapabilities bt_type, + const char *device_name, + NMBluez5DunContext *dun_context, + GError *error) +{ + char sbuf_cap[100]; + + if (error) { + nm_assert (!device_name); + nm_assert (!dun_context); + + _LOGI ("%s [%s]: connect failed: %s", + nm_bluetooth_capability_to_string (bzobj->x_device_connect_bt_type, sbuf_cap, sizeof (sbuf_cap)), + bzobj->object_path, + error->message); + + _device_connect_req_data_complete (g_steal_pointer (&bzobj->x_device.c_req_data), + self, + NULL, + error); + _connect_disconnect (self, bzobj, "cleanup after connect failure"); return; } - g_dbus_proxy_call (priv->introspect_proxy, - "Introspect", - NULL, - G_DBUS_CALL_FLAGS_NO_AUTO_START, - 3000, - priv->async_cancellable, - check_bluez_and_try_setup_do_introspect, - async_data_pack (self)); + nm_assert (bzobj->x_device_connect_bt_type == bt_type); + nm_assert (device_name); + nm_assert ((bt_type == NM_BT_CAPABILITY_DUN) == (!!dun_context)); + nm_assert (bzobj->x_device.c_req_data); + + g_clear_object (&bzobj->x_device.c_req_data->int_cancellable); + + bzobj->x_device.connect_dun_context = dun_context; + + _LOGD ("%s [%s]: connect successful to device %s", + nm_bluetooth_capability_to_string (bzobj->x_device_connect_bt_type, sbuf_cap, sizeof (sbuf_cap)), + bzobj->object_path, + device_name); + + /* we already have another over-all timer running. But after we connected the device, + * we still need to wait for bluez to acknowledge the connected state (via D-Bus, for NAP). + * For DUN profiles we likely are already fully connected by now. + * + * Anyway, schedule another timeout that is possibly shorter than the overall, original + * timeout. Now this should go down fast. */ + bzobj->x_device.c_req_data->timeout_wait_connect_id = g_timeout_add (5000, + _connect_timeout_wait_connected_cb, + bzobj), + bzobj->x_device.c_req_data->device_name = g_strdup (device_name); + + if ( _bzobjs_device_is_usable (bzobj, NULL, NULL) + && _bzobjs_device_is_connected (bzobj)) { + /* We are now connected. Schedule the task that completes the state. */ + _process_change_idle_schedule (self, bzobj); + } +} + +#if WITH_BLUEZ5_DUN +static void +_connect_dun_notify_tty_hangup_cb (NMBluez5DunContext *context, + gpointer user_data) +{ + BzDBusObj *bzobj = user_data; + + _connect_disconnect (bzobj->self, + bzobj, + "DUN connection hung up"); } static void -check_bluez_and_try_setup (NMBluezManager *self) +_connect_dun_step2_cb (NMBluez5DunContext *context, + const char *rfcomm_dev, + GError *error, + gpointer user_data) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + BzDBusObj *bzobj; + + if (nm_utils_error_is_cancelled (error, FALSE)) + return; + + bzobj = user_data; + + if (rfcomm_dev) { + /* We want to early notifiy about the rfcomm path. That is because we might still delay + * to signal full activation longer (asynchronously). But the earliest time the callback + * is invoked with the rfcomm path, we just created the device synchronously. + * + * By already notifying the caller about the path early, it avoids a race where ModemManager + * would find the modem before the bluetooth code considers the profile fully activated. */ - g_return_if_fail (!priv->bluez_version); + nm_assert (!error); + nm_assert (bzobj->x_device.c_req_data); - /* there should be no ongoing detection. Anyway, cleanup_checking. */ - cleanup_checking (self, FALSE); + if (!g_cancellable_is_cancelled (bzobj->x_device.c_req_data->ext_cancellable)) + bzobj->x_device.c_req_data->callback (bzobj->self, FALSE, rfcomm_dev, NULL, bzobj->x_device.c_req_data->callback_user_data); - priv->async_cancellable = g_cancellable_new (); + if (!context) { + /* No context set. This means, we just got notified about the rfcomm path and need to wait + * longer, for the next callback. */ + return; + } + } - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - NM_BLUEZ_SERVICE, - "/", - DBUS_INTERFACE_INTROSPECTABLE, - priv->async_cancellable, - check_bluez_and_try_setup_on_new_proxy, - async_data_pack (self)); + _connect_returned (bzobj->self, bzobj, NM_BT_CAPABILITY_DUN, rfcomm_dev, context, error); } static void -start (NMDeviceFactory *factory) +_connect_dun_step1_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + BzDBusObj *bzobj_adapter; + BzDBusObj *bzobj; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); + + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) + return; + + bzobj = user_data; + + if (error) { + _LOGT ("DUN: [%s]: bluetooth device connect failed: %s", bzobj->object_path, error->message); + /* we actually ignore this error. Let's try, maybe we still can connect via DUN. */ + g_clear_error (&error); + } else + _LOGT ("DUN: [%s]: bluetooth device connected successfully", bzobj->object_path); + + if (!_bzobjs_device_is_usable (bzobj, &bzobj_adapter, NULL)) { + nm_utils_error_set (&error, NM_UTILS_ERROR_UNKNOWN, + "device %s is not usable for DUN after connect", + bzobj->object_path); + _connect_returned (bzobj->self, bzobj, NM_BT_CAPABILITY_DUN, NULL, NULL, error); + return; + } + + if (!nm_bluez5_dun_connect (bzobj_adapter->d_adapter.address, + bzobj->d_device.address, + bzobj->x_device.c_req_data->int_cancellable, + _connect_dun_step2_cb, + bzobj, + _connect_dun_notify_tty_hangup_cb, + bzobj, + &error)) { + _connect_returned (bzobj->self, bzobj, NM_BT_CAPABILITY_DUN, NULL, NULL, error); + return; + } +} +#endif + +static void +_connect_nap_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - check_bluez_and_try_setup (NM_BLUEZ_MANAGER (factory)); + gs_unref_variant GVariant *ret = NULL; + const char *network_iface_name = NULL; + gs_free_error GError *error = NULL; + BzDBusObj *bzobj; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); + + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) + return; + + if (ret) + g_variant_get (ret, "(&s)", &network_iface_name); + + bzobj = user_data; + + _connect_returned (bzobj->self, bzobj, NM_BT_CAPABILITY_NAP, network_iface_name, NULL, error); +} + +static void +_connect_cancelled_cb (GCancellable *cancellable, + BzDBusObj *bzobj) +{ + _connect_disconnect (bzobj->self, bzobj, "connect cancelled"); } +static gboolean +_connect_timeout_wait_connected_cb (gpointer user_data) +{ + BzDBusObj *bzobj = user_data; + + bzobj->x_device.c_req_data->timeout_wait_connect_id = 0; + _connect_disconnect (bzobj->self, bzobj, "timeout waiting for connected"); + return G_SOURCE_REMOVE; +} + +static gboolean +_connect_timeout_cb (gpointer user_data) +{ + BzDBusObj *bzobj = user_data; + + bzobj->x_device.c_req_data->timeout_id = 0; + _connect_disconnect (bzobj->self, bzobj, "timeout connecting"); + return G_SOURCE_REMOVE; +} + +static void +_connect_disconnect (NMBluezManager *self, + BzDBusObj *bzobj, + const char *reason) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + DeviceConnectReqData *c_req_data; + char sbuf_cap[100]; + gboolean bt_type; + + if (bzobj->x_device_connect_bt_type == NM_BT_CAPABILITY_NONE) { + nm_assert (!bzobj->x_device.c_req_data); + return; + } + + bt_type = bzobj->x_device_connect_bt_type; + nm_assert (NM_IN_SET (bt_type, NM_BT_CAPABILITY_DUN, NM_BT_CAPABILITY_NAP)); + bzobj->x_device_connect_bt_type = NM_BT_CAPABILITY_NONE; + + c_req_data = g_steal_pointer (&bzobj->x_device.c_req_data); + + _LOGD ("%s [%s]: disconnect due to %s", + nm_bluetooth_capability_to_string (bt_type, sbuf_cap, sizeof (sbuf_cap)), + bzobj->object_path, + reason); + + if (c_req_data) + nm_clear_g_cancellable (&c_req_data->int_cancellable); + + if (bt_type == NM_BT_CAPABILITY_DUN) { + /* For DUN devices, we also called org.bluez.Device1.Connect() (because in order + * for nm_bluez5_dun_connect() to succeed, we need to be already connected *why??). + * + * But upon disconnect we don't call Disconnect() because we don't know whether somebody + * else also uses the bluetooth device for other purposes. During disconnect we only + * terminate the DUN connection, but don't disconnect entirely. I think that's the + * best we can do. */ +#if WITH_BLUEZ5_DUN + nm_clear_pointer (&bzobj->x_device.connect_dun_context, nm_bluez5_dun_disconnect); +#else + nm_assert_not_reached (); +#endif + } else { + if (priv->name_owner) { + gs_unref_object GCancellable *cancellable = NULL; + + cancellable = g_cancellable_new (); + + nm_shutdown_wait_obj_register_cancellable_full (cancellable, + g_strdup_printf ("bt-disconnect-nap[%s]", bzobj->object_path), + TRUE); + + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + bzobj->object_path, + NM_BLUEZ5_NETWORK_INTERFACE, + "Disconnect", + g_variant_new("()"), + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + cancellable, + _dbus_call_complete_cb_nop, + NULL); + } + } + + if (c_req_data) { + gs_free_error GError *error = NULL; + + nm_utils_error_set (&error, + NM_UTILS_ERROR_UNKNOWN, + "connect aborted due to %s", + reason); + _device_connect_req_data_complete (c_req_data, self, NULL, error); + } +} + +gboolean +nm_bluez_manager_connect (NMBluezManager *self, + const char *object_path, + NMBluetoothCapabilities connection_bt_type, + int timeout_msec, + GCancellable *cancellable, + NMBluezManagerConnectCb callback, + gpointer callback_user_data, + GError **error) +{ + gs_unref_object GCancellable *int_cancellable = NULL; + DeviceConnectReqData *c_req_data; + NMBluezManagerPrivate *priv; + BzDBusObj *bzobj; + char sbuf_cap[100]; + + g_return_val_if_fail (NM_IS_BLUEZ_MANAGER (self), FALSE); + g_return_val_if_fail (NM_IN_SET (connection_bt_type, NM_BT_CAPABILITY_DUN, + NM_BT_CAPABILITY_NAP), FALSE); + g_return_val_if_fail (callback, FALSE); + + nm_assert (timeout_msec > 0); + + priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + + bzobj = _bzobjs_get (self, object_path); + + if (!bzobj) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "device %s does not exist", + object_path); + return FALSE; + } + + if (!_bzobjs_device_is_usable (bzobj, NULL, NULL)) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "device %s is not usable", + object_path); + return FALSE; + } + + if (!NM_FLAGS_ALL (bzobj->d_device_capabilities, connection_bt_type)) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "device %s has not the required capabilities", + object_path); + return FALSE; + } + +#if !WITH_BLUEZ5_DUN + if (connection_bt_type == NM_BT_CAPABILITY_DUN) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "DUN is not supported"); + return FALSE; + } +#endif + + _connect_disconnect (self, bzobj, "new activation"); + + _LOGD ("%s [%s]: connecting...", + nm_bluetooth_capability_to_string (connection_bt_type, sbuf_cap, sizeof (sbuf_cap)), + bzobj->object_path); + + int_cancellable = g_cancellable_new(); + +#if WITH_BLUEZ5_DUN + if (connection_bt_type == NM_BT_CAPABILITY_DUN) { + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + bzobj->object_path, + NM_BLUEZ5_DEVICE_INTERFACE, + "Connect", + NULL, + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + timeout_msec, + int_cancellable, + _connect_dun_step1_cb, + bzobj); + } else +#endif + { + nm_assert (connection_bt_type == NM_BT_CAPABILITY_NAP); + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + bzobj->object_path, + NM_BLUEZ5_NETWORK_INTERFACE, + "Connect", + g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), + G_VARIANT_TYPE ("(s)"), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + timeout_msec, + int_cancellable, + _connect_nap_cb, + bzobj); + } + + c_req_data = g_slice_new (DeviceConnectReqData); + *c_req_data = (DeviceConnectReqData) { + .int_cancellable = g_steal_pointer (&int_cancellable), + .ext_cancellable = g_object_ref (cancellable), + .callback = callback, + .callback_user_data = callback_user_data, + .ext_cancelled_id = g_signal_connect (cancellable, + "cancelled", + G_CALLBACK (_connect_cancelled_cb), + bzobj), + .timeout_id = g_timeout_add (timeout_msec, + _connect_timeout_cb, + bzobj), + }; + + bzobj->x_device_connect_bt_type = connection_bt_type; + bzobj->x_device.c_req_data = c_req_data; + + return TRUE; +} + +void +nm_bluez_manager_disconnect (NMBluezManager *self, + const char *object_path) +{ + BzDBusObj *bzobj; + + g_return_if_fail (NM_IS_BLUEZ_MANAGER (self)); + g_return_if_fail (object_path); + + bzobj = _bzobjs_get (self, object_path); + if (!bzobj) + return; + + _connect_disconnect (self, bzobj, "disconnected by user"); +} + +/*****************************************************************************/ + static NMDevice * create_device (NMDeviceFactory *factory, const char *iface, @@ -407,8 +2789,8 @@ create_device (NMDeviceFactory *factory, NMConnection *connection, gboolean *out_ignore) { - g_warn_if_fail (plink->type == NM_LINK_TYPE_BNEP); *out_ignore = TRUE; + g_return_val_if_fail (plink->type == NM_LINK_TYPE_BNEP, NULL); return NULL; } @@ -433,7 +2815,25 @@ nm_bluez_manager_init (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); + priv->vtable_network_server = (NMBtVTableNetworkServer) { + .is_available = _network_server_vt_is_available, + .register_bridge = _network_server_vt_register_bridge, + .unregister_bridge = _network_server_vt_unregister_bridge, + }; + + c_list_init (&priv->network_server_lst_head); + c_list_init (&priv->process_change_lst_head); + + priv->conn_data_heads = g_hash_table_new_full (_conn_data_head_hash, _conn_data_head_equal, g_free, NULL); + priv->conn_data_elems = g_hash_table_new_full (nm_pdirect_hash, nm_pdirect_equal, nm_g_slice_free_fcn (ConnDataElem), NULL); + + priv->bzobjs = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal, (GDestroyNotify) _bz_dbus_obj_free, NULL); + + priv->manager = g_object_ref (NM_MANAGER_GET); priv->settings = g_object_ref (NM_SETTINGS_GET); + priv->dbus_connection = nm_g_object_ref (NM_MAIN_DBUS_CONNECTION_GET); + + g_atomic_pointer_compare_and_exchange (&nm_bt_vtable_network_server, NULL, &priv->vtable_network_server); } static void @@ -442,22 +2842,25 @@ dispose (GObject *object) NMBluezManager *self = NM_BLUEZ_MANAGER (object); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - if (priv->manager4) { - g_signal_handlers_disconnect_by_func (priv->manager4, manager_bdaddr_added_cb, self); - g_clear_object (&priv->manager4); - } - if (priv->manager5) { - g_signal_handlers_disconnect_by_data (priv->manager5, self); - g_clear_object (&priv->manager5); - } + /* FIXME(shutdown): we need a nm_device_factory_stop() hook to first unregister all + * BzDBusObj instances and do necessary cleanup actions (like disconnecting devices + * or deleting panu_connection). */ - cleanup_checking (self, TRUE); + nm_assert (c_list_is_empty (&priv->network_server_lst_head)); + nm_assert (c_list_is_empty (&priv->process_change_lst_head)); + nm_assert (priv->process_change_idle_id == 0); - priv->bluez_version = 0; + g_atomic_pointer_compare_and_exchange (&nm_bt_vtable_network_server, &priv->vtable_network_server, NULL); + + _cleanup_all (self); G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); g_clear_object (&priv->settings); + g_clear_object (&priv->manager); + g_clear_object (&priv->dbus_connection); + + nm_clear_pointer (&priv->bzobjs, g_hash_table_destroy); } static void @@ -466,10 +2869,10 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS (klass); - object_class->dispose = dispose; + object_class->dispose = dispose; factory_class->get_supported_types = get_supported_types; - factory_class->create_device = create_device; - factory_class->match_connection = match_connection; - factory_class->start = start; + factory_class->create_device = create_device; + factory_class->match_connection = match_connection; + factory_class->start = start; } diff --git a/src/devices/bluetooth/nm-bluez-manager.h b/src/devices/bluetooth/nm-bluez-manager.h new file mode 100644 index 00000000..85dbaa83 --- /dev/null +++ b/src/devices/bluetooth/nm-bluez-manager.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2009 - 2019 Red Hat, Inc. + */ + +#ifndef __NM_BLUEZ_MANAGER_H__ +#define __NM_BLUEZ_MANAGER_H__ + +#define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) +#define NM_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManager)) +#define NM_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) +#define NM_IS_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ_MANAGER)) +#define NM_IS_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ_MANAGER)) +#define NM_BLUEZ_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) + +typedef struct _NMBluezManager NMBluezManager; +typedef struct _NMBluezManagerClass NMBluezManagerClass; + +GType nm_bluez_manager_get_type (void); + +typedef void (*NMBluezManagerConnectCb) (NMBluezManager *self, + gboolean is_completed /* or else is early notification with DUN path */, + const char *device_name, + GError *error, + gpointer user_data); + +gboolean nm_bluez_manager_connect (NMBluezManager *self, + const char *object_path, + NMBluetoothCapabilities connection_bt_type, + int timeout_msec, + GCancellable *cancellable, + NMBluezManagerConnectCb callback, + gpointer callback_user_data, + GError **error); + +void nm_bluez_manager_disconnect (NMBluezManager *self, + const char *object_path); + +#endif /* __NM_BLUEZ_MANAGER_H__ */ diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c deleted file mode 100644 index bd230e90..00000000 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ /dev/null @@ -1,456 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-bluez4-adapter.h" - -#include "nm-dbus-interface.h" -#include "nm-bluez-device.h" -#include "nm-bluez-common.h" -#include "nm-core-internal.h" -#include "settings/nm-settings.h" - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_PATH, - PROP_ADDRESS, -); - -enum { - INITIALIZED, - DEVICE_ADDED, - DEVICE_REMOVED, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct { - char *path; - GDBusProxy *proxy; - GCancellable *proxy_cancellable; - gboolean initialized; - - char *address; - GHashTable *devices; - - /* Cached for devices */ - NMSettings *settings; -} NMBluez4AdapterPrivate; - -struct _NMBluez4Adapter { - GObject parent; - NMBluez4AdapterPrivate _priv; -}; - -struct _NMBluez4AdapterClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) - -#define NM_BLUEZ4_ADAPTER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMBluez4Adapter, NM_IS_BLUEZ4_ADAPTER) - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_BT -#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-adapter", __VA_ARGS__) - -/*****************************************************************************/ - -static void device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device); - -/*****************************************************************************/ - -const char * -nm_bluez4_adapter_get_path (NMBluez4Adapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), NULL); - - return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->path; -} - -const char * -nm_bluez4_adapter_get_address (NMBluez4Adapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), NULL); - - return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->address; -} - -gboolean -nm_bluez4_adapter_get_initialized (NMBluez4Adapter *self) -{ - g_return_val_if_fail (NM_IS_BLUEZ4_ADAPTER (self), FALSE); - - return NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->initialized; -} - -GSList * -nm_bluez4_adapter_get_devices (NMBluez4Adapter *self) -{ - GSList *devices = NULL; - GHashTableIter iter; - NMBluezDevice *device; - - g_hash_table_iter_init (&iter, NM_BLUEZ4_ADAPTER_GET_PRIVATE (self)->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - if (nm_bluez_device_get_usable (device)) - devices = g_slist_append (devices, device); - } - return devices; -} - -static void -emit_device_removed (NMBluez4Adapter *self, NMBluezDevice *device) -{ - _LOGD ("(%s): bluez device now unusable", - nm_bluez_device_get_path (device)); - g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); -} - -static void -device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) -{ - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - - if (nm_bluez_device_get_usable (device)) { - _LOGD ("(%s): bluez device now usable (device address is %s)", - nm_bluez_device_get_path (device), - nm_bluez_device_get_address (device)); - g_signal_emit (self, signals[DEVICE_ADDED], 0, device); - } else - emit_device_removed (self, device); -} - -static void -device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) -{ - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - - _LOGD ("(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); - if (!success) - device_do_remove (self, device); -} - -static void -device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device) -{ - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - - if (g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device))) { - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); - - if (nm_bluez_device_get_usable (device)) - emit_device_removed (self, device); - - g_object_unref (device); - } -} - -static void -device_created (GDBusProxy *proxy, const char *path, gpointer user_data) -{ - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - NMBluezDevice *device; - - device = nm_bluez_device_new (path, priv->address, priv->settings, 4); - g_signal_connect (device, NM_BLUEZ_DEVICE_INITIALIZED, G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::" NM_BLUEZ_DEVICE_USABLE, G_CALLBACK (device_usable), self); - g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); - - _LOGD ("(%s): new bluez device found", path); -} - -static void -device_removed (GDBusProxy *proxy, const char *path, gpointer user_data) -{ - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - NMBluezDevice *device; - - _LOGD ("(%s): bluez device removed", path); - - device = g_hash_table_lookup (priv->devices, path); - if (device) - device_do_remove (self, device); -} - -static void -get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) -{ - NMBluez4Adapter *self; - NMBluez4AdapterPrivate *priv; - gs_free_error GError *error = NULL; - GVariant *ret, *properties; - char **devices; - int i; - - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, - G_VARIANT_TYPE ("(a{sv})"), &error); - - if ( !ret - && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_BLUEZ4_ADAPTER (user_data); - priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - - g_clear_object (&priv->proxy_cancellable); - - if (!ret) { - g_dbus_error_strip_remote_error (error); - _LOGW ("bluez error getting adapter properties: %s", error->message); - goto done; - } - - properties = g_variant_get_child_value (ret, 0); - - (void) g_variant_lookup (properties, "Address", "s", &priv->address); - if (g_variant_lookup (properties, "Devices", "^ao", &devices)) { - for (i = 0; devices[i]; i++) - device_created (priv->proxy, devices[i], self); - g_strfreev (devices); - } - - g_variant_unref (properties); - g_variant_unref (ret); - - priv->initialized = TRUE; - -done: - g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized); -} - -static void -_proxy_new_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - NMBluez4Adapter *self; - NMBluez4AdapterPrivate *priv; - gs_free_error GError *error = NULL; - GDBusProxy *proxy; - - proxy = g_dbus_proxy_new_for_bus_finish (result, &error); - if ( !proxy - && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = user_data; - priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - - if (!proxy) { - _LOGW ("bluez error creating D-Bus proxy: %s", error->message); - g_clear_object (&priv->proxy_cancellable); - g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized); - return; - } - - priv->proxy = proxy; - - _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (device_created), self); - _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (device_removed), self); - - g_dbus_proxy_call (priv->proxy, "GetProperties", - NULL, - G_DBUS_CALL_FLAGS_NONE, -1, - priv->proxy_cancellable, - get_properties_cb, - self); -} - -/*****************************************************************************/ - -static gboolean -_find_all (gpointer key, gpointer value, gpointer user_data) -{ - return TRUE; -} - -/*****************************************************************************/ - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE ((NMBluez4Adapter *) object); - - switch (prop_id) { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_ADDRESS: - g_value_set_string (value, priv->address); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE ((NMBluez4Adapter *) object); - - switch (prop_id) { - case PROP_PATH: - /* construct-only */ - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_bluez4_adapter_init (NMBluez4Adapter *self) -{ - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - - priv->devices = g_hash_table_new_full (nm_str_hash, g_str_equal, - NULL, NULL); -} - -NMBluez4Adapter * -nm_bluez4_adapter_new (const char *path, NMSettings *settings) -{ - NMBluez4Adapter *self; - NMBluez4AdapterPrivate *priv; - - g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); - - self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, - NM_BLUEZ4_ADAPTER_PATH, path, - NULL); - priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - - priv->settings = g_object_ref (settings); - - priv->proxy_cancellable = g_cancellable_new (); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - NM_BLUEZ_SERVICE, - priv->path, - NM_BLUEZ4_ADAPTER_INTERFACE, - priv->proxy_cancellable, - _proxy_new_cb, - self); - return self; -} - -static void -dispose (GObject *object) -{ - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object); - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - NMBluezDevice *device; - - nm_clear_g_cancellable (&priv->proxy_cancellable); - - while ((device = g_hash_table_find (priv->devices, _find_all, NULL))) - device_do_remove (self, device); - - if (priv->proxy) { - g_signal_handlers_disconnect_by_data (priv->proxy, self); - g_clear_object (&priv->proxy); - } - - G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object); - NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - - g_hash_table_destroy (priv->devices); - g_free (priv->address); - g_free (priv->path); - - G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object); - - g_object_unref (priv->settings); -} - -static void -nm_bluez4_adapter_class_init (NMBluez4AdapterClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (config_class); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - obj_properties[PROP_PATH] = - g_param_spec_string (NM_BLUEZ4_ADAPTER_PATH, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ADDRESS] = - g_param_spec_string (NM_BLUEZ4_ADAPTER_ADDRESS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[INITIALIZED] = g_signal_new (NM_BLUEZ4_ADAPTER_INITIALIZED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[DEVICE_ADDED] = g_signal_new (NM_BLUEZ4_ADAPTER_DEVICE_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - signals[DEVICE_REMOVED] = g_signal_new (NM_BLUEZ4_ADAPTER_DEVICE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); -} - diff --git a/src/devices/bluetooth/nm-bluez4-adapter.h b/src/devices/bluetooth/nm-bluez4-adapter.h deleted file mode 100644 index 82bd2de8..00000000 --- a/src/devices/bluetooth/nm-bluez4-adapter.h +++ /dev/null @@ -1,57 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 - 2012 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ -#define __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ - -#include "nm-bluez-device.h" - -#define NM_TYPE_BLUEZ4_ADAPTER (nm_bluez4_adapter_get_type ()) -#define NM_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4Adapter)) -#define NM_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) -#define NM_IS_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ4_ADAPTER)) -#define NM_IS_BLUEZ4_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_ADAPTER)) -#define NM_BLUEZ4_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4AdapterClass)) - -/* Properties */ -#define NM_BLUEZ4_ADAPTER_PATH "path" -#define NM_BLUEZ4_ADAPTER_ADDRESS "address" - -/* Signals */ -#define NM_BLUEZ4_ADAPTER_INITIALIZED "initialized" -#define NM_BLUEZ4_ADAPTER_DEVICE_ADDED "device-added" -#define NM_BLUEZ4_ADAPTER_DEVICE_REMOVED "device-removed" - -typedef struct _NMBluez4Adapter NMBluez4Adapter; -typedef struct _NMBluez4AdapterClass NMBluez4AdapterClass; - -GType nm_bluez4_adapter_get_type (void); - -NMBluez4Adapter *nm_bluez4_adapter_new (const char *path, - NMSettings *settings); - -const char *nm_bluez4_adapter_get_path (NMBluez4Adapter *self); - -const char *nm_bluez4_adapter_get_address (NMBluez4Adapter *self); - -gboolean nm_bluez4_adapter_get_initialized (NMBluez4Adapter *self); - -GSList *nm_bluez4_adapter_get_devices (NMBluez4Adapter *self); - -#endif /* __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ */ diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c deleted file mode 100644 index 8327776d..00000000 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ /dev/null @@ -1,355 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2013 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-bluez4-manager.h" - -#include <signal.h> -#include <stdlib.h> - -#include "nm-bluez4-adapter.h" -#include "nm-bluez-common.h" -#include "nm-core-internal.h" -#include "settings/nm-settings.h" - -/*****************************************************************************/ - -enum { - BDADDR_ADDED, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct { - gulong name_owner_changed_id; - - NMSettings *settings; - - GDBusProxy *proxy; - GCancellable *proxy_cancellable; - - NMBluez4Adapter *adapter; -} NMBluez4ManagerPrivate; - -struct _NMBluez4Manager { - GObject parent; - NMBluez4ManagerPrivate _priv; -}; - -struct _NMBluez4ManagerClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE (NMBluez4Manager, nm_bluez4_manager, G_TYPE_OBJECT) - -#define NM_BLUEZ4_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMBluez4Manager, NM_IS_BLUEZ4_MANAGER) - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_BT -#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez4-manager", __VA_ARGS__) - -/*****************************************************************************/ - -static void -emit_bdaddr_added (NMBluez4Manager *self, NMBluezDevice *device) -{ - g_signal_emit (self, signals[BDADDR_ADDED], 0, - device, - nm_bluez_device_get_address (device), - nm_bluez_device_get_name (device), - nm_bluez_device_get_path (device), - nm_bluez_device_get_capabilities (device)); -} - -void -nm_bluez4_manager_query_devices (NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - GSList *devices, *iter; - - if (!priv->adapter) - return; - - devices = nm_bluez4_adapter_get_devices (priv->adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); - g_slist_free (devices); -} - -static void -device_added (NMBluez4Adapter *adapter, NMBluezDevice *device, gpointer user_data) -{ - emit_bdaddr_added (NM_BLUEZ4_MANAGER (user_data), device); -} - -static void -device_removed (NMBluez4Adapter *adapter, NMBluezDevice *device, gpointer user_data) -{ - /* Re-emit the signal on the device for now; flatten this later */ - g_signal_emit_by_name (device, NM_BLUEZ_DEVICE_REMOVED); -} - -static void -adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_data) -{ - NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - if (success) { - GSList *devices, *iter; - - devices = nm_bluez4_adapter_get_devices (adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - emit_bdaddr_added (self, NM_BLUEZ_DEVICE (iter->data)); - g_slist_free (devices); - - g_signal_connect (adapter, NM_BLUEZ4_ADAPTER_DEVICE_ADDED, - G_CALLBACK (device_added), self); - g_signal_connect (adapter, NM_BLUEZ4_ADAPTER_DEVICE_REMOVED, - G_CALLBACK (device_removed), self); - } else { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -adapter_removed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - if (priv->adapter && !strcmp (path, nm_bluez4_adapter_get_path (priv->adapter))) { - if (nm_bluez4_adapter_get_initialized (priv->adapter)) { - GSList *devices, *iter; - - devices = nm_bluez4_adapter_get_devices (priv->adapter); - for (iter = devices; iter; iter = g_slist_next (iter)) - g_signal_emit_by_name (NM_BLUEZ_DEVICE (iter->data), NM_BLUEZ_DEVICE_REMOVED); - g_slist_free (devices); - } - - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - const char *cur_path = NULL; - - if (priv->adapter) - cur_path = nm_bluez4_adapter_get_path (priv->adapter); - - if (cur_path) { - if (!path || strcmp (path, cur_path)) { - /* Default adapter changed */ - adapter_removed (priv->proxy, cur_path, self); - } else { - /* This adapter is already the default */ - return; - } - } - - /* Add the new default adapter */ - if (path) { - priv->adapter = nm_bluez4_adapter_new (path, priv->settings); - g_signal_connect (priv->adapter, NM_BLUEZ4_ADAPTER_INITIALIZED, - G_CALLBACK (adapter_initialized), self); - } -} - -static void -default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) -{ - NMBluez4Manager *self; - NMBluez4ManagerPrivate *priv; - gs_unref_variant GVariant *ret = NULL; - gs_free_error GError *error = NULL; - const char *default_adapter; - - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, - G_VARIANT_TYPE ("(o)"), &error); - if ( !ret - && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_BLUEZ4_MANAGER (user_data); - priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - g_clear_object (&priv->proxy_cancellable); - - if (!ret) { - /* Ignore "No such adapter" errors; just means bluetooth isn't active */ - if ( !_nm_dbus_error_has_name (error, "org.bluez.Error.NoSuchAdapter") - && !_nm_dbus_error_has_name (error, "org.freedesktop.systemd1.LoadFailed") - && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { - g_dbus_error_strip_remote_error (error); - _LOGW ("bluez error getting default adapter: %s", - error->message); - } - return; - } - - g_variant_get (ret, "(&o)", &default_adapter); - default_adapter_changed (priv->proxy, default_adapter, self); -} - -static void -name_owner_changed (NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - gs_free char *owner = NULL; - - nm_clear_g_cancellable (&priv->proxy_cancellable); - - owner = g_dbus_proxy_get_name_owner (priv->proxy); - if (!owner) { - /* Throwing away the adapter removes all devices too */ - g_clear_object (&priv->adapter); - return; - } - - priv->proxy_cancellable = g_cancellable_new (); - - g_dbus_proxy_call (priv->proxy, "DefaultAdapter", - NULL, - G_DBUS_CALL_FLAGS_NONE, -1, - priv->proxy_cancellable, - default_adapter_cb, - self); -} - -static void -name_owner_changed_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - name_owner_changed (user_data); -} - -static void -_proxy_new_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - NMBluez4Manager *self; - NMBluez4ManagerPrivate *priv; - gs_free_error GError *error = NULL; - GDBusProxy *proxy; - - proxy = g_dbus_proxy_new_for_bus_finish (result, &error); - if ( !proxy - && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = user_data; - priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - if (!proxy) { - _LOGW ("bluez error creating D-Bus proxy: %s", error->message); - g_clear_object (&priv->proxy_cancellable); - return; - } - - priv->proxy = proxy; - - _nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (adapter_removed), self); - _nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (default_adapter_changed), self); - g_signal_connect (priv->proxy, "notify::g-name-owner", - G_CALLBACK (name_owner_changed_cb), self); - - name_owner_changed (self); -} - -/*****************************************************************************/ - -static void -nm_bluez4_manager_init (NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - priv->proxy_cancellable = g_cancellable_new (); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - NM_BLUEZ_SERVICE, - NM_BLUEZ_MANAGER_PATH, - NM_BLUEZ4_MANAGER_INTERFACE, - priv->proxy_cancellable, - _proxy_new_cb, - self); -} - -NMBluez4Manager * -nm_bluez4_manager_new (NMSettings *settings) -{ - NMBluez4Manager *instance; - - g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); - - instance = g_object_new (NM_TYPE_BLUEZ4_MANAGER, NULL); - NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->settings = g_object_ref (settings); - return instance; -} - -static void -dispose (GObject *object) -{ - NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object); - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - nm_clear_g_cancellable (&priv->proxy_cancellable); - - if (priv->proxy) { - g_signal_handlers_disconnect_by_data (priv->proxy, self); - g_clear_object (&priv->proxy); - } - - g_clear_object (&priv->adapter); - - G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); - - g_clear_object (&priv->settings); -} - -static void -nm_bluez4_manager_class_init (NMBluez4ManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dispose; - - signals[BDADDR_ADDED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); -} - diff --git a/src/devices/bluetooth/nm-bluez4-manager.h b/src/devices/bluetooth/nm-bluez4-manager.h deleted file mode 100644 index f46379ff..00000000 --- a/src/devices/bluetooth/nm-bluez4-manager.h +++ /dev/null @@ -1,40 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2013 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_BLUEZ4_MANAGER_H__ -#define __NETWORKMANAGER_BLUEZ4_MANAGER_H__ - -#define NM_TYPE_BLUEZ4_MANAGER (nm_bluez4_manager_get_type ()) -#define NM_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4Manager)) -#define NM_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) -#define NM_IS_BLUEZ4_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ4_MANAGER)) -#define NM_IS_BLUEZ4_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ4_MANAGER)) -#define NM_BLUEZ4_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ4_MANAGER, NMBluez4ManagerClass)) - -typedef struct _NMBluez4Manager NMBluez4Manager; -typedef struct _NMBluez4ManagerClass NMBluez4ManagerClass; - -GType nm_bluez4_manager_get_type (void); - -NMBluez4Manager *nm_bluez4_manager_new (NMSettings *settings); - -void nm_bluez4_manager_query_devices (NMBluez4Manager *manager); - -#endif /* __NETWORKMANAGER_BLUEZ4_MANAGER_H__ */ diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c index b9a1fa0a..af463d1a 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.c +++ b/src/devices/bluetooth/nm-bluez5-dun.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -32,145 +18,407 @@ #include "nm-bt-error.h" #include "NetworkManagerUtils.h" +#define RFCOMM_FMT "/dev/rfcomm%d" + +/*****************************************************************************/ + +typedef struct { + GCancellable *cancellable; + NMBluez5DunConnectCb callback; + gpointer callback_user_data; + + sdp_session_t *sdp_session; + + GError *rfcomm_sdp_search_error; + + gint64 connect_open_tty_started_at; + + gulong cancelled_id; + + guint source_id; + + guint8 sdp_session_try_count; +} ConnectData; + struct _NMBluez5DunContext { + const char *dst_str; + + ConnectData *cdat; + + NMBluez5DunNotifyTtyHangupCb notify_tty_hangup_cb; + gpointer notify_tty_hangup_user_data; + + char *rfcomm_tty_path; + + int rfcomm_sock_fd; + int rfcomm_tty_fd; + int rfcomm_tty_no; + int rfcomm_channel; + + guint rfcomm_tty_poll_id; + bdaddr_t src; bdaddr_t dst; - char *src_str; - char *dst_str; - int rfcomm_channel; - int rfcomm_fd; - int rfcomm_tty_fd; - int rfcomm_id; - NMBluez5DunFunc callback; - gpointer user_data; - sdp_session_t *sdp_session; - guint sdp_watch_id; + + char src_str[]; }; -static void -dun_connect (NMBluez5DunContext *context) +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG_PREFIX_NAME "bluez" +#define _NMLOG(level, context, ...) \ + G_STMT_START { \ + if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \ + const NMBluez5DunContext *const _context = (context); \ + \ + _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \ + "%s: DUN[%s] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + _context->src_str \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + +static void _context_invoke_callback_success (NMBluez5DunContext *context); +static void _context_invoke_callback_fail_and_free (NMBluez5DunContext *context, + GError *error); +static void _context_free (NMBluez5DunContext *context); +static int _connect_open_tty (NMBluez5DunContext *context); +static gboolean _connect_sdp_session_start (NMBluez5DunContext *context, + GError **error); + +/*****************************************************************************/ + +NM_AUTO_DEFINE_FCN0 (NMBluez5DunContext *, _nm_auto_free_context, _context_free) +#define nm_auto_free_context nm_auto(_nm_auto_free_context) + +/*****************************************************************************/ + +const char * +nm_bluez5_dun_context_get_adapter (const NMBluez5DunContext *context) { - struct sockaddr_rc sa; - int devid, try = 30; - char tty[100]; - const int ttylen = sizeof (tty) - 1; - GError *error = NULL; - int errsv; + return context->src_str; +} - struct rfcomm_dev_req req = { - .flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP), - .dev_id = -1, - .channel = context->rfcomm_channel - }; +const char * +nm_bluez5_dun_context_get_remote (const NMBluez5DunContext *context) +{ + return context->dst_str; +} - context->rfcomm_fd = socket (AF_BLUETOOTH, SOCK_STREAM | SOCK_CLOEXEC, BTPROTO_RFCOMM); - if (context->rfcomm_fd < 0) { - errsv = errno; - error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Failed to create RFCOMM socket: (%d) %s", - errsv, nm_strerror_native (errsv)); - goto done; - } +const char * +nm_bluez5_dun_context_get_rfcomm_dev (const NMBluez5DunContext *context) +{ + return context->rfcomm_tty_path; +} - /* Connect to the remote device */ - sa.rc_family = AF_BLUETOOTH; - sa.rc_channel = 0; - memcpy (&sa.rc_bdaddr, &context->src, ETH_ALEN); - if (bind (context->rfcomm_fd, (struct sockaddr *) &sa, sizeof(sa))) { - errsv = errno; - error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Failed to bind socket: (%d) %s", - errsv, nm_strerror_native (errsv)); - goto done; +/*****************************************************************************/ + +static gboolean +_rfcomm_tty_poll_cb (GIOChannel *stream, + GIOCondition condition, + gpointer user_data) +{ + NMBluez5DunContext *context = user_data; + + _LOGD (context, "receive %s%s%s signal on rfcomm file descriptor", + NM_FLAGS_HAS (condition, G_IO_ERR) ? "ERR" : "", + NM_FLAGS_ALL (condition, G_IO_HUP | G_IO_ERR) ? "," : "", + NM_FLAGS_HAS (condition, G_IO_HUP) ? "HUP" : ""); + + context->rfcomm_tty_poll_id = 0; + context->notify_tty_hangup_cb (context, + context->notify_tty_hangup_user_data); + return G_SOURCE_REMOVE; +} + +static gboolean +_connect_open_tty_retry_cb (gpointer user_data) +{ + NMBluez5DunContext *context = user_data; + int r; + + r = _connect_open_tty (context); + if (r >= 0) + return G_SOURCE_REMOVE; + + if (nm_utils_get_monotonic_timestamp_ns () > context->cdat->connect_open_tty_started_at + (30 * 100 * NM_UTILS_NS_PER_MSEC)) { + gs_free_error GError *error = NULL; + + context->cdat->source_id = 0; + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "give up waiting to open %s device: %s (%d)", + context->rfcomm_tty_path, + nm_strerror_native (r), + -r); + _context_invoke_callback_fail_and_free (context, error); + return G_SOURCE_REMOVE; } - sa.rc_channel = context->rfcomm_channel; - memcpy (&sa.rc_bdaddr, &context->dst, ETH_ALEN); - if (connect (context->rfcomm_fd, (struct sockaddr *) &sa, sizeof (sa)) ) { - errsv = errno; - error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Failed to connect to remote device: (%d) %s", - errsv, nm_strerror_native (errsv)); - goto done; + return G_SOURCE_CONTINUE; +} + +static int +_connect_open_tty (NMBluez5DunContext *context) +{ + nm_auto_unref_io_channel GIOChannel *io_channel = NULL; + int fd; + int errsv; + + fd = open (context->rfcomm_tty_path, O_RDONLY | O_NOCTTY | O_CLOEXEC); + if (fd < 0) { + errsv = NM_ERRNO_NATIVE (errno); + + if (context->cdat->source_id == 0) { + _LOGD (context, "failed opening tty "RFCOMM_FMT": %s (%d). Start polling...", + context->rfcomm_tty_no, + nm_strerror_native (errsv), + errsv); + context->cdat->connect_open_tty_started_at = nm_utils_get_monotonic_timestamp_ns (); + context->cdat->source_id = g_timeout_add (100, + _connect_open_tty_retry_cb, + context); + } + return -errsv; } - nm_log_dbg (LOGD_BT, "(%s): connected to %s on channel %d", - context->src_str, context->dst_str, context->rfcomm_channel); + context->rfcomm_tty_fd = fd; + + io_channel = g_io_channel_unix_new (context->rfcomm_tty_fd); + context->rfcomm_tty_poll_id = g_io_add_watch (io_channel, + G_IO_ERR | G_IO_HUP, + _rfcomm_tty_poll_cb, + context); + + _context_invoke_callback_success (context); + return 0; +} + +static void +_connect_create_rfcomm (NMBluez5DunContext *context) +{ + gs_free_error GError *error = NULL; + struct rfcomm_dev_req req; + int devid; + int errsv; + int r; + + _LOGD (context, "connected to %s on channel %d", + context->dst_str, context->rfcomm_channel); /* Create an RFCOMM kernel device for the DUN channel */ + memset (&req, 0, sizeof (req)); + req.dev_id = -1; + req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP); + req.channel = context->rfcomm_channel; memcpy (&req.src, &context->src, ETH_ALEN); memcpy (&req.dst, &context->dst, ETH_ALEN); - devid = ioctl (context->rfcomm_fd, RFCOMMCREATEDEV, &req); + devid = ioctl (context->rfcomm_sock_fd, RFCOMMCREATEDEV, &req); if (devid < 0) { - errsv = errno; - error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Failed to create rfcomm device: (%d) %s", - errsv, nm_strerror_native (errsv)); - goto done; + errsv = NM_ERRNO_NATIVE (errno); + if (errsv == EBADFD) { + /* hm. We use a non-blocking socket to connect. Above getsockopt(SOL_SOCKET,SO_ERROR) indicated + * success, but still now we fail with EBADFD. I think that is a bug and we should get the + * failure during connect(). + * + * Anyway, craft a less confusing error message than + * "failed to create rfcomm device: File descriptor in bad state (77)". */ + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "unknown failure to connect to DUN device"); + } else { + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to create rfcomm device: %s (%d)", + nm_strerror_native (errsv), errsv); + } + _context_invoke_callback_fail_and_free (context, error); + return; } - context->rfcomm_id = devid; - snprintf (tty, ttylen, "/dev/rfcomm%d", devid); - while ((context->rfcomm_tty_fd = open (tty, O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0 && try--) { - if (try) { - g_usleep (100 * 1000); - continue; - } + context->rfcomm_tty_no = devid; + context->rfcomm_tty_path = g_strdup_printf (RFCOMM_FMT, devid); + + r = _connect_open_tty (context); + if (r < 0) { + /* we created the rfcomm device, but cannot yet open it. That means, we are + * not yet fully connected. However, we notify the caller about "what we learned + * so far". Note that this happens synchronously. + * + * The purpose is that once we proceed synchrnously, modem-manager races with + * the detection of the modem. We want to notify the caller first about the + * device name. */ + context->cdat->callback (NULL, + context->rfcomm_tty_path, + NULL, + context->cdat->callback_user_data); + } +} - error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Failed to find rfcomm device: %s", - tty); - break; +static gboolean +_connect_socket_connect_cb (GIOChannel *stream, + GIOCondition condition, + gpointer user_data) +{ + NMBluez5DunContext *context = user_data; + gs_free_error GError *error = NULL; + int errsv = 0; + socklen_t slen = sizeof(errsv); + int r; + + context->cdat->source_id = 0; + + r = getsockopt (context->rfcomm_sock_fd, SOL_SOCKET, SO_ERROR, &errsv, &slen); + + if (r < 0) { + errsv = errno; + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to complete connecting RFCOMM socket: %s (%d)", + nm_strerror_native (errsv), errsv); + _context_invoke_callback_fail_and_free (context, error); + return G_SOURCE_REMOVE; } -done: - context->callback (context, tty, error, context->user_data); + if (errsv != 0) { + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to connect RFCOMM socket: %s (%d)", + nm_strerror_native (errsv), errsv); + _context_invoke_callback_fail_and_free (context, error); + return G_SOURCE_REMOVE; + } + + _connect_create_rfcomm (context); + return G_SOURCE_REMOVE; } static void -sdp_search_cleanup (NMBluez5DunContext *context) +_connect_socket_connect (NMBluez5DunContext *context) { - if (context->sdp_session) { - sdp_close (context->sdp_session); - context->sdp_session = NULL; + gs_free_error GError *error = NULL; + struct sockaddr_rc sa; + int errsv; + + context->rfcomm_sock_fd = socket (AF_BLUETOOTH, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_RFCOMM); + if (context->rfcomm_sock_fd < 0) { + errsv = errno; + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to create RFCOMM socket: %s (%d)", + nm_strerror_native (errsv), errsv); + _context_invoke_callback_fail_and_free (context, error); + return; + } + + /* Connect to the remote device */ + memset (&sa, 0, sizeof (sa)); + sa.rc_family = AF_BLUETOOTH; + sa.rc_channel = 0; + memcpy (&sa.rc_bdaddr, &context->src, ETH_ALEN); + if (bind (context->rfcomm_sock_fd, + (struct sockaddr *) &sa, + sizeof(sa)) != 0) { + errsv = errno; + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to bind socket: %s (%d)", + nm_strerror_native (errsv), errsv); + _context_invoke_callback_fail_and_free (context, error); + return; + } + + memset (&sa, 0, sizeof (sa)); + sa.rc_family = AF_BLUETOOTH; + sa.rc_channel = context->rfcomm_channel; + memcpy (&sa.rc_bdaddr, &context->dst, ETH_ALEN); + if (connect (context->rfcomm_sock_fd, + (struct sockaddr *) &sa, + sizeof (sa)) != 0) { + nm_auto_unref_io_channel GIOChannel *io_channel = NULL; + + errsv = errno; + if (errsv != EINPROGRESS) { + g_set_error (&error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to connect to remote device: %s (%d)", + nm_strerror_native (errsv), errsv); + _context_invoke_callback_fail_and_free (context, error); + return; + } + + _LOGD (context, "connecting to %s on channel %d...", + context->dst_str, + context->rfcomm_channel); + + io_channel = g_io_channel_unix_new (context->rfcomm_sock_fd); + context->cdat->source_id = g_io_add_watch (io_channel, + G_IO_OUT, + _connect_socket_connect_cb, + context); + return; } - nm_clear_g_source (&context->sdp_watch_id); + _connect_create_rfcomm (context); } static void -sdp_search_completed_cb (uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *user_data) +_connect_sdp_search_cb (uint8_t type, + uint16_t status, + uint8_t *rsp, + size_t size, + void *user_data) { NMBluez5DunContext *context = user_data; - int scanned, seqlen = 0, bytesleft = size; + int scanned; + int seqlen = 0; + int bytesleft = size; uint8_t dataType; int channel = -1; - nm_log_dbg (LOGD_BT, "(%s -> %s): SDP search finished with type=%d status=%d", - context->src_str, context->dst_str, status, type); + if ( context->cdat->rfcomm_sdp_search_error + || context->rfcomm_channel >= 0) + return; + + _LOGD (context, "SDP search finished with type=%d status=%d", + status, type); /* SDP response received */ - if (status || type != SDP_SVC_SEARCH_ATTR_RSP) { - GError *error = g_error_new (NM_BT_ERROR, - NM_BT_ERROR_DUN_CONNECT_FAILED, - "Did not get a Service Discovery response"); - context->callback (context, NULL, error, context->user_data); - goto done; + if ( status + || type != SDP_SVC_SEARCH_ATTR_RSP) { + g_set_error (&context->cdat->rfcomm_sdp_search_error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "did not get a Service Discovery response"); + return; } scanned = sdp_extract_seqtype (rsp, bytesleft, &dataType, &seqlen); - nm_log_dbg (LOGD_BT, "(%s -> %s): SDP sequence type scanned=%d length=%d", - context->src_str, context->dst_str, scanned, seqlen); + _LOGD (context, "SDP sequence type scanned=%d length=%d", + scanned, seqlen); scanned = sdp_extract_seqtype (rsp, bytesleft, &dataType, &seqlen); - if (!scanned || !seqlen) { + if ( !scanned + || !seqlen) { /* Short read or unknown sequence type */ - GError *error = g_error_new (NM_BT_ERROR, - NM_BT_ERROR_DUN_CONNECT_FAILED, - "Improper Service Discovery response"); - context->callback (context, NULL, error, context->user_data); - goto done; + g_set_error (&context->cdat->rfcomm_sdp_search_error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "improper Service Discovery response"); + return; } rsp += scanned; @@ -194,90 +442,153 @@ sdp_search_completed_cb (uint8_t type, uint16_t status, uint8_t *rsp, size_t siz channel = sdp_get_proto_port (protos, RFCOMM_UUID); sdp_list_free (protos, NULL); - nm_log_dbg (LOGD_BT, "(%s -> %s): SDP channel=%d", - context->src_str, context->dst_str, channel); + _LOGD (context, "SDP channel=%d", + channel); } sdp_record_free (rec); scanned += recsize; rsp += recsize; bytesleft -= recsize; - } while ((scanned < (ssize_t) size) && (bytesleft > 0) && (channel < 0)); - -done: - if (channel != -1) { - context->rfcomm_channel = channel; - dun_connect (context); + } while ( scanned < (ssize_t) size + && bytesleft > 0 + && channel < 0); + + if (channel == -1) { + g_set_error (&context->cdat->rfcomm_sdp_search_error, + NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "did not receive rfcomm-channel"); + return; } - sdp_search_cleanup (context); + context->rfcomm_channel = channel; } static gboolean -sdp_search_process_cb (GIOChannel *channel, GIOCondition condition, gpointer user_data) +_connect_sdp_search_io_cb (GIOChannel *io_channel, + GIOCondition condition, + gpointer user_data) { NMBluez5DunContext *context = user_data; - - nm_log_dbg (LOGD_BT, "(%s -> %s): SDP search progressed with condition=%d", - context->src_str, context->dst_str, condition); + gs_free_error GError *error = NULL; + int errsv; if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { - GError *error = g_error_new (NM_BT_ERROR, - NM_BT_ERROR_DUN_CONNECT_FAILED, - "Service Discovery interrupted"); - context->callback (context, NULL, error, context->user_data); - sdp_search_cleanup (context); - return FALSE; + _LOGD (context, "SDP search returned with invalid IO condition 0x%x", + (guint) condition); + error = g_error_new (NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "Service Discovery interrupted"); + context->cdat->source_id = 0; + _context_invoke_callback_fail_and_free (context, error); + return G_SOURCE_REMOVE; } - if (sdp_process (context->sdp_session) < 0) { - nm_log_dbg (LOGD_BT, "(%s -> %s): SDP search finished", - context->src_str, context->dst_str); + if (sdp_process (context->cdat->sdp_session) == 0) { + _LOGD (context, "SDP search still not finished"); + return G_SOURCE_CONTINUE; + } - /* Search finished successfully. */ - return FALSE; + context->cdat->source_id = 0; + + if ( context->rfcomm_channel < 0 + && !context->cdat->rfcomm_sdp_search_error) { + errsv = sdp_get_error (context->cdat->sdp_session); + _LOGD (context, "SDP search failed: %s (%d)", + nm_strerror_native (errsv), errsv); + error = g_error_new (NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "Service Discovery failed with %s (%d)", + nm_strerror_native (errsv), errsv); + _context_invoke_callback_fail_and_free (context, error); + return G_SOURCE_REMOVE; } - /* Search progressed successfully. */ - return TRUE; + if (context->cdat->rfcomm_sdp_search_error) { + _LOGD (context, "SDP search failed to complete: %s", context->cdat->rfcomm_sdp_search_error->message); + _context_invoke_callback_fail_and_free (context, context->cdat->rfcomm_sdp_search_error); + return G_SOURCE_REMOVE; + } + + nm_clear_pointer (&context->cdat->sdp_session, sdp_close); + + _connect_socket_connect (context); + + return G_SOURCE_REMOVE; } static gboolean -sdp_connect_watch (GIOChannel *channel, GIOCondition condition, gpointer user_data) +_connect_sdp_session_start_on_idle_cb (gpointer user_data) { NMBluez5DunContext *context = user_data; - sdp_list_t *search, *attrs; + gs_free_error GError *error = NULL; + + context->cdat->source_id = 0; + + _LOGD (context, "retry starting sdp-session..."); + + if (!_connect_sdp_session_start (context, &error)) + _context_invoke_callback_fail_and_free (context, error); + + return G_SOURCE_REMOVE; +} + +static gboolean +_connect_sdp_io_cb (GIOChannel *io_channel, + GIOCondition condition, + gpointer user_data) +{ + NMBluez5DunContext *context = user_data; + sdp_list_t *search; + sdp_list_t *attrs; uuid_t svclass; uint16_t attr; - int fd, fd_err = 0; - int err; + int fd; + int errsv; + int fd_err = 0; + int r; socklen_t len = sizeof (fd_err); - GError *error = NULL; + gs_free_error GError *error = NULL; + + context->cdat->source_id = 0; - context->sdp_watch_id = 0; + fd = g_io_channel_unix_get_fd (io_channel); + + _LOGD (context, "sdp-session ready to connect with fd=%d", fd); - fd = g_io_channel_unix_get_fd (channel); if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &fd_err, &len) < 0) { - err = errno; - nm_log_dbg (LOGD_BT, "(%s -> %s): getsockopt error=%d", - context->src_str, context->dst_str, err); - } else { - err = fd_err; - nm_log_dbg (LOGD_BT, "(%s -> %s): SO_ERROR error=%d", - context->src_str, context->dst_str, fd_err); + errsv = NM_ERRNO_NATIVE (errno); + error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, + "error for getsockopt on Service Discovery socket: %s (%d)", + nm_strerror_native (errsv), errsv); + goto done; } - if (err != 0) { + if (fd_err != 0) { + errsv = nm_errno_native (fd_err); + + if ( NM_IN_SET (errsv, ECONNREFUSED, EHOSTDOWN) + && --context->cdat->sdp_session_try_count > 0) { + /* *sigh* */ + _LOGD (context, "sdp-session failed with %s (%d). Retry in a bit", nm_strerror_native (errsv), errsv); + nm_clear_g_source (&context->cdat->source_id); + context->cdat->source_id = g_timeout_add (1000, + _connect_sdp_session_start_on_idle_cb, + context); + return G_SOURCE_REMOVE; + } + error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Error on Service Discovery socket: (%d) %s", - err, nm_strerror_native (err)); + "error on Service Discovery socket: %s (%d)", + nm_strerror_native (errsv), errsv); goto done; } - if (sdp_set_notify (context->sdp_session, sdp_search_completed_cb, context) < 0) { + if (sdp_set_notify (context->cdat->sdp_session, _connect_sdp_search_cb, context) < 0) { /* Should not be reached, only can fail if we passed bad sdp_session. */ error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Could not request Service Discovery notification"); + "could not set Service Discovery notification"); goto done; } @@ -286,124 +597,261 @@ sdp_connect_watch (GIOChannel *channel, GIOCondition condition, gpointer user_da attr = SDP_ATTR_PROTO_DESC_LIST; attrs = sdp_list_append (NULL, &attr); - if (!sdp_service_search_attr_async (context->sdp_session, search, SDP_ATTR_REQ_INDIVIDUAL, attrs)) { - /* Set callback responsible for update the internal SDP transaction */ - context->sdp_watch_id = g_io_add_watch (channel, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - sdp_search_process_cb, - context); - } else { - err = sdp_get_error (context->sdp_session); - error = g_error_new (NM_BT_ERROR, - NM_BT_ERROR_DUN_CONNECT_FAILED, - "Error starting Service Discovery: (%d) %s", - err, nm_strerror_native (err)); - } + r = sdp_service_search_attr_async (context->cdat->sdp_session, + search, + SDP_ATTR_REQ_INDIVIDUAL, + attrs); sdp_list_free (attrs, NULL); sdp_list_free (search, NULL); -done: - if (error) { - context->callback (context, NULL, error, context->user_data); - sdp_search_cleanup (context); + if (r < 0) { + errsv = nm_errno_native (sdp_get_error (context->cdat->sdp_session)); + error = g_error_new (NM_BT_ERROR, + NM_BT_ERROR_DUN_CONNECT_FAILED, + "error starting Service Discovery: %s (%d)", + nm_strerror_native (errsv), errsv); + goto done; } + /* Set callback responsible for update the internal SDP transaction */ + context->cdat->source_id = g_io_add_watch (io_channel, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + _connect_sdp_search_io_cb, + context); + +done: + if (error) + _context_invoke_callback_fail_and_free (context, error); return G_SOURCE_REMOVE; } -NMBluez5DunContext * -nm_bluez5_dun_new (const char *adapter, - const char *remote) +/*****************************************************************************/ +static void +_connect_cancelled_cb (GCancellable *cancellable, + NMBluez5DunContext *context) { - NMBluez5DunContext *context; - - context = g_slice_new0 (NMBluez5DunContext); - str2ba (adapter, &context->src); - str2ba (remote, &context->dst); - context->src_str = g_strdup (adapter); - context->dst_str = g_strdup (remote); - context->rfcomm_channel = -1; - context->rfcomm_id = -1; - context->rfcomm_fd = -1; - return context; + gs_free_error GError *error = NULL; + + if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) + g_return_if_reached (); + + _context_invoke_callback_fail_and_free (context, error); } -void -nm_bluez5_dun_connect (NMBluez5DunContext *context, - NMBluez5DunFunc callback, - gpointer user_data) +static gboolean +_connect_sdp_session_start (NMBluez5DunContext *context, + GError **error) { - GIOChannel *channel; + nm_auto_unref_io_channel GIOChannel *io_channel = NULL; - context->callback = callback; - context->user_data = user_data; + nm_assert (context->cdat); - if (context->rfcomm_channel != -1) { - nm_log_dbg (LOGD_BT, "(%s): channel number on device %s cached: %d", - context->src_str, context->dst_str, context->rfcomm_channel); - /* FIXME: don't invoke the callback synchronously. */ - dun_connect (context); - return; + nm_clear_g_source (&context->cdat->source_id); + nm_clear_pointer (&context->cdat->sdp_session, sdp_close); + + context->cdat->sdp_session = sdp_connect (&context->src, &context->dst, SDP_NON_BLOCKING); + if (!context->cdat->sdp_session) { + int errsv = nm_errno_native (errno); + + g_set_error (error, NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, + "failed to connect to the SDP server: %s (%d)", + nm_strerror_native (errsv), errsv); + return FALSE; } - nm_log_dbg (LOGD_BT, "(%s): starting channel number discovery for device %s", - context->src_str, context->dst_str); + io_channel = g_io_channel_unix_new (sdp_get_socket (context->cdat->sdp_session)); + context->cdat->source_id = g_io_add_watch (io_channel, + G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + _connect_sdp_io_cb, + context); + return TRUE; +} - context->sdp_session = sdp_connect (&context->src, &context->dst, SDP_NON_BLOCKING); - if (!context->sdp_session) { - GError *error; - int err = sdp_get_error (context->sdp_session); +/*****************************************************************************/ + +gboolean +nm_bluez5_dun_connect (const char *adapter, + const char *remote, + GCancellable *cancellable, + NMBluez5DunConnectCb callback, + gpointer callback_user_data, + NMBluez5DunNotifyTtyHangupCb notify_tty_hangup_cb, + gpointer notify_tty_hangup_user_data, + GError **error) +{ + nm_auto_free_context NMBluez5DunContext *context = NULL; + ConnectData *cdat; + gsize src_l; + gsize dst_l; + + g_return_val_if_fail (adapter, FALSE); + g_return_val_if_fail (remote, FALSE); + g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE); + g_return_val_if_fail (callback, FALSE); + g_return_val_if_fail (notify_tty_hangup_cb, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + nm_assert (!g_cancellable_is_cancelled (cancellable)); + + src_l = strlen (adapter) + 1; + dst_l = strlen (remote) + 1; + + cdat = g_slice_new (ConnectData); + *cdat = (ConnectData) { + .callback = callback, + .callback_user_data = callback_user_data, + .cancellable = g_object_ref (cancellable), + .sdp_session_try_count = 5, + }; - error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, - "Failed to connect to the SDP server: (%d) %s", - err, nm_strerror_native (err)); - /* FIXME: don't invoke the callback synchronously. */ - context->callback (context, NULL, error, context->user_data); - return; + context = g_malloc (sizeof (NMBluez5DunContext) + src_l + dst_l); + *context = (NMBluez5DunContext) { + .cdat = cdat, + .notify_tty_hangup_cb = notify_tty_hangup_cb, + .notify_tty_hangup_user_data = notify_tty_hangup_user_data, + .rfcomm_tty_no = -1, + .rfcomm_sock_fd = -1, + .rfcomm_tty_fd = -1, + .rfcomm_channel = -1, + }; + memcpy (&context->src_str[0], adapter, src_l); + context->dst_str = &context->src_str[src_l]; + memcpy ((char *) context->dst_str, remote, dst_l); + + if (str2ba (adapter, &context->src) < 0) { + g_set_error (error, NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, + "invalid source"); + return FALSE; } - /* FIXME(shutdown): make connect cancellable. */ - channel = g_io_channel_unix_new (sdp_get_socket (context->sdp_session)); - context->sdp_watch_id = g_io_add_watch (channel, - G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - sdp_connect_watch, - context); - g_io_channel_unref (channel); + if (str2ba (remote, &context->dst) < 0) { + g_set_error (error, NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED, + "invalid remote"); + return FALSE; + } + + context->cdat->cancelled_id = g_signal_connect (context->cdat->cancellable, + "cancelled", + G_CALLBACK (_connect_cancelled_cb), + context); + + if (!_connect_sdp_session_start (context, error)) + return FALSE; + + _LOGD (context, "starting channel number discovery for device %s", + context->dst_str); + + g_steal_pointer (&context); + return TRUE; } -/* Only clean up connection-related stuff to allow reconnect */ +/*****************************************************************************/ + void -nm_bluez5_dun_cleanup (NMBluez5DunContext *context) +nm_bluez5_dun_disconnect (NMBluez5DunContext *context) { - g_return_if_fail (context != NULL); + nm_assert (context); + nm_assert (!context->cdat); - sdp_search_cleanup (context); + _LOGD (context, "disconnecting DUN connection"); - if (context->rfcomm_fd >= 0) { - if (context->rfcomm_id >= 0) { - struct rfcomm_dev_req req = { 0 }; + _context_free (context); +} - req.dev_id = context->rfcomm_id; - (void) ioctl (context->rfcomm_fd, RFCOMMRELEASEDEV, &req); - context->rfcomm_id = -1; - } - nm_close (context->rfcomm_fd); - context->rfcomm_fd = -1; - } +/*****************************************************************************/ - nm_close (context->rfcomm_tty_fd); - context->rfcomm_tty_fd = -1; +static void +_context_cleanup_connect_data (NMBluez5DunContext *context) +{ + ConnectData *cdat; + + cdat = g_steal_pointer (&context->cdat); + if (!cdat) + return; + + nm_clear_g_signal_handler (cdat->cancellable, &cdat->cancelled_id); + + nm_clear_g_source (&cdat->source_id); + + nm_clear_pointer (&cdat->sdp_session, sdp_close); + + g_clear_object (&cdat->cancellable); + + g_clear_error (&cdat->rfcomm_sdp_search_error); + + nm_g_slice_free (cdat); } -void -nm_bluez5_dun_free (NMBluez5DunContext *context) +static void +_context_invoke_callback (NMBluez5DunContext *context, + GError *error) +{ + NMBluez5DunConnectCb callback; + gpointer callback_user_data; + + nm_assert (context); + nm_assert (context->cdat); + nm_assert (context->cdat->callback); + nm_assert (error || context->rfcomm_tty_path); + + if (!error) + _LOGD (context, "connected via \"%s\"", context->rfcomm_tty_path); + else if (nm_utils_error_is_cancelled (error, FALSE)) + _LOGD (context, "cancelled"); + else + _LOGD (context, "failed to connect: %s", error->message); + + callback = context->cdat->callback; + callback_user_data = context->cdat->callback_user_data; + + _context_cleanup_connect_data (context); + + callback (error ? NULL : context, + error ? NULL : context->rfcomm_tty_path, + error, + callback_user_data); +} + +static void +_context_invoke_callback_success (NMBluez5DunContext *context) { - g_return_if_fail (context != NULL); + nm_assert (context->rfcomm_tty_path); + _context_invoke_callback (context, NULL); +} + +static void +_context_invoke_callback_fail_and_free (NMBluez5DunContext *context, + GError *error) +{ + nm_assert (error); + _context_invoke_callback (context, error); + _context_free (context); +} + +static void +_context_free (NMBluez5DunContext *context) +{ + nm_assert (context); + + _context_cleanup_connect_data (context); + + nm_clear_g_source (&context->rfcomm_tty_poll_id); + + if (context->rfcomm_sock_fd >= 0) { + if (context->rfcomm_tty_no >= 0) { + struct rfcomm_dev_req req; + + memset (&req, 0, sizeof (struct rfcomm_dev_req)); + req.dev_id = context->rfcomm_tty_no; + context->rfcomm_tty_no = -1; + (void) ioctl (context->rfcomm_sock_fd, RFCOMMRELEASEDEV, &req); + } + nm_close (nm_steal_fd (&context->rfcomm_sock_fd)); + } - nm_bluez5_dun_cleanup (context); - g_clear_pointer (&context->src_str, g_free); - g_clear_pointer (&context->dst_str, g_free); - g_slice_free (NMBluez5DunContext, context); + if (context->rfcomm_tty_fd >= 0) + nm_close (nm_steal_fd (&context->rfcomm_tty_fd)); + nm_clear_g_free (&context->rfcomm_tty_path); + g_free (context); } diff --git a/src/devices/bluetooth/nm-bluez5-dun.h b/src/devices/bluetooth/nm-bluez5-dun.h index b605414b..b3f22965 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.h +++ b/src/devices/bluetooth/nm-bluez5-dun.h @@ -1,43 +1,38 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ -#ifndef _NM_BLUEZ5_UTILS_H_ -#define _NM_BLUEZ5_UTILS_H_ +#ifndef __NM_BLUEZ5_DUN_H__ +#define __NM_BLUEZ5_DUN_H__ typedef struct _NMBluez5DunContext NMBluez5DunContext; -typedef void (*NMBluez5DunFunc) (NMBluez5DunContext *context, - const char *rfcomm_dev, - GError *error, - gpointer user_data); +#if WITH_BLUEZ5_DUN -NMBluez5DunContext *nm_bluez5_dun_new (const char *adapter, - const char *remote); +typedef void (*NMBluez5DunConnectCb) (NMBluez5DunContext *context, + const char *rfcomm_dev, + GError *error, + gpointer user_data); -void nm_bluez5_dun_connect (NMBluez5DunContext *context, - NMBluez5DunFunc callback, - gpointer user_data); +typedef void (*NMBluez5DunNotifyTtyHangupCb) (NMBluez5DunContext *context, + gpointer user_data); -/* Clean up connection resources */ -void nm_bluez5_dun_cleanup (NMBluez5DunContext *context); +gboolean nm_bluez5_dun_connect (const char *adapter, + const char *remote, + GCancellable *cancellable, + NMBluez5DunConnectCb callback, + gpointer callback_user_data, + NMBluez5DunNotifyTtyHangupCb notify_tty_hangup_cb, + gpointer notify_tty_hangup_user_data, + GError **error); -/* Clean up and dispose all resources */ -void nm_bluez5_dun_free (NMBluez5DunContext *context); +void nm_bluez5_dun_disconnect (NMBluez5DunContext *context); -#endif /* _NM_BLUEZ5_UTILS_H_ */ +const char *nm_bluez5_dun_context_get_adapter (const NMBluez5DunContext *context); +const char *nm_bluez5_dun_context_get_remote (const NMBluez5DunContext *context); +const char *nm_bluez5_dun_context_get_rfcomm_dev (const NMBluez5DunContext *context); + +#endif /* WITH_BLUEZ5_DUN */ + +#endif /* __NM_BLUEZ5_DUN_H__ */ diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c deleted file mode 100644 index 9c5e8644..00000000 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ /dev/null @@ -1,596 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2017 Red Hat, Inc. - * Copyright (C) 2013 Intel Corporation. - */ - -#include "nm-default.h" - -#include "nm-bluez5-manager.h" - -#include <signal.h> -#include <stdlib.h> - -#include "nm-core-internal.h" - -#include "c-list/src/c-list.h" -#include "nm-bluez-device.h" -#include "nm-bluez-common.h" -#include "devices/nm-device-bridge.h" -#include "settings/nm-settings.h" - -/*****************************************************************************/ - -enum { - BDADDR_ADDED, - NETWORK_SERVER_ADDED, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct { - NMSettings *settings; - - GDBusProxy *proxy; - - GHashTable *devices; - - CList network_servers; -} NMBluez5ManagerPrivate; - -struct _NMBluez5Manager { - GObject parent; - NMBtVTableNetworkServer network_server_vtable; - NMBluez5ManagerPrivate _priv; -}; - -struct _NMBluez5ManagerClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE (NMBluez5Manager, nm_bluez5_manager, G_TYPE_OBJECT) - -#define NM_BLUEZ5_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMBluez5Manager, NM_IS_BLUEZ5_MANAGER) - -#define NM_BLUEZ5_MANAGER_GET_NETWORK_SERVER_VTABLE(self) (&(self)->network_server_vtable) -#define NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER(vtable) \ - NM_BLUEZ5_MANAGER(((char *)(vtable)) - offsetof (struct _NMBluez5Manager, network_server_vtable)) - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_BT -#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bluez5", __VA_ARGS__) - -/*****************************************************************************/ - -static void device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self); -static void device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *self); - -/*****************************************************************************/ - -typedef struct { - char *path; - char *addr; - NMDevice *device; - CList lst_ns; -} NetworkServer; - -static NetworkServer * -_find_network_server (NMBluez5Manager *self, const char *path, NMDevice *device) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NetworkServer *network_server; - - nm_assert (path || NM_IS_DEVICE (device)); - - c_list_for_each_entry (network_server, &priv->network_servers, lst_ns) { - if (path && !nm_streq (network_server->path, path)) - continue; - if (device && network_server->device != device) - continue; - return network_server; - } - return NULL; -} - -static NetworkServer * -_find_network_server_for_addr (NMBluez5Manager *self, const char *addr) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NetworkServer *network_server; - - c_list_for_each_entry (network_server, &priv->network_servers, lst_ns) { - /* The address lookups need a server not assigned to a device - * and tolerate an empty address as a wildcard for "any". */ - if ( !network_server->device - && (!addr || nm_streq (network_server->addr, addr))) - return network_server; - } - return NULL; -} - -static void -_network_server_unregister (NMBluez5Manager *self, NetworkServer *network_server) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - - if (!network_server->device) { - /* Not connected. */ - return; - } - - _LOGI ("NAP: unregistering %s from %s", - nm_device_get_iface (network_server->device), - network_server->addr); - - g_dbus_connection_call (g_dbus_proxy_get_connection (priv->proxy), - NM_BLUEZ_SERVICE, - network_server->path, - NM_BLUEZ5_NETWORK_SERVER_INTERFACE, - "Unregister", - g_variant_new ("(s)", BLUETOOTH_CONNECT_NAP), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, NULL, NULL); - - g_clear_object (&network_server->device); -} - -static void -_network_server_free (NMBluez5Manager *self, NetworkServer *network_server) -{ - _network_server_unregister (self, network_server); - c_list_unlink_stale (&network_server->lst_ns); - g_free (network_server->path); - g_free (network_server->addr); - g_slice_free (NetworkServer, network_server); -} - -static gboolean -network_server_is_available (const NMBtVTableNetworkServer *vtable, - const char *addr) -{ - NMBluez5Manager *self = NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER (vtable); - - return !!_find_network_server_for_addr (self, addr); -} - -static gboolean -network_server_register_bridge (const NMBtVTableNetworkServer *vtable, - const char *addr, - NMDevice *device) -{ - NMBluez5Manager *self = NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER (vtable); - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NetworkServer *network_server = _find_network_server_for_addr (self, addr); - - nm_assert (NM_IS_DEVICE (device)); - nm_assert (!_find_network_server (self, NULL, device)); - - if (!network_server) { - /* The device checked that a network server is available, before - * starting the activation, but for some reason it no longer is. - * Indicate that the activation should not proceed. */ - _LOGI ("NAP: %s is not available for %s", addr, nm_device_get_iface (device)); - return FALSE; - } - - _LOGI ("NAP: registering %s on %s", nm_device_get_iface (device), network_server->addr); - - g_dbus_connection_call (g_dbus_proxy_get_connection (priv->proxy), - NM_BLUEZ_SERVICE, - network_server->path, - NM_BLUEZ5_NETWORK_SERVER_INTERFACE, - "Register", - g_variant_new ("(ss)", BLUETOOTH_CONNECT_NAP, nm_device_get_iface (device)), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, NULL, NULL); - - network_server->device = g_object_ref (device); - - return TRUE; -} - -static gboolean -network_server_unregister_bridge (const NMBtVTableNetworkServer *vtable, - NMDevice *device) -{ - NMBluez5Manager *self = NETWORK_SERVER_VTABLE_GET_NM_BLUEZ5_MANAGER (vtable); - NetworkServer *network_server = _find_network_server (self, NULL, device); - - if (network_server) - _network_server_unregister (self, network_server); - - return TRUE; -} - -static void -network_server_removed (GDBusProxy *proxy, const char *path, NMBluez5Manager *self) -{ - NetworkServer *network_server; - - network_server = _find_network_server (self, path, NULL); - if (!network_server) - return; - - if (network_server->device) { - nm_device_queue_state (network_server->device, NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_BT_FAILED); - } - _LOGI ("NAP: removed interface %s", network_server->addr); - _network_server_free (self, network_server); -} - -static void -network_server_added (GDBusProxy *proxy, const char *path, const char *addr, NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NetworkServer *network_server; - - /* If BlueZ messes up and announces a single network server twice, - * make sure we get rid of the older instance first. */ - network_server_removed (proxy, path, self); - - network_server = g_slice_new0 (NetworkServer); - network_server->path = g_strdup (path); - network_server->addr = g_strdup (addr); - c_list_link_before (&priv->network_servers, &network_server->lst_ns); - - _LOGI ("NAP: added interface %s", addr); - - g_signal_emit (self, signals[NETWORK_SERVER_ADDED], 0); -} - -/*****************************************************************************/ - -static void -emit_bdaddr_added (NMBluez5Manager *self, NMBluezDevice *device) -{ - g_signal_emit (self, signals[BDADDR_ADDED], 0, - device, - nm_bluez_device_get_address (device), - nm_bluez_device_get_name (device), - nm_bluez_device_get_path (device), - nm_bluez_device_get_capabilities (device)); -} - -void -nm_bluez5_manager_query_devices (NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - if (nm_bluez_device_get_usable (device)) - emit_bdaddr_added (self, device); - } -} - -static void -remove_device (NMBluez5Manager *self, NMBluezDevice *device) -{ - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_initialized), self); - g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_usable), self); - if (nm_bluez_device_get_usable (device)) - g_signal_emit_by_name (device, NM_BLUEZ_DEVICE_REMOVED); -} - -static void -remove_all_devices (NMBluez5Manager *self) -{ - GHashTableIter iter; - NMBluezDevice *device; - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - - g_hash_table_iter_init (&iter, priv->devices); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { - g_hash_table_iter_steal (&iter); - remove_device (self, device); - g_object_unref (device); - } -} - -static void -device_usable (NMBluezDevice *device, GParamSpec *pspec, NMBluez5Manager *self) -{ - gboolean usable = nm_bluez_device_get_usable (device); - - _LOGD ("(%s): bluez device now %s", - nm_bluez_device_get_path (device), - usable ? "usable" : "unusable"); - - if (usable) { - _LOGD ("(%s): bluez device address %s", - nm_bluez_device_get_path (device), - nm_bluez_device_get_address (device)); - emit_bdaddr_added (self, device); - } else - g_signal_emit_by_name (device, NM_BLUEZ_DEVICE_REMOVED); -} - -static void -device_initialized (NMBluezDevice *device, gboolean success, NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - - _LOGD ("(%s): bluez device %s", - nm_bluez_device_get_path (device), - success ? "initialized" : "failed to initialize"); - if (!success) - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); -} - -static void -device_added (GDBusProxy *proxy, const char *path, NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - - device = nm_bluez_device_new (path, NULL, priv->settings, 5); - g_signal_connect (device, NM_BLUEZ_DEVICE_INITIALIZED, G_CALLBACK (device_initialized), self); - g_signal_connect (device, "notify::" NM_BLUEZ_DEVICE_USABLE, G_CALLBACK (device_usable), self); - g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); - - _LOGD ("(%s): new bluez device found", path); -} - -static void -device_removed (GDBusProxy *proxy, const char *path, NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NMBluezDevice *device; - - _LOGD ("(%s): bluez device removed", path); - - device = g_hash_table_lookup (priv->devices, path); - if (device) { - g_hash_table_steal (priv->devices, nm_bluez_device_get_path (device)); - remove_device (NM_BLUEZ5_MANAGER (self), device); - g_object_unref (device); - } -} - -static void -object_manager_interfaces_added (GDBusProxy *proxy, - const char *path, - GVariant *dict, - NMBluez5Manager *self) -{ - if (g_variant_lookup (dict, NM_BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL)) - device_added (proxy, path, self); - if (g_variant_lookup (dict, NM_BLUEZ5_NETWORK_SERVER_INTERFACE, "a{sv}", NULL)) { - gs_unref_variant GVariant *adapter = g_variant_lookup_value (dict, NM_BLUEZ5_ADAPTER_INTERFACE, G_VARIANT_TYPE_DICTIONARY); - const char *address; - - if ( adapter - && g_variant_lookup (adapter, "Address", "&s", &address)) - network_server_added (proxy, path, address, self); - } -} - -static void -object_manager_interfaces_removed (GDBusProxy *proxy, - const char *path, - const char **ifaces, - NMBluez5Manager *self) -{ - if (ifaces && g_strv_contains (ifaces, NM_BLUEZ5_DEVICE_INTERFACE)) - device_removed (proxy, path, self); - if (ifaces && g_strv_contains (ifaces, NM_BLUEZ5_NETWORK_SERVER_INTERFACE)) - network_server_removed (proxy, path, self); -} - -static void -get_managed_objects_cb (GDBusProxy *proxy, - GAsyncResult *res, - NMBluez5Manager *self) -{ - gs_unref_variant GVariant *variant0 = NULL; - GVariant *variant, *ifaces; - GVariantIter i; - GError *error = NULL; - const char *path; - - variant = _nm_dbus_proxy_call_finish (proxy, res, - G_VARIANT_TYPE ("(a{oa{sa{sv}}})"), - &error); - if (!variant) { - if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) - _LOGW ("Couldn't get managed objects: not running Bluez5?"); - else { - g_dbus_error_strip_remote_error (error); - _LOGW ("Couldn't get managed objects: %s", error->message); - } - g_clear_error (&error); - return; - } - variant0 = g_variant_get_child_value (variant, 0); - g_variant_iter_init (&i, variant0); - while ((g_variant_iter_next (&i, "{&o*}", &path, &ifaces))) { - object_manager_interfaces_added (proxy, path, ifaces, self); - g_variant_unref (ifaces); - } - - g_variant_unref (variant); -} - -static void name_owner_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data); - -static void -on_proxy_acquired (GObject *object, - GAsyncResult *res, - NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - - priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (!priv->proxy) { - _LOGW ("Couldn't acquire object manager proxy: %s", error->message); - g_clear_error (&error); - return; - } - - g_signal_connect (priv->proxy, "notify::g-name-owner", - G_CALLBACK (name_owner_changed_cb), self); - - /* Get already managed devices. */ - g_dbus_proxy_call (priv->proxy, "GetManagedObjects", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) get_managed_objects_cb, - self); - - _nm_dbus_signal_connect (priv->proxy, "InterfacesAdded", G_VARIANT_TYPE ("(oa{sa{sv}})"), - G_CALLBACK (object_manager_interfaces_added), self); - _nm_dbus_signal_connect (priv->proxy, "InterfacesRemoved", G_VARIANT_TYPE ("(oas)"), - G_CALLBACK (object_manager_interfaces_removed), self); -} - -static void -bluez_connect (NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - - g_return_if_fail (priv->proxy == NULL); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - NM_BLUEZ_SERVICE, - NM_BLUEZ_MANAGER_PATH, - NM_OBJECT_MANAGER_INTERFACE, - NULL, - (GAsyncReadyCallback) on_proxy_acquired, - self); -} - -static void -name_owner_changed_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - char *owner; - - if (priv->devices) { - owner = g_dbus_proxy_get_name_owner (priv->proxy); - if (!owner) - remove_all_devices (self); - g_free (owner); - } -} - -/*****************************************************************************/ - -static void -nm_bluez5_manager_init (NMBluez5Manager *self) -{ - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - NMBtVTableNetworkServer *network_server_vtable = NM_BLUEZ5_MANAGER_GET_NETWORK_SERVER_VTABLE (self); - - bluez_connect (self); - - priv->devices = g_hash_table_new_full (nm_str_hash, g_str_equal, - NULL, g_object_unref); - - c_list_init (&priv->network_servers); - - nm_assert (!nm_bt_vtable_network_server); - network_server_vtable->is_available = network_server_is_available; - network_server_vtable->register_bridge = network_server_register_bridge; - network_server_vtable->unregister_bridge = network_server_unregister_bridge; - nm_bt_vtable_network_server = network_server_vtable; -} - -NMBluez5Manager * -nm_bluez5_manager_new (NMSettings *settings) -{ - NMBluez5Manager *instance = NULL; - - g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); - - instance = g_object_new (NM_TYPE_BLUEZ5_MANAGER, NULL); - NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->settings = g_object_ref (settings); - return instance; -} - -static void -dispose (GObject *object) -{ - NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - CList *iter, *safe; - - c_list_for_each_safe (iter, safe, &priv->network_servers) - _network_server_free (self, c_list_entry (iter, NetworkServer, lst_ns)); - - if (priv->proxy) { - g_signal_handlers_disconnect_by_func (priv->proxy, G_CALLBACK (name_owner_changed_cb), self); - g_clear_object (&priv->proxy); - } - - g_hash_table_remove_all (priv->devices); - - G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - - g_hash_table_destroy (priv->devices); - - G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->finalize (object); - - g_object_unref (priv->settings); -} - -static void -nm_bluez5_manager_class_init (NMBluez5ManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dispose; - object_class->finalize = finalize; - - signals[BDADDR_ADDED] = - g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 5, G_TYPE_OBJECT, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); - - signals[NETWORK_SERVER_ADDED] = - g_signal_new (NM_BLUEZ_MANAGER_NETWORK_SERVER_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h deleted file mode 100644 index 14ac842e..00000000 --- a/src/devices/bluetooth/nm-bluez5-manager.h +++ /dev/null @@ -1,40 +0,0 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2013 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_BLUEZ5_MANAGER_H__ -#define __NETWORKMANAGER_BLUEZ5_MANAGER_H__ - -#define NM_TYPE_BLUEZ5_MANAGER (nm_bluez5_manager_get_type ()) -#define NM_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5Manager)) -#define NM_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) -#define NM_IS_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_BLUEZ5_MANAGER)) -#define NM_IS_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_BLUEZ5_MANAGER)) -#define NM_BLUEZ5_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) - -typedef struct _NMBluez5Manager NMBluez5Manager; -typedef struct _NMBluez5ManagerClass NMBluez5ManagerClass; - -GType nm_bluez5_manager_get_type (void); - -NMBluez5Manager *nm_bluez5_manager_new (NMSettings *settings); - -void nm_bluez5_manager_query_devices (NMBluez5Manager *manager); - -#endif /* __NETWORKMANAGER_BLUEZ5_MANAGER_H__ */ diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/devices/bluetooth/nm-bt-error.c index bc9e5aa4..8aa4283d 100644 --- a/src/devices/bluetooth/nm-bt-error.c +++ b/src/devices/bluetooth/nm-bt-error.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/nm-bt-error.h b/src/devices/bluetooth/nm-bt-error.h index ed7ed90d..258fca8d 100644 --- a/src/devices/bluetooth/nm-bt-error.h +++ b/src/devices/bluetooth/nm-bt-error.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index f8626011..497810c3 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2011 Red Hat, Inc. */ @@ -23,8 +9,9 @@ #include <stdio.h> +#include "nm-core-internal.h" #include "nm-bluez-common.h" -#include "nm-bluez-device.h" +#include "nm-bluez-manager.h" #include "devices/nm-device-private.h" #include "ppp/nm-ppp-manager.h" #include "nm-setting-connection.h" @@ -48,10 +35,12 @@ _LOG_DECLARE_SELF(NMDeviceBt); /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_BT_NAME, +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceBt, + PROP_BT_BDADDR, + PROP_BT_BZ_MGR, PROP_BT_CAPABILITIES, - PROP_BT_DEVICE, + PROP_BT_DBUS_PATH, + PROP_BT_NAME, ); enum { @@ -64,24 +53,38 @@ static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { NMModemManager *modem_manager; - gboolean mm_running; + NMBluezManager *bz_mgr; - NMBluezDevice *bt_device; + char *dbus_path; char *bdaddr; char *name; - guint32 capabilities; - gboolean connected; - gboolean have_iface; + char *connect_rfcomm_iface; + + GSList *connect_modem_candidates; - char *rfcomm_iface; NMModem *modem; - guint timeout_id; - GCancellable *cancellable; + GCancellable *connect_bz_cancellable; + + gulong connect_watch_link_id; + + guint connect_watch_link_idle_id; + + guint connect_wait_modem_id; + + NMBluetoothCapabilities capabilities:6; + + NMBluetoothCapabilities connect_bt_type:6; /* BT type of the current connection */ + + NMDeviceStageState stage1_bt_state:3; + NMDeviceStageState stage1_modem_prepare_state:3; + + bool is_connected:1; + + bool mm_running:1; - guint32 bt_type; /* BT type of the current connection */ } NMDeviceBtPrivate; struct _NMDeviceBt { @@ -95,42 +98,65 @@ struct _NMDeviceBtClass { G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) -#define NM_DEVICE_BT_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceBt, NM_IS_DEVICE_BT) - -/*****************************************************************************/ - -static gboolean modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *out_failure_reason); +#define NM_DEVICE_BT_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceBt, NM_IS_DEVICE_BT, NMDevice) /*****************************************************************************/ -guint32 nm_device_bt_get_capabilities (NMDeviceBt *self) +NMBluetoothCapabilities nm_device_bt_get_capabilities (NMDeviceBt *self) { g_return_val_if_fail (NM_IS_DEVICE_BT (self), NM_BT_CAPABILITY_NONE); return NM_DEVICE_BT_GET_PRIVATE (self)->capabilities; } -static guint32 +static NMBluetoothCapabilities get_connection_bt_type (NMConnection *connection) { NMSettingBluetooth *s_bt; const char *bt_type; s_bt = nm_connection_get_setting_bluetooth (connection); - if (!s_bt) - return NM_BT_CAPABILITY_NONE; - bt_type = nm_setting_bluetooth_get_connection_type (s_bt); - g_assert (bt_type); - - if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)) - return NM_BT_CAPABILITY_DUN; - else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)) - return NM_BT_CAPABILITY_NAP; + if (s_bt) { + bt_type = nm_setting_bluetooth_get_connection_type (s_bt); + if (bt_type) { + if (nm_streq (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)) + return NM_BT_CAPABILITY_DUN; + else if (nm_streq (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)) + return NM_BT_CAPABILITY_NAP; + } + } return NM_BT_CAPABILITY_NONE; } +static gboolean +get_connection_bt_type_check (NMDeviceBt *self, + NMConnection *connection, + NMBluetoothCapabilities *out_bt_type, + GError **error) +{ + NMBluetoothCapabilities bt_type; + + bt_type = get_connection_bt_type (connection); + + NM_SET_OUT (out_bt_type, bt_type); + + if (bt_type == NM_BT_CAPABILITY_NONE) { + nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "profile is not a PANU/DUN bluetooth type"); + return FALSE; + } + + if (!NM_FLAGS_ALL (NM_DEVICE_BT_GET_PRIVATE (self)->capabilities, bt_type)) { + nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "device does not support bluetooth type"); + return FALSE; + } + + return TRUE; +} + static NMDeviceCapabilities get_generic_capabilities (NMDevice *device) { @@ -142,17 +168,24 @@ can_auto_connect (NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); - guint32 bt_type; + NMDeviceBt *self = NM_DEVICE_BT (device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + NMBluetoothCapabilities bt_type; nm_assert (!specific_object || !*specific_object); if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->can_auto_connect (device, sett_conn, NULL)) return FALSE; + if (!get_connection_bt_type_check (self, + nm_settings_connection_get_connection (sett_conn), + &bt_type, + NULL)) + return FALSE; + /* Can't auto-activate a DUN connection without ModemManager */ - bt_type = get_connection_bt_type (nm_settings_connection_get_connection (sett_conn)); - if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) + if ( bt_type == NM_BT_CAPABILITY_DUN + && priv->mm_running == FALSE) return FALSE; return TRUE; @@ -161,20 +194,16 @@ can_auto_connect (NMDevice *device, static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); + NMDeviceBt *self = NM_DEVICE_BT (device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMSettingBluetooth *s_bt; const char *bdaddr; - guint32 bt_type; if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->check_connection_compatible (device, connection, error)) return FALSE; - bt_type = get_connection_bt_type (connection); - if (!NM_FLAGS_ALL (priv->capabilities, bt_type)) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "device does not support bluetooth type of profile"); + if (!get_connection_bt_type_check (self, connection, NULL, error)) return FALSE; - } s_bt = nm_connection_get_setting_bluetooth (connection); @@ -200,18 +229,15 @@ check_connection_available (NMDevice *device, const char *specific_object, GError **error) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); - guint32 bt_type; + NMDeviceBt *self = NM_DEVICE_BT (device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + NMBluetoothCapabilities bt_type; - bt_type = get_connection_bt_type (connection); - if (!(bt_type & priv->capabilities)) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "device does not support bluetooth type"); + if (!get_connection_bt_type_check (self, connection, &bt_type, error)) return FALSE; - } - /* DUN connections aren't available without ModemManager */ - if (bt_type == NM_BT_CAPABILITY_DUN && priv->mm_running == FALSE) { + if ( bt_type == NM_BT_CAPABILITY_DUN + && !priv->mm_running) { nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "ModemManager missing for DUN profile"); return FALSE; @@ -227,11 +253,12 @@ complete_connection (NMDevice *device, NMConnection *const*existing_connections, GError **error) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMSettingBluetooth *s_bt; const char *setting_bdaddr; const char *ctype; - gboolean is_dun = FALSE, is_pan = FALSE; + gboolean is_dun = FALSE; + gboolean is_pan = FALSE; NMSettingGsm *s_gsm; NMSettingCdma *s_cdma; NMSettingSerial *s_serial; @@ -274,7 +301,10 @@ complete_connection (NMDevice *device, } /* PAN can't use any DUN-related settings */ - if (s_gsm || s_cdma || s_serial || s_ppp) { + if ( s_gsm + || s_cdma + || s_serial + || s_ppp) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, @@ -304,7 +334,8 @@ complete_connection (NMDevice *device, } /* Need at least a GSM or a CDMA setting */ - if (!s_gsm && !s_cdma) { + if ( !s_gsm + && !s_cdma) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, @@ -441,20 +472,19 @@ static void modem_auth_result (NMModem *modem, GError *error, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); if (error) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - } else { - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - - /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ - g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - if (!modem_stage1 (NM_DEVICE_BT (device), priv->modem, &failure_reason)) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, failure_reason); + return; } + + priv->stage1_modem_prepare_state = NM_DEVICE_STAGE_STATE_INIT; + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -463,45 +493,33 @@ modem_prepare_result (NMModem *modem, guint i_reason, gpointer user_data) { - NMDeviceBt *self = NM_DEVICE_BT (user_data); - NMDevice *device = NM_DEVICE (self); + NMDeviceBt *self = user_data; + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMDeviceStateReason reason = i_reason; NMDeviceState state; - state = nm_device_get_state (device); - g_return_if_fail (state == NM_DEVICE_STATE_CONFIG || state == NM_DEVICE_STATE_NEED_AUTH); - - if (success) { - NMActRequest *req; - NMActStageReturn ret; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - - req = nm_device_get_act_request (device); - g_return_if_fail (req); - - ret = nm_modem_act_stage2_config (modem, req, &failure_reason); - switch (ret) { - case NM_ACT_STAGE_RETURN_POSTPONE: - break; - case NM_ACT_STAGE_RETURN_SUCCESS: - nm_device_activate_schedule_stage3_ip_config_start (device); - break; - case NM_ACT_STAGE_RETURN_FAILURE: - default: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, failure_reason); - break; - } - } else { + state = nm_device_get_state (NM_DEVICE (self)); + + g_return_if_fail (NM_IN_SET (state, NM_DEVICE_STATE_PREPARE, + NM_DEVICE_STATE_NEED_AUTH)); + + nm_assert (priv->stage1_modem_prepare_state == NM_DEVICE_STAGE_STATE_PENDING); + + if (!success) { if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT) { /* If the connect failed because the SIM PIN was wrong don't allow * the device to be auto-activated anymore, which would risk locking * the SIM if the incorrect PIN continues to be used. */ - nm_device_autoconnect_blocked_set (device, NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN); + nm_device_autoconnect_blocked_set (NM_DEVICE (self), NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN); } - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); + return; } + + priv->stage1_modem_prepare_state = NM_DEVICE_STAGE_STATE_COMPLETED; + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); } static void @@ -510,7 +528,7 @@ device_state_changed (NMDevice *device, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); if (priv->modem) nm_modem_device_state_changed (priv->modem, new_state, old_state); @@ -519,7 +537,8 @@ device_state_changed (NMDevice *device, * since the device could be both DUN and NAP capable and thus may not * change state (which rechecks available connections) when MM comes and goes. */ - if (priv->mm_running && (priv->capabilities & NM_BT_CAPABILITY_DUN)) + if ( priv->mm_running + && NM_FLAGS_HAS (priv->capabilities, NM_BT_CAPABILITY_DUN)) nm_device_recheck_available_connections (device); } @@ -541,8 +560,10 @@ modem_ip4_config_result (NMModem *modem, nm_device_ip_method_failed (device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else - nm_device_activate_schedule_ip_config_result (device, AF_INET, NM_IP_CONFIG_CAST (config)); + return; + } + + nm_device_activate_schedule_ip_config_result (device, AF_INET, NM_IP_CONFIG_CAST (config)); } static void @@ -561,29 +582,6 @@ ip_ifindex_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) } } -static gboolean -modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *out_failure_reason) -{ - NMActRequest *req; - NMActStageReturn ret; - - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req, FALSE); - - ret = nm_modem_act_stage1_prepare (modem, req, out_failure_reason); - switch (ret) { - case NM_ACT_STAGE_RETURN_POSTPONE: - case NM_ACT_STAGE_RETURN_SUCCESS: - /* Success, wait for the 'prepare-result' signal */ - return TRUE; - case NM_ACT_STAGE_RETURN_FAILURE: - default: - break; - } - - return FALSE; -} - /*****************************************************************************/ static void @@ -593,7 +591,7 @@ modem_cleanup (NMDeviceBt *self) if (priv->modem) { g_signal_handlers_disconnect_matched (priv->modem, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); - g_clear_object (&priv->modem); + nm_clear_pointer (&priv->modem, nm_modem_unclaim); } } @@ -608,11 +606,13 @@ modem_state_cb (NMModem *modem, NMDevice *device = NM_DEVICE (user_data); NMDeviceState dev_state = nm_device_get_state (device); - if (new_state <= NM_MODEM_STATE_DISABLING && old_state > NM_MODEM_STATE_DISABLING) { + if ( new_state <= NM_MODEM_STATE_DISABLING + && old_state > NM_MODEM_STATE_DISABLING) { /* Will be called whenever something external to NM disables the * modem directly through ModemManager. */ - if (nm_device_is_activating (device) || dev_state == NM_DEVICE_STATE_ACTIVATED) { + if ( nm_device_is_activating (device) + || dev_state == NM_DEVICE_STATE_ACTIVATED) { nm_device_state_changed (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_USER_REQUESTED); @@ -620,13 +620,15 @@ modem_state_cb (NMModem *modem, } } - if (new_state < NM_MODEM_STATE_CONNECTING && - old_state >= NM_MODEM_STATE_CONNECTING && - dev_state >= NM_DEVICE_STATE_NEED_AUTH && - dev_state <= NM_DEVICE_STATE_ACTIVATED) { + if ( new_state < NM_MODEM_STATE_CONNECTING + && old_state >= NM_MODEM_STATE_CONNECTING + && dev_state >= NM_DEVICE_STATE_NEED_AUTH + && dev_state <= NM_DEVICE_STATE_ACTIVATED) { /* Fail the device if the modem disconnects unexpectedly while the * device is activating/activated. */ - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER); return; } } @@ -637,66 +639,56 @@ modem_removed_cb (NMModem *modem, gpointer user_data) NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceState state; - /* Fail the device if the modem was removed while active */ state = nm_device_get_state (NM_DEVICE (self)); - if ( state == NM_DEVICE_STATE_ACTIVATED - || nm_device_is_activating (NM_DEVICE (self))) { + if ( nm_device_is_activating (NM_DEVICE (self)) + || state == NM_DEVICE_STATE_ACTIVATED) { nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); - } else - modem_cleanup (self); + return; + } + + modem_cleanup (self); } static gboolean -component_added (NMDevice *device, GObject *component) +modem_try_claim (NMDeviceBt *self, + NMModem *modem) { - NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - NMModem *modem; + gs_free char *rfcomm_base_name = NULL; NMDeviceState state; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - if ( !component - || !NM_IS_MODEM (component)) + if (priv->modem) { + if (priv->modem == modem) + return TRUE; return FALSE; + } - modem = NM_MODEM (component); - if (!priv->rfcomm_iface) + if (nm_modem_is_claimed (modem)) return FALSE; - { - gs_free char *base = NULL; - - base = g_path_get_basename (priv->rfcomm_iface); - if (!nm_streq (base, nm_modem_get_control_port (modem))) - return FALSE; - } + if (!priv->connect_rfcomm_iface) + return FALSE; - /* Got the modem */ - nm_clear_g_source (&priv->timeout_id); - nm_clear_g_cancellable (&priv->cancellable); + rfcomm_base_name = g_path_get_basename (priv->connect_rfcomm_iface); + if (!nm_streq0 (rfcomm_base_name, nm_modem_get_control_port (modem))) + return FALSE; - /* Can only accept the modem in stage2, but since the interface matched + /* Can only accept the modem in stage1, but since the interface matched * what we were expecting, don't let anything else claim the modem either. */ state = nm_device_get_state (NM_DEVICE (self)); - if (state != NM_DEVICE_STATE_CONFIG) { - _LOGW (LOGD_BT | LOGD_MB, + if (state != NM_DEVICE_STATE_PREPARE) { + _LOGD (LOGD_BT | LOGD_MB, "modem found but device not in correct state (%d)", nm_device_get_state (NM_DEVICE (self))); - return TRUE; + return FALSE; } - _LOGI (LOGD_BT | LOGD_MB, - "Activation: (bluetooth) Stage 2 of 5 (Device Configure) modem found."); + priv->modem = nm_modem_claim (modem); + priv->stage1_modem_prepare_state = NM_DEVICE_STAGE_STATE_INIT; - if (priv->modem) { - g_warn_if_reached (); - modem_cleanup (self); - } - - priv->modem = g_object_ref (modem); g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), self); g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); @@ -705,92 +697,187 @@ component_added (NMDevice *device, GObject *component) g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self); g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self); g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self); - g_signal_connect (modem, "notify::" NM_MODEM_IP_IFINDEX, G_CALLBACK (ip_ifindex_changed_cb), self); - /* Kick off the modem connection */ - if (!modem_stage1 (self, modem, &failure_reason)) - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, failure_reason); + _LOGD (LOGD_BT | LOGD_MB, + "modem found"); return TRUE; } -static gboolean -modem_find_timeout (gpointer user_data) +static void +mm_modem_added_cb (NMModemManager *manager, + NMModem *modem, + gpointer user_data) +{ + NMDeviceBt *self = user_data; + NMDeviceBtPrivate *priv; + + if (!modem_try_claim (user_data, modem)) + return; + + priv = NM_DEVICE_BT_GET_PRIVATE (self); + + if (priv->stage1_bt_state == NM_DEVICE_STAGE_STATE_COMPLETED) + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); +} + +/*****************************************************************************/ + +void +_nm_device_bt_notify_set_connected (NMDeviceBt *self, + gboolean connected) { - NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - priv->timeout_id = 0; - nm_clear_g_cancellable (&priv->cancellable); + connected = !!connected; + if (priv->is_connected == connected) + return; + + priv->is_connected = connected; + if ( connected + || priv->stage1_bt_state != NM_DEVICE_STAGE_STATE_COMPLETED + || nm_device_get_state (NM_DEVICE (self)) > NM_DEVICE_STATE_ACTIVATED) { + _LOGT (LOGD_BT, "set-connected: %d", connected); + return; + } + + _LOGT (LOGD_BT, "set-connected: %d (disconnecting device...)", connected); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND); - return FALSE; + NM_DEVICE_STATE_REASON_CARRIER); } -static void -check_connect_continue (NMDeviceBt *self) +static gboolean +connect_watch_link_idle_cb (gpointer user_data) { - NMDevice *device = NM_DEVICE (self); + NMDeviceBt *self = user_data; NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP); - gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN); + int ifindex; - if (!priv->connected || !priv->have_iface) - return; + priv->connect_watch_link_idle_id = 0; + + if (nm_device_get_state (NM_DEVICE (self)) <= NM_DEVICE_STATE_ACTIVATED) { + ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self)); + if ( ifindex > 0 + && !nm_platform_link_get (nm_device_get_platform (NM_DEVICE (self)), ifindex)) { + _LOGT (LOGD_BT, "device disappeared"); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + } + } + + return G_SOURCE_REMOVE; +} + +static void +connect_watch_link_cb (NMPlatform *platform, + int obj_type_i, + int ifindex, + NMPlatformLink *info, + int change_type_i, + NMDevice *self) +{ + const NMPlatformSignalChangeType change_type = change_type_i; + NMDeviceBtPrivate *priv; + + /* bluez doesn't notify us when the connection disconnects. + * Neither does NMManager (or NMDevice) tell us when the ip-ifindex goes away. + * This is horrible, and should be improved. For now, watch the link ourself... */ + + if (NM_IN_SET (change_type, NM_PLATFORM_SIGNAL_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED)) { + priv = NM_DEVICE_BT_GET_PRIVATE (self); + if (priv->connect_watch_link_idle_id == 0) + priv->connect_watch_link_idle_id = g_idle_add (connect_watch_link_idle_cb, self); + } +} - _LOGI (LOGD_BT, - "Activation: (bluetooth) Stage 2 of 5 (Device Configure) successful. Will connect via %s.", - dun ? "DUN" : (pan ? "PAN" : "unknown")); +static gboolean +connect_wait_modem_timeout (gpointer user_data) +{ + NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - nm_clear_g_source (&priv->timeout_id); - nm_clear_g_cancellable (&priv->cancellable); + /* since this timeout is longer than the connect timeout, we must have already + * hit the connect-timeout first or being connected. */ + nm_assert (priv->stage1_bt_state == NM_DEVICE_STAGE_STATE_COMPLETED); - if (pan) { - /* Bluez says we're connected now. Start IP config. */ - nm_device_activate_schedule_stage3_ip_config_start (device); - } else if (dun) { - /* Wait for ModemManager to find the modem */ - priv->timeout_id = g_timeout_add_seconds (30, modem_find_timeout, self); + priv->connect_wait_modem_id = 0; + nm_clear_g_cancellable (&priv->connect_bz_cancellable); - _LOGI (LOGD_BT | LOGD_MB, - "Activation: (bluetooth) Stage 2 of 5 (Device Configure) waiting for modem to appear."); - } else - g_assert_not_reached (); + if (priv->modem) + _LOGD (LOGD_BT, "timeout connecting modem for DUN connection"); + else + _LOGD (LOGD_BT, "timeout finding modem for DUN connection"); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND); + return G_SOURCE_REMOVE; } static void -bluez_connect_cb (NMBluezDevice *bt_device, - const char *device_name, - GError *error, - gpointer user_data) +connect_bz_cb (NMBluezManager *bz_mgr, + gboolean is_complete, + const char *device_name, + GError *error, + gpointer user_data) { - gs_unref_object NMDeviceBt *self = user_data; - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + NMDeviceBt *self; + NMDeviceBtPrivate *priv; + char sbuf[100]; if (nm_utils_error_is_cancelled (error, FALSE)) return; - nm_clear_g_source (&priv->timeout_id); - g_clear_object (&priv->cancellable); + self = user_data; + priv = NM_DEVICE_BT_GET_PRIVATE (self); + + nm_assert (nm_device_is_activating (NM_DEVICE (self))); + nm_assert (NM_IN_SET ((NMBluetoothCapabilities) priv->connect_bt_type, NM_BT_CAPABILITY_DUN, + NM_BT_CAPABILITY_NAP)); - if (!nm_device_is_activating (NM_DEVICE (self))) + if (!is_complete) { + nm_assert (priv->connect_bt_type == NM_BT_CAPABILITY_DUN); + nm_assert (device_name); + nm_assert (!error); + + if (!nm_streq0 (priv->connect_rfcomm_iface, device_name)) { + nm_assert (!priv->connect_rfcomm_iface); + _LOGD (LOGD_BT, "DUN is still connecting but got serial port \"%s\" to claim modem", device_name); + g_free (priv->connect_rfcomm_iface); + priv->connect_rfcomm_iface = g_strdup (device_name); + } return; + } + + g_clear_object (&priv->connect_bz_cancellable); if (!device_name) { - _LOGW (LOGD_BT, "Error connecting with bluez: %s", error->message); + _LOGW (LOGD_BT, "%s connect request failed: %s", + nm_bluetooth_capability_to_string (priv->connect_bt_type, sbuf, sizeof (sbuf)), + error->message); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BT_FAILED); return; } - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - g_free (priv->rfcomm_iface); - priv->rfcomm_iface = g_strdup (device_name); - } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { + _LOGD (LOGD_BT, "%s connect request successful (%s)", + nm_bluetooth_capability_to_string (priv->connect_bt_type, sbuf, sizeof (sbuf)), + device_name); + + if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) { + if (!nm_streq0 (priv->connect_rfcomm_iface, device_name)) { + nm_assert_not_reached (); + g_free (priv->connect_rfcomm_iface); + priv->connect_rfcomm_iface = g_strdup (device_name); + } + } else { + nm_assert (priv->connect_bt_type == NM_BT_CAPABILITY_NAP); if (!nm_device_set_ip_iface (NM_DEVICE (self), device_name)) { _LOGW (LOGD_BT, "Error connecting with bluez: cannot find device %s", device_name); nm_device_state_changed (NM_DEVICE (self), @@ -798,107 +885,121 @@ bluez_connect_cb (NMBluezDevice *bt_device, NM_DEVICE_STATE_REASON_BT_FAILED); return; } + priv->connect_watch_link_id = g_signal_connect (nm_device_get_platform (NM_DEVICE (self)), + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK (connect_watch_link_cb), + self); } - _LOGD (LOGD_BT, "connect request successful"); - - /* Stage 3 gets scheduled when Bluez says we're connected */ - priv->have_iface = TRUE; - check_connect_continue (self); -} - -static void -bluez_connected_changed (NMBluezDevice *bt_device, - GParamSpec *pspec, - NMDevice *device) -{ - NMDeviceBt *self = NM_DEVICE_BT (device); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean connected; - NMDeviceState state; - - state = nm_device_get_state (device); - connected = nm_bluez_device_get_connected (bt_device); - if (connected) { - if (state == NM_DEVICE_STATE_CONFIG) { - _LOGD (LOGD_BT, "connected to the device"); - - priv->connected = TRUE; - check_connect_continue (self); - } - } else { - gboolean fail = FALSE; - - /* Bluez says we're disconnected from the device. Suck. */ - - if (nm_device_is_activating (device)) { - _LOGI (LOGD_BT, "Activation: (bluetooth) bluetooth link disconnected."); - fail = TRUE; - } else if (state == NM_DEVICE_STATE_ACTIVATED) { - _LOGI (LOGD_BT, "bluetooth link disconnected."); - fail = TRUE; - } - - if (fail) { - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CARRIER); - priv->connected = FALSE; - } + if (!priv->is_connected) { + /* we got the callback from NMBluezManager with succes. We actually should be + * connected and this line shouldn't be reached. */ + nm_assert_not_reached (); + _LOGE (LOGD_BT, "bluetooth is unexpectedly not in connected state"); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + return; } -} -static gboolean -bt_connect_timeout (gpointer user_data) -{ - NMDeviceBt *self = NM_DEVICE_BT (user_data); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - - _LOGD (LOGD_BT, "initial connection timed out"); - - priv->timeout_id = 0; - nm_clear_g_cancellable (&priv->cancellable); - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_BT_FAILED); - return FALSE; + priv->stage1_bt_state = NM_DEVICE_STAGE_STATE_COMPLETED; + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); } static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) +act_stage1_prepare (NMDevice *device, + NMDeviceStateReason *out_failure_reason) { NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gs_free_error GError *error = NULL; NMConnection *connection; connection = nm_device_get_applied_connection (device); g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); - priv->bt_type = get_connection_bt_type (connection); - if (priv->bt_type == NM_BT_CAPABILITY_NONE) { - // FIXME: set a reason code + priv->connect_bt_type = get_connection_bt_type (connection); + if (priv->connect_bt_type == NM_BT_CAPABILITY_NONE) { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_BT_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } - if (priv->bt_type == NM_BT_CAPABILITY_DUN && !priv->mm_running) { + if ( priv->connect_bt_type == NM_BT_CAPABILITY_DUN + && !priv->mm_running) { NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE); return NM_ACT_STAGE_RETURN_FAILURE; } - _LOGD (LOGD_BT, "requesting connection to the device"); + if (priv->stage1_bt_state == NM_DEVICE_STAGE_STATE_PENDING) + return NM_ACT_STAGE_RETURN_POSTPONE; + else if (priv->stage1_bt_state == NM_DEVICE_STAGE_STATE_INIT) { + gs_unref_object GCancellable *cancellable = NULL; + char sbuf[100]; + + _LOGD (LOGD_BT, "connecting to %s bluetooth device", + nm_bluetooth_capability_to_string (priv->connect_bt_type, sbuf, sizeof (sbuf))); + + cancellable = g_cancellable_new (); + + if (!nm_bluez_manager_connect (priv->bz_mgr, + priv->dbus_path, + priv->connect_bt_type, + 30000, + cancellable, + connect_bz_cb, + self, + &error)) { + _LOGD (LOGD_BT, "cannot connect to bluetooth device: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_BT_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + priv->connect_bz_cancellable = g_steal_pointer (&cancellable); + priv->stage1_bt_state = NM_DEVICE_STAGE_STATE_PENDING; + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) { + if (!priv->modem) { + gs_free NMModem **modems = NULL; + guint i, n; + + if (priv->connect_wait_modem_id == 0) + priv->connect_wait_modem_id = g_timeout_add_seconds (30, connect_wait_modem_timeout, self); + + modems = nm_modem_manager_get_modems (priv->modem_manager, &n); + for (i = 0; i < n; i++) { + if (modem_try_claim (self, modems[i])) + break; + } + if (!priv->modem) + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + if (priv->stage1_modem_prepare_state == NM_DEVICE_STAGE_STATE_PENDING) + return NM_ACT_STAGE_RETURN_POSTPONE; + if (priv->stage1_modem_prepare_state == NM_DEVICE_STAGE_STATE_INIT) { + priv->stage1_modem_prepare_state = NM_DEVICE_STAGE_STATE_PENDING; + return nm_modem_act_stage1_prepare (priv->modem, + nm_device_get_act_request (NM_DEVICE (self)), + out_failure_reason); + } + } - nm_clear_g_source (&priv->timeout_id); - nm_clear_g_cancellable (&priv->cancellable); + return NM_ACT_STAGE_RETURN_SUCCESS; +} - priv->timeout_id = g_timeout_add_seconds (30, bt_connect_timeout, device); - priv->cancellable = g_cancellable_new (); +static NMActStageReturn +act_stage2_config (NMDevice *device, + NMDeviceStateReason *out_failure_reason) +{ + NMDeviceBt *self = NM_DEVICE_BT (device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - nm_bluez_device_connect_async (priv->bt_device, - priv->bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP), - priv->cancellable, - bluez_connect_cb, - g_object_ref (self)); + if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) + nm_modem_act_stage2_config (priv->modem); - return NM_ACT_STAGE_RETURN_POSTPONE; + return NM_ACT_STAGE_RETURN_SUCCESS; } static NMActStageReturn @@ -907,11 +1008,11 @@ act_stage3_ip_config_start (NMDevice *device, gpointer *out_config, NMDeviceStateReason *out_failure_reason) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); nm_assert_addr_family (addr_family); - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) { if (addr_family == AF_INET) { return nm_modem_stage3_ip4_config_start (priv->modem, device, @@ -930,15 +1031,17 @@ act_stage3_ip_config_start (NMDevice *device, static void deactivate (NMDevice *device) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - priv->have_iface = FALSE; - priv->connected = FALSE; + nm_clear_g_signal_handler (nm_device_get_platform (device), &priv->connect_watch_link_id); + nm_clear_g_source (&priv->connect_watch_link_idle_id); + priv->stage1_bt_state = NM_DEVICE_STAGE_STATE_INIT; + nm_clear_g_source (&priv->connect_wait_modem_id); + nm_clear_g_cancellable (&priv->connect_bz_cancellable); - nm_clear_g_source (&priv->timeout_id); - nm_clear_g_cancellable (&priv->cancellable); + priv->stage1_bt_state = NM_DEVICE_STAGE_STATE_INIT; - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) { if (priv->modem) { nm_modem_deactivate (priv->modem, device); @@ -952,22 +1055,53 @@ deactivate (NMDevice *device) } } - if (priv->bt_type != NM_BT_CAPABILITY_NONE) - nm_bluez_device_disconnect (priv->bt_device); - - priv->bt_type = NM_BT_CAPABILITY_NONE; + if (priv->connect_bt_type != NM_BT_CAPABILITY_NONE) { + priv->connect_bt_type = NM_BT_CAPABILITY_NONE; + nm_bluez_manager_disconnect (priv->bz_mgr, priv->dbus_path); + } - g_free (priv->rfcomm_iface); - priv->rfcomm_iface = NULL; + nm_clear_g_free (&priv->connect_rfcomm_iface); if (NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate) NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate (device); } -static void -bluez_device_removed (NMBluezDevice *bdev, gpointer user_data) +void +_nm_device_bt_notify_removed (NMDeviceBt *self) +{ + g_signal_emit_by_name (self, NM_DEVICE_REMOVED); +} + +/*****************************************************************************/ + +gboolean +_nm_device_bt_for_same_device (NMDeviceBt *self, + const char *dbus_path, + const char *bdaddr, + const char *name, + NMBluetoothCapabilities capabilities) { - g_signal_emit_by_name (NM_DEVICE_BT (user_data), NM_DEVICE_REMOVED); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + + return nm_streq (priv->dbus_path, dbus_path) + && nm_streq (priv->bdaddr, bdaddr) + && capabilities == priv->capabilities + && (!name || nm_streq (priv->name, name)); +} + +void +_nm_device_bt_notify_set_name (NMDeviceBt *self, const char *name) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + + nm_assert (name); + + if (!nm_streq (priv->name, name)) { + _LOGT (LOGD_BT, "set-name: %s", name); + g_free (priv->name); + priv->name = g_strdup (name); + _notify (self, PROP_BT_NAME); + } } /*****************************************************************************/ @@ -1028,9 +1162,6 @@ get_property (GObject *object, guint prop_id, case PROP_BT_CAPABILITIES: g_value_set_uint (value, priv->capabilities); break; - case PROP_BT_DEVICE: - g_value_set_object (value, priv->bt_device); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1044,19 +1175,32 @@ set_property (GObject *object, guint prop_id, NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) object); switch (prop_id) { + case PROP_BT_BZ_MGR: + /* construct-only */ + priv->bz_mgr = g_object_ref (g_value_get_pointer (value)); + nm_assert (NM_IS_BLUEZ_MANAGER (priv->bz_mgr)); + break; + case PROP_BT_DBUS_PATH: + /* construct-only */ + priv->dbus_path = g_value_dup_string (value); + nm_assert (priv->dbus_path); + break; + case PROP_BT_BDADDR: + /* construct-only */ + priv->bdaddr = g_value_dup_string (value); + nm_assert (priv->bdaddr); + break; case PROP_BT_NAME: /* construct-only */ priv->name = g_value_dup_string (value); + nm_assert (priv->name); break; case PROP_BT_CAPABILITIES: /* construct-only */ priv->capabilities = g_value_get_uint (value); - break; - case PROP_BT_DEVICE: - /* construct-only */ - priv->bt_device = g_value_dup_object (value); - if (!priv->bt_device) - g_return_if_reached (); + nm_assert (NM_IN_SET ((NMBluetoothCapabilities) priv->capabilities, NM_BT_CAPABILITY_DUN, + NM_BT_CAPABILITY_NAP, + NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1076,7 +1220,6 @@ constructed (GObject *object) { NMDeviceBt *self = NM_DEVICE_BT (object); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - const char *my_hwaddr; G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); @@ -1085,74 +1228,69 @@ constructed (GObject *object) nm_modem_manager_name_owner_ref (priv->modem_manager); g_signal_connect (priv->modem_manager, + NM_MODEM_MANAGER_MODEM_ADDED, + G_CALLBACK (mm_modem_added_cb), + self); + + g_signal_connect (priv->modem_manager, "notify::"NM_MODEM_MANAGER_NAME_OWNER, G_CALLBACK (mm_name_owner_changed_cb), self); - if (priv->bt_device) { - /* Watch for BT device property changes */ - g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, - G_CALLBACK (bluez_connected_changed), - object); - g_signal_connect (priv->bt_device, NM_BLUEZ_DEVICE_REMOVED, - G_CALLBACK (bluez_device_removed), object); - } - - my_hwaddr = nm_device_get_hw_address (NM_DEVICE (object)); - if (my_hwaddr) - priv->bdaddr = g_strdup (my_hwaddr); - else - g_warn_if_reached (); - set_mm_running (self); } -NMDevice * -nm_device_bt_new (NMBluezDevice *bt_device, - const char *udi, +NMDeviceBt * +nm_device_bt_new (NMBluezManager *bz_mgr, + const char *dbus_path, const char *bdaddr, const char *name, - guint32 capabilities) + NMBluetoothCapabilities capabilities) { - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (bdaddr != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (NM_IS_BLUEZ_MANAGER (bz_mgr), NULL); + g_return_val_if_fail (dbus_path, NULL); + g_return_val_if_fail (bdaddr, NULL); + g_return_val_if_fail (name, NULL); g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL); - g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (bt_device), NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT, - NM_DEVICE_UDI, udi, - NM_DEVICE_IFACE, bdaddr, - NM_DEVICE_DRIVER, "bluez", - NM_DEVICE_PERM_HW_ADDRESS, bdaddr, - NM_DEVICE_BT_DEVICE, bt_device, - NM_DEVICE_BT_NAME, name, - NM_DEVICE_BT_CAPABILITIES, capabilities, - NM_DEVICE_TYPE_DESC, "Bluetooth", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BT, - NULL); + + return g_object_new (NM_TYPE_DEVICE_BT, + NM_DEVICE_UDI, dbus_path, + NM_DEVICE_IFACE, bdaddr, + NM_DEVICE_DRIVER, "bluez", + NM_DEVICE_PERM_HW_ADDRESS, bdaddr, + NM_DEVICE_BT_BDADDR, bdaddr, + NM_DEVICE_BT_BZ_MGR, bz_mgr, + NM_DEVICE_BT_CAPABILITIES, (guint) capabilities, + NM_DEVICE_BT_DBUS_PATH, dbus_path, + NM_DEVICE_BT_NAME, name, + NM_DEVICE_TYPE_DESC, "Bluetooth", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BT, + NULL); } static void dispose (GObject *object) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) object); + NMDeviceBt *self = NM_DEVICE_BT (object); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - nm_clear_g_source (&priv->timeout_id); - nm_clear_g_cancellable (&priv->cancellable); + nm_clear_g_signal_handler (nm_device_get_platform (NM_DEVICE (self)), &priv->connect_watch_link_id); + nm_clear_g_source (&priv->connect_watch_link_idle_id); - g_signal_handlers_disconnect_matched (priv->bt_device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); + nm_clear_g_source (&priv->connect_wait_modem_id); + nm_clear_g_cancellable (&priv->connect_bz_cancellable); if (priv->modem_manager) { - g_signal_handlers_disconnect_by_func (priv->modem_manager, G_CALLBACK (mm_name_owner_changed_cb), object); + g_signal_handlers_disconnect_by_func (priv->modem_manager, G_CALLBACK (mm_name_owner_changed_cb), self); nm_modem_manager_name_owner_unref (priv->modem_manager); g_clear_object (&priv->modem_manager); } - modem_cleanup (NM_DEVICE_BT (object)); - g_clear_object (&priv->bt_device); + modem_cleanup (self); G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object); + + g_clear_object (&priv->bz_mgr); } static void @@ -1160,7 +1298,8 @@ finalize (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE ((NMDeviceBt *) object); - g_free (priv->rfcomm_iface); + g_free (priv->connect_rfcomm_iface); + g_free (priv->dbus_path); g_free (priv->name); g_free (priv->bdaddr); @@ -1202,17 +1341,34 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) device_class->get_generic_capabilities = get_generic_capabilities; device_class->can_auto_connect = can_auto_connect; device_class->deactivate = deactivate; + device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; device_class->check_connection_compatible = check_connection_compatible; device_class->check_connection_available = check_connection_available; device_class->complete_connection = complete_connection; device_class->is_available = is_available; - device_class->component_added = component_added; device_class->get_configured_mtu = nm_modem_get_configured_mtu; device_class->state_changed = device_state_changed; + obj_properties[PROP_BT_BZ_MGR] = + g_param_spec_pointer (NM_DEVICE_BT_BZ_MGR, "", "", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_BT_BDADDR] = + g_param_spec_string (NM_DEVICE_BT_BDADDR, "", "", + NULL, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_BT_DBUS_PATH] = + g_param_spec_string (NM_DEVICE_BT_DBUS_PATH, "", "", + NULL, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_BT_NAME] = g_param_spec_string (NM_DEVICE_BT_NAME, "", "", NULL, @@ -1225,12 +1381,6 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_BT_DEVICE] = - g_param_spec_object (NM_DEVICE_BT_DEVICE, "", "", - NM_TYPE_BLUEZ_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[PPP_STATS] = diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h index 6c8a5773..ecb5781b 100644 --- a/src/devices/bluetooth/nm-device-bt.h +++ b/src/devices/bluetooth/nm-device-bt.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 Red Hat, Inc. */ @@ -21,7 +7,6 @@ #define __NETWORKMANAGER_DEVICE_BT_H__ #include "devices/nm-device.h" -#include "nm-bluez-device.h" #define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ()) #define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt)) @@ -30,9 +15,11 @@ #define NM_IS_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BT)) #define NM_DEVICE_BT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) -#define NM_DEVICE_BT_NAME "name" +#define NM_DEVICE_BT_BDADDR "bt-bdaddr" +#define NM_DEVICE_BT_BZ_MGR "bt-bz-mgr" #define NM_DEVICE_BT_CAPABILITIES "bt-capabilities" -#define NM_DEVICE_BT_DEVICE "bt-device" +#define NM_DEVICE_BT_DBUS_PATH "bt-dbus-path" +#define NM_DEVICE_BT_NAME "bt-name" #define NM_DEVICE_BT_PPP_STATS "ppp-stats" @@ -41,13 +28,21 @@ typedef struct _NMDeviceBtClass NMDeviceBtClass; GType nm_device_bt_get_type (void); -NMDevice *nm_device_bt_new (NMBluezDevice *bt_device, - const char *udi, - const char *bdaddr, - const char *name, - guint32 capabilities); +struct _NMBluezManager; -guint32 nm_device_bt_get_capabilities (NMDeviceBt *device); +NMDeviceBt *nm_device_bt_new (struct _NMBluezManager *bz_mgr, + const char *dbus_path, + const char *bdaddr, + const char *name, + NMBluetoothCapabilities capabilities); + +gboolean _nm_device_bt_for_same_device (NMDeviceBt *device, + const char *dbus_path, + const char *bdaddr, + const char *name, + NMBluetoothCapabilities capabilities); + +NMBluetoothCapabilities nm_device_bt_get_capabilities (NMDeviceBt *device); struct _NMModem; @@ -55,4 +50,11 @@ gboolean nm_device_bt_modem_added (NMDeviceBt *device, struct _NMModem *modem, const char *driver); +void _nm_device_bt_notify_removed (NMDeviceBt *self); + +void _nm_device_bt_notify_set_name (NMDeviceBt *self, const char *name); + +void _nm_device_bt_notify_set_connected (NMDeviceBt *self, + gboolean connected); + #endif /* __NETWORKMANAGER_DEVICE_BT_H__ */ diff --git a/src/devices/bluetooth/tests/nm-bt-test.c b/src/devices/bluetooth/tests/nm-bt-test.c new file mode 100644 index 00000000..02cfd228 --- /dev/null +++ b/src/devices/bluetooth/tests/nm-bt-test.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: LGPL-2.1+ + +#include "nm-default.h" + +#include <glib-unix.h> + +#include "devices/bluetooth/nm-bluez5-dun.h" + +#include "nm-test-utils-core.h" + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG(level, ...) \ + nm_log ((level), _NMLOG_DOMAIN, \ + NULL, NULL, \ + "bt%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + NM_PRINT_FMT_QUOTED (gl.argv_cmd, "[", gl.argv_cmd, "]", "") \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + +/*****************************************************************************/ + +struct { + int argc; + const char *const*argv; + const char *argv_cmd; + GMainLoop *loop; +} gl; + +typedef struct _MainCmdInfo { + const char *name; + int (*main_func) (const struct _MainCmdInfo *main_cmd_info); +} MainCmdInfo; + +/*****************************************************************************/ + +#if WITH_BLUEZ5_DUN + +typedef struct { + NMBluez5DunContext *dun_context; + GCancellable *cancellable; + guint timeout_id; + guint sig_term_id; + guint sig_int_id; +} DunConnectData; + +static void +_dun_connect_cb (NMBluez5DunContext *context, + const char *rfcomm_dev, + GError *error, + gpointer user_data) +{ + DunConnectData *dun_connect_data = user_data; + + g_assert (dun_connect_data); + g_assert (!dun_connect_data->dun_context); + g_assert ((!!error) != (!!rfcomm_dev)); + + if (rfcomm_dev && !context) { + _LOGI ("dun-connect notifies path \"%s\". Wait longer...", rfcomm_dev); + return; + } + + if (rfcomm_dev) { + g_assert (context); + _LOGI ("dun-connect completed with path \"%s\"", rfcomm_dev); + } else { + g_assert (!context); + _LOGI ("dun-connect failed with error: %s", error->message); + } + + dun_connect_data->dun_context = context; + + g_main_loop_quit (gl.loop); +} + +static void +_dun_notify_tty_hangup_cb (NMBluez5DunContext *context, + gpointer user_data) +{ + _LOGI ("dun-connect: notified TTY hangup"); +} + +static gboolean +_timeout_cb (gpointer user_data) +{ + DunConnectData *dun_connect_data = user_data; + + _LOGI ("timeout"); + dun_connect_data->timeout_id = 0; + if (dun_connect_data->cancellable) + g_cancellable_cancel (dun_connect_data->cancellable); + return G_SOURCE_REMOVE; +} + +static gboolean +_sig_xxx_cb (DunConnectData *dun_connect_data, int sigid) +{ + _LOGI ("signal %s received", sigid == SIGTERM ? "SIGTERM" : "SIGINT"); + g_main_loop_quit (gl.loop); + return G_SOURCE_CONTINUE; +} + +static gboolean +_sig_term_cb (gpointer user_data) +{ + return _sig_xxx_cb (user_data, SIGTERM); +} + +static gboolean +_sig_int_cb (gpointer user_data) +{ + return _sig_xxx_cb (user_data, SIGINT); +} +#endif + +static int +do_dun_connect (const MainCmdInfo *main_cmd_info) +{ +#if WITH_BLUEZ5_DUN + gs_unref_object GCancellable *cancellable = NULL; + gs_free_error GError *error = NULL; + const char *adapter; + const char *remote; + DunConnectData dun_connect_data = { }; + + if (gl.argc < 4) { + _LOGE ("missing arguments \"adapter\" and \"remote\""); + return -1; + } + + adapter = gl.argv[2]; + remote = gl.argv[3]; + + cancellable = g_cancellable_new (); + dun_connect_data.cancellable = cancellable; + + if (!nm_bluez5_dun_connect (adapter, + remote, + cancellable, + _dun_connect_cb, + &dun_connect_data, + _dun_notify_tty_hangup_cb, + &dun_connect_data, + &error)) { + _LOGE ("connect failed to start: %s", error->message); + return -1; + } + + dun_connect_data.timeout_id = g_timeout_add (60000, _timeout_cb, &dun_connect_data); + + g_main_loop_run (gl.loop); + + nm_clear_g_source (&dun_connect_data.timeout_id); + + if (dun_connect_data.dun_context) { + + dun_connect_data.sig_term_id = g_unix_signal_add (SIGTERM, _sig_term_cb, &dun_connect_data); + dun_connect_data.sig_int_id = g_unix_signal_add (SIGINT, _sig_int_cb, &dun_connect_data); + + g_main_loop_run (gl.loop); + + nm_clear_g_source (&dun_connect_data.sig_term_id); + nm_clear_g_source (&dun_connect_data.sig_int_id); + + nm_bluez5_dun_disconnect (g_steal_pointer (&dun_connect_data.dun_context)); + } + + return 0; +#else + _LOGE ("compiled without bluetooth DUN support"); + return 1; +#endif +} + +/*****************************************************************************/ + +NMTST_DEFINE (); + +int +main (int argc, char **argv) +{ + static const MainCmdInfo main_cmd_infos[] = { + { .name = "dun-connect", .main_func = do_dun_connect, }, + }; + int exit_code = 0; + guint i; + + if (!g_getenv ("G_MESSAGES_DEBUG")) + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + + nmtst_init_with_logging (&argc, &argv, "DEBUG", "ALL"); + + nm_logging_init (NULL, TRUE); + + gl.argv = (const char *const*) argv; + gl.argc = argc; + gl.loop = g_main_loop_new (NULL, FALSE); + + _LOGI ("bluetooth test util start"); + + gl.argv_cmd = argc >= 2 ? argv[1] : NULL; + + for (i = 0; i < G_N_ELEMENTS (main_cmd_infos); i++) { + if (nm_streq0 (main_cmd_infos[i].name, gl.argv_cmd)) { + _LOGD ("start \"%s\"", gl.argv_cmd); + exit_code = main_cmd_infos[i].main_func (&main_cmd_infos[i]); + _LOGD ("completed with %d", exit_code); + break; + } + } + if (gl.argv_cmd && i >= G_N_ELEMENTS (main_cmd_infos)) { + nm_log_err (LOGD_BT, "invalid command \"%s\"", gl.argv_cmd); + exit_code = -1; + } + + nm_clear_pointer (&gl.loop, g_main_loop_unref); + + return exit_code; +} diff --git a/src/devices/nm-acd-manager.c b/src/devices/nm-acd-manager.c index 036c4709..6e7a2a0f 100644 --- a/src/devices/nm-acd-manager.c +++ b/src/devices/nm-acd-manager.c @@ -1,16 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Copyright (C) 2015-2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 - 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/nm-acd-manager.h b/src/devices/nm-acd-manager.h index 53c88e4b..4afe509d 100644 --- a/src/devices/nm-acd-manager.h +++ b/src/devices/nm-acd-manager.h @@ -1,16 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Copyright (C) 2015-2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 - 2018 Red Hat, Inc. */ #ifndef __NM_ACD_MANAGER__ diff --git a/src/devices/nm-device-6lowpan.c b/src/devices/nm-device-6lowpan.c index 7a279431..0289a360 100644 --- a/src/devices/nm-device-6lowpan.c +++ b/src/devices/nm-device-6lowpan.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -230,20 +216,6 @@ update_connection (NMDevice *device, NMConnection *connection) NULL); } -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) -{ - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_6lowpan_parent_class)->act_stage1_prepare (dev, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ static void @@ -273,7 +245,7 @@ nm_device_6lowpan_class_init (NMDevice6LowpanClass *klass) device_class->connection_type_check_compatible = NM_SETTING_6LOWPAN_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_6LOWPAN); - device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->complete_connection = complete_connection; device_class->create_and_realize = create_and_realize; device_class->get_generic_capabilities = get_generic_capabilities; diff --git a/src/devices/nm-device-6lowpan.h b/src/devices/nm-device-6lowpan.h index 86edf4af..7d427235 100644 --- a/src/devices/nm-device-6lowpan.h +++ b/src/devices/nm-device-6lowpan.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_6LOWPAN_H__ diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 50494526..c6ecb2e8 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -213,10 +199,10 @@ set_simple_option (NMDevice *device, set_bond_attr (device, mode, opt, value); } -static NMActStageReturn -apply_bonding_config (NMDevice *device) +static gboolean +apply_bonding_config (NMDeviceBond *self) { - NMDeviceBond *self = NM_DEVICE_BOND (device); + NMDevice *device = NM_DEVICE (self); NMSettingBond *s_bond; int ifindex = nm_device_get_ifindex (device); const char *mode_str, *value; @@ -239,7 +225,7 @@ apply_bonding_config (NMDevice *device) s_bond = nm_device_get_applied_setting (device, NM_TYPE_SETTING_BOND); - g_return_val_if_fail (s_bond, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (s_bond, FALSE); mode_str = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); if (!mode_str) @@ -248,7 +234,7 @@ apply_bonding_config (NMDevice *device) mode = _nm_setting_bond_mode_from_string (mode_str); if (mode == NM_BOND_MODE_UNKNOWN) { _LOGW (LOGD_BOND, "unknown bond mode '%s'", mode_str); - return NM_ACT_STAGE_RETURN_FAILURE; + return FALSE; } /* Set mode first, as some other options (e.g. arp_interval) are valid @@ -334,24 +320,26 @@ apply_bonding_config (NMDevice *device) else set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); - return NM_ACT_STAGE_RETURN_SUCCESS; + return TRUE; } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { + NMDeviceBond *self = NM_DEVICE_BOND (device); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - /* Interface must be down to set bond options */ - nm_device_take_down (dev, TRUE); - ret = apply_bonding_config (dev); - if (ret != NM_ACT_STAGE_RETURN_FAILURE) - ret = nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE); - nm_device_bring_up (dev, TRUE, NULL); + nm_device_take_down (device, TRUE); + if (!apply_bonding_config (self)) + ret = NM_ACT_STAGE_RETURN_FAILURE; + else { + if (!nm_device_hw_addr_set_cloned (device, + nm_device_get_applied_connection (device), + FALSE)) + ret = NM_ACT_STAGE_RETURN_FAILURE; + } + nm_device_bring_up (device, TRUE, NULL); return ret; } @@ -416,10 +404,12 @@ release_slave (NMDevice *device, int ifindex_slave; int ifindex; - ifindex = nm_device_get_ifindex (device); - if ( ifindex <= 0 - || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) - configure = FALSE; + if (configure) { + ifindex = nm_device_get_ifindex (device); + if ( ifindex <= 0 + || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) + configure = FALSE; + } ifindex_slave = nm_device_get_ip_ifindex (slave); diff --git a/src/devices/nm-device-bond.h b/src/devices/nm-device-bond.h index 9448950b..7964f2a2 100644 --- a/src/devices/nm-device-bond.h +++ b/src/devices/nm-device-bond.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_BOND_H__ diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 91d824b3..72a8ce2b 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -36,7 +22,9 @@ _LOG_DECLARE_SELF(NMDeviceBridge); struct _NMDeviceBridge { NMDevice parent; + GCancellable *bt_cancellable; bool vlan_configured:1; + bool bt_registered:1; }; struct _NMDeviceBridgeClass { @@ -64,6 +52,7 @@ check_connection_available (NMDevice *device, const char *specific_object, GError **error) { + NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); NMSettingBluetooth *s_bt; if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_available (device, connection, flags, specific_object, error)) @@ -80,13 +69,18 @@ check_connection_available (NMDevice *device, } bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); - if (!nm_bt_vtable_network_server->is_available (nm_bt_vtable_network_server, bdaddr)) { + if (!nm_bt_vtable_network_server->is_available (nm_bt_vtable_network_server, + bdaddr, + ( self->bt_cancellable + || self->bt_registered) + ? device + : NULL)) { if (bdaddr) nm_utils_error_set (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "not suitable NAP device \"%s\" available", bdaddr); + "no suitable NAP device \"%s\" available", bdaddr); else nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "not suitable NAP device available"); + "no suitable NAP device available"); return FALSE; } } @@ -225,7 +219,7 @@ commit_option (NMDevice *device, NMSetting *setting, const Option *option, gbool GParamSpec *pspec; GValue val = G_VALUE_INIT; guint32 uval = 0; - gs_free char *value = NULL; + char value[100]; g_assert (setting); @@ -258,10 +252,10 @@ commit_option (NMDevice *device, NMSetting *setting, const Option *option, gbool if (option->user_hz_compensate) uval *= 100; } else - g_assert_not_reached (); + nm_assert_not_reached (); g_value_unset (&val); - value = g_strdup_printf ("%u", uval); + nm_sprintf_buf (value, "%u", uval); if (slave) nm_platform_sysctl_slave_set_option (nm_device_get_platform (device), ifindex, option->sysname, value); else @@ -497,27 +491,16 @@ bridge_set_vlan_options (NMDevice *device, NMSettingBridge *s_bridge) static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMActStageReturn ret; NMConnection *connection; NMSetting *s_bridge; const Option *option; - NM_DEVICE_BRIDGE (device)->vlan_configured = FALSE; - - ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - connection = nm_device_get_applied_connection (device); g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + s_bridge = (NMSetting *) nm_connection_get_setting_bridge (connection); g_return_val_if_fail (s_bridge, NM_ACT_STAGE_RETURN_FAILURE); - if (!nm_device_hw_addr_set_cloned (device, connection, FALSE)) { - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - for (option = master_options; option->name; option++) commit_option (device, s_bridge, option, FALSE); @@ -529,9 +512,53 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_SUCCESS; } +static void +_bt_register_bridge_cb (GError *error, + gpointer user_data) +{ + NMDeviceBridge *self; + + if (nm_utils_error_is_cancelled (error, FALSE)) + return; + + self = user_data; + + g_clear_object (&self->bt_cancellable); + + if (error) { + _LOGD (LOGD_DEVICE, "bluetooth NAP server failed to register bridge: %s", error->message); + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + return; + } + + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); +} + +void +_nm_device_bridge_notify_unregister_bt_nap (NMDevice *device, + const char *reason) +{ + NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); + + _LOGD (LOGD_DEVICE, "bluetooth NAP server unregistered from bridge: %s%s", + reason, + self->bt_registered ? "" : " (was no longer registered)"); + + nm_clear_g_cancellable (&self->bt_cancellable); + + if (self->bt_registered) { + self->bt_registered = FALSE; + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + } +} + static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { + NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); NMConnection *connection; NMSettingBluetooth *s_bt; @@ -539,14 +566,32 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) s_bt = _nm_connection_get_setting_bluetooth_for_nap (connection); if (s_bt) { - if ( !nm_bt_vtable_network_server - || !nm_bt_vtable_network_server->register_bridge (nm_bt_vtable_network_server, - nm_setting_bluetooth_get_bdaddr (s_bt), - device)) { - /* The HCI we could use is no longer present. */ - *out_failure_reason = NM_DEVICE_STATE_REASON_REMOVED; + gs_free_error GError *error = NULL; + + if (!nm_bt_vtable_network_server) { + _LOGD (LOGD_DEVICE, "bluetooth NAP server failed because bluetooth plugin not available"); + *out_failure_reason = NM_DEVICE_STATE_REASON_BT_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; } + + if (self->bt_cancellable) + return NM_ACT_STAGE_RETURN_POSTPONE; + + self->bt_cancellable = g_cancellable_new (); + if (!nm_bt_vtable_network_server->register_bridge (nm_bt_vtable_network_server, + nm_setting_bluetooth_get_bdaddr (s_bt), + device, + self->bt_cancellable, + _bt_register_bridge_cb, + device, + &error)) { + _LOGD (LOGD_DEVICE, "bluetooth NAP server failed to register bridge: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_BT_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + self->bt_registered = TRUE; + return NM_ACT_STAGE_RETURN_POSTPONE; } return NM_ACT_STAGE_RETURN_SUCCESS; @@ -555,9 +600,17 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) static void deactivate (NMDevice *device) { - if (nm_bt_vtable_network_server) { - /* always call unregister. It does nothing if the device - * isn't registered as a hotspot bridge. */ + NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); + + _LOGD (LOGD_DEVICE, "deactivate bridge%s", + self->bt_registered ? " (registered as NAP bluetooth device)" : ""); + + self->vlan_configured = FALSE; + + nm_clear_g_cancellable (&self->bt_cancellable); + + if (self->bt_registered) { + self->bt_registered = FALSE; nm_bt_vtable_network_server->unregister_bridge (nm_bt_vtable_network_server, device); } @@ -628,10 +681,12 @@ release_slave (NMDevice *device, int ifindex_slave; int ifindex; - ifindex = nm_device_get_ifindex (device); - if ( ifindex <= 0 - || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) - configure = FALSE; + if (configure) { + ifindex = nm_device_get_ifindex (device); + if ( ifindex <= 0 + || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) + configure = FALSE; + } ifindex_slave = nm_device_get_ip_ifindex (slave); @@ -758,6 +813,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) device_class->master_update_slave_connection = master_update_slave_connection; device_class->create_and_realize = create_and_realize; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; device_class->deactivate = deactivate; diff --git a/src/devices/nm-device-bridge.h b/src/devices/nm-device-bridge.h index bc5ed04c..fb614d40 100644 --- a/src/devices/nm-device-bridge.h +++ b/src/devices/nm-device-bridge.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_BRIDGE_H__ @@ -36,4 +22,7 @@ GType nm_device_bridge_get_type (void); extern const NMBtVTableNetworkServer *nm_bt_vtable_network_server; +void _nm_device_bridge_notify_unregister_bt_nap (NMDevice *device, + const char *reason); + #endif /* __NETWORKMANAGER_DEVICE_BRIDGE_H__ */ diff --git a/src/devices/nm-device-dummy.c b/src/devices/nm-device-dummy.c index 9c0c3035..465a293b 100644 --- a/src/devices/nm-device-dummy.c +++ b/src/devices/nm-device-dummy.c @@ -1,14 +1,6 @@ -/* 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -116,21 +108,6 @@ create_and_realize (NMDevice *device, return TRUE; } -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_dummy_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ static void @@ -167,7 +144,7 @@ nm_device_dummy_class_init (NMDeviceDummyClass *klass) device_class->create_and_realize = create_and_realize; device_class->get_generic_capabilities = get_generic_capabilities; device_class->update_connection = update_connection; - device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; } diff --git a/src/devices/nm-device-dummy.h b/src/devices/nm-device-dummy.h index a380d366..e95be72d 100644 --- a/src/devices/nm-device-dummy.h +++ b/src/devices/nm-device-dummy.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_DUMMY_H__ diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c index 1d7a060e..79673201 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/devices/nm-device-ethernet-utils.c @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2011 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/nm-device-ethernet-utils.h b/src/devices/nm-device-ethernet-utils.h index 6355c4ec..0e16f4b8 100644 --- a/src/devices/nm-device-ethernet-utils.h +++ b/src/devices/nm-device-ethernet-utils.h @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2011 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index b2b05883..6b80c4ed 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2014 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -853,14 +839,19 @@ link_negotiation_set (NMDevice *device) autoneg = nm_setting_wired_get_auto_negotiate (s_wired); speed = nm_setting_wired_get_speed (s_wired); duplex = link_duplex_to_platform (nm_setting_wired_get_duplex (s_wired)); - if (!autoneg && !speed && !duplex) { + if ( !autoneg + && !speed + && !duplex) { _LOGD (LOGD_DEVICE, "set-link: ignore link negotiation"); return; } } - if (!nm_platform_ethtool_get_link_settings (nm_device_get_platform (device), nm_device_get_ifindex (device), - &link_autoneg, &link_speed, &link_duplex)) { + if (!nm_platform_ethtool_get_link_settings (nm_device_get_platform (device), + nm_device_get_ifindex (device), + &link_autoneg, + &link_speed, + &link_duplex)) { _LOGW (LOGD_DEVICE, "set-link: unable to retrieve link negotiation"); return; } @@ -873,16 +864,18 @@ link_negotiation_set (NMDevice *device) return; } - if (autoneg && !speed && !duplex) + if ( autoneg + && !speed + && !duplex) _LOGD (LOGD_DEVICE, "set-link: configure auto-negotiation"); else { _LOGD (LOGD_DEVICE, "set-link: configure %snegotiation (%u Mbit%s - %s duplex%s)", autoneg ? "auto-" : "static ", speed ?: link_speed, speed ? "" : "*", - duplex - ? nm_platform_link_duplex_type_to_string (duplex) - : nm_platform_link_duplex_type_to_string (link_duplex), + duplex + ? nm_platform_link_duplex_type_to_string (duplex) + : nm_platform_link_duplex_type_to_string (link_duplex), duplex ? "" : "*"); } @@ -903,9 +896,10 @@ pppoe_reconnect_delay (gpointer user_data) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); priv->pppoe_wait_id = 0; + priv->last_pppoe_time = 0; _LOGI (LOGD_DEVICE, "PPPoE reconnect delay complete, resuming connection..."); - nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); - return FALSE; + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); + return G_SOURCE_REMOVE; } static NMActStageReturn @@ -913,35 +907,33 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; link_negotiation_set (device); - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; - /* If we're re-activating a PPPoE connection a short while after * a previous PPPoE connection was torn down, wait a bit to allow the * remote side to handle the disconnection. Otherwise the peer may * get confused and fail to negotiate the new connection. (rh #1023503) + * + * FIXME(shutdown): when exiting, we also need to wait before quiting, + * at least for additional NM_SHUTDOWN_TIMEOUT_MS seconds because + * otherwise after restart the device won't work for the first seconds. */ - if (priv->last_pppoe_time) { + if (priv->last_pppoe_time != 0) { gint32 delay = nm_utils_get_monotonic_timestamp_s () - priv->last_pppoe_time; if ( delay < PPPOE_RECONNECT_DELAY && nm_device_get_applied_setting (device, 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); - priv->pppoe_wait_id = g_timeout_add_seconds (delay, - pppoe_reconnect_delay, - self); + if (priv->pppoe_wait_id == 0) { + _LOGI (LOGD_DEVICE, "delaying PPPoE reconnect for %d seconds to ensure peer is ready...", + delay); + priv->pppoe_wait_id = g_timeout_add_seconds (delay, + pppoe_reconnect_delay, + self); + } return NM_ACT_STAGE_RETURN_POSTPONE; } + nm_clear_g_source (&priv->pppoe_wait_id); priv->last_pppoe_time = 0; } @@ -1743,6 +1735,7 @@ static void reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMDeviceState state = nm_device_get_state (device); NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->reapply_connection (device, con_old, @@ -1750,8 +1743,10 @@ reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_n _LOGD (LOGD_DEVICE, "reapplying wired settings"); - link_negotiation_set (device); - wake_on_lan_enable (device); + if (state >= NM_DEVICE_STATE_PREPARE) + link_negotiation_set (device); + if (state >= NM_DEVICE_STATE_CONFIG) + wake_on_lan_enable (device); } static void @@ -1864,6 +1859,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) device_class->new_default_connection = new_default_connection; device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->act_stage2_config = act_stage2_config; device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; device_class->get_configured_mtu = get_configured_mtu; diff --git a/src/devices/nm-device-ethernet.h b/src/devices/nm-device-ethernet.h index d7de519c..08962232 100644 --- a/src/devices/nm-device-ethernet.h +++ b/src/devices/nm-device-ethernet.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index c0ec1d2e..232e69ef 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -1,19 +1,5 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ @@ -36,7 +22,6 @@ enum { DEVICE_ADDED, - COMPONENT_ADDED, LAST_SIGNAL }; @@ -46,17 +31,6 @@ G_DEFINE_ABSTRACT_TYPE (NMDeviceFactory, nm_device_factory, G_TYPE_OBJECT) /*****************************************************************************/ -gboolean -nm_device_factory_emit_component_added (NMDeviceFactory *factory, GObject *component) -{ - gboolean consumed = FALSE; - - g_return_val_if_fail (NM_IS_DEVICE_FACTORY (factory), FALSE); - - g_signal_emit (factory, signals[COMPONENT_ADDED], 0, component, &consumed); - return consumed; -} - static void nm_device_factory_get_supported_types (NMDeviceFactory *factory, const NMLinkType **out_link_types, @@ -195,16 +169,8 @@ nm_device_factory_class_init (NMDeviceFactoryClass *klass) signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceFactoryClass, device_added), - NULL, NULL, NULL, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, NM_TYPE_DEVICE); - - signals[COMPONENT_ADDED] = g_signal_new (NM_DEVICE_FACTORY_COMPONENT_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceFactoryClass, component_added), - g_signal_accumulator_true_handled, NULL, NULL, - G_TYPE_BOOLEAN, 1, G_TYPE_OBJECT); } /*****************************************************************************/ diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h index 7fe371ad..7a323d49 100644 --- a/src/devices/nm-device-factory.h +++ b/src/devices/nm-device-factory.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2014 Red Hat, Inc. */ @@ -36,7 +22,6 @@ #define NM_IS_DEVICE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_FACTORY)) #define NM_DEVICE_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactoryClass)) -#define NM_DEVICE_FACTORY_COMPONENT_ADDED "component-added" #define NM_DEVICE_FACTORY_DEVICE_ADDED "device-added" typedef struct { @@ -131,36 +116,6 @@ typedef struct { NMConnection *connection, gboolean *out_ignore); - /* Signals */ - - /** - * device_added: - * @factory: the #NMDeviceFactory - * @device: the new #NMDevice subclass - * - * The factory emits this signal if it finds a new device by itself. - */ - void (*device_added) (NMDeviceFactory *factory, NMDevice *device); - - /** - * component_added: - * @factory: the #NMDeviceFactory - * @component: a new component which existing devices may wish to claim - * - * The factory emits this signal when an appearance of some component - * native to it could be interesting to some of the already existing devices. - * The devices then indicate if they took interest in claiming the component. - * - * For example, the WWAN factory may indicate that a new modem is available, - * which an existing Bluetooth device may wish to claim. It emits a signal - * passing the modem instance around to see if any device claims it. - * If no device claims the component, the plugin is allowed to create a new - * #NMDevice instance for that component and emit the "device-added" signal. - * - * Returns: %TRUE if the component was claimed by a device, %FALSE if not - */ - gboolean (*component_added) (NMDeviceFactory *factory, GObject *component); - } NMDeviceFactoryClass; GType nm_device_factory_get_type (void); @@ -202,10 +157,6 @@ NMDevice * nm_device_factory_create_device (NMDeviceFactory *factory, gboolean *out_ignore, GError **error); -/* For use by implementations */ -gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory, - GObject *component); - #define NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(...) \ { static NMLinkType const _link_types_declared[] = { __VA_ARGS__, NM_LINK_TYPE_NONE }; _link_types = _link_types_declared; } #define NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(...) \ diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 39232acf..5f9e13c3 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/nm-device-generic.h b/src/devices/nm-device-generic.h index 9c59851a..5dd90a3a 100644 --- a/src/devices/nm-device-generic.h +++ b/src/devices/nm-device-generic.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_GENERIC_H__ diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index e39329a9..9f79d9bb 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -76,16 +62,11 @@ static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { nm_auto_close int dirfd = -1; - NMActStageReturn ret; NMSettingInfiniband *s_infiniband; char ifname_verified[IFNAMSIZ]; const char *transport_mode; gboolean ok; - ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - s_infiniband = nm_device_get_applied_setting (device, NM_TYPE_SETTING_INFINIBAND); g_return_val_if_fail (s_infiniband, NM_ACT_STAGE_RETURN_FAILURE); @@ -94,7 +75,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) dirfd = nm_platform_sysctl_open_netdir (nm_device_get_platform (device), nm_device_get_ifindex (device), ifname_verified); if (dirfd < 0) { - if (!strcmp (transport_mode, "datagram")) + if (nm_streq (transport_mode, "datagram")) return NM_ACT_STAGE_RETURN_SUCCESS; else { NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_INFINIBAND_MODE); @@ -210,6 +191,32 @@ update_connection (NMDevice *device, NMConnection *connection) } static gboolean +can_reapply_change (NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class; + + if (nm_streq (setting_name, NM_SETTING_INFINIBAND_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_INFINIBAND_SETTING_NAME, + error, + NM_SETTING_INFINIBAND_MTU); /* reapplied with IP config */ + } + + device_class = NM_DEVICE_CLASS (nm_device_infiniband_parent_class); + return device_class->can_reapply_change (device, + setting_name, + s_old, + s_new, + diffs, + error); +} + +static gboolean create_and_realize (NMDevice *device, NMConnection *connection, NMDevice *parent, @@ -361,6 +368,7 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) device_class->connection_type_check_compatible = NM_SETTING_INFINIBAND_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_INFINIBAND); + device_class->can_reapply_change = can_reapply_change; device_class->create_and_realize = create_and_realize; device_class->unrealize = unrealize; device_class->get_generic_capabilities = get_generic_capabilities; diff --git a/src/devices/nm-device-infiniband.h b/src/devices/nm-device-infiniband.h index 55d0aadc..6f46ef50 100644 --- a/src/devices/nm-device-infiniband.h +++ b/src/devices/nm-device-infiniband.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_INFINIBAND_H__ diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index f070dd5f..0becb5e5 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -967,21 +953,6 @@ set_property (GObject *object, guint prop_id, } } -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ static void @@ -1068,7 +1039,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) NM_LINK_TYPE_IPIP, NM_LINK_TYPE_SIT); - device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->link_changed = link_changed; device_class->can_reapply_change = can_reapply_change; device_class->complete_connection = complete_connection; diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h index e38d36eb..a8f30711 100644 --- a/src/devices/nm-device-ip-tunnel.h +++ b/src/devices/nm-device-ip-tunnel.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_IP_TUNNEL_H__ diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index c45a0552..2c56e526 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c index 13798f5e..c9592a49 100644 --- a/src/devices/nm-device-macsec.c +++ b/src/devices/nm-device-macsec.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -324,8 +310,10 @@ macsec_secrets_cb (NMActRequest *req, nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - } else - nm_device_activate_schedule_stage1_device_prepare (device); + return; + } + + nm_device_activate_schedule_stage1_device_prepare (device); } static void diff --git a/src/devices/nm-device-macsec.h b/src/devices/nm-device-macsec.h index e6919d4c..38a7dbae 100644 --- a/src/devices/nm-device-macsec.h +++ b/src/devices/nm-device-macsec.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NM_DEVICE_MACSEC_H__ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 964e0f61..3633f02d 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -430,21 +416,6 @@ update_connection (NMDevice *device, NMConnection *connection) NULL); } -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ static void @@ -536,7 +507,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP); device_class->mtu_parent_delta = 0; - device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->check_connection_compatible = check_connection_compatible; device_class->complete_connection = complete_connection; device_class->create_and_realize = create_and_realize; diff --git a/src/devices/nm-device-macvlan.h b/src/devices/nm-device-macvlan.h index 9e76f5c9..8fcf97cd 100644 --- a/src/devices/nm-device-macvlan.h +++ b/src/devices/nm-device-macvlan.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_MACVLAN_H__ diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c index f2e68f73..32403ff6 100644 --- a/src/devices/nm-device-ppp.c +++ b/src/devices/nm-device-ppp.c @@ -1,13 +1,5 @@ -/* 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ @@ -88,7 +80,7 @@ ppp_ifindex_set (NMPPPManager *ppp_manager, } if (old_name) - nm_manager_remove_device (nm_manager_get (), old_name, NM_DEVICE_TYPE_PPP); + nm_manager_remove_device (NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP); nm_device_activate_schedule_stage3_ip_config_start (device); } diff --git a/src/devices/nm-device-ppp.h b/src/devices/nm-device-ppp.h index 097f4b97..5a169b37 100644 --- a/src/devices/nm-device-ppp.h +++ b/src/devices/nm-device-ppp.h @@ -1,13 +1,5 @@ -/* 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 83feb130..e87733ef 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2011 Red Hat, Inc. */ @@ -26,6 +12,12 @@ /* This file should only be used by subclasses of NMDevice */ typedef enum { + NM_DEVICE_STAGE_STATE_INIT = 0, + NM_DEVICE_STAGE_STATE_PENDING = 1, + NM_DEVICE_STAGE_STATE_COMPLETED = 2, +} NMDeviceStageState; + +typedef enum { NM_DEVICE_IP_STATE_NONE, NM_DEVICE_IP_STATE_WAIT, NM_DEVICE_IP_STATE_CONF, diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index afe83f50..77b46a59 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -351,18 +337,17 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); - NMActStageReturn ret; - ret = NM_DEVICE_CLASS (nm_device_tun_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - /* Nothing to do for TUN devices */ - if (priv->props.type == IFF_TUN) - return NM_ACT_STAGE_RETURN_SUCCESS; - - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; + if (priv->props.type == IFF_TUN) { + /* Nothing to do for TUN devices */ + } else { + if (!nm_device_hw_addr_set_cloned (device, + nm_device_get_applied_connection (device), + FALSE)) { + *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + } return NM_ACT_STAGE_RETURN_SUCCESS; } diff --git a/src/devices/nm-device-tun.h b/src/devices/nm-device-tun.h index f665b942..2f87d3bc 100644 --- a/src/devices/nm-device-tun.h +++ b/src/devices/nm-device-tun.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_TUN_H__ diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index 0d6425d4..5c26a036 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/nm-device-veth.h b/src/devices/nm-device-veth.h index 07217ff9..15da6ab8 100644 --- a/src/devices/nm-device-veth.h +++ b/src/devices/nm-device-veth.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_VETH_H__ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index f8f6a597..b6efeb81 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2011 - 2012 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 - 2012 Red Hat, Inc. */ #include "nm-default.h" @@ -477,14 +463,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDevice *parent_device; NMSettingVlan *s_vlan; - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; /* Change MAC address to parent's one if needed */ parent_device = nm_device_parent_get_device (device); @@ -497,7 +475,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) if (s_vlan) { gs_free NMVlanQosMapping *ingress_map = NULL; gs_free NMVlanQosMapping *egress_map = NULL; - guint n_ingress_map = 0, n_egress_map = 0; + guint n_ingress_map = 0; + guint n_egress_map = 0; _nm_setting_vlan_get_priorities (s_vlan, NM_VLAN_INGRESS_MAP, @@ -520,7 +499,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) n_egress_map); } - return ret; + return NM_ACT_STAGE_RETURN_SUCCESS; } /*****************************************************************************/ @@ -584,6 +563,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) device_class->link_changed = link_changed; device_class->unrealize_notify = unrealize_notify; device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->act_stage1_prepare = act_stage1_prepare; device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent; device_class->is_available = is_available; diff --git a/src/devices/nm-device-vlan.h b/src/devices/nm-device-vlan.h index c463db58..a5d50a4a 100644 --- a/src/devices/nm-device-vlan.h +++ b/src/devices/nm-device-vlan.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2012 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_VLAN_H__ diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index 1a700ba4..29be6854 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -481,21 +467,6 @@ update_connection (NMDevice *device, NMConnection *connection) } } -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMActStageReturn ret; - - ret = NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - - if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) - return NM_ACT_STAGE_RETURN_FAILURE; - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - /*****************************************************************************/ static void @@ -620,7 +591,7 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) device_class->complete_connection = complete_connection; device_class->get_generic_capabilities = get_generic_capabilities; device_class->update_connection = update_connection; - device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; obj_properties[PROP_ID] = diff --git a/src/devices/nm-device-vxlan.h b/src/devices/nm-device-vxlan.h index dd14d910..a36bdf49 100644 --- a/src/devices/nm-device-vxlan.h +++ b/src/devices/nm-device-vxlan.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013, 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013, 2014 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_VXLAN_H__ diff --git a/src/devices/nm-device-wireguard.c b/src/devices/nm-device-wireguard.c index 5d640b62..c916fa46 100644 --- a/src/devices/nm-device-wireguard.c +++ b/src/devices/nm-device-wireguard.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Javier Arteaga <jarteaga@jbeta.is> + * Copyright (C) 2018 Javier Arteaga <jarteaga@jbeta.is> */ #include "nm-default.h" @@ -1276,8 +1262,10 @@ _secrets_cb (NMActRequest *req, nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - } else - nm_device_activate_schedule_stage1_device_prepare (device); + return; + } + + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -1518,17 +1506,6 @@ link_config_delayed_resolver_cb (gpointer user_data) } static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) -{ - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (device); - - priv->auto_default_route_initialized = FALSE; - priv->auto_default_route_priority_initialized = FALSE; - - return NM_DEVICE_CLASS (nm_device_wireguard_parent_class)->act_stage1_prepare (device, out_failure_reason); -} - -static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { @@ -1810,23 +1787,27 @@ reapply_connection (NMDevice *device, NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (self); gs_unref_object NMIPConfig *ip4_config = NULL; gs_unref_object NMIPConfig *ip6_config = NULL; - - priv->auto_default_route_refresh = TRUE; - - ip4_config = _get_dev2_ip_config (self, AF_INET); - ip6_config = _get_dev2_ip_config (self, AF_INET6); - - nm_device_set_dev2_ip_config (device, AF_INET, ip4_config); - nm_device_set_dev2_ip_config (device, AF_INET6, ip6_config); + NMDeviceState state = nm_device_get_state (device); NM_DEVICE_CLASS (nm_device_wireguard_parent_class)->reapply_connection (device, con_old, con_new); - link_config (NM_DEVICE_WIREGUARD (device), - "reapply", - LINK_CONFIG_MODE_REAPPLY, - NULL); + if (state >= NM_DEVICE_STATE_CONFIG) { + priv->auto_default_route_refresh = TRUE; + link_config (NM_DEVICE_WIREGUARD (device), + "reapply", + LINK_CONFIG_MODE_REAPPLY, + NULL); + } + + if (state >= NM_DEVICE_STATE_IP_CONFIG) { + ip4_config = _get_dev2_ip_config (self, AF_INET); + ip6_config = _get_dev2_ip_config (self, AF_INET6); + + nm_device_set_dev2_ip_config (device, AF_INET, ip4_config); + nm_device_set_dev2_ip_config (device, AF_INET6, ip6_config); + } } /*****************************************************************************/ @@ -1968,7 +1949,6 @@ nm_device_wireguard_class_init (NMDeviceWireGuardClass *klass) device_class->connection_type_check_compatible = NM_SETTING_WIREGUARD_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_WIREGUARD); - device_class->act_stage1_prepare = act_stage1_prepare; device_class->state_changed = device_state_changed; device_class->create_and_realize = create_and_realize; device_class->act_stage2_config = act_stage2_config; diff --git a/src/devices/nm-device-wireguard.h b/src/devices/nm-device-wireguard.h index 3ad41f9b..67318042 100644 --- a/src/devices/nm-device-wireguard.h +++ b/src/devices/nm-device-wireguard.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Javier Arteaga <jarteaga@jbeta.is> + * Copyright (C) 2018 Javier Arteaga <jarteaga@jbeta.is> */ #ifndef __NM_DEVICE_WIREGUARD_H__ diff --git a/src/devices/nm-device-wpan.c b/src/devices/nm-device-wpan.c index 88234412..b947aba6 100644 --- a/src/devices/nm-device-wpan.c +++ b/src/devices/nm-device-wpan.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Lubomir Rintel <lkundrak@v3.sk> +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk> */ #include "nm-default.h" @@ -131,12 +117,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) NMDevice *lowpan_device = NULL; NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - ret = NM_DEVICE_CLASS (nm_device_wpan_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - platform = nm_device_get_platform (device); - g_return_val_if_fail (platform, NM_ACT_STAGE_RETURN_FAILURE); + nm_assert (NM_IS_PLATFORM (platform)); ifindex = nm_device_get_ifindex (device); @@ -147,7 +129,11 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) g_return_val_if_fail (s_wpan, NM_ACT_STAGE_RETURN_FAILURE); hwaddr = nm_platform_link_get_address (platform, ifindex, &hwaddr_len); - g_return_val_if_fail (hwaddr, NM_ACT_STAGE_RETURN_FAILURE); + + if (!hwaddr) { + *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } /* As of kernel 4.16, the 6LoWPAN devices layered on top of WPANs * need to be DOWN as well as the WPAN device itself in order to @@ -156,8 +142,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) NM_LINK_TYPE_6LOWPAN, hwaddr, hwaddr_len); - if (lowpan_plink && NM_FLAGS_HAS (lowpan_plink->n_ifi_flags, IFF_UP)) { - lowpan_device = nm_manager_get_device_by_ifindex (nm_manager_get (), + if ( lowpan_plink + && NM_FLAGS_HAS (lowpan_plink->n_ifi_flags, IFF_UP)) { + lowpan_device = nm_manager_get_device_by_ifindex (NM_MANAGER_GET, lowpan_plink->ifindex); } @@ -192,6 +179,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) } ret = NM_ACT_STAGE_RETURN_SUCCESS; + out: nm_device_bring_up (device, TRUE, NULL); diff --git a/src/devices/nm-device-wpan.h b/src/devices/nm-device-wpan.h index 33f24776..d86a9614 100644 --- a/src/devices/nm-device-wpan.h +++ b/src/devices/nm-device-wpan.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Lubomir Rintel <lkundrak@v3.sk> +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk> */ #ifndef __NETWORKMANAGER_DEVICE_WPAN_H__ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index b3d97af7..e7a4a059 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -64,6 +50,7 @@ #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" #include "nm-setting-ethtool.h" +#include "nm-setting-user.h" #include "nm-auth-utils.h" #include "nm-keep-alive.h" #include "nm-netns.h" @@ -102,11 +89,6 @@ _LOG_DECLARE_SELF (NMDevice); typedef void (*ActivationHandleFunc) (NMDevice *self); -typedef struct { - ActivationHandleFunc func; - guint id; -} ActivationHandleData; - typedef enum { CLEANUP_TYPE_KEEP, CLEANUP_TYPE_REMOVED, @@ -243,6 +225,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, PROP_RX_BYTES, PROP_IP4_CONNECTIVITY, PROP_IP6_CONNECTIVITY, + PROP_INTERFACE_FLAGS, ); typedef struct _NMDevicePrivate { @@ -333,8 +316,23 @@ typedef struct _NMDevicePrivate { NMActRequest * queued_act_request; bool queued_act_request_is_waiting_for_carrier:1; NMDBusTrackObjPath act_request; - ActivationHandleData act_handle4; /* for layer2 and IPv4. */ - ActivationHandleData act_handle6; + + union { + struct { + guint activation_source_id_6; + guint activation_source_id_4; /* for layer2 and IPv4. */ + }; + guint activation_source_id_x[2]; + }; + + union { + struct { + ActivationHandleFunc activation_source_func_6; + ActivationHandleFunc activation_source_func_4; /* for layer2 and IPv4. */ + }; + ActivationHandleFunc activation_source_func_x[2]; + }; + guint recheck_assume_id; struct { @@ -394,7 +392,6 @@ typedef struct _NMDevicePrivate { NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:5; bool is_enslaved:1; - bool master_ready_handled:1; bool ipv6ll_handle:1; /* TRUE if NM handles the device's IPv6LL address */ bool ipv6ll_has:1; @@ -403,6 +400,8 @@ typedef struct _NMDevicePrivate { bool concheck_rp_filter_checked:1; + NMDeviceStageState stage1_sriov_state:3; + /* Generic DHCP stuff */ char * dhcp_anycast_address; @@ -489,7 +488,7 @@ typedef struct _NMDevicePrivate { /* Firewall */ FirewallState fw_state:4; NMFirewallManager *fw_mgr; - NMFirewallManagerCallId fw_call; + NMFirewallManagerCallId *fw_call; /* IPv4LL stuff */ sd_ipv4ll * ipv4ll; @@ -585,6 +584,7 @@ typedef struct _NMDevicePrivate { } concheck_x[2]; guint check_delete_unrealized_id; + guint32 interface_flags; struct { SriovOp *pending; /* SR-IOV operation currently running */ @@ -633,7 +633,6 @@ static void _carrier_wait_check_queued_act_request (NMDevice *self); static gint64 _get_carrier_wait_ms (NMDevice *self); static const char *_activation_func_to_string (ActivationHandleFunc func); -static void activation_source_handle_cb (NMDevice *self, int addr_family); static void _set_state_full (NMDevice *self, NMDeviceState state, @@ -671,6 +670,10 @@ static void (*const activate_stage4_ip_config_timeout_x[2]) (NMDevice *self) = { activate_stage4_ip_config_timeout_4, }; +static void sriov_op_cb (GError *error, gpointer user_data); + +static void activate_stage2_device_config (NMDevice *self); + static void activate_stage5_ip_config_result_4 (NMDevice *self); static void activate_stage5_ip_config_result_6 (NMDevice *self); @@ -1347,6 +1350,7 @@ _get_stable_id (NMDevice *self, NM_PRINT_FMT_QUOTED (stable_type == NM_UTILS_STABLE_TYPE_GENERATED, " from \"", generated, "\"", "")); } + nm_assert (priv->current_stable_id); *out_stable_type = priv->current_stable_id_type; return priv->current_stable_id; } @@ -1716,7 +1720,7 @@ _parent_set_ifindex (NMDevice *self, } if (parent_ifindex > 0) { - parent_device = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + parent_device = nm_manager_get_device_by_ifindex (NM_MANAGER_GET, parent_ifindex); if (parent_device == self) parent_device = NULL; } else @@ -2209,7 +2213,7 @@ nm_device_get_route_metric (NMDevice *self, if (route_metric >= 0) goto out; - route_metric = nm_manager_device_route_metric_reserve (nm_manager_get (), + route_metric = nm_manager_device_route_metric_reserve (NM_MANAGER_GET, nm_device_get_ip_ifindex (self), nm_device_get_device_type (self)); out: @@ -3021,18 +3025,18 @@ concheck_cb (NMConnectivity *connectivity, self_keep_alive = g_object_ref (self); - _LOGT (LOGD_CONCHECK, "connectivity: [Ipv%c] complete check (seq:%llu, state:%s)", - nm_utils_addr_family_to_char (handle->addr_family), - (long long unsigned) handle->seq, - nm_connectivity_state_to_string (state)); - /* keep @self alive, while we invoke callbacks. */ priv = NM_DEVICE_GET_PRIVATE (self); - nm_assert (!handle || c_list_contains (&priv->concheck_lst_head, &handle->concheck_lst)); + nm_assert (handle && c_list_contains (&priv->concheck_lst_head, &handle->concheck_lst)); seq = handle->seq; + _LOGT (LOGD_CONCHECK, "connectivity: [Ipv%c] complete check (seq:%llu, state:%s)", + nm_utils_addr_family_to_char (handle->addr_family), + (long long unsigned) handle->seq, + nm_connectivity_state_to_string (state)); + /* find out, if there are any periodic checks pending (either whether they * were scheduled before or after @handle. */ any_periodic_before = FALSE; @@ -3600,12 +3604,26 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMDeviceState state = nm_device_get_state (self); + gboolean notify_flags = FALSE; if (priv->carrier == carrier) return; + if (NM_FLAGS_ALL (priv->capabilities, + NM_DEVICE_CAP_CARRIER_DETECT + | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) { + if (carrier) + priv->interface_flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER; + else + priv->interface_flags &= ~NM_DEVICE_INTERFACE_FLAG_CARRIER; + notify_flags = TRUE; + } + priv->carrier = carrier; - _notify (self, PROP_CARRIER); + if (notify_flags) + nm_gobject_notify_together (self, PROP_CARRIER, PROP_INTERFACE_FLAGS); + else + _notify (self, PROP_CARRIER); if (priv->carrier) { _LOGI (LOGD_DEVICE, "carrier: link connected"); @@ -3675,7 +3693,7 @@ device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink) if (plink->master <= 0) return; - master = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->master); + master = nm_manager_get_device_by_ifindex (NM_MANAGER_GET, plink->master); plink_master = nm_platform_link_get (nm_device_get_platform (self), plink->master); plink_master_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink_master)); @@ -3802,6 +3820,33 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) g_array_unref (dns_domains); } +static void +device_update_interface_flags (NMDevice *self, const NMPlatformLink *plink) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceInterfaceFlags flags = NM_DEVICE_INTERFACE_FLAG_NONE; + + if (plink && NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP)) + flags |= NM_DEVICE_INTERFACE_FLAG_UP; + if (plink && NM_FLAGS_HAS (plink->n_ifi_flags, IFF_LOWER_UP)) + flags |= NM_DEVICE_INTERFACE_FLAG_LOWER_UP; + + if (NM_FLAGS_ALL (priv->capabilities, + NM_DEVICE_CAP_CARRIER_DETECT + | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) { + if (priv->carrier) + flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER; + } else { + if (plink && NM_FLAGS_HAS (plink->n_ifi_flags, IFF_LOWER_UP)) + flags |= NM_DEVICE_INTERFACE_FLAG_CARRIER; + } + + if (flags != priv->interface_flags) { + priv->interface_flags = flags; + _notify (self, PROP_INTERFACE_FLAGS); + } +} + static gboolean device_link_changed (NMDevice *self) { @@ -3889,6 +3934,8 @@ device_link_changed (NMDevice *self) && !nm_device_has_capability (self, NM_DEVICE_CAP_NONSTANDARD_CARRIER)) nm_device_set_carrier (self, pllink->connected); + device_update_interface_flags (self, pllink); + klass->link_changed (self, pllink); /* Update DHCP, etc, if needed */ @@ -4241,9 +4288,11 @@ nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink _notify (self, PROP_IFINDEX); NM_DEVICE_GET_CLASS (self)->link_changed (self, plink); } + + device_update_interface_flags (self, plink); } -static void sriov_op_cb (GError *error, gpointer user_data); +/*****************************************************************************/ static void sriov_op_start (NMDevice *self, SriovOp *op) @@ -4276,11 +4325,14 @@ sriov_op_cb (GError *error, gpointer user_data) priv->sriov.pending = NULL; + g_clear_object (&op->cancellable); + if (op->callback) op->callback (error, op->callback_data); - g_clear_object (&op->cancellable); - g_slice_free (SriovOp, op); + nm_assert (!priv->sriov.pending); + + nm_g_slice_free (op); if (priv->sriov.next) { sriov_op_start (self, @@ -4289,41 +4341,82 @@ sriov_op_cb (GError *error, gpointer user_data) } static void -sriov_op_queue (NMDevice *self, - guint num_vfs, - NMTernary autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data) +sriov_op_queue_op (NMDevice *self, + SriovOp *op) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - GError *error = NULL; - SriovOp *op; - - op = g_slice_new0 (SriovOp); - op->num_vfs = num_vfs; - op->autoprobe = autoprobe; - op->callback = callback; - op->callback_data = callback_data; if (priv->sriov.next) { + SriovOp *op_next = g_steal_pointer (&priv->sriov.next); + /* Cancel the next operation immediately */ - if (priv->sriov.next->callback) { + if (op_next->callback) { + gs_free_error GError *error = NULL; + nm_utils_error_set_cancelled (&error, FALSE, NULL); - priv->sriov.next->callback (error, priv->sriov.next->callback_data); - g_clear_error (&error); + op_next->callback (error, op_next->callback_data); } - g_slice_free (SriovOp, priv->sriov.next); - priv->sriov.next = NULL; - } - if (priv->sriov.pending) { + nm_g_slice_free (op_next); + + if (!priv->sriov.pending) { + /* This (having "next" set but "pending" not) can only happen if we are + * called from inside the callback again. + * + * That means we append the new request as "next" and return. Once + * the callback returns, it will schedule the request. */ + priv->sriov.next = op; + return; + } + } else if (priv->sriov.pending) { priv->sriov.next = op; g_cancellable_cancel (priv->sriov.pending->cancellable); - } else + return; + } + + if (op) sriov_op_start (self, op); } static void +sriov_op_queue (NMDevice *self, + guint num_vfs, + NMTernary autoprobe, + NMPlatformAsyncCallback callback, + gpointer callback_data) +{ + SriovOp *op; + + /* We usually never want to cancel an async write operation, unless it's superseded + * by a newer operation (that resets the state). That is, because we need to ensure + * that we never end up doing two concurrent writes (since we write on a background + * thread, that would be unordered/racy). + * Of course, since we queue requests only per-device, when devices get renamed we + * might end up writing the same sysctl concurrently still. But that's really + * unlikely, and don't rename after udev completes! + * + * The "next" operation is not yet even started. It can be replaced/canceled right away + * when a newer request comes. + * The "pending" operation is currently ongoing, and we may cancel it if + * we have a follow-up operation (queued in "next"). Unless we have a such + * a newer request, we cannot cancel it! + * + * FIXME(shutdown): However, during shutdown we don't have a follow-up write request to cancel + * this operation and we have to give it at least some time to complete. The solution is that + * we register a way to abort the last call during shutdown, and after NM_SHUTDOWN_TIMEOUT_MS + * grace period we pull the plug and cancel it. */ + + op = g_slice_new (SriovOp); + *op = (SriovOp) { + .num_vfs = num_vfs, + .autoprobe = autoprobe, + .callback = callback, + .callback_data = callback_data, + }; + sriov_op_queue_op (self, op); +} + +static void device_init_static_sriov_num_vfs (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -4746,42 +4839,24 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) return TRUE; } -/** - * nm_device_notify_component_added(): - * @self: the #NMDevice - * @component: the component being added by a plugin - * - * Called by the manager to notify the device that a new component has - * been found. The device implementation should return %TRUE if it - * wishes to claim the component, or %FALSE if it cannot. - * - * Returns: %TRUE to claim the component, %FALSE if the component cannot be - * claimed. - */ -gboolean -nm_device_notify_component_added (NMDevice *self, GObject *component) +void +nm_device_notify_availability_maybe_changed (NMDevice *self) { - NMDeviceClass *klass; NMDevicePrivate *priv; - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE (self); - klass = NM_DEVICE_GET_CLASS (self); - - if (priv->state == NM_DEVICE_STATE_DISCONNECTED) { - /* A device could have stayed disconnected because it would - * want to register with a network server that now become - * available. */ - nm_device_recheck_available_connections (self); - if (g_hash_table_size (priv->available_connections) > 0) - nm_device_emit_recheck_auto_activate (self); - } - if (klass->component_added) - return klass->component_added (self, component); + if (priv->state != NM_DEVICE_STATE_DISCONNECTED) + return; - return FALSE; + /* A device could have stayed disconnected because it would + * want to register with a network server that now become + * available. */ + nm_device_recheck_available_connections (self); + if (g_hash_table_size (priv->available_connections) > 0) + nm_device_emit_recheck_auto_activate (self); } /** @@ -5856,9 +5931,10 @@ check_connection_compatible (NMDevice *self, NMConnection *connection, GError ** return FALSE; } - conn_iface = nm_manager_get_connection_iface (nm_manager_get (), + conn_iface = nm_manager_get_connection_iface (NM_MANAGER_GET, connection, NULL, + NULL, &local); /* We always need a interface name for virtual devices, but for @@ -6103,119 +6179,102 @@ dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer us /*****************************************************************************/ -static gboolean -activation_source_handle_cb4 (gpointer user_data) -{ - activation_source_handle_cb (user_data, AF_INET); - return G_SOURCE_REMOVE; -} - -static gboolean -activation_source_handle_cb6 (gpointer user_data) -{ - activation_source_handle_cb (user_data, AF_INET6); - return G_SOURCE_REMOVE; -} - -static ActivationHandleData * -activation_source_get_by_family (NMDevice *self, - int addr_family, - GSourceFunc *out_idle_func) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - switch (addr_family) { - case AF_INET6: - NM_SET_OUT (out_idle_func, activation_source_handle_cb6); - return &priv->act_handle6; - case AF_INET: - NM_SET_OUT (out_idle_func, activation_source_handle_cb4); - return &priv->act_handle4; - } - g_return_val_if_reached (NULL); -} - static void activation_source_clear (NMDevice *self, int addr_family) { - ActivationHandleData *act_data; - - act_data = activation_source_get_by_family (self, addr_family, NULL); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const gboolean IS_IPv4 = (addr_family == AF_INET); - if (act_data->id) { + if (priv->activation_source_id_x[IS_IPv4] != 0) { _LOGD (LOGD_DEVICE, "activation-stage: clear %s,v%c (id %u)", - _activation_func_to_string (act_data->func), + _activation_func_to_string (priv->activation_source_func_x[IS_IPv4]), nm_utils_addr_family_to_char (addr_family), - act_data->id); - nm_clear_g_source (&act_data->id); - act_data->func = NULL; + priv->activation_source_id_x[IS_IPv4]); + nm_clear_g_source (&priv->activation_source_id_x[IS_IPv4]); + priv->activation_source_func_x[IS_IPv4] = NULL; } } -static void +static gboolean activation_source_handle_cb (NMDevice *self, int addr_family) { - ActivationHandleData *act_data, a; + NMDevicePrivate *priv; + const gboolean IS_IPv4 = (addr_family == AF_INET); + ActivationHandleFunc activation_source_func; + guint activation_source_id; - g_return_if_fail (NM_IS_DEVICE (self)); + g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); - act_data = activation_source_get_by_family (self, addr_family, NULL); + priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (act_data->id); - g_return_if_fail (act_data->func); + activation_source_func = priv->activation_source_func_x[IS_IPv4]; + activation_source_id = priv->activation_source_id_x[IS_IPv4]; - a = *act_data; + g_return_val_if_fail (activation_source_id != 0, G_SOURCE_REMOVE); + nm_assert (activation_source_func); - act_data->func = NULL; - act_data->id = 0; + priv->activation_source_func_x[IS_IPv4] = NULL; + priv->activation_source_id_x[IS_IPv4] = 0; _LOGD (LOGD_DEVICE, "activation-stage: invoke %s,v%c (id %u)", - _activation_func_to_string (a.func), + _activation_func_to_string (activation_source_func), nm_utils_addr_family_to_char (addr_family), - a.id); + activation_source_id); - a.func (self); + activation_source_func (self); - _LOGD (LOGD_DEVICE, "activation-stage: complete %s,v%c (id %u)", - _activation_func_to_string (a.func), + _LOGT (LOGD_DEVICE, "activation-stage: complete %s,v%c (id %u)", + _activation_func_to_string (activation_source_func), nm_utils_addr_family_to_char (addr_family), - a.id); + activation_source_id); + + return G_SOURCE_REMOVE; +} + +static gboolean +activation_source_handle_cb_4 (gpointer user_data) +{ + return activation_source_handle_cb (user_data, AF_INET); +} + +static gboolean +activation_source_handle_cb_6 (gpointer user_data) +{ + return activation_source_handle_cb (user_data, AF_INET6); } static void activation_source_schedule (NMDevice *self, ActivationHandleFunc func, int addr_family) { - ActivationHandleData *act_data; - GSourceFunc source_func = NULL; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const gboolean IS_IPv4 = (addr_family == AF_INET); guint new_id = 0; - act_data = activation_source_get_by_family (self, addr_family, &source_func); - - if (act_data->id && act_data->func == func) { - /* Don't bother rescheduling the same function that's about to - * run anyway. Fixes issues with crappy wireless drivers sending - * streams of associate events before NM has had a chance to process - * the first one. - */ - _LOGD (LOGD_DEVICE, "activation-stage: already scheduled %s,v%c (id %u)", + if ( priv->activation_source_id_x[IS_IPv4] != 0 + && priv->activation_source_func_x[IS_IPv4] == func) { + /* Scheduling the same stage multiple times is fine. */ + _LOGT (LOGD_DEVICE, "activation-stage: already scheduled %s,v%c (id %u)", _activation_func_to_string (func), nm_utils_addr_family_to_char (addr_family), - act_data->id); + priv->activation_source_id_x[IS_IPv4]); return; } - new_id = g_idle_add (source_func, self); + new_id = g_idle_add ( IS_IPv4 + ? activation_source_handle_cb_4 + : activation_source_handle_cb_6, + self); - if (act_data->id) { - _LOGW (LOGD_DEVICE, "activation-stage: schedule %s,v%c which replaces %s,v%c (id %u -> %u)", + if (priv->activation_source_id_x[IS_IPv4] != 0) { + _LOGD (LOGD_DEVICE, "activation-stage: schedule %s,v%c which replaces %s,v%c (id %u -> %u)", _activation_func_to_string (func), nm_utils_addr_family_to_char (addr_family), - _activation_func_to_string (act_data->func), + _activation_func_to_string (priv->activation_source_func_x[IS_IPv4]), nm_utils_addr_family_to_char (addr_family), - act_data->id, new_id); - nm_clear_g_source (&act_data->id); + priv->activation_source_id_x[IS_IPv4], new_id); + nm_clear_g_source (&priv->activation_source_id_x[IS_IPv4]); } else { _LOGD (LOGD_DEVICE, "activation-stage: schedule %s,v%c (id %u)", _activation_func_to_string (func), @@ -6223,19 +6282,38 @@ activation_source_schedule (NMDevice *self, ActivationHandleFunc func, int addr_ new_id); } - act_data->func = func; - act_data->id = new_id; + priv->activation_source_func_x[IS_IPv4] = func; + priv->activation_source_id_x[IS_IPv4] = new_id; } -static gboolean -activation_source_is_scheduled (NMDevice *self, - ActivationHandleFunc func, - int addr_family) +static void +activation_source_invoke_sync (NMDevice *self, ActivationHandleFunc func, int addr_family) { - ActivationHandleData *act_data; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const gboolean IS_IPv4 = (addr_family == AF_INET); - act_data = activation_source_get_by_family (self, addr_family, NULL); - return act_data->func == func; + if (priv->activation_source_id_x[IS_IPv4] == 0) { + _LOGD (LOGD_DEVICE, "activation-stage: synchronously invoke %s,v%c", + _activation_func_to_string (func), + nm_utils_addr_family_to_char (addr_family)); + } else if (priv->activation_source_func_x[IS_IPv4] == func) { + _LOGD (LOGD_DEVICE, "activation-stage: synchronously invoke %s,v%c which was already scheduled (id %u)", + _activation_func_to_string (func), + nm_utils_addr_family_to_char (addr_family), + priv->activation_source_id_x[IS_IPv4]); + } else { + _LOGD (LOGD_DEVICE, "activation-stage: synchronously invoke %s,v%c which replaces %s,v%c (id %u)", + _activation_func_to_string (func), + nm_utils_addr_family_to_char (addr_family), + _activation_func_to_string (priv->activation_source_func_x[IS_IPv4]), + nm_utils_addr_family_to_char (addr_family), + priv->activation_source_id_x[IS_IPv4]); + } + + nm_clear_g_source (&priv->activation_source_id_x[IS_IPv4]); + priv->activation_source_func_x[IS_IPv4] = NULL; + + func (self); } /*****************************************************************************/ @@ -6248,22 +6326,18 @@ master_ready (NMDevice *self, NMActiveConnection *master_connection; NMDevice *master; - g_return_if_fail (priv->state == NM_DEVICE_STATE_PREPARE); - g_return_if_fail (!priv->master_ready_handled); - /* Notify a master device that it has a new slave */ - g_return_if_fail (nm_active_connection_get_master_ready (active)); - master_connection = nm_active_connection_get_master (active); + nm_assert (nm_active_connection_get_master_ready (active)); - priv->master_ready_handled = TRUE; - nm_clear_g_signal_handler (active, &priv->master_ready_id); + master_connection = nm_active_connection_get_master (active); master = nm_active_connection_get_device (master_connection); _LOGD (LOGD_DEVICE, "master connection ready; master device %s", nm_device_get_iface (master)); - if (priv->master && priv->master != master) + if ( priv->master + && priv->master != master) nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); /* If the master didn't change, add-slave only rechecks whether to assume a connection. */ @@ -6277,8 +6351,12 @@ master_ready_cb (NMActiveConnection *active, GParamSpec *pspec, NMDevice *self) { - master_ready (self, active); - nm_device_activate_schedule_stage2_device_config (self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + nm_assert (nm_active_connection_get_master_ready (active)); + + if (priv->state == NM_DEVICE_STATE_PREPARE) + nm_device_activate_schedule_stage1_device_prepare (self); } static void @@ -6424,64 +6502,9 @@ sriov_params_cb (GError *error, gpointer data) return; } - nm_device_activate_schedule_stage2_device_config (self); -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *self, NMDeviceStateReason *out_failure_reason) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMSettingSriov *s_sriov; - guint i, num; + priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_COMPLETED; - if ( priv->ifindex > 0 - && nm_device_has_capability (self, NM_DEVICE_CAP_SRIOV) - && (s_sriov = nm_device_get_applied_setting (self, NM_TYPE_SETTING_SRIOV))) { - nm_auto_freev NMPlatformVF **plat_vfs = NULL; - gs_free_error GError *error = NULL; - NMSriovVF *vf; - NMTernary autoprobe; - gpointer *data; - - autoprobe = nm_setting_sriov_get_autoprobe_drivers (s_sriov); - if (autoprobe == NM_TERNARY_DEFAULT) { - autoprobe = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, - NM_CON_DEFAULT ("sriov.autoprobe-drivers"), - self, - NM_TERNARY_FALSE, - NM_TERNARY_TRUE, - NM_TERNARY_TRUE); - } - - num = nm_setting_sriov_get_num_vfs (s_sriov); - plat_vfs = g_new0 (NMPlatformVF *, num + 1); - for (i = 0; i < num; i++) { - vf = nm_setting_sriov_get_vf (s_sriov, i); - plat_vfs[i] = sriov_vf_config_to_platform (self, vf, &error); - if (!plat_vfs[i]) { - _LOGE (LOGD_DEVICE, - "failed to apply SR-IOV VF '%s': %s", - nm_utils_sriov_vf_to_str (vf, FALSE, NULL), - error->message); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - } - - /* When changing the number of VFs the kernel can block - * for very long time in the write to sysfs, especially - * if autoprobe-drivers is enabled. Do it asynchronously - * to avoid blocking the entire NM process. - */ - data = nm_utils_user_data_pack (self, g_steal_pointer (&plat_vfs)); - sriov_op_queue (self, - nm_setting_sriov_get_total_vfs (s_sriov), - autoprobe, - sriov_params_cb, - data); - return NM_ACT_STAGE_RETURN_POSTPONE; - } - return NM_ACT_STAGE_RETURN_SUCCESS; + nm_device_activate_schedule_stage1_device_prepare (self); } /* @@ -6495,6 +6518,8 @@ activate_stage1_device_prepare (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMActiveConnection *active; + NMActiveConnection *master; priv->v4_route_table_initialized = FALSE; priv->v6_route_table_initialized = FALSE; @@ -6509,21 +6534,117 @@ activate_stage1_device_prepare (NMDevice *self) nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); + if (priv->stage1_sriov_state != NM_DEVICE_STAGE_STATE_COMPLETED) { + NMSettingSriov *s_sriov; + + if (nm_device_sys_iface_state_is_external_or_assume (self)) { + /* pass */ + } else if (priv->stage1_sriov_state == NM_DEVICE_STAGE_STATE_PENDING) + return; + else if ( priv->ifindex > 0 + && nm_device_has_capability (self, NM_DEVICE_CAP_SRIOV) + && (s_sriov = nm_device_get_applied_setting (self, NM_TYPE_SETTING_SRIOV))) { + nm_auto_freev NMPlatformVF **plat_vfs = NULL; + gs_free_error GError *error = NULL; + NMSriovVF *vf; + NMTernary autoprobe; + guint i, num; + + autoprobe = nm_setting_sriov_get_autoprobe_drivers (s_sriov); + if (autoprobe == NM_TERNARY_DEFAULT) { + autoprobe = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, + NM_CON_DEFAULT ("sriov.autoprobe-drivers"), + self, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + NM_TERNARY_TRUE); + } + + num = nm_setting_sriov_get_num_vfs (s_sriov); + plat_vfs = g_new0 (NMPlatformVF *, num + 1); + for (i = 0; i < num; i++) { + vf = nm_setting_sriov_get_vf (s_sriov, i); + plat_vfs[i] = sriov_vf_config_to_platform (self, vf, &error); + if (!plat_vfs[i]) { + _LOGE (LOGD_DEVICE, + "failed to apply SR-IOV VF '%s': %s", + nm_utils_sriov_vf_to_str (vf, FALSE, NULL), + error->message); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED); + return; + } + } + + /* When changing the number of VFs the kernel can block + * for very long time in the write to sysfs, especially + * if autoprobe-drivers is enabled. Do it asynchronously + * to avoid blocking the entire NM process. + */ + sriov_op_queue (self, + nm_setting_sriov_get_total_vfs (s_sriov), + autoprobe, + sriov_params_cb, + nm_utils_user_data_pack (self, + g_steal_pointer (&plat_vfs))); + priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING; + return; + } + priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_COMPLETED; + } + /* Assumed connections were already set up outside NetworkManager */ if (!nm_device_sys_iface_state_is_external_or_assume (self)) { - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); + + if (klass->act_stage1_prepare_set_hwaddr_ethernet) { + if (!nm_device_hw_addr_set_cloned (self, + nm_device_get_applied_connection (self), + FALSE)) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } + } + + if (klass->act_stage1_prepare) { + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + + ret = klass->act_stage1_prepare (self, &failure_reason); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); + return; + } + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) + return; + + nm_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + } + } - ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &failure_reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + active = NM_ACTIVE_CONNECTION (priv->act_request.obj); + master = nm_active_connection_get_master (active); + if (master) { + if (nm_active_connection_get_state (master) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + _LOGD (LOGD_DEVICE, "master connection is deactivating"); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); return; - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, failure_reason); + } + /* If the master connection is ready for slaves, attach ourselves */ + if (!nm_active_connection_get_master_ready (active)) { + if (priv->master_ready_id == 0) { + _LOGD (LOGD_DEVICE, "waiting for master connection to become ready"); + priv->master_ready_id = g_signal_connect (active, + "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, + (GCallback) master_ready_cb, + self); + } return; } - g_return_if_fail (ret == NM_ACT_STAGE_RETURN_SUCCESS); } + nm_clear_g_signal_handler (priv->act_request.obj, &priv->master_ready_id); + if (master) + master_ready (self, active); - nm_device_activate_schedule_stage2_device_config (self); + activation_source_invoke_sync (self, activate_stage2_device_config, AF_INET); } /* @@ -6914,44 +7035,8 @@ activate_stage2_device_config (NMDevice *self) void nm_device_activate_schedule_stage2_device_config (NMDevice *self) { - NMDevicePrivate *priv; - g_return_if_fail (NM_IS_DEVICE (self)); - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->act_request.obj); - - if (!priv->master_ready_handled) { - NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request.obj); - NMActiveConnection *master; - - master = nm_active_connection_get_master (active); - - if (!master) { - g_warn_if_fail (!priv->master_ready_id); - priv->master_ready_handled = TRUE; - } else { - /* If the master connection is ready for slaves, attach ourselves */ - if (nm_active_connection_get_master_ready (active)) - master_ready (self, active); - else if (nm_active_connection_get_state (master) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { - _LOGD (LOGD_DEVICE, "master connection is deactivating"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); - } else { - _LOGD (LOGD_DEVICE, "waiting for master connection to become ready"); - - if (priv->master_ready_id == 0) { - priv->master_ready_id = g_signal_connect (active, - "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, - (GCallback) master_ready_cb, - self); - } - /* Postpone */ - return; - } - } - } - activation_source_schedule (self, activate_stage2_device_config, AF_INET); } @@ -7403,8 +7488,6 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) /* Stop any ongoing DHCP transaction on this device */ nm_clear_g_signal_handler (priv->dhcp4.client, &priv->dhcp4.state_sigid); - nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE); - if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) nm_dhcp_client_stop (priv->dhcp4.client, release); @@ -7552,7 +7635,7 @@ ip_config_merge_and_apply (NMDevice *self, nm_ip_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); if (priv->ext_ip_config_x[IS_IPv4]) - nm_ip_config_merge (composite, priv->ext_ip_config_x[IS_IPv4], NM_IP_CONFIG_MERGE_DEFAULT, 0); + nm_ip_config_merge (composite, priv->ext_ip_config_x[IS_IPv4], NM_IP_CONFIG_MERGE_EXTERNAL, 0); /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. @@ -7658,8 +7741,6 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) NULL, NULL, NULL, NULL); - nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE); - return TRUE; } @@ -7688,7 +7769,13 @@ dhcp4_fail (NMDevice *self, NMDhcpState dhcp_state) _ip_state_to_string (priv->ip_state_4), priv->dhcp4.was_active); - /* Keep client running if there are static addresses configured + /* The client is always left running after a failure. */ + + /* Nothing to do if we failed before... */ + if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL) + goto clear_config; + + /* ... and also if there are static addresses configured * on the interface. */ if ( priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE @@ -7704,14 +7791,12 @@ dhcp4_fail (NMDevice *self, NMDhcpState dhcp_state) */ if ( dhcp_state == NM_DHCP_STATE_TERMINATED || (!priv->dhcp4.was_active && priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)) { - dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); nm_device_activate_schedule_ip_config_timeout (self, AF_INET); return; } /* In any other case (expired lease, assumed connection, etc.), - * start a grace period in which we keep the client running, - * hoping that it will regain a lease. + * wait for some time before failing the IP method. */ if (!priv->dhcp4.grace_id) { priv->dhcp4.grace_id = g_timeout_add_seconds (DHCP_GRACE_PERIOD_SEC, @@ -7869,6 +7954,191 @@ get_dhcp_timeout (NMDevice *self, int addr_family) return timeout ?: NM_DHCP_TIMEOUT_DEFAULT; } +/** + * dhcp_get_iaid: + * @self: the #NMDevice + * @addr_family: the address family + * @connection: the connection + * @out_is_explicit: on return, %TRUE if the user set a valid IAID in + * the connection or in global configuration; %FALSE if the connection + * property was empty and no valid global configuration was provided. + * + * Returns: a IAID value for this device and the given connection. + */ +static guint32 +dhcp_get_iaid (NMDevice *self, + int addr_family, + NMConnection *connection, + gboolean *out_is_explicit) +{ + NMSettingIPConfig *s_ip; + const char *iaid_str; + gs_free char *iaid_str_free = NULL; + guint32 iaid; + const char *iface; + const char *fail_reason; + gboolean is_explicit = TRUE; + + s_ip = nm_connection_get_setting_ip_config (connection, addr_family); + iaid_str = nm_setting_ip_config_get_dhcp_iaid (s_ip); + if (!iaid_str) { + iaid_str_free = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + addr_family == AF_INET + ? NM_CON_DEFAULT ("ipv4.dhcp-iaid") + : NM_CON_DEFAULT ("ipv6.dhcp-iaid"), + self); + iaid_str = iaid_str_free; + if (!iaid_str) { + iaid_str = NM_IAID_IFNAME; + is_explicit = FALSE; + } else if (!_nm_utils_iaid_verify (iaid_str, NULL)) { + _LOGW (LOGD_DEVICE, "invalid global default '%s' for ipv%c.dhcp-iaid", + iaid_str, + nm_utils_addr_family_to_char (addr_family)); + iaid_str = NM_IAID_IFNAME; + is_explicit = FALSE; + } + } + + if (nm_streq0 (iaid_str, NM_IAID_MAC)) { + const NMPlatformLink *pllink; + + pllink = nm_platform_link_get (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self)); + if (!pllink || pllink->l_address.len < 4) { + fail_reason = "invalid link-layer address"; + goto out_fail; + } + + /* @iaid is in native endianness. Use unaligned_read_be32() + * so that the IAID for a given MAC address is the same on + * BE and LE machines. */ + iaid = unaligned_read_be32 (&pllink->l_address.data[pllink->l_address.len - 4]); + goto out_good; + } else if (nm_streq0 (iaid_str, NM_IAID_PERM_MAC)) { + guint8 hwaddr_buf[NM_UTILS_HWADDR_LEN_MAX]; + const char *hwaddr_str; + gsize hwaddr_len; + + hwaddr_str = nm_device_get_permanent_hw_address (self); + if (!hwaddr_str) { + fail_reason = "no permanent link-layer address"; + goto out_fail; + } + + if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_buf, sizeof (hwaddr_buf), &hwaddr_len)) + g_return_val_if_reached (0); + + if (hwaddr_len < 4) { + fail_reason = "invalid link-layer address"; + goto out_fail; + } + + iaid = unaligned_read_be32 (&hwaddr_buf[hwaddr_len - 4]); + goto out_good; + } else if (nm_streq (iaid_str, "stable")) { + nm_auto_free_checksum GChecksum *sum = NULL; + guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1]; + NMUtilsStableType stable_type; + const char *stable_id; + guint32 salted_header; + const guint8 *host_id; + gsize host_id_len; + + stable_id = _get_stable_id (self, connection, &stable_type); + salted_header = htonl (53390459 + stable_type); + nm_utils_host_id_get (&host_id, &host_id_len); + iface = nm_device_get_ip_iface (self); + + sum = g_checksum_new (G_CHECKSUM_SHA1); + g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header)); + g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1); + g_checksum_update (sum, (const guchar *) iface, strlen (iface) + 1); + g_checksum_update (sum, (const guchar *) host_id, host_id_len); + nm_utils_checksum_get_digest (sum, digest); + + iaid = unaligned_read_be32 (digest); + goto out_good; + } else if ((iaid = _nm_utils_ascii_str_to_int64 (iaid_str, 10, 0, G_MAXUINT32, -1)) != -1) { + goto out_good; + } else { + iface = nm_device_get_ip_iface (self); + iaid = nm_utils_create_dhcp_iaid (TRUE, + (const guint8 *) iface, + strlen (iface)); + goto out_good; + } + +out_fail: + nm_assert (fail_reason); + _LOGW ( addr_family == AF_INET + ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4) + : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6), + "ipv%c.dhcp-iaid: failure to generate IAID: %s. Using interface-name based IAID", + nm_utils_addr_family_to_char (addr_family), fail_reason); + is_explicit = FALSE; + iface = nm_device_get_ip_iface (self); + iaid = nm_utils_create_dhcp_iaid (TRUE, + (const guint8 *) iface, + strlen (iface)); +out_good: + _LOGD ( addr_family == AF_INET + ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4) + : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6), + "ipv%c.dhcp-iaid: using %u (0x%08x) IAID (str: '%s', explicit %d)", + nm_utils_addr_family_to_char (addr_family), iaid, iaid, + iaid_str, is_explicit); + NM_SET_OUT (out_is_explicit, is_explicit); + return iaid; +} + +static NMDhcpHostnameFlags +get_dhcp_hostname_flags (NMDevice *self, int addr_family) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip; + NMDhcpHostnameFlags flags; + gs_free_error GError *error = NULL; + + g_return_val_if_fail (NM_IS_DEVICE (self), NM_DHCP_HOSTNAME_FLAG_NONE); + + connection = nm_device_get_applied_connection (self); + s_ip = nm_connection_get_setting_ip_config (connection, addr_family); + g_return_val_if_fail (s_ip, NM_DHCP_HOSTNAME_FLAG_NONE); + + if (!nm_setting_ip_config_get_dhcp_send_hostname (s_ip)) + return NM_DHCP_HOSTNAME_FLAG_NONE; + + flags = nm_setting_ip_config_get_dhcp_hostname_flags (s_ip); + if (flags != NM_DHCP_HOSTNAME_FLAG_NONE) + return flags; + + flags = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, + addr_family == AF_INET + ? NM_CON_DEFAULT ("ipv4.dhcp-hostname-flags") + : NM_CON_DEFAULT ("ipv6.dhcp-hostname-flags"), + self, + 0, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS, + 0); + + if (!_nm_utils_validate_dhcp_hostname_flags (flags, addr_family, &error)) { + _LOGW (LOGD_DEVICE, "invalid global default value 0x%x for ipv%d.%s: %s", + (guint) flags, + addr_family == AF_INET ? 4 : 6, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, + error->message); + flags = NM_DHCP_HOSTNAME_FLAG_NONE; + } + + if (flags != NM_DHCP_HOSTNAME_FLAG_NONE) + return flags; + + if (addr_family == AF_INET) + return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4; + else + return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6; +} + static GBytes * dhcp4_get_client_id (NMDevice *self, NMConnection *connection, @@ -7945,8 +8215,9 @@ dhcp4_get_client_id (NMDevice *self, } if (nm_streq (client_id, "duid")) { - result = nm_utils_dhcp_client_id_systemd_node_specific (TRUE, - nm_device_get_ip_iface (self)); + guint32 iaid = dhcp_get_iaid (self, AF_INET, connection, NULL); + + result = nm_utils_dhcp_client_id_systemd_node_specific (iaid); goto out_good; } @@ -7960,11 +8231,7 @@ dhcp4_get_client_id (NMDevice *self, gsize host_id_len; stable_id = _get_stable_id (self, connection, &stable_type); - if (!stable_id) - g_return_val_if_reached (NULL); - salted_header = htonl (2011610591 + stable_type); - nm_utils_host_id_get (&host_id, &host_id_len); sum = g_checksum_new (G_CHECKSUM_SHA1); @@ -8044,12 +8311,12 @@ dhcp4_start (NMDevice *self) nm_setting_ip_config_get_dhcp_send_hostname (s_ip4), nm_setting_ip_config_get_dhcp_hostname (s_ip4), nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)), + get_dhcp_hostname_flags (self, AF_INET), client_id, get_dhcp_timeout (self, AF_INET), priv->dhcp_anycast_address, NULL, &error); - if (!priv->dhcp4.client) { _LOGW (LOGD_DHCP4, "failure to start DHCP: %s", error->message); g_clear_error (&error); @@ -8061,8 +8328,6 @@ dhcp4_start (NMDevice *self) G_CALLBACK (dhcp4_state_changed), self); - nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP4, TRUE); - if (nm_device_sys_iface_state_is_external_or_assume (self)) priv->dhcp4.was_active = TRUE; @@ -8267,8 +8532,6 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) g_clear_object (&priv->dhcp6.client); } - nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE); - if (priv->dhcp6.config) { nm_dbus_object_clear_and_unexport (&priv->dhcp6.config); _notify (self, PROP_DHCP6_CONFIG); @@ -8302,8 +8565,6 @@ dhcp6_lease_change (NMDevice *self) NULL, NULL, NULL, NULL); - nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE); - return TRUE; } @@ -8333,10 +8594,16 @@ dhcp6_fail (NMDevice *self, NMDhcpState dhcp_state) _ip_state_to_string (priv->ip_state_6), priv->dhcp6.was_active); + /* The client is always left running after a failure. */ + + /* Nothing to do if we failed before... */ + if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL) + goto clear_config; + is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED); if (is_dhcp_managed) { - /* Keep client running if there are static addresses configured + /* ... and also if there are static addresses configured * on the interface. */ if ( priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE @@ -8352,14 +8619,12 @@ dhcp6_fail (NMDevice *self, NMDhcpState dhcp_state) */ if ( dhcp_state == NM_DHCP_STATE_TERMINATED || (!priv->dhcp6.was_active && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)) { - dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); nm_device_activate_schedule_ip_config_timeout (self, AF_INET6); return; } /* In any other case (expired lease, assumed connection, etc.), - * start a grace period in which we keep the client running, - * hoping that it will regain a lease. + * wait for some time before failing the IP method. */ if (!priv->dhcp6.grace_id) { priv->dhcp6.grace_id = g_timeout_add_seconds (DHCP_GRACE_PERIOD_SEC, @@ -8690,8 +8955,6 @@ dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboole } digest; stable_id = _get_stable_id (self, connection, &stable_type); - if (!stable_id) - g_return_val_if_reached (NULL); if (NM_IN_STRSET (duid, "stable-ll", "stable-llt")) { /* for stable LL/LLT DUIDs, we still need a hardware address to detect @@ -8820,6 +9083,8 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) gboolean enforce_duid = FALSE; const NMPlatformLink *pllink; GError *error = NULL; + guint32 iaid; + gboolean iaid_explicit; const NMPlatformIP6Address *ll_addr = NULL; @@ -8844,6 +9109,8 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) bcast_hwaddr = nmp_link_address_get_as_bytes (&pllink->l_broadcast); } + iaid = dhcp_get_iaid (self, AF_INET6, connection, &iaid_explicit); + duid = dhcp6_get_duid (self, connection, hwaddr, &enforce_duid); priv->dhcp6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_multi_index (self), @@ -8857,8 +9124,11 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) nm_device_get_route_metric (self, AF_INET6), nm_setting_ip_config_get_dhcp_send_hostname (s_ip6), nm_setting_ip_config_get_dhcp_hostname (s_ip6), + get_dhcp_hostname_flags (self, AF_INET6), duid, enforce_duid, + iaid, + iaid_explicit, get_dhcp_timeout (self, AF_INET6), priv->dhcp_anycast_address, (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, @@ -8893,7 +9163,6 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; - NMSettingIPConfig *s_ip6; nm_dbus_object_clear_and_unexport (&priv->dhcp6.config); priv->dhcp6.config = nm_dhcp6_config_new (); @@ -8903,11 +9172,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll) g_clear_pointer (&priv->dhcp6.event_id, g_free); connection = nm_device_get_applied_connection (self); - g_assert (connection); - s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (!nm_setting_ip_config_get_may_fail (s_ip6) || - !strcmp (nm_setting_ip_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_DHCP)) - nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP6, TRUE); + g_return_val_if_fail (connection, FALSE); if (wait_for_ll) { /* ensure link local is ready... */ @@ -9134,13 +9399,12 @@ check_and_add_ipv6ll_addr (NMDevice *self) const char *stable_id; stable_id = _get_stable_id (self, connection, &stable_type); - if ( !stable_id - || !nm_utils_ipv6_addr_set_stable_privacy (stable_type, - &lladdr, - nm_device_get_iface (self), - stable_id, - priv->linklocal6_dad_counter++, - &error)) { + if (!nm_utils_ipv6_addr_set_stable_privacy (stable_type, + &lladdr, + nm_device_get_iface (self), + stable_id, + priv->linklocal6_dad_counter++, + &error)) { _LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); g_clear_error (&error); linklocal6_failed (self); @@ -9794,7 +10058,6 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) g_assert (s_ip6); stable_id = _get_stable_id (self, connection, &stable_type); - g_assert (stable_id); priv->ndisc = nm_lndp_ndisc_new (nm_device_get_platform (self), nm_device_get_ip_ifindex (self), nm_device_get_ip_iface (self), @@ -9817,9 +10080,6 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) "IPv6 private addresses. This feature is not available"); } - if (!nm_setting_ip_config_get_may_fail (nm_connection_get_setting_ip6_config (connection))) - nm_device_add_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, TRUE); - /* ensure link local is ready... */ if (!linklocal6_start (self)) { /* wait for the LL address to show up */ @@ -9840,8 +10100,6 @@ addrconf6_cleanup (NMDevice *self) nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_changed_id); nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_timeout_id); - nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE); - applied_config_clear (&priv->ac_ip6_config); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); @@ -10002,7 +10260,7 @@ _ip6_privacy_get (NMDevice *self) return ip6_privacy; if (!nm_device_get_ip_ifindex (self)) - return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;; + return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; /* 3.) No valid default-value configured. Fallback to reading sysctl. * @@ -10376,7 +10634,7 @@ activate_stage3_ip_config_start (NMDevice *self) static void fw_change_zone_cb (NMFirewallManager *firewall_manager, - NMFirewallManagerCallId call_id, + NMFirewallManagerCallId *call_id, GError *error, gpointer user_data) { @@ -10389,6 +10647,7 @@ fw_change_zone_cb (NMFirewallManager *firewall_manager, if (priv->fw_call != call_id) g_return_if_reached (); + priv->fw_call = NULL; if (nm_utils_error_is_cancelled (error, FALSE)) @@ -10668,7 +10927,7 @@ start_sharing (NMDevice *self, NMIP4Config *config, GError **error) * the announced setting without restarting dnsmasq. That means, if the default * route changes w.r.t. being metered, then the shared connection does not get * updated before reactivating. */ - announce_android_metered = NM_IN_SET (nm_manager_get_metered (nm_manager_get ()), + announce_android_metered = NM_IN_SET (nm_manager_get_metered (NM_MANAGER_GET), NM_METERED_YES, NM_METERED_GUESS_YES); break; @@ -10841,8 +11100,6 @@ activate_stage5_ip_config_result_4 (NMDevice *self) if (do_announce) nm_device_arp_announce (self); - nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE); - /* Enter the IP_CHECK state if this is the first method to complete */ _set_ip_state (self, AF_INET, NM_DEVICE_IP_STATE_DONE); check_ip_state (self, FALSE, TRUE); @@ -11004,8 +11261,6 @@ activate_stage5_ip_config_result_6 (NMDevice *self) return; } } - nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE); - nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE); /* Start IPv6 forwarding if we need it */ method = nm_device_get_effective_ip_config_method (self, AF_INET6); @@ -11360,7 +11615,8 @@ nm_device_reactivate_ip4_config (NMDevice *self, } } - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + if ( nm_device_get_ip_ifindex (self) > 0 + && !ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); } } @@ -11433,7 +11689,8 @@ nm_device_reactivate_ip6_config (NMDevice *self, } } - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + if ( nm_device_get_ip_ifindex (self) > 0 + && !ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); } } @@ -11492,10 +11749,19 @@ can_reapply_change (NMDevice *self, NM_SETTING_CONNECTION_MDNS, NM_SETTING_CONNECTION_LLMNR); } else if (NM_IN_STRSET (setting_name, + NM_SETTING_USER_SETTING_NAME, NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_SETTING_NAME)) { return TRUE; + } else if ( nm_streq (setting_name, NM_SETTING_WIRED_SETTING_NAME) + && NM_IN_SET (NM_DEVICE_GET_CLASS (self)->get_configured_mtu, + nm_device_get_configured_mtu_wired_parent, + nm_device_get_configured_mtu_for_wired)) { + return nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_WIRED_SETTING_NAME, + error, + NM_SETTING_WIRED_MTU); } else { g_set_error (error, NM_DEVICE_ERROR, @@ -11541,7 +11807,8 @@ check_and_reapply_connection (NMDevice *self, NMSettingIPConfig *s_ip6_old, *s_ip6_new; GHashTableIter iter; - if (priv->state != NM_DEVICE_STATE_ACTIVATED) { + if ( priv->state < NM_DEVICE_STATE_PREPARE + || priv->state > NM_DEVICE_STATE_ACTIVATED) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, @@ -11654,24 +11921,31 @@ check_and_reapply_connection (NMDevice *self, *************************************************************************/ klass->reapply_connection (self, con_old, con_new); - nm_device_update_firewall_zone (self); - nm_device_update_metered (self); - lldp_init (self, FALSE); + if (priv->state >= NM_DEVICE_STATE_CONFIG) + lldp_init (self, FALSE); - s_ip4_old = nm_connection_get_setting_ip4_config (con_old); - s_ip4_new = nm_connection_get_setting_ip4_config (con_new); - s_ip6_old = nm_connection_get_setting_ip6_config (con_old); - s_ip6_new = nm_connection_get_setting_ip6_config (con_new); + if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) { + s_ip4_old = nm_connection_get_setting_ip4_config (con_old); + s_ip4_new = nm_connection_get_setting_ip4_config (con_new); + s_ip6_old = nm_connection_get_setting_ip6_config (con_old); + s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - /* Allow reapply of MTU */ - priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; + /* Allow reapply of MTU */ + priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; - nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); - nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); - _routing_rules_sync (self, NM_TERNARY_TRUE); + _routing_rules_sync (self, NM_TERNARY_TRUE); - reactivate_proxy_config (self); + reactivate_proxy_config (self); + } + + if (priv->state >= NM_DEVICE_STATE_IP_CHECK) + nm_device_update_firewall_zone (self); + + if (priv->state >= NM_DEVICE_STATE_ACTIVATED) + nm_device_update_metered (self); return TRUE; } @@ -11768,7 +12042,8 @@ impl_device_reapply (NMDBusObject *obj, return; } - if (priv->state != NM_DEVICE_STATE_ACTIVATED) { + if ( priv->state < NM_DEVICE_STATE_PREPARE + || priv->state > NM_DEVICE_STATE_ACTIVATED) { error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, "Device is not activated"); @@ -12353,7 +12628,7 @@ nm_device_is_activating (NMDevice *self) * handler is actually run. If there's an activation handler scheduled * we're activating anyway. */ - return priv->act_handle4.id ? TRUE : FALSE; + return priv->activation_source_id_4 != 0; } NMProxyConfig * @@ -13335,9 +13610,8 @@ queued_ip_config_change (NMDevice *self, int addr_family) * it changing IP configurations before they are applied. Postpone the * update in such case. */ - if (activation_source_is_scheduled (self, - activate_stage5_ip_config_result_x[IS_IPv4], - addr_family)) + if ( priv->activation_source_id_x[IS_IPv4] != 0 + && priv->activation_source_func_x[IS_IPv4] == activate_stage5_ip_config_result_x[IS_IPv4]) return G_SOURCE_CONTINUE; priv->queued_ip_config_id_x[IS_IPv4] = 0; @@ -14115,6 +14389,11 @@ nm_device_update_metered (NMDevice *self) } } + if ( value == NM_METERED_INVALID + && NM_DEVICE_GET_CLASS (self)->get_guessed_metered + && NM_DEVICE_GET_CLASS (self)->get_guessed_metered (self)) + value = NM_METERED_GUESS_YES; + /* Try to guess a value using the metered flag in IP configuration */ if (value == NM_METERED_INVALID) { if ( priv->ip_config_4 @@ -14676,8 +14955,10 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) _cancel_activation (self); + priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_INIT; + if (cleanup_type != CLEANUP_TYPE_KEEP) { - nm_manager_device_route_metric_clear (nm_manager_get (), + nm_manager_device_route_metric_clear (NM_MANAGER_GET, nm_device_get_ip_ifindex (self)); } @@ -14754,10 +15035,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) if (priv->act_request.obj) { nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request.obj), AF_INET, FALSE); - - priv->master_ready_handled = FALSE; nm_clear_g_signal_handler (priv->act_request.obj, &priv->master_ready_id); - act_request_set (self, NULL); } @@ -14949,7 +15227,7 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup (nm_connection_get_uuid (connection))); stable_id = _get_stable_id (self, connection, &stable_type); - if (stable_id && stable_type != NM_UTILS_STABLE_TYPE_UUID) { + if (stable_type != NM_UTILS_STABLE_TYPE_UUID) { g_ptr_array_add (argv, g_strdup ("--stable-id")); g_ptr_array_add (argv, g_strdup_printf ("%d %s", (int) stable_type, stable_id)); } @@ -15112,9 +15390,9 @@ deactivate_ready (NMDevice *self, NMDeviceStateReason reason) if (priv->dispatcher.call_id) return; - if (priv->sriov.pending) + if ( priv->sriov.pending + || priv->sriov.next) return; - nm_assert (!priv->sriov.next); nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason); } @@ -15208,6 +15486,13 @@ _set_state_full (NMDevice *self, old_state = priv->state; + if ( state == NM_DEVICE_STATE_FAILED + && nm_device_sys_iface_state_is_external_or_assume (self)) { + /* Avoid tearing down assumed connection, assume it's connected */ + state = NM_DEVICE_STATE_ACTIVATED; + reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; + } + /* Do nothing if state isn't changing, but as a special case allow * re-setting UNAVAILABLE if the device is missing firmware so that we * can retry device initialization. @@ -15459,14 +15744,6 @@ _set_state_full (NMDevice *self, */ _cancel_activation (self); - if (nm_device_sys_iface_state_is_external_or_assume (self)) { - /* Avoid tearing down assumed connection, assume it's connected */ - nm_device_queue_state (self, - NM_DEVICE_STATE_ACTIVATED, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - break; - } - sett_conn = nm_device_get_settings_connection (self); _LOGW (LOGD_DEVICE | LOGD_WIFI, "Activation: failed for connection '%s'", @@ -16237,12 +16514,10 @@ _hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi, } stable_id = _get_stable_id (self, connection, &stable_type); - if (stable_id) { - hw_addr_generated = nm_utils_hw_addr_gen_stable_eth (stable_type, stable_id, - nm_device_get_ip_iface (self), - nm_device_get_initial_hw_address (self), - _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp)); - } + hw_addr_generated = nm_utils_hw_addr_gen_stable_eth (stable_type, stable_id, + nm_device_get_ip_iface (self), + nm_device_get_initial_hw_address (self), + _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp)); if (!hw_addr_generated) { g_set_error (error, NM_DEVICE_ERROR, @@ -16698,14 +16973,15 @@ dispose (GObject *object) _cleanup_generic_pre (self, CLEANUP_TYPE_KEEP); - g_warn_if_fail (c_list_is_empty (&priv->slaves)); - g_assert (priv->master_ready_id == 0); + nm_assert (c_list_is_empty (&priv->slaves)); /* Let the kernel manage IPv6LL again */ set_nm_ipv6ll (self, FALSE); _cleanup_generic_post (self, CLEANUP_TYPE_KEEP); + nm_assert (priv->master_ready_id == 0); + g_hash_table_remove_all (priv->ip6_saved_properties); nm_clear_g_source (&priv->recheck_assume_id); @@ -17093,6 +17369,9 @@ get_property (GObject *object, guint prop_id, case PROP_IP6_CONNECTIVITY: g_value_set_uint (value, priv->concheck_x[0].state); break; + case PROP_INTERFACE_FLAGS: + g_value_set_uint (value, priv->interface_flags); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -17181,6 +17460,7 @@ static const NMDBusInterfaceInfoExtended interface_info_device = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Real", "b", NM_DEVICE_REAL), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Ip4Connectivity", "u", NM_DEVICE_IP4_CONNECTIVITY), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Ip6Connectivity", "u", NM_DEVICE_IP6_CONNECTIVITY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("InterfaceFlags", "u", NM_DEVICE_INTERFACE_FLAGS), ), ), }; @@ -17221,7 +17501,6 @@ nm_device_class_init (NMDeviceClass *klass) klass->link_changed = link_changed; klass->is_available = is_available; - klass->act_stage1_prepare = act_stage1_prepare; klass->act_stage2_config = act_stage2_config; klass->act_stage3_ip_config_start = act_stage3_ip_config_start; klass->act_stage4_ip_config_timeout = act_stage4_ip_config_timeout; @@ -17409,14 +17688,6 @@ nm_device_class_init (NMDeviceClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - /** - * NMDevice:metered: - * - * Whether the connection is metered. - * - * Since: 1.2 - **/ obj_properties[PROP_METERED] = g_param_spec_uint (NM_DEVICE_METERED, "", "", 0, G_MAXUINT32, NM_METERED_UNKNOWN, @@ -17465,6 +17736,13 @@ nm_device_class_init (NMDeviceClass *klass) NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_INTERFACE_FLAGS] = + g_param_spec_uint (NM_DEVICE_INTERFACE_FLAGS, "", "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 412a57a0..518c66ca 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -67,9 +53,6 @@ nm_device_state_reason_check (NMDeviceStateReason reason) } #define NM_PENDING_ACTION_AUTOACTIVATE "autoactivate" -#define NM_PENDING_ACTION_DHCP4 "dhcp4" -#define NM_PENDING_ACTION_DHCP6 "dhcp6" -#define NM_PENDING_ACTION_AUTOCONF6 "autoconf6" #define NM_PENDING_ACTION_RECHECK_AVAILABLE "recheck-available" #define NM_PENDING_ACTION_CARRIER_WAIT "carrier-wait" #define NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT "waiting-for-supplicant" @@ -149,6 +132,7 @@ nm_device_state_reason_check (NMDeviceStateReason reason) #define NM_DEVICE_IP4_CONNECTIVITY "ip4-connectivity" #define NM_DEVICE_IP6_CONNECTIVITY "ip6-connectivity" +#define NM_DEVICE_INTERFACE_FLAGS "interface-flags" #define NM_TYPE_DEVICE (nm_device_get_type ()) #define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice)) @@ -435,23 +419,6 @@ typedef struct _NMDeviceClass { int new_ifindex, NMDevice *new_parent); - /** - * component_added: - * @self: the #NMDevice - * @component: the component (device, modem, etc) which was added - * - * Notifies @self that a new component that a device might be interested - * in was detected by some device factory. It may include an object of - * %GObject subclass to help the devices decide whether it claims that - * particular object itself and the emitting factory should not. - * - * Returns: %TRUE if the component was claimed exclusively and no further - * devices should be notified of the new component. %FALSE to indicate - * that the component was not exclusively claimed and other devices should - * be notified. - */ - gboolean (* component_added) (NMDevice *self, GObject *component); - gboolean (* owns_iface) (NMDevice *self, const char *iface); NMConnection * (* new_default_connection) (NMDevice *self); @@ -472,10 +439,15 @@ typedef struct _NMDeviceClass { guint32 (* get_dhcp_timeout) (NMDevice *self, int addr_family); + gboolean (* get_guessed_metered) (NMDevice *self); + /* Controls, whether to call act_stage2_config() callback also for assuming * a device or for external activations. In this case, act_stage2_config() must * take care not to touch the device's configuration. */ bool act_stage2_config_also_for_external_or_assume:1; + + bool act_stage1_prepare_set_hwaddr_ethernet:1; + } NMDeviceClass; typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, @@ -825,7 +797,7 @@ gboolean nm_device_check_connection_available (NMDevice *device, const char *specific_object, GError **error); -gboolean nm_device_notify_component_added (NMDevice *device, GObject *component); +void nm_device_notify_availability_maybe_changed (NMDevice *self); gboolean nm_device_owns_iface (NMDevice *device, const char *iface); @@ -885,12 +857,22 @@ void nm_device_check_connectivity_cancel (NMDeviceConnectivityHandle *handle); NMConnectivityState nm_device_get_connectivity_state (NMDevice *self, int addr_family); typedef struct _NMBtVTableNetworkServer NMBtVTableNetworkServer; + +typedef void (*NMBtVTableRegisterCallback) (GError *error, + gpointer user_data); + struct _NMBtVTableNetworkServer { gboolean (*is_available) (const NMBtVTableNetworkServer *vtable, - const char *addr); + const char *addr, + NMDevice *device_accept_busy); + gboolean (*register_bridge) (const NMBtVTableNetworkServer *vtable, const char *addr, - NMDevice *device); + NMDevice *device, + GCancellable *cancellable, + NMBtVTableRegisterCallback callback, + gpointer callback_user_data, + GError **error); gboolean (*unregister_bridge) (const NMBtVTableNetworkServer *vtable, NMDevice *device); }; diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 469ccce1..4c9e7705 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h index c44ca59f..92e1d00f 100644 --- a/src/devices/nm-lldp-listener.h +++ b/src/devices/nm-lldp-listener.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/devices/ovs/meson.build b/src/devices/ovs/meson.build index 834b27b0..27e1b4d0 100644 --- a/src/devices/ovs/meson.build +++ b/src/devices/ovs/meson.build @@ -7,14 +7,15 @@ sources = files( ) deps = [ + daemon_nm_default_dep, jansson_dep, - nm_dep, ] libnm_device_plugin_ovs = shared_module( 'nm-device-plugin-ovs', sources: sources, dependencies: deps, + c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, @@ -28,10 +29,3 @@ test( check_exports, args: [libnm_device_plugin_ovs.full_path(), linker_script_devices], ) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-ovs: src/devices/ovs/libnm-device-plugin-ovs.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/ovs/.libs/libnm-device-plugin-ovs.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/ovs/.libs/libnm-device-plugin-ovs.so) -''' diff --git a/src/devices/ovs/nm-device-ovs-bridge.c b/src/devices/ovs/nm-device-ovs-bridge.c index be707e7a..59096803 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.c +++ b/src/devices/ovs/nm-device-ovs-bridge.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/ovs/nm-device-ovs-bridge.h b/src/devices/ovs/nm-device-ovs-bridge.h index 631b4754..07a1fee7 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.h +++ b/src/devices/ovs/nm-device-ovs-bridge.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/devices/ovs/nm-device-ovs-interface.c index 83de3c3d..726e9901 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/devices/ovs/nm-device-ovs-interface.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -112,7 +98,9 @@ link_changed (NMDevice *device, { NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (device); - if (pllink && priv->waiting_for_interface) { + if ( pllink + && priv->waiting_for_interface + && nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { priv->waiting_for_interface = FALSE; nm_device_bring_up (device, TRUE, NULL); nm_device_activate_schedule_stage3_ip_config_start (device); @@ -156,6 +144,15 @@ can_unmanaged_external_down (NMDevice *self) return FALSE; } +static void +deactivate (NMDevice *device) +{ + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE (device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE (self); + + priv->waiting_for_interface = FALSE; +} + /*****************************************************************************/ static void @@ -185,6 +182,7 @@ nm_device_ovs_interface_class_init (NMDeviceOvsInterfaceClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_OPENVSWITCH); + device_class->deactivate = deactivate; device_class->get_type_description = get_type_description; device_class->create_and_realize = create_and_realize; device_class->get_generic_capabilities = get_generic_capabilities; diff --git a/src/devices/ovs/nm-device-ovs-interface.h b/src/devices/ovs/nm-device-ovs-interface.h index a748e206..e31dac8b 100644 --- a/src/devices/ovs/nm-device-ovs-interface.h +++ b/src/devices/ovs/nm-device-ovs-interface.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_OVS_INTERFACE_H__ diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c index 39e64b3f..0955e8a9 100644 --- a/src/devices/ovs/nm-device-ovs-port.c +++ b/src/devices/ovs/nm-device-ovs-port.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/ovs/nm-device-ovs-port.h b/src/devices/ovs/nm-device-ovs-port.h index 5ccf1ec1..7edbf02f 100644 --- a/src/devices/ovs/nm-device-ovs-port.h +++ b/src/devices/ovs/nm-device-ovs-port.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DEVICE_OVS_PORT_H__ diff --git a/src/devices/ovs/nm-ovs-factory.c b/src/devices/ovs/nm-ovs-factory.c index fdf07bd3..d6dd13eb 100644 --- a/src/devices/ovs/nm-ovs-factory.c +++ b/src/devices/ovs/nm-ovs-factory.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ @@ -83,7 +69,7 @@ new_device_from_type (const char *name, NMDeviceType device_type) const char *type_desc; NMLinkType link_type = NM_LINK_TYPE_NONE; - if (nm_manager_get_device (nm_manager_get (), name, device_type)) + if (nm_manager_get_device (NM_MANAGER_GET, name, device_type)) return NULL; if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) { @@ -130,7 +116,7 @@ ovsdb_device_removed (NMOvsdb *ovsdb, const char *name, NMDeviceType device_type NMDevice *device; NMDeviceState device_state; - device = nm_manager_get_device (nm_manager_get (), name, device_type); + device = nm_manager_get_device (NM_MANAGER_GET, name, device_type); if (!device) return; @@ -158,7 +144,7 @@ ovsdb_interface_failed (NMOvsdb *ovsdb, _LOGI (name, connection_uuid, "ovs interface \"%s\" (%s) failed: %s", name, connection_uuid, error); - device = nm_manager_get_device (nm_manager_get (), name, NM_DEVICE_TYPE_OVS_INTERFACE); + device = nm_manager_get_device (NM_MANAGER_GET, name, NM_DEVICE_TYPE_OVS_INTERFACE); if (!device) return; diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index c0e68db3..ec4f5c74 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/ovs/nm-ovsdb.h b/src/devices/ovs/nm-ovsdb.h index e7f9d719..59f46206 100644 --- a/src/devices/ovs/nm-ovsdb.h +++ b/src/devices/ovs/nm-ovsdb.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_OVSDB_H__ diff --git a/src/devices/team/meson.build b/src/devices/team/meson.build index 3f755012..0e63183b 100644 --- a/src/devices/team/meson.build +++ b/src/devices/team/meson.build @@ -4,15 +4,16 @@ sources = files( ) deps = [ + daemon_nm_default_dep, jansson_dep, libteamdctl_dep, - nm_dep, ] libnm_device_plugin_team = shared_module( 'nm-device-plugin-team', sources: sources, dependencies: deps, + c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, @@ -26,10 +27,3 @@ test( check_exports, args: [libnm_device_plugin_team.full_path(), linker_script_devices], ) - -# FIXME: check_so_symbols replacement -''' -check-local-devices-team: src/devices/team/libnm-device-plugin-team.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/team/.libs/libnm-device-plugin-team.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/team/.libs/libnm-device-plugin-team.so) -''' diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 4661a840..fb9c9c69 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us> * Copyright (C) 2018 Red Hat, Inc. */ @@ -49,14 +35,14 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceTeam, typedef struct { struct teamdctl *tdc; + char *config; GPid teamd_pid; guint teamd_process_watch; guint teamd_timeout; guint teamd_read_timeout; guint teamd_dbus_watch; - char *config; - gboolean kill_in_progress; - NMConnection *connection; + bool kill_in_progress:1; + NMDeviceStageState stage1_state:3; } NMDeviceTeamPrivate; struct _NMDeviceTeam { @@ -70,11 +56,11 @@ struct _NMDeviceTeamClass { G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) -#define NM_DEVICE_TEAM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceTeam, NM_IS_DEVICE_TEAM) +#define NM_DEVICE_TEAM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceTeam, NM_IS_DEVICE_TEAM, NMDevice) /*****************************************************************************/ -static gboolean teamd_start (NMDevice *device, NMConnection *connection); +static gboolean teamd_start (NMDeviceTeam *self); /*****************************************************************************/ @@ -141,9 +127,8 @@ _get_config (NMDeviceTeam *self) } static gboolean -teamd_read_config (NMDevice *device) +teamd_read_config (NMDeviceTeam *self) { - NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); const char *config = NULL; int err; @@ -170,11 +155,11 @@ teamd_read_config (NMDevice *device) static gboolean teamd_read_timeout_cb (gpointer user_data) { - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE ((NMDeviceTeam *) user_data); + NMDeviceTeam *self = user_data; + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); - teamd_read_config ((NMDevice *) user_data); priv->teamd_read_timeout = 0; - + teamd_read_config (self); return G_SOURCE_REMOVE; } @@ -192,8 +177,9 @@ update_connection (NMDevice *device, NMConnection *connection) } /* Read the configuration only if not already set */ - if (!priv->config && ensure_teamd_connection (device)) - teamd_read_config (device); + if ( !priv->config + && ensure_teamd_connection (device)) + teamd_read_config (self); /* Restore previous tdc state */ if (priv->tdc && !tdc) { @@ -273,31 +259,32 @@ master_update_slave_connection (NMDevice *self, } /*****************************************************************************/ + static void teamd_kill_cb (pid_t pid, gboolean success, int child_status, void *user_data) { - NMDevice *device = NM_DEVICE (user_data); - NMDeviceTeam *self = (NMDeviceTeam *) device; + gs_unref_object NMDeviceTeam *self = user_data; NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); priv->kill_in_progress = FALSE; - if (priv->connection) { - _LOGT (LOGD_TEAM, "kill terminated, starting teamd..."); - if (!teamd_start (device, priv->connection)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); - } - g_clear_object (&priv->connection); + if (nm_device_get_state (NM_DEVICE (self)) != NM_DEVICE_STATE_PREPARE) { + _LOGT (LOGD_TEAM, "kill terminated"); + return; + } + + _LOGT (LOGD_TEAM, "kill terminated, starting teamd..."); + if (!teamd_start (self)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } - g_object_unref (device); } static void -teamd_cleanup (NMDevice *device, gboolean free_tdc) +teamd_cleanup (NMDeviceTeam *self, gboolean free_tdc) { - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE ((NMDeviceTeam *) device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); nm_clear_g_source (&priv->teamd_process_watch); nm_clear_g_source (&priv->teamd_timeout); @@ -305,15 +292,18 @@ teamd_cleanup (NMDevice *device, gboolean free_tdc) if (priv->teamd_pid > 0) { priv->kill_in_progress = TRUE; - nm_utils_kill_child_async (priv->teamd_pid, SIGTERM, - LOGD_TEAM, "teamd", + nm_utils_kill_child_async (priv->teamd_pid, + SIGTERM, + LOGD_TEAM, + "teamd", 2000, teamd_kill_cb, - g_object_ref (device)); + g_object_ref (self)); priv->teamd_pid = 0; } - if (priv->tdc && free_tdc) { + if ( priv->tdc + && free_tdc) { teamdctl_disconnect (priv->tdc); teamdctl_free (priv->tdc); priv->tdc = NULL; @@ -333,7 +323,7 @@ teamd_timeout_cb (gpointer user_data) if (priv->teamd_pid && !priv->tdc) { /* Timed out launching our own teamd process */ _LOGW (LOGD_TEAM, "teamd timed out"); - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); g_warn_if_fail (nm_device_is_activating (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); @@ -341,7 +331,7 @@ teamd_timeout_cb (gpointer user_data) /* Read again the configuration after the timeout since it might * have changed. */ - if (!teamd_read_config (device)) { + if (!teamd_read_config (self)) { _LOGW (LOGD_TEAM, "failed to read teamd configuration"); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } @@ -388,7 +378,7 @@ teamd_dbus_appeared (GDBusConnection *connection, if (ret) { g_variant_get (ret, "(u)", &pid); if (pid != priv->teamd_pid) - teamd_cleanup (device, FALSE); + teamd_cleanup (self, FALSE); } else { _LOGW (LOGD_TEAM, "failed to determine D-Bus name owner"); /* If we can't determine the bus name owner, don't kill our @@ -403,16 +393,21 @@ teamd_dbus_appeared (GDBusConnection *connection, * device activation. */ success = ensure_teamd_connection (device); - if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) { - if (success) - success = teamd_read_config (device); - if (success) - nm_device_activate_schedule_stage2_device_config (device); - else if (!nm_device_sys_iface_state_is_external_or_assume (device)) { - teamd_cleanup (device, TRUE); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); - } + + if ( nm_device_get_state (device) != NM_DEVICE_STATE_PREPARE + || priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING) + return; + + if (success) + success = teamd_read_config (self); + + if (!success) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + return; } + + priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED; + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -437,15 +432,16 @@ teamd_dbus_vanished (GDBusConnection *dbus_connection, } _LOGI (LOGD_TEAM, "teamd vanished from D-Bus"); - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); /* Attempt to respawn teamd */ - if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_ACTIVATED) { - NMConnection *connection = nm_device_get_applied_connection (device); - - g_assert (connection); - if (!teamd_start (device, connection)) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + if ( state >= NM_DEVICE_STATE_PREPARE + && state <= NM_DEVICE_STATE_ACTIVATED) { + if (!teamd_start (self)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + } } } @@ -470,7 +466,7 @@ teamd_process_watch_cb (GPid pid, int status, gpointer user_data) (state >= NM_DEVICE_STATE_PREPARE) && (state <= NM_DEVICE_STATE_ACTIVATED)) { _LOGW (LOGD_TEAM, "teamd process %lld quit unexpectedly; failing activation", (long long) pid); - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } @@ -525,11 +521,11 @@ teamd_kill (NMDeviceTeam *self, const char *teamd_binary, GError **error) } static gboolean -teamd_start (NMDevice *device, NMConnection *connection) +teamd_start (NMDeviceTeam *self) { - NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); - const char *iface = nm_device_get_ip_iface (device); + const char *iface = nm_device_get_ip_iface (NM_DEVICE (self)); + NMConnection *connection; gs_unref_ptrarray GPtrArray *argv = NULL; gs_free_error GError *error = NULL; gs_free char *tmp_str = NULL; @@ -540,8 +536,13 @@ teamd_start (NMDevice *device, NMConnection *connection) gs_free char *cloned_mac = NULL; gs_free const char **envp = NULL; + connection = nm_device_get_applied_connection (NM_DEVICE (self)); + s_team = nm_connection_get_setting_team (connection); - g_return_val_if_fail (s_team, FALSE); + if (!s_team) + g_return_val_if_reached (FALSE); + + nm_assert (iface); teamd_binary = nm_utils_find_helper ("teamd", NULL, NULL); if (!teamd_binary) { @@ -553,7 +554,7 @@ teamd_start (NMDevice *device, NMConnection *connection) g_warn_if_reached (); if (!priv->teamd_pid) teamd_kill (self, teamd_binary, NULL); - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); } /* Start teamd now */ @@ -568,7 +569,7 @@ teamd_start (NMDevice *device, NMConnection *connection) g_ptr_array_add (argv, (gpointer) iface); config = nm_setting_team_get_config (s_team); - if (!nm_device_hw_addr_get_cloned (device, connection, FALSE, &cloned_mac, NULL, &error)) { + if (!nm_device_hw_addr_get_cloned (NM_DEVICE (self), connection, FALSE, &cloned_mac, NULL, &error)) { _LOGW (LOGD_DEVICE, "set-hw-addr: %s", error->message); return FALSE; } @@ -615,18 +616,18 @@ teamd_start (NMDevice *device, NMConnection *connection) if (!g_spawn_async ("/", (char **) argv->pdata, (char **) envp, G_SPAWN_DO_NOT_REAP_CHILD, teamd_child_setup, NULL, &priv->teamd_pid, &error)) { _LOGW (LOGD_TEAM, "Activation: (team) failed to start teamd: %s", error->message); - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); return FALSE; } /* Start a timeout for teamd to appear at D-Bus */ if (!priv->teamd_timeout) - priv->teamd_timeout = g_timeout_add_seconds (5, teamd_timeout_cb, device); + priv->teamd_timeout = g_timeout_add_seconds (5, teamd_timeout_cb, self); /* Monitor the child process so we know when it dies */ priv->teamd_process_watch = g_child_watch_add (priv->teamd_pid, teamd_process_watch_cb, - device); + self); _LOGI (LOGD_TEAM, "Activation: (team) started teamd [pid %u]...", (guint) priv->teamd_pid); return TRUE; @@ -637,21 +638,21 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; gs_free_error GError *error = NULL; NMSettingTeam *s_team; - NMConnection *connection; const char *cfg; - ret = NM_DEVICE_CLASS (nm_device_team_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; + s_team = nm_device_get_applied_setting (device, NM_TYPE_SETTING_TEAM); + if (!s_team) + g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_device_get_applied_connection (device); - g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING) + return NM_ACT_STAGE_RETURN_POSTPONE; - s_team = nm_connection_get_setting_team (connection); - g_return_val_if_fail (s_team, NM_ACT_STAGE_RETURN_FAILURE); + if (priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED) + return NM_ACT_STAGE_RETURN_SUCCESS; + + priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING; if (priv->tdc) { /* If the existing teamd config is the same as we're about to use, @@ -660,7 +661,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) * have a PID, then we must fail. */ cfg = teamdctl_config_get_raw (priv->tdc); - if (cfg && nm_streq0 (cfg, nm_setting_team_get_config (s_team))) { + if ( cfg + && nm_streq0 (cfg, nm_setting_team_get_config (s_team))) { _LOGD (LOGD_TEAM, "using existing matching teamd config"); return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -675,17 +677,18 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) } _LOGD (LOGD_TEAM, "existing teamd config mismatch; respawning..."); - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); } if (priv->kill_in_progress) { _LOGT (LOGD_TEAM, "kill in progress, wait before starting teamd"); - priv->connection = g_object_ref (connection); return NM_ACT_STAGE_RETURN_POSTPONE; } - return teamd_start (device, connection) ? - NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE; + if (!teamd_start (self)) + return NM_ACT_STAGE_RETURN_FAILURE; + + return NM_ACT_STAGE_RETURN_POSTPONE; } static void @@ -694,16 +697,19 @@ deactivate (NMDevice *device) NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; + if (nm_device_sys_iface_state_is_external (device)) return; - if (priv->teamd_pid || priv->tdc) + if ( priv->teamd_pid + || priv->tdc) _LOGI (LOGD_TEAM, "deactivation: stopping teamd..."); if (!priv->teamd_pid) teamd_kill (self, NULL, NULL); - teamd_cleanup (device, TRUE); - g_clear_object (&priv->connection); + + teamd_cleanup (self, TRUE); } static gboolean @@ -773,27 +779,27 @@ release_slave (NMDevice *device, { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); - gboolean success; + gboolean do_release, success; + NMSettingTeamPort *s_port; int ifindex_slave; int ifindex; - ifindex = nm_device_get_ifindex (device); - if ( ifindex <= 0 - || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) - configure = FALSE; + do_release = configure; + if (do_release) { + ifindex = nm_device_get_ifindex (device); + if ( ifindex <= 0 + || !nm_platform_link_get (nm_device_get_platform (device), ifindex)) + do_release = FALSE; + } ifindex_slave = nm_device_get_ip_ifindex (slave); if (ifindex_slave <= 0) { _LOGD (LOGD_TEAM, "team port %s is already released", nm_device_get_ip_iface (slave)); - return; - } - - if (configure) { + } else if (do_release) { success = nm_platform_link_release (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), ifindex_slave); - if (success) _LOGI (LOGD_TEAM, "released team port %s", nm_device_get_ip_iface (slave)); else @@ -814,6 +820,13 @@ release_slave (NMDevice *device, self); } else _LOGI (LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface (slave)); + + /* Delete any port configuration we previously set */ + if ( configure + && priv->tdc + && (s_port = nm_device_get_applied_setting (slave, NM_TYPE_SETTING_TEAM_PORT)) + && (nm_setting_team_port_get_config (s_port))) + teamdctl_port_config_update_raw (priv->tdc, nm_device_get_ip_iface (slave), "{}"); } static gboolean @@ -869,7 +882,7 @@ static void constructed (GObject *object) { NMDevice *device = NM_DEVICE (object); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE ((NMDeviceTeam *) device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device); char *tmp_str = NULL; G_OBJECT_CLASS (nm_device_team_parent_class)->constructed (object); @@ -901,15 +914,15 @@ nm_device_team_new (const char *iface) static void dispose (GObject *object) { - NMDevice *device = NM_DEVICE (object); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE ((NMDeviceTeam *) device); + NMDeviceTeam *self = NM_DEVICE_TEAM (object); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); if (priv->teamd_dbus_watch) { g_bus_unwatch_name (priv->teamd_dbus_watch); priv->teamd_dbus_watch = 0; } - teamd_cleanup (device, TRUE); + teamd_cleanup (self, TRUE); g_clear_pointer (&priv->config, g_free); G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); diff --git a/src/devices/team/nm-device-team.h b/src/devices/team/nm-device-team.h index 0c0b5101..71312c07 100644 --- a/src/devices/team/nm-device-team.h +++ b/src/devices/team/nm-device-team.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __NETWORKMANAGER_DEVICE_TEAM_H__ diff --git a/src/devices/team/nm-team-factory.c b/src/devices/team/nm-team-factory.c index 21a85701..3768217b 100644 --- a/src/devices/team/nm-team-factory.c +++ b/src/devices/team/nm-team-factory.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -58,7 +44,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES ( G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create (GError **error) { - nm_manager_set_capability (nm_manager_get (), NM_CAPABILITY_TEAM); + nm_manager_set_capability (NM_MANAGER_GET, NM_CAPABILITY_TEAM); return (NMDeviceFactory *) g_object_new (NM_TYPE_TEAM_FACTORY, NULL); } diff --git a/src/devices/tests/meson.build b/src/devices/tests/meson.build index 4b4c5c7e..bb53d1ee 100644 --- a/src/devices/tests/meson.build +++ b/src/devices/tests/meson.build @@ -7,8 +7,10 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) + test( 'devices/' + test_unit, test_script, diff --git a/src/devices/tests/test-acd.c b/src/devices/tests/test-acd.c index 42accfaf..da5e4f2d 100644 --- a/src/devices/tests/test-acd.c +++ b/src/devices/tests/test-acd.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index ad157b7e..bd71c9e3 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/devices/wifi/meson.build b/src/devices/wifi/meson.build index 4dfbe4c8..6566f201 100644 --- a/src/devices/wifi/meson.build +++ b/src/devices/wifi/meson.build @@ -19,14 +19,11 @@ if enable_iwd ) endif -deps = [ - nm_dep, -] - libnm_device_plugin_wifi = shared_module( 'nm-device-plugin-wifi', sources: sources, - dependencies: deps, + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, install: true, @@ -41,13 +38,20 @@ test( args: [libnm_device_plugin_wifi.full_path(), linker_script_devices], ) -# FIXME: check_so_symbols replacement -''' -check-local-devices-wifi: src/devices/wifi/libnm-device-plugin-wifi.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so) -''' - if enable_tests - subdir('tests') + test_unit = 'test-devices-wifi' + + exe = executable( + test_unit, + ['tests/' + test_unit + '.c'] + common_sources, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, + ) + + test( + test_unit, + test_script, + args: test_args + [exe.full_path()], + timeout: default_test_timeout, + ) endif diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index 0e6759e1..6b587e3f 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Intel Corporation */ @@ -1714,18 +1700,14 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceIwd *self = NM_DEVICE_IWD (device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - NMActStageReturn ret; NMWifiAP *ap = NULL; + gs_unref_object NMWifiAP *ap_fake = NULL; NMActRequest *req; NMConnection *connection; NMSettingWireless *s_wireless; const char *mode; const char *ap_path; - ret = NM_DEVICE_CLASS (nm_device_iwd_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - req = nm_device_get_act_request (device); g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); @@ -1741,7 +1723,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) goto add_new; ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL; + ap = ap_path + ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) + : NULL; if (ap) { set_current_ap (self, ap, TRUE); return NM_ACT_STAGE_RETURN_SUCCESS; @@ -1767,19 +1751,19 @@ add_new: * until the real one is found in the scan list (Ad-Hoc or Hidden), or until * the device is deactivated (Ad-Hoc or Hotspot). */ - ap = nm_wifi_ap_new_fake_from_connection (connection); - g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE); + ap_fake = nm_wifi_ap_new_fake_from_connection (connection); + if (!ap_fake) + g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE); - if (nm_wifi_ap_is_hotspot (ap)) - nm_wifi_ap_set_address (ap, nm_device_get_hw_address (device)); + if (nm_wifi_ap_is_hotspot (ap_fake)) + nm_wifi_ap_set_address (ap_fake, nm_device_get_hw_address (device)); g_object_freeze_notify (G_OBJECT (self)); - ap_add_remove (self, TRUE, ap, FALSE); + ap_add_remove (self, TRUE, ap_fake, FALSE); g_object_thaw_notify (G_OBJECT (self)); - set_current_ap (self, ap, FALSE); + set_current_ap (self, ap_fake, FALSE); nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); - g_object_unref (ap); + nm_dbus_object_get_path (NM_DBUS_OBJECT (ap_fake))); return NM_ACT_STAGE_RETURN_SUCCESS; } diff --git a/src/devices/wifi/nm-device-iwd.h b/src/devices/wifi/nm-device-iwd.h index aab45b7b..586e02f4 100644 --- a/src/devices/wifi/nm-device-iwd.h +++ b/src/devices/wifi/nm-device-iwd.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Intel Corporation */ diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index aa50c420..c19ec766 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -1,26 +1,11 @@ -/* NetworkManager -- Network link manager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Dan Williams <dcbw@redhat.com> * Sjoerd Simons <sjoerd.simons@collabora.co.uk> * Daniel Drake <dsd@laptop.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2005 - 2014 Red Hat, Inc. - * (C) Copyright 2008 Collabora Ltd. - * (C) Copyright 2009 One Laptop per Child + * Copyright (C) 2005 - 2014 Red Hat, Inc. + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 One Laptop per Child */ #include "nm-default.h" @@ -58,7 +43,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceOlpcMesh, typedef struct { NMDevice *companion; NMManager *manager; - gboolean stage1_waiting; + bool stage1_waiting:1; } NMDeviceOlpcMeshPrivate; struct _NMDeviceOlpcMesh { @@ -145,13 +130,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - NMActStageReturn ret; gboolean scanning; - ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - /* disconnect companion device, if it is connected */ if (nm_device_get_act_request (NM_DEVICE (priv->companion))) { _LOGI (LOGD_OLPC, "disconnecting companion device %s", @@ -171,6 +151,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_POSTPONE; } + priv->stage1_waiting = FALSE; return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -273,10 +254,9 @@ companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_d return; g_object_get (companion, NM_DEVICE_WIFI_SCANNING, &scanning, NULL); - if (!scanning) { priv->stage1_waiting = FALSE; - nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); } } @@ -469,7 +449,7 @@ constructed (GObject *object) G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->constructed (object); - priv->manager = g_object_ref (nm_manager_get ()); + priv->manager = g_object_ref (NM_MANAGER_GET); g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED, G_CALLBACK (device_added_cb), self); g_signal_connect (priv->manager, NM_MANAGER_DEVICE_REMOVED, G_CALLBACK (device_removed_cb), self); diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h index 619fc46a..e6e76d6f 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.h +++ b/src/devices/wifi/nm-device-olpc-mesh.h @@ -1,26 +1,11 @@ -/* NetworkManager -- Network link manager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Dan Williams <dcbw@redhat.com> * Sjoerd Simons <sjoerd.simons@collabora.co.uk> * Daniel Drake <dsd@laptop.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2005 Red Hat, Inc. - * (C) Copyright 2008 Collabora Ltd. - * (C) Copyright 2009 One Laptop per Child + * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 One Laptop per Child */ #ifndef __NETWORKMANAGER_DEVICE_OLPC_MESH_H__ diff --git a/src/devices/wifi/nm-device-wifi-p2p.c b/src/devices/wifi/nm-device-wifi-p2p.c index 649f36d0..34ff70fa 100644 --- a/src/devices/wifi/nm-device-wifi-p2p.c +++ b/src/devices/wifi/nm-device-wifi-p2p.c @@ -1,21 +1,6 @@ -/* NetworkManager -- Wi-Fi P2P Device - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -63,6 +48,7 @@ typedef struct { CList peers_lst_head; + guint find_peer_timeout_id; guint sup_timeout_id; guint peer_dump_id; guint peer_missing_id; @@ -349,7 +335,7 @@ supplicant_find_timeout_cb (gpointer user_data) NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (user_data); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self); - priv->sup_timeout_id = 0; + priv->find_peer_timeout_id = 0; nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); @@ -368,27 +354,16 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self); - NMActStageReturn ret; - NMActRequest *req; NMConnection *connection; NMSettingWifiP2P *s_wifi_p2p; NMWifiP2PPeer *peer; - nm_clear_g_source (&priv->sup_timeout_id); - - ret = NM_DEVICE_CLASS (nm_device_wifi_p2p_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - if (!priv->mgmt_iface) { NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } - req = nm_device_get_act_request (NM_DEVICE (self)); - g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection (req); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); s_wifi_p2p = NM_SETTING_WIFI_P2P (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIFI_P2P)); @@ -397,33 +372,19 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); if (!peer) { /* Set up a timeout on the find attempt and run a find for the same period of time */ - priv->sup_timeout_id = g_timeout_add_seconds (10, - supplicant_find_timeout_cb, - self); - - nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10); + if (priv->find_peer_timeout_id == 0) { + priv->find_peer_timeout_id = g_timeout_add_seconds (10, + supplicant_find_timeout_cb, + self); + nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10); + } return NM_ACT_STAGE_RETURN_POSTPONE; } return NM_ACT_STAGE_RETURN_SUCCESS; } -static void -cleanup_p2p_connect_attempt (NMDeviceWifiP2P *self, gboolean disconnect) -{ - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self); - - nm_clear_g_source (&priv->sup_timeout_id); - nm_clear_g_source (&priv->peer_missing_id); - - if (priv->mgmt_iface) - nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); - - if (disconnect && priv->group_iface) - nm_supplicant_interface_p2p_disconnect (priv->group_iface); -} - /* * supplicant_connection_timeout_cb * @@ -461,7 +422,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) NMWifiP2PPeer *peer; GBytes *wfd_ies; - nm_clear_g_source (&priv->sup_timeout_id); + if (nm_clear_g_source (&priv->find_peer_timeout_id)) + nm_assert_not_reached (); if (!priv->mgmt_iface) { NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); @@ -493,9 +455,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) "pbc", NULL); /* Set up a timeout on the connect attempt */ - priv->sup_timeout_id = g_timeout_add_seconds (45, - supplicant_connection_timeout_cb, - self); + if (priv->sup_timeout_id == 0) { + priv->sup_timeout_id = g_timeout_add_seconds (45, + supplicant_connection_timeout_cb, + self); + } /* We'll get stage3 started when the P2P group has been started */ return NM_ACT_STAGE_RETURN_POSTPONE; @@ -550,17 +514,19 @@ peer_add_remove (NMDeviceWifiP2P *self, if (is_adding) { /* If we are in prepare state, then we are currently runnign a find * to search for the requested peer. */ - if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) { + if (priv->find_peer_timeout_id != 0) { NMConnection *connection; + nm_assert (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE); + connection = nm_device_get_applied_connection (device); - g_assert (connection); + nm_assert (NM_IS_CONNECTION (connection)); peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); if (peer) { /* A peer for the connection was found, cancel the timeout and go to configure state. */ - nm_clear_g_source (&priv->sup_timeout_id); - nm_device_activate_schedule_stage2_device_config (device); + nm_clear_g_source (&priv->find_peer_timeout_id); + nm_device_activate_schedule_stage1_device_prepare (device); } } @@ -620,8 +586,17 @@ deactivate (NMDevice *device) { NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (device); int ifindex = nm_device_get_ip_ifindex (device); + NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self); + + nm_clear_g_source (&priv->find_peer_timeout_id); + nm_clear_g_source (&priv->sup_timeout_id); + nm_clear_g_source (&priv->peer_missing_id); - cleanup_p2p_connect_attempt (self, TRUE); + if (priv->mgmt_iface) + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (priv->group_iface) + nm_supplicant_interface_p2p_disconnect (priv->group_iface); /* Clear any critical protocol notification in the Wi-Fi stack */ if (ifindex > 0) @@ -922,6 +897,7 @@ supplicant_interfaces_release (NMDeviceWifiP2P *self, gboolean set_is_waiting) nm_supplicant_manager_set_wfd_ies (priv->sup_mgr, NULL); g_signal_handlers_disconnect_by_data (priv->mgmt_iface, self); g_clear_object (&priv->mgmt_iface); + nm_clear_g_source (&priv->find_peer_timeout_id); nm_clear_g_source (&priv->sup_timeout_id); } diff --git a/src/devices/wifi/nm-device-wifi-p2p.h b/src/devices/wifi/nm-device-wifi-p2p.h index a13eef15..df25ec65 100644 --- a/src/devices/wifi/nm-device-wifi-p2p.h +++ b/src/devices/wifi/nm-device-wifi-p2p.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Wi-Fi P2P Device - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_DEVICE_WIFI_P2P_H__ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index f690100b..65ba2bcc 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -411,7 +397,9 @@ set_current_ap (NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available NM80211Mode mode = nm_wifi_ap_get_mode (old_ap); /* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */ - if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_wifi_ap_get_fake (old_ap)) + if ( NM_IN_SET (mode, NM_802_11_MODE_ADHOC, + NM_802_11_MODE_AP) + || nm_wifi_ap_get_fake (old_ap)) ap_add_remove (self, FALSE, old_ap, recheck_available_connections); g_object_unref (old_ap); } @@ -645,36 +633,6 @@ deactivate_reset_hw_addr (NMDevice *device) } static gboolean -is_adhoc_wpa (NMConnection *connection) -{ - NMSettingWireless *s_wifi; - NMSettingWirelessSecurity *s_wsec; - const char *mode, *key_mgmt; - - /* The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - - s_wifi = nm_connection_get_setting_wireless (connection); - g_return_val_if_fail (s_wifi != NULL, FALSE); - - mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) != 0) - return FALSE; - - s_wsec = nm_connection_get_setting_wireless_security (connection); - if (!s_wsec) - return FALSE; - - key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); - if (g_strcmp0 (key_mgmt, "wpa-none") != 0) - return FALSE; - - return TRUE; -} - -static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); @@ -720,12 +678,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection, GError return FALSE; } - if (is_adhoc_wpa (connection)) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "Ad-Hoc WPA networks are not supported"); - return FALSE; - } - /* Early exit if supplicant or device doesn't support requested mode */ mode = nm_setting_wireless_get_mode (s_wireless); if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) { @@ -953,19 +905,6 @@ complete_connection (NMDevice *device, return FALSE; } - /* The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - if (is_adhoc_wpa (connection)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("WPA Ad-Hoc disabled due to kernel bugs")); - g_prefix_error (error, "%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); - return FALSE; - } - ssid_utf8 = _nm_utils_ssid_to_utf8 (ssid); nm_utils_complete_generic (nm_device_get_platform (device), connection, @@ -1278,7 +1217,8 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic) /* Don't scan when a an AP or Ad-Hoc connection is active as it will * disrupt connected clients or peers. */ - if (priv->mode == NM_802_11_MODE_ADHOC || priv->mode == NM_802_11_MODE_AP) + if (NM_IN_SET (priv->mode, NM_802_11_MODE_ADHOC, + NM_802_11_MODE_AP)) return TRUE; switch (nm_device_get_state (NM_DEVICE (self))) { @@ -1781,8 +1721,10 @@ wifi_secrets_cb (NMActRequest *req, nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - } else - nm_device_activate_schedule_stage1_device_prepare (device); + return; + } + + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -1801,10 +1743,11 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface, NMDeviceWifi *self) { NMActRequest *req; - GVariant *val, *secrets = NULL; + gs_unref_variant GVariant *val_key = NULL; + gs_unref_variant GVariant *secrets = NULL; + gs_free_error GError *error = NULL; const char *array; gsize psk_len = 0; - GError *error = NULL; if (nm_device_get_state (NM_DEVICE (self)) != NM_DEVICE_STATE_NEED_AUTH) { _LOGI (LOGD_DEVICE | LOGD_WIFI, "WPS: The connection can't be updated with credentials"); @@ -1816,11 +1759,11 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface, req = nm_device_get_act_request (NM_DEVICE (self)); g_return_if_fail (NM_IS_ACT_REQUEST (req)); - val = g_variant_lookup_value (credentials, "Key", G_VARIANT_TYPE_BYTESTRING); - if (val) { + val_key = g_variant_lookup_value (credentials, "Key", G_VARIANT_TYPE_BYTESTRING); + if (val_key) { char psk[64]; - array = g_variant_get_fixed_array (val, &psk_len, 1); + array = g_variant_get_fixed_array (val_key, &psk_len, 1); if (psk_len >= 8 && psk_len <= 63) { memcpy (psk, array, psk_len); psk[psk_len] = '\0'; @@ -1833,22 +1776,22 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface, } if (!secrets) _LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: ignore invalid PSK"); - g_variant_unref (val); - } - if (secrets) { - if (nm_settings_connection_new_secrets (nm_act_request_get_settings_connection (req), - nm_act_request_get_applied_connection (req), - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - secrets, - &error)) { - wifi_secrets_cancel (self); - nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); - } else { - _LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: Could not update the connection with credentials: %s", error->message); - g_error_free (error); - } - g_variant_unref (secrets); } + + if (!secrets) + return; + + if (!nm_settings_connection_new_secrets (nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + secrets, + &error)) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: Could not update the connection with credentials: %s", error->message); + return; + } + + wifi_secrets_cancel (self); + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); } static gboolean @@ -2458,9 +2401,9 @@ supplicant_connection_timeout_cb (gpointer user_data) connection = nm_act_request_get_applied_connection (req); g_assert (connection); - if ( priv->mode == NM_802_11_MODE_ADHOC - || priv->mode == NM_802_11_MODE_MESH - || priv->mode == NM_802_11_MODE_AP) { + if (NM_IN_SET (priv->mode, NM_802_11_MODE_ADHOC, + NM_802_11_MODE_MESH, + NM_802_11_MODE_AP)) { /* In Ad-Hoc and AP modes there's nothing to check the encryption key * (if any), so supplicant timeouts here are almost certainly the wifi * driver being really stupid. @@ -2666,18 +2609,14 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMActStageReturn ret; NMWifiAP *ap = NULL; + gs_unref_object NMWifiAP *ap_fake = NULL; NMActRequest *req; NMConnection *connection; NMSettingWireless *s_wireless; const char *mode; const char *ap_path; - ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - req = nm_device_get_act_request (NM_DEVICE (self)); g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); @@ -2703,62 +2642,49 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) priv->mode = NM_802_11_MODE_MESH; _notify (self, PROP_MODE); - /* The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - if (is_adhoc_wpa (connection)) { - _LOGW (LOGD_WIFI, "Ad-Hoc WPA disabled due to kernel bugs"); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - /* expire the temporary MAC address used during scanning */ priv->hw_addr_scan_expire = 0; /* Set spoof MAC to the interface */ - if (!nm_device_hw_addr_set_cloned (device, connection, TRUE)) + if (!nm_device_hw_addr_set_cloned (device, connection, TRUE)) { + *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; + } /* AP and Mesh modes never use a specific object or existing scanned AP */ - if (priv->mode != NM_802_11_MODE_AP && priv->mode != NM_802_11_MODE_MESH) { + if (!NM_IN_SET (priv->mode, NM_802_11_MODE_AP, + NM_802_11_MODE_MESH)) { ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL; - if (ap) - goto done; - - ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); + ap = ap_path + ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) + : NULL; } + if (!ap) + ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); - if (ap) { - nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); - goto done; - } + if (!ap) { + /* If the user is trying to connect to an AP that NM doesn't yet know about + * (hidden network or something), starting a Hotspot or joining a Mesh, + * create a fake APfrom the security settings in the connection. This "fake" + * AP gets used until the real one is found in the scan list (Ad-Hoc or Hidden), + * or until the device is deactivated (Hotspot). + */ + ap_fake = nm_wifi_ap_new_fake_from_connection (connection); + if (!ap_fake) + g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE); - /* If the user is trying to connect to an AP that NM doesn't yet know about - * (hidden network or something), starting a Hotspot or joining a Mesh, - * create a fake APfrom the security settings in the connection. This "fake" - * AP gets used until the real one is found in the scan list (Ad-Hoc or Hidden), - * or until the device is deactivated (Hotspot). - */ - ap = nm_wifi_ap_new_fake_from_connection (connection); - g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE); + if (nm_wifi_ap_is_hotspot (ap_fake)) + nm_wifi_ap_set_address (ap_fake, nm_device_get_hw_address (device)); - if (nm_wifi_ap_is_hotspot (ap)) - nm_wifi_ap_set_address (ap, nm_device_get_hw_address (device)); + g_object_freeze_notify (G_OBJECT (self)); + ap_add_remove (self, TRUE, ap_fake, TRUE); + g_object_thaw_notify (G_OBJECT (self)); + ap = ap_fake; + } - g_object_freeze_notify (G_OBJECT (self)); - ap_add_remove (self, TRUE, ap, TRUE); - g_object_thaw_notify (G_OBJECT (self)); set_current_ap (self, ap, FALSE); nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); - g_object_unref (ap); - return NM_ACT_STAGE_RETURN_SUCCESS; - -done: - set_current_ap (self, ap, TRUE); return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -2893,8 +2819,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) * if the user didn't specify one and we didn't find an AP that matched * the connection, just pick a frequency the device supports. */ - if ( ap_mode == NM_802_11_MODE_ADHOC - || ap_mode == NM_802_11_MODE_MESH + if ( NM_IN_SET (ap_mode, NM_802_11_MODE_ADHOC, + NM_802_11_MODE_MESH) || nm_wifi_ap_is_hotspot (ap)) ensure_hotspot_frequency (self, s_wireless, ap); @@ -3242,6 +3168,15 @@ set_enabled (NMDevice *device, gboolean enabled) } static gboolean +get_guessed_metered (NMDevice *device) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + return priv->current_ap && nm_wifi_ap_get_metered (priv->current_ap); +} + +static gboolean can_reapply_change (NMDevice *device, const char *setting_name, NMSetting *s_old, @@ -3274,6 +3209,7 @@ static void reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceState state = nm_device_get_state (device); NM_DEVICE_CLASS (nm_device_wifi_parent_class)->reapply_connection (device, con_old, @@ -3281,7 +3217,8 @@ reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_n _LOGD (LOGD_DEVICE, "reapplying wireless settings"); - if (!wake_on_wlan_enable (self)) + if ( state >= NM_DEVICE_STATE_CONFIG + && !wake_on_wlan_enable (self)) _LOGW (LOGD_DEVICE | LOGD_WIFI, "Cannot configure WoWLAN."); } @@ -3451,6 +3388,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) device_class->check_connection_available = check_connection_available; device_class->complete_connection = complete_connection; device_class->get_enabled = get_enabled; + device_class->get_guessed_metered = get_guessed_metered; device_class->set_enabled = set_enabled; device_class->act_stage1_prepare = act_stage1_prepare; diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h index 82f62be6..aaf47143 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2016 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index c79f6cc6..470cb1c9 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Intel Corporation */ @@ -912,7 +898,7 @@ nm_iwd_manager_init (NMIwdManager *self) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - priv->manager = g_object_ref (nm_manager_get ()); + priv->manager = g_object_ref (NM_MANAGER_GET); g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED, G_CALLBACK (device_added), self); diff --git a/src/devices/wifi/nm-iwd-manager.h b/src/devices/wifi/nm-iwd-manager.h index b410e4ce..c50963fe 100644 --- a/src/devices/wifi/nm-iwd-manager.h +++ b/src/devices/wifi/nm-iwd-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Intel Corporation */ diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index c7ab7f04..ee7dc236 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -67,10 +53,12 @@ struct _NMWifiAPPrivate { NM80211ApSecurityFlags wpa_flags; /* WPA-related flags */ NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ + bool metered:1; + /* Non-scanned attributes */ - bool fake:1; /* Whether or not the AP is from a scan */ - bool hotspot:1; /* Whether the AP is a local device's hotspot network */ - gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ + bool fake:1; /* Whether or not the AP is from a scan */ + bool hotspot:1; /* Whether the AP is a local device's hotspot network */ + gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ }; typedef struct _NMWifiAPPrivate NMWifiAPPrivate; @@ -406,6 +394,12 @@ nm_wifi_ap_set_last_seen (NMWifiAP *ap, gint32 last_seen) return FALSE; } +gboolean +nm_wifi_ap_get_metered (const NMWifiAP *self) +{ + return NM_WIFI_AP_GET_PRIVATE (self)->metered; +} + /*****************************************************************************/ static NM80211ApSecurityFlags @@ -731,44 +725,50 @@ get_max_rate_vht (const guint8 *bytes, guint len, guint32 *out_maxrate) /* Management Frame Information Element IDs, ieee80211_eid */ #define WLAN_EID_HT_CAPABILITY 45 #define WLAN_EID_VHT_CAPABILITY 191 +#define WLAN_EID_VENDOR_SPECIFIC 221 -static guint32 -get_max_rate (const guint8 *bytes, gsize len) +static void +parse_ies (const guint8 *bytes, gsize len, guint32 *out_max_rate, gboolean *out_metered) { guint8 id, elem_len; - guint32 max_rate = 0; + guint32 m; - while (len) { - guint32 m; + *out_max_rate = 0; + *out_metered = FALSE; + while (len) { if (len < 2) - return 0; + break; id = *bytes++; elem_len = *bytes++; len -= 2; if (elem_len > len) - return 0; + break; switch (id) { case WLAN_EID_HT_CAPABILITY: - if (!get_max_rate_ht (bytes, elem_len, &m)) - return 0; - max_rate = NM_MAX (max_rate, m); + if (get_max_rate_ht (bytes, elem_len, &m)) + *out_max_rate = NM_MAX (*out_max_rate, m); break; case WLAN_EID_VHT_CAPABILITY: - if (!get_max_rate_vht (bytes, elem_len, &m)) - return 0; - max_rate = NM_MAX (max_rate, m); + if (get_max_rate_vht (bytes, elem_len, &m)) + *out_max_rate = NM_MAX (*out_max_rate, m); + break; + case WLAN_EID_VENDOR_SPECIFIC: + if ( len == 8 + && bytes[0] == 0x00 /* OUI: Microsoft */ + && bytes[1] == 0x50 + && bytes[2] == 0xf2 + && bytes[3] == 0x11) /* OUI type: Network cost */ + *out_metered = (bytes[7] > 1); /* Cost level > 1 */ break; } len -= elem_len; bytes += elem_len; } - - return max_rate; } /*****************************************************************************/ @@ -788,7 +788,8 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, gint16 i16; guint16 u16; gboolean changed = FALSE; - guint32 max_rate; + gboolean metered; + guint32 max_rate, rate; g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE); g_return_val_if_fail (properties, FALSE); @@ -869,9 +870,12 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING); if (v) { bytes = g_variant_get_fixed_array (v, &len, 1); - max_rate = NM_MAX (max_rate, get_max_rate (bytes, len)); + parse_ies (bytes, len, &rate, &metered); + max_rate = NM_MAX (max_rate, rate); g_variant_unref (v); + priv->metered = metered; } + if (max_rate) changed |= nm_wifi_ap_set_max_bitrate (ap, max_rate / 1000); @@ -1002,7 +1006,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self, export_path = "/"; g_snprintf (str_buf, buf_len, - "%17s %-35s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us sup:%s [nm:%s]", + "%17s %-35s [ %c %3u %3u%% %c%c W:%04X R:%04X ] %3us sup:%s [nm:%s]", priv->address ?: "(none)", (ssid_to_free = _nm_utils_ssid_to_string (priv->ssid)), (priv->mode == NM_802_11_MODE_ADHOC @@ -1017,6 +1021,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self, chan, priv->strength, priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : '_', + priv->metered ? 'M' : '_', priv->wpa_flags & 0xFFFF, priv->rsn_flags & 0xFFFF, priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1, @@ -1232,7 +1237,7 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection) const char *mode, *band, *key_mgmt; guint32 channel; NM80211ApSecurityFlags flags; - gboolean psk = FALSE, eap = FALSE; + gboolean psk = FALSE, eap = FALSE, adhoc = FALSE; g_return_val_if_fail (connection != NULL, NULL); @@ -1252,9 +1257,10 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection) if (mode) { if (!strcmp (mode, "infrastructure")) nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA); - else if (!strcmp (mode, "adhoc")) + else if (!strcmp (mode, "adhoc")) { nm_wifi_ap_set_mode (ap, NM_802_11_MODE_ADHOC); - else if (!strcmp (mode, "mesh")) + adhoc = TRUE; + } else if (!strcmp (mode, "mesh")) nm_wifi_ap_set_mode (ap, NM_802_11_MODE_MESH); else if (!strcmp (mode, "ap")) { nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA); @@ -1293,7 +1299,7 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection) psk = !strcmp (key_mgmt, "wpa-psk"); eap = !strcmp (key_mgmt, "wpa-eap"); - if (psk || eap) { + if (!adhoc && (psk || eap)) { if (has_proto (s_wireless_sec, PROTO_WPA)) { flags = priv->wpa_flags | (eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK); nm_wifi_ap_set_wpa_flags (ap, flags); @@ -1305,42 +1311,27 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection) add_pair_ciphers (ap, s_wireless_sec); add_group_ciphers (ap, s_wireless_sec); - } else if (!strcmp (key_mgmt, "wpa-none")) { - guint32 i; - - /* Ad-Hoc has special requirements: proto=WPA, pairwise=(none), and - * group=TKIP/CCMP (but not both). + } else if (adhoc && psk) { + /* Ad-Hoc has special requirements: proto=RSN, pairwise=CCMP and + * group=CCMP. */ - flags = priv->wpa_flags | NM_802_11_AP_SEC_KEY_MGMT_PSK; - /* Clear ciphers; pairwise must be unset anyway, and group gets set below */ + /* Clear ciphers; only CCMP is supported */ flags &= ~( NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_PAIR_TKIP - | NM_802_11_AP_SEC_PAIR_CCMP | NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104 - | NM_802_11_AP_SEC_GROUP_TKIP - | NM_802_11_AP_SEC_GROUP_CCMP); + | NM_802_11_AP_SEC_GROUP_TKIP); - for (i = 0; i < nm_setting_wireless_security_get_num_groups (s_wireless_sec); i++) { - if (!strcmp (nm_setting_wireless_security_get_group (s_wireless_sec, i), "ccmp")) { - flags |= NM_802_11_AP_SEC_GROUP_CCMP; - break; - } - } - - /* Default to TKIP since not all WPA-capable cards can do CCMP */ - if (!(flags & NM_802_11_AP_SEC_GROUP_CCMP)) - flags |= NM_802_11_AP_SEC_GROUP_TKIP; + flags |= NM_802_11_AP_SEC_PAIR_CCMP; + flags |= NM_802_11_AP_SEC_GROUP_CCMP; + nm_wifi_ap_set_rsn_flags (ap, flags); - nm_wifi_ap_set_wpa_flags (ap, flags); - - /* Don't use Ad-Hoc RSN yet */ - nm_wifi_ap_set_rsn_flags (ap, NM_802_11_AP_SEC_NONE); + /* Don't use Ad-Hoc WPA (WPA-none) anymore */ + nm_wifi_ap_set_wpa_flags (ap, NM_802_11_AP_SEC_NONE); } - done: return ap; diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 755e722c..472dfdf9 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -95,6 +81,7 @@ gboolean nm_wifi_ap_get_fake (const NMWifiAP *ap); gboolean nm_wifi_ap_set_fake (NMWifiAP *ap, gboolean fake); NM80211ApFlags nm_wifi_ap_get_flags (const NMWifiAP *self); +gboolean nm_wifi_ap_get_metered (const NMWifiAP *self); const char *nm_wifi_ap_to_string (const NMWifiAP *self, char *str_buf, diff --git a/src/devices/wifi/nm-wifi-common.c b/src/devices/wifi/nm-wifi-common.c index 96828d59..087465b5 100644 --- a/src/devices/wifi/nm-wifi-common.c +++ b/src/devices/wifi/nm-wifi-common.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/devices/wifi/nm-wifi-common.h b/src/devices/wifi/nm-wifi-common.h index 81d657ec..829df826 100644 --- a/src/devices/wifi/nm-wifi-common.h +++ b/src/devices/wifi/nm-wifi-common.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_WIFI_COMMON_H__ diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c index 2f069882..821460a5 100644 --- a/src/devices/wifi/nm-wifi-factory.c +++ b/src/devices/wifi/nm-wifi-factory.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 - 2014 Red Hat, Inc. */ diff --git a/src/devices/wifi/nm-wifi-p2p-peer.c b/src/devices/wifi/nm-wifi-p2p-peer.c index 4b524623..f8da0046 100644 --- a/src/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/devices/wifi/nm-wifi-p2p-peer.c @@ -1,20 +1,5 @@ -/* NetworkManager -- Wi-Fi P2P Peer - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/devices/wifi/nm-wifi-p2p-peer.h b/src/devices/wifi/nm-wifi-p2p-peer.h index d6ff7abc..07f25cc1 100644 --- a/src/devices/wifi/nm-wifi-p2p-peer.h +++ b/src/devices/wifi/nm-wifi-p2p-peer.h @@ -1,20 +1,5 @@ -/* NetworkManager -- Wi-Fi P2P Peer - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/devices/wifi/nm-wifi-utils.c b/src/devices/wifi/nm-wifi-utils.c index 426eeea8..b9b7ec42 100644 --- a/src/devices/wifi/nm-wifi-utils.c +++ b/src/devices/wifi/nm-wifi-utils.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2011 Red Hat, Inc. + * Copyright (C) 2011 Red Hat, Inc. */ #include "nm-default.h" @@ -297,96 +283,79 @@ verify_wpa_psk (NMSettingWirelessSecurity *s_wsec, guint32 rsn_flags, GError **error) { - const char *key_mgmt, *auth_alg, *tmp; - int n; + const char *key_mgmt, *auth_alg; key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); - if (key_mgmt) { - if (!strcmp (key_mgmt, "wpa-psk") || !strcmp (key_mgmt, "wpa-none")) { - if (s_8021x) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("WPA-PSK authentication is incompatible with 802.1x")); - g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME); - return FALSE; - } + if (!nm_streq0 (key_mgmt, "wpa-psk")) + return TRUE; - if (auth_alg && strcmp (auth_alg, "open")) { - /* WPA must use "open" authentication */ - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("WPA-PSK requires 'open' authentication")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); - return FALSE; - } - } + if (s_8021x) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("WPA-PSK authentication is incompatible with 802.1x")); + g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME); + return FALSE; + } - if (!strcmp (key_mgmt, "wpa-none")) { - if (!adhoc) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("WPA Ad-Hoc authentication requires an Ad-Hoc mode AP")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MODE); - return FALSE; - } + if (auth_alg && !nm_streq (auth_alg, "open")) { + /* WPA must use "open" authentication */ + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("WPA-PSK requires 'open' authentication")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } - /* Ad-Hoc WPA requires 'wpa' proto, 'none' pairwise, and 'tkip' group */ - n = nm_setting_wireless_security_get_num_protos (s_wsec); - tmp = (n > 0) ? nm_setting_wireless_security_get_proto (s_wsec, 0) : NULL; - if (n > 1 || !tmp || strcmp (tmp, "wpa")) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("WPA Ad-Hoc authentication requires 'wpa' protocol")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PROTO); - return FALSE; - } + /* Make sure the AP's capabilities support WPA-PSK */ + if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Access point does not support PSK but setting requires it")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } - n = nm_setting_wireless_security_get_num_pairwise (s_wsec); - tmp = (n > 0) ? nm_setting_wireless_security_get_pairwise (s_wsec, 0) : NULL; - if (n > 1 || g_strcmp0 (tmp, "none")) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("WPA Ad-Hoc authentication requires 'none' pairwise cipher")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_PAIRWISE); - return FALSE; - } + if (adhoc) { + /* Ad-Hoc RSN requires 'rsn' proto, 'ccmp' pairwise, and 'ccmp' group */ + if ( nm_setting_wireless_security_get_num_protos (s_wsec) != 1 + || !nm_streq0 (nm_setting_wireless_security_get_proto (s_wsec, 0), "rsn")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("WPA Ad-Hoc authentication requires 'rsn' protocol")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PROTO); + return FALSE; + } - n = nm_setting_wireless_security_get_num_groups (s_wsec); - tmp = (n > 0) ? nm_setting_wireless_security_get_group (s_wsec, 0) : NULL; - if (n > 1 || !tmp || strcmp (tmp, "tkip")) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("WPA Ad-Hoc requires 'tkip' group cipher")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_GROUP); - return FALSE; - } + if ( nm_setting_wireless_security_get_num_pairwise (s_wsec) != 1 + || !nm_streq0 (nm_setting_wireless_security_get_pairwise (s_wsec, 0), "ccmp")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("WPA Ad-Hoc authentication requires 'ccmp' pairwise cipher")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PAIRWISE); + return FALSE; } - if (!strcmp (key_mgmt, "wpa-psk")) { - /* Make sure the AP's capabilities support WPA-PSK */ - if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Access point does not support PSK but setting requires it")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); - return FALSE; - } + if ( nm_setting_wireless_security_get_num_groups (s_wsec) != 1 + || !nm_streq0 (nm_setting_wireless_security_get_group (s_wsec, 0), "ccmp")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("WPA Ad-Hoc requires 'ccmp' group cipher")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_GROUP); + return FALSE; } } @@ -463,61 +432,52 @@ verify_adhoc (NMSettingWirelessSecurity *s_wsec, { const char *key_mgmt = NULL, *leap_username = NULL, *auth_alg = NULL; + if (!adhoc) + return TRUE; + if (s_wsec) { key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); leap_username = nm_setting_wireless_security_get_leap_username (s_wsec); } - if (adhoc) { - if (key_mgmt && strcmp (key_mgmt, "wpa-none") && strcmp (key_mgmt, "none")) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Access point mode is Ad-Hoc but setting requires Infrastructure security")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); - return FALSE; - } + if (key_mgmt && !NM_IN_STRSET (key_mgmt, "none", "wpa-psk")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Ad-Hoc mode requires 'none' or 'wpa-psk' key management")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } - if (s_8021x) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("Ad-Hoc mode is incompatible with 802.1x security")); - g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME); - return FALSE; - } + if (s_8021x) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("Ad-Hoc mode is incompatible with 802.1x security")); + g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME); + return FALSE; + } - if (leap_username) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Ad-Hoc mode is incompatible with LEAP security")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); - return FALSE; - } + if (leap_username) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Ad-Hoc mode is incompatible with LEAP security")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } - if (auth_alg && strcmp (auth_alg, "open")) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Ad-Hoc mode requires 'open' authentication")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); - return FALSE; - } - } else { - if (key_mgmt && !strcmp (key_mgmt, "wpa-none")) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Access point mode is Infrastructure but setting requires Ad-Hoc security")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); - return FALSE; - } + if (auth_alg && !nm_streq (auth_alg, "open")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Ad-Hoc mode requires 'open' authentication")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; } return TRUE; @@ -773,11 +733,13 @@ nm_wifi_utils_complete_connection (GBytes *ap_ssid, return FALSE; if (adhoc) { - g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL); - /* Ad-Hoc does not support RSN/WPA2 */ - nm_setting_wireless_security_add_proto (s_wsec, "wpa"); - nm_setting_wireless_security_add_pairwise (s_wsec, "none"); - nm_setting_wireless_security_add_group (s_wsec, "tkip"); + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", + NULL); + nm_setting_wireless_security_add_proto (s_wsec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp"); + nm_setting_wireless_security_add_group (s_wsec, "ccmp"); } else if (s_8021x) { g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", diff --git a/src/devices/wifi/nm-wifi-utils.h b/src/devices/wifi/nm-wifi-utils.h index 251d122f..982080b9 100644 --- a/src/devices/wifi/nm-wifi-utils.h +++ b/src/devices/wifi/nm-wifi-utils.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2011 Red Hat, Inc. + * Copyright (C) 2011 Red Hat, Inc. */ #ifndef __NM_WIFI_UTILS_H__ diff --git a/src/devices/wifi/tests/meson.build b/src/devices/wifi/tests/meson.build deleted file mode 100644 index ba756d53..00000000 --- a/src/devices/wifi/tests/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -test_unit = 'test-devices-wifi' - -exe = executable( - test_unit, - [test_unit + '.c'] + common_sources, - dependencies: test_nm_dep, -) - -test( - test_unit, - test_script, - args: test_args + [exe.full_path()], - timeout: default_test_timeout, -) diff --git a/src/devices/wifi/tests/test-devices-wifi.c b/src/devices/wifi/tests/test-devices-wifi.c index a0b3e17f..a960e7a2 100644 --- a/src/devices/wifi/tests/test-devices-wifi.c +++ b/src/devices/wifi/tests/test-devices-wifi.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2011 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index 7ccebcb5..c368a590 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -3,6 +3,7 @@ global: nm_modem_act_stage1_prepare; nm_modem_act_stage2_config; nm_modem_check_connection_compatible; + nm_modem_claim; nm_modem_complete_connection; nm_modem_deactivate; nm_modem_deactivate_async; @@ -14,15 +15,17 @@ global: nm_modem_get_device_id; nm_modem_get_driver; nm_modem_get_iid; - nm_modem_get_path; nm_modem_get_ip_ifindex; nm_modem_get_operator_code; + nm_modem_get_path; nm_modem_get_secrets; nm_modem_get_state; nm_modem_get_type; nm_modem_get_uid; nm_modem_ip4_pre_commit; + nm_modem_is_claimed; nm_modem_manager_get; + nm_modem_manager_get_modems; nm_modem_manager_get_type; nm_modem_manager_name_owner_get; nm_modem_manager_name_owner_ref; @@ -32,6 +35,7 @@ global: nm_modem_stage3_ip4_config_start; nm_modem_stage3_ip6_config_start; nm_modem_state_to_string; + nm_modem_unclaim; local: *; }; diff --git a/src/devices/wwan/meson.build b/src/devices/wwan/meson.build index 482dc205..ed6f8010 100644 --- a/src/devices/wwan/meson.build +++ b/src/devices/wwan/meson.build @@ -1,13 +1,15 @@ -sources = files( +nm_service_providers_source = files('nm-service-providers.c') + +sources = nm_service_providers_source + files( 'nm-modem-broadband.c', 'nm-modem.c', 'nm-modem-manager.c', ) deps = [ + daemon_nm_default_dep, libsystemd_dep, mm_glib_dep, - nm_dep, ] if enable_ofono @@ -20,16 +22,17 @@ libnm_wwan = shared_module( 'nm-wwan', sources: sources, dependencies: deps, - link_args: [ - '-Wl,--version-script,@0@'.format(linker_script), - ], + c_args: daemon_c_flags, + link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, install: true, install_dir: nm_plugindir, ) +wwan_inc = include_directories('.') + libnm_wwan_dep = declare_dependency( - include_directories: include_directories('.'), + include_directories: wwan_inc, link_with: libnm_wwan, ) @@ -50,6 +53,7 @@ libnm_device_plugin_wwan = shared_module( 'nm-device-plugin-wwan', sources: sources, dependencies: deps, + c_args: daemon_c_flags, link_with: libnm_wwan, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, @@ -66,11 +70,21 @@ run_target( depends: libnm_device_plugin_wwan, ) -# FIXME: check_so_symbols replacement -''' -check-local-devices-wwan: src/devices/wwan/libnm-device-plugin-wwan.la src/devices/wwan/libnm-wwan.la - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so "$(srcdir)/linker-script-devices.ver" - $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-device-plugin-wwan.so) - $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-wwan.so "$(srcdir)/src/devices/wwan/libnm-wwan.ver" - $(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-wwan.so) -''' +if enable_tests + test_unit = 'test-service-providers' + + exe = executable( + test_unit, + ['tests/' + test_unit + '.c'] + nm_service_providers_source, + include_directories: wwan_inc, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, + ) + + test( + 'wwan/' + test_unit, + test_script, + timeout: default_test_timeout, + args: test_args + [exe.full_path()], + ) +endif diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 042a6ca4..3e6ccc8f 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2019 Red Hat, Inc. */ @@ -48,10 +34,11 @@ typedef struct { NMModem *modem; NMDeviceModemCapabilities caps; NMDeviceModemCapabilities current_caps; - gboolean rf_enabled; char *device_id; char *operator_code; char *apn; + bool rf_enabled:1; + NMDeviceStageState stage1_state:3; } NMDeviceModemPrivate; struct _NMDeviceModem { @@ -119,16 +106,17 @@ modem_prepare_result (NMModem *modem, gpointer user_data) { NMDeviceModem *self = NM_DEVICE_MODEM (user_data); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); - NMDeviceState state; NMDeviceStateReason reason = i_reason; - state = nm_device_get_state (device); - g_return_if_fail (state == NM_DEVICE_STATE_PREPARE); + if ( nm_device_get_state (device) != NM_DEVICE_STATE_PREPARE + || priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING) { + nm_assert_not_reached (); + success = FALSE; + } - if (success) - nm_device_activate_schedule_stage2_device_config (device); - else { + if (!success) { /* There are several reasons to block autoconnection at device level: * * - Wrong SIM-PIN: The device won't autoconnect because it doesn't make sense @@ -164,7 +152,11 @@ modem_prepare_result (NMModem *modem, break; } nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + return; } + + priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED; + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -187,16 +179,19 @@ static void modem_auth_result (NMModem *modem, GError *error, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); if (error) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); - } else { - /* Otherwise, on success for modem secrets we need to schedule stage1 again */ - g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - nm_device_activate_schedule_stage1_device_prepare (device); + return; } + + priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; + nm_device_activate_schedule_stage1_device_prepare (device); } static void @@ -355,7 +350,7 @@ modem_state_cb (NMModem *modem, NMModemState new_state = new_state_i; NMModemState old_state = old_state_i; NMDevice *device = NM_DEVICE (user_data); - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); NMDeviceState dev_state = nm_device_get_state (device); if (new_state <= NM_MODEM_STATE_DISABLING && @@ -409,7 +404,7 @@ modem_removed_cb (NMModem *modem, gpointer user_data) static gboolean owns_iface (NMDevice *device, const char *iface) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); g_return_val_if_fail (priv->modem, FALSE); @@ -447,7 +442,7 @@ get_generic_capabilities (NMDevice *device) static const char * get_type_description (NMDevice *device) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); if (NM_FLAGS_HAS (priv->current_caps, NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS)) return "gsm"; @@ -464,7 +459,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection, GError if (!NM_DEVICE_CLASS (nm_device_modem_parent_class)->check_connection_compatible (device, connection, error)) return FALSE; - if (!nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, + if (!nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, connection, error ? &local : NULL)) { if (error) { @@ -530,7 +525,7 @@ complete_connection (NMDevice *device, NMConnection *const*existing_connections, GError **error) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); return nm_modem_complete_connection (priv->modem, nm_device_get_iface (device), @@ -542,7 +537,10 @@ complete_connection (NMDevice *device, static void deactivate (NMDevice *device) { - nm_modem_deactivate (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + + nm_modem_deactivate (priv->modem, device); + priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; } /*****************************************************************************/ @@ -583,28 +581,32 @@ deactivate_async (NMDevice *self, static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMActStageReturn ret; + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); NMActRequest *req; - ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage1_prepare (device, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS) - return ret; - req = nm_device_get_act_request (device); g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); - return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, out_failure_reason); + if (priv->stage1_state == NM_DEVICE_STAGE_STATE_INIT) { + priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING; + return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, + req, + out_failure_reason); + } + + if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING) + return NM_ACT_STAGE_RETURN_POSTPONE; + + nm_assert (priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED); + return NM_ACT_STAGE_RETURN_SUCCESS; } static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMActRequest *req; - - req = nm_device_get_act_request (device); - g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); + nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem); - return nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, out_failure_reason); + return NM_ACT_STAGE_RETURN_SUCCESS; } static NMActStageReturn @@ -632,7 +634,7 @@ act_stage3_ip_config_start (NMDevice *device, static void ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) { - nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, device, config); + nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, config); } static gboolean @@ -654,7 +656,7 @@ get_ip_iface_identifier (NMDevice *device, NMUtilsIPv6IfaceId *out_iid) static gboolean get_enabled (NMDevice *device) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); NMModemState modem_state = nm_modem_get_state (priv->modem); return priv->rf_enabled && (modem_state >= NM_MODEM_STATE_LOCKED); @@ -710,7 +712,7 @@ set_modem (NMDeviceModem *self, NMModem *modem) g_return_if_fail (modem != NULL); - priv->modem = g_object_ref (modem); + priv->modem = nm_modem_claim (modem); g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); @@ -745,7 +747,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); switch (prop_id) { case PROP_MODEM: @@ -776,7 +778,7 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); switch (prop_id) { case PROP_MODEM: @@ -834,11 +836,11 @@ nm_device_modem_new (NMModem *modem) static void dispose (GObject *object) { - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); if (priv->modem) { g_signal_handlers_disconnect_by_data (priv->modem, NM_DEVICE_MODEM (object)); - g_clear_object (&priv->modem); + nm_clear_pointer (&priv->modem, nm_modem_unclaim); } g_clear_pointer (&priv->device_id, g_free); diff --git a/src/devices/wwan/nm-device-modem.h b/src/devices/wwan/nm-device-modem.h index 0a557f57..842096e2 100644 --- a/src/devices/wwan/nm-device-modem.h +++ b/src/devices/wwan/nm-device-modem.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Red Hat, Inc. */ diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 216fedfe..a1ae8671 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -1,25 +1,12 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> */ #include "nm-default.h" #include "nm-modem-broadband.h" +#include "nm-service-providers.h" #include <arpa/inet.h> #include <libmm-glib.h> @@ -274,7 +261,10 @@ create_cdma_connect_properties (NMConnection *connection) } static MMSimpleConnectProperties * -create_gsm_connect_properties (NMConnection *connection) +create_gsm_connect_properties (NMConnection *connection, + const char *apn, + const char *username, + const char *password) { NMSettingGsm *setting; NMSettingPpp *s_ppp; @@ -282,11 +272,14 @@ create_gsm_connect_properties (NMConnection *connection) const char *str; setting = nm_connection_get_setting_gsm (connection); + properties = mm_simple_connect_properties_new (); - /* Blank APN ("") means the default subscription APN */ - str = nm_setting_gsm_get_apn (setting); - mm_simple_connect_properties_set_apn (properties, str ?: ""); + mm_simple_connect_properties_set_apn (properties, apn ?: ""); + if (username) + mm_simple_connect_properties_set_user (properties, username); + if (password) + mm_simple_connect_properties_set_password (properties, password); str = nm_setting_gsm_get_network_id (setting); if (str) @@ -296,14 +289,6 @@ create_gsm_connect_properties (NMConnection *connection) if (str) mm_simple_connect_properties_set_pin (properties, str); - str = nm_setting_gsm_get_username (setting); - if (str) - mm_simple_connect_properties_set_user (properties, str); - - str = nm_setting_gsm_get_password (setting); - if (str) - mm_simple_connect_properties_set_password (properties, str); - /* Roaming */ if (nm_setting_gsm_get_home_only (setting)) mm_simple_connect_properties_set_allow_roaming (properties, FALSE); @@ -356,16 +341,26 @@ connect_ready (MMModemSimple *simple_iface, GAsyncResult *res, NMModemBroadband *self) { - ConnectContext *ctx = self->_priv.ctx; + ConnectContext *ctx; GError *error = NULL; NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; + MMBearer *bearer; - self->_priv.bearer = mm_modem_simple_connect_finish (simple_iface, res, &error); + bearer = mm_modem_simple_connect_finish (simple_iface, res, &error); + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + return; + } + + ctx = self->_priv.ctx; if (!ctx) return; + self->_priv.bearer = bearer; + if (!self->_priv.bearer) { if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED) && @@ -457,6 +452,95 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) } static void +find_gsm_apn_cb (const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, + const GSList *dns, + GError *error, + gpointer user_data) +{ + NMModemBroadband *self = user_data; + NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE (self); + ConnectContext *ctx = priv->ctx; + + if (error) { + _LOGW ("failed to connect '%s': APN not found: %s", + nm_connection_get_id (ctx->connection), error->message); + + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_GSM_APN_FAILED); + connect_context_clear (self); + return; + } + + /* Blank APN ("") means the default subscription APN */ + ctx->connect_properties = create_gsm_connect_properties (ctx->connection, + apn, + username, + password); + g_return_if_fail (ctx->connect_properties); + connect_context_step (self); +} + +static gboolean +try_create_connect_properties (NMModemBroadband *self) +{ + NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE (self); + ConnectContext *ctx = priv->ctx; + + if (MODEM_CAPS_3GPP (ctx->caps)) { + NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (ctx->connection); + + if (!s_gsm || nm_setting_gsm_get_auto_config (s_gsm)) { + gs_unref_object MMModem3gpp *modem_3gpp = NULL; + const char *network_id = NULL; + + s_gsm = nm_connection_get_setting_gsm (ctx->connection); + if (s_gsm) + network_id = nm_setting_gsm_get_network_id (s_gsm); + if (!network_id) { + if (mm_modem_get_state (self->_priv.modem_iface) < MM_MODEM_STATE_REGISTERED) + return FALSE; + modem_3gpp = mm_object_get_modem_3gpp (priv->modem_object); + network_id = mm_modem_3gpp_get_operator_code (modem_3gpp); + } + if (!network_id) { + _LOGW ("failed to connect '%s': unable to determine the network id", + nm_connection_get_id (ctx->connection)); + goto out; + } + + nm_service_providers_find_gsm_apn (MOBILE_BROADBAND_PROVIDER_INFO_DATABASE, + network_id, + ctx->cancellable, + find_gsm_apn_cb, + self); + } else { + ctx->connect_properties = create_gsm_connect_properties (ctx->connection, + nm_setting_gsm_get_apn (s_gsm), + nm_setting_gsm_get_username (s_gsm), + nm_setting_gsm_get_password (s_gsm)); + g_return_val_if_fail (ctx->connect_properties, TRUE); + } + + return TRUE; + } else if (MODEM_CAPS_3GPP2 (ctx->caps)) { + ctx->connect_properties = create_cdma_connect_properties (ctx->connection); + g_return_val_if_fail (ctx->connect_properties, FALSE); + return TRUE; + } else { + _LOGW ("failed to connect '%s': not a mobile broadband modem", + nm_connection_get_id (ctx->connection)); + } + +out: + nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); + connect_context_clear (self); + return TRUE; +} + +static void connect_context_step (NMModemBroadband *self) { ConnectContext *ctx = self->_priv.ctx; @@ -500,22 +584,11 @@ connect_context_step (NMModemBroadband *self) if (mm_modem_get_state (self->_priv.modem_iface) <= MM_MODEM_STATE_LOCKED) break; - /* Create core connect properties based on the modem capabilities */ - g_assert (!ctx->connect_properties); - - if (MODEM_CAPS_3GPP (ctx->caps)) - ctx->connect_properties = create_gsm_connect_properties (ctx->connection); - else if (MODEM_CAPS_3GPP2 (ctx->caps)) - ctx->connect_properties = create_cdma_connect_properties (ctx->connection); - else { - _LOGW ("failed to connect '%s': not a mobile broadband modem", - nm_connection_get_id (ctx->connection)); + if (!try_create_connect_properties (self)) + break; - nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); - connect_context_clear (self); + if (!self->_priv.ctx) break; - } - g_assert (ctx->connect_properties); /* Build up list of IP types that we need to use in the retries */ ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), ctx->connection, &error); @@ -534,6 +607,9 @@ connect_context_step (NMModemBroadband *self) } /* fall through */ case CONNECT_STEP_CONNECT: + if (!ctx->connect_properties) + break; + if (ctx->ip_types_i < ctx->ip_types->len) { NMModemIPType current; @@ -546,7 +622,7 @@ connect_context_step (NMModemBroadband *self) else if (current == NM_MODEM_IP_TYPE_IPV4V6) mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4V6); else - g_assert_not_reached (); + g_return_if_reached (); _nm_modem_set_apn (NM_MODEM (self), mm_simple_connect_properties_get_apn (ctx->connect_properties)); @@ -556,7 +632,7 @@ connect_context_step (NMModemBroadband *self) mm_modem_simple_connect (self->_priv.simple_iface, ctx->connect_properties, - NULL, + ctx->cancellable, (GAsyncReadyCallback) connect_ready, self); break; @@ -586,9 +662,9 @@ connect_context_step (NMModemBroadband *self) } static NMActStageReturn -act_stage1_prepare (NMModem *_self, - NMConnection *connection, - NMDeviceStateReason *out_failure_reason) +modem_act_stage1_prepare (NMModem *_self, + NMConnection *connection, + NMDeviceStateReason *out_failure_reason) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); @@ -689,6 +765,9 @@ complete_connection (NMModem *modem, if (!s_gsm) { s_gsm = (NMSettingGsm *) nm_setting_gsm_new (); nm_connection_add_setting (connection, NM_SETTING (s_gsm)); + g_object_set (G_OBJECT (s_gsm), + NM_SETTING_GSM_AUTO_CONFIG, TRUE, + NULL); } if (!nm_setting_gsm_get_device_id (s_gsm)) { @@ -876,8 +955,8 @@ static_stage3_ip4_done (NMModemBroadband *self) guint32 ip4_route_table, ip4_route_metric; NMPlatformIP4Route *r; - g_assert (self->_priv.ipv4_config); - g_assert (self->_priv.bearer); + g_return_val_if_fail (self->_priv.ipv4_config, FALSE); + g_return_val_if_fail (self->_priv.bearer, FALSE); self->_priv.idle_id_ip4 = 0; @@ -908,7 +987,7 @@ static_stage3_ip4_done (NMModemBroadband *self) } data_port = mm_bearer_get_interface (self->_priv.bearer); - g_assert (data_port); + g_return_val_if_fail (data_port, FALSE); config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port)); @@ -983,7 +1062,7 @@ stage3_ip6_done (NMModemBroadband *self) const char **dns; guint i; - g_assert (self->_priv.ipv6_config); + g_return_val_if_fail (self->_priv.ipv6_config, FALSE); self->_priv.idle_id_ip6 = 0; memset (&address, 0, sizeof (address)); @@ -1015,7 +1094,8 @@ stage3_ip6_done (NMModemBroadband *self) _LOGI ("IPv6 base configuration:"); data_port = mm_bearer_get_interface (self->_priv.bearer); - g_assert (data_port); + g_return_val_if_fail (data_port, FALSE); + config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port)); @@ -1383,8 +1463,9 @@ set_property (GObject *object, /* construct-only */ self->_priv.modem_object = g_value_dup_object (value); self->_priv.modem_iface = mm_object_get_modem (self->_priv.modem_object); + g_return_if_fail (self->_priv.modem_iface); self->_priv.modem_3gpp_iface = mm_object_get_modem_3gpp (self->_priv.modem_object); - g_assert (self->_priv.modem_iface != NULL); + g_signal_connect (self->_priv.modem_iface, "state-changed", G_CALLBACK (modem_state_changed), @@ -1512,7 +1593,7 @@ nm_modem_broadband_class_init (NMModemBroadbandClass *klass) modem_class->get_user_pass = get_user_pass; modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem; modem_class->complete_connection = complete_connection; - modem_class->act_stage1_prepare = act_stage1_prepare; + modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare; modem_class->owns_port = owns_port; obj_properties[PROP_MODEM] = diff --git a/src/devices/wwan/nm-modem-broadband.h b/src/devices/wwan/nm-modem-broadband.h index 9404f0b9..43041e2b 100644 --- a/src/devices/wwan/nm-modem-broadband.h +++ b/src/devices/wwan/nm-modem-broadband.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 - Aleksander Morgado <aleksander@gnu.org> */ diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index db2c0192..daccf68a 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. * Copyright (C) 2009 - 2013 Canonical Ltd. @@ -149,6 +135,20 @@ remove_one_modem (gpointer key, gpointer value, gpointer user_data) /*****************************************************************************/ +NMModem ** +nm_modem_manager_get_modems (NMModemManager *self, + guint *out_len) +{ + g_return_val_if_fail (NM_IS_MODEM_MANAGER (self), NULL); + + return (NMModem **) nm_utils_hash_values_to_array (NM_MODEM_MANAGER_GET_PRIVATE (self)->modems, + NULL, + NULL, + out_len); +} + +/*****************************************************************************/ + static void modm_clear_manager (NMModemManager *self) { diff --git a/src/devices/wwan/nm-modem-manager.h b/src/devices/wwan/nm-modem-manager.h index 1a26fd9f..97a2126a 100644 --- a/src/devices/wwan/nm-modem-manager.h +++ b/src/devices/wwan/nm-modem-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. * Copyright (C) 2009 Canonical Ltd. @@ -51,4 +37,7 @@ void nm_modem_manager_name_owner_unref (NMModemManager *self); const char *nm_modem_manager_name_owner_get (NMModemManager *self); +NMModem **nm_modem_manager_get_modems (NMModemManager *self, + guint *out_len); + #endif /* __NETWORKMANAGER_MODEM_MANAGER_H__ */ diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c index 31111b62..b68cd7e8 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/devices/wwan/nm-modem-ofono.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 - 2016 Canonical Ltd. */ @@ -1114,9 +1100,9 @@ create_connect_properties (NMConnection *connection) } static NMActStageReturn -act_stage1_prepare (NMModem *modem, - NMConnection *connection, - NMDeviceStateReason *out_failure_reason) +modem_act_stage1_prepare (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *out_failure_reason) { NMModemOfono *self = NM_MODEM_OFONO (modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE (self); @@ -1308,6 +1294,6 @@ nm_modem_ofono_class_init (NMModemOfonoClass *klass) modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem; - modem_class->act_stage1_prepare = act_stage1_prepare; + modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare; modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; } diff --git a/src/devices/wwan/nm-modem-ofono.h b/src/devices/wwan/nm-modem-ofono.h index 1dcd79b0..4ff2fbdd 100644 --- a/src/devices/wwan/nm-modem-ofono.h +++ b/src/devices/wwan/nm-modem-ofono.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 - Canonical Ltd. */ diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index fb2316d5..ad6449b1 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. */ @@ -110,6 +96,8 @@ typedef struct _NMModemPrivate { /* PPP stats */ guint32 in_bytes; guint32 out_bytes; + + bool claimed:1; } NMModemPrivate; G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) @@ -187,6 +175,53 @@ nm_modem_state_to_string (NMModemState state) return NULL; } +/*****************************************************************************/ + +gboolean +nm_modem_is_claimed (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), FALSE); + + return NM_MODEM_GET_PRIVATE (self)->claimed; +} + +NMModem * +nm_modem_claim (NMModem *self) +{ + NMModemPrivate *priv; + + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + priv = NM_MODEM_GET_PRIVATE (self); + + g_return_val_if_fail (!priv->claimed, NULL); + + priv->claimed = TRUE; + return g_object_ref (self); +} + +void +nm_modem_unclaim (NMModem *self) +{ + NMModemPrivate *priv; + + g_return_if_fail (NM_IS_MODEM (self)); + + priv = NM_MODEM_GET_PRIVATE (self); + + g_return_if_fail (priv->claimed); + + /* we don't actually unclaim the instance. This instance should not be re-used + * by another owner, that is because we only claim modems as we receive them. + * There is no mechanism that somebody else would later re-use them again. + * + * // priv->claimed = FALSE; */ + + g_object_unref (self); +} + +/*****************************************************************************/ + NMModemState nm_modem_get_state (NMModem *self) { @@ -976,9 +1011,9 @@ nm_modem_get_secrets (NMModem *self, /*****************************************************************************/ static NMActStageReturn -act_stage1_prepare (NMModem *modem, - NMConnection *connection, - NMDeviceStateReason *out_failure_reason) +modem_act_stage1_prepare (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *out_failure_reason) { NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_UNKNOWN); return NM_ACT_STAGE_RETURN_FAILURE; @@ -995,6 +1030,8 @@ nm_modem_act_stage1_prepare (NMModem *self, NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; NMConnection *connection; + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); + if (priv->act_request) g_object_unref (priv->act_request); priv->act_request = g_object_ref (req); @@ -1005,7 +1042,7 @@ nm_modem_act_stage1_prepare (NMModem *self, setting_name = nm_connection_need_secrets (connection, &hints); if (!setting_name) { nm_assert (!hints); - return NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self, connection, out_failure_reason); + return NM_MODEM_GET_CLASS (self)->modem_act_stage1_prepare (self, connection, out_failure_reason); } /* Secrets required... */ @@ -1029,19 +1066,18 @@ nm_modem_act_stage1_prepare (NMModem *self, /*****************************************************************************/ -NMActStageReturn -nm_modem_act_stage2_config (NMModem *self, - NMActRequest *req, - NMDeviceStateReason *out_failure_reason) +void +nm_modem_act_stage2_config (NMModem *self) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemPrivate *priv; + + g_return_if_fail (NM_IS_MODEM (self)); + priv = NM_MODEM_GET_PRIVATE (self); /* Clear secrets tries counter since secrets were successfully used * already if we get here. */ priv->secrets_tries = 0; - - return NM_ACT_STAGE_RETURN_SUCCESS; } /*****************************************************************************/ @@ -1800,7 +1836,7 @@ nm_modem_class_init (NMModemClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - klass->act_stage1_prepare = act_stage1_prepare; + klass->modem_act_stage1_prepare = modem_act_stage1_prepare; klass->stage3_ip6_config_request = stage3_ip6_config_request; klass->deactivate_cleanup = deactivate_cleanup; diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index fccb4fec..f2de990b 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2011 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. */ @@ -136,9 +122,9 @@ typedef struct { NMConnection *const*existing_connections, GError **error); - NMActStageReturn (*act_stage1_prepare) (NMModem *modem, - NMConnection *connection, - NMDeviceStateReason *out_failure_reason); + NMActStageReturn (*modem_act_stage1_prepare) (NMModem *modem, + NMConnection *connection, + NMDeviceStateReason *out_failure_reason); NMActStageReturn (*static_stage3_ip4_config_start) (NMModem *self, NMActRequest *req, @@ -167,6 +153,10 @@ typedef struct { GType nm_modem_get_type (void); +gboolean nm_modem_is_claimed (NMModem *modem); +NMModem *nm_modem_claim (NMModem *modem); +void nm_modem_unclaim (NMModem *modem); + const char *nm_modem_get_path (NMModem *modem); const char *nm_modem_get_uid (NMModem *modem); const char *nm_modem_get_control_port (NMModem *modem); @@ -222,9 +212,7 @@ NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem, NMActRequest *req, NMDeviceStateReason *out_failure_reason); -NMActStageReturn nm_modem_act_stage2_config (NMModem *modem, - NMActRequest *req, - NMDeviceStateReason *out_failure_reason); +void nm_modem_act_stage2_config (NMModem *modem); NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem, NMDevice *device, diff --git a/src/devices/wwan/nm-service-providers.c b/src/devices/wwan/nm-service-providers.c new file mode 100644 index 00000000..5140f7ed --- /dev/null +++ b/src/devices/wwan/nm-service-providers.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2009 Novell, Inc. + * Author: Tambet Ingo (tambet@gmail.com). + * Copyright (C) 2009 - 2019 Red Hat, Inc. + * Copyright (C) 2012 Lanedo GmbH + */ + +#include "nm-default.h" + +#include "nm-service-providers.h" + +typedef enum { + PARSER_TOPLEVEL = 0, + PARSER_COUNTRY, + PARSER_PROVIDER, + PARSER_METHOD_GSM, + PARSER_METHOD_GSM_APN, + PARSER_METHOD_CDMA, + PARSER_DONE, + PARSER_ERROR +} ParseContextState; + +typedef struct { + char *mccmnc; + NMServiceProvidersGsmApnCallback callback; + gpointer user_data; + GCancellable *cancellable; + GMarkupParseContext *ctx; + char buffer[4096]; + + char *text_buffer; + ParseContextState state; + + gboolean mccmnc_matched; + gboolean found_internet_apn; + char *apn; + char *username; + char *password; + char *gateway; + char *auth_method; + GSList *dns; +} ParseContext; + +/*****************************************************************************/ + +static void +parser_toplevel_start (ParseContext *parse_context, + const char *name, + const char **attribute_names, + const char **attribute_values) +{ + int i; + + if (strcmp (name, "serviceproviders") == 0) { + for (i = 0; attribute_names && attribute_names[i]; i++) { + if (strcmp (attribute_names[i], "format") == 0) { + if (strcmp (attribute_values[i], "2.0")) { + g_warning ("%s: mobile broadband provider database format '%s'" + " not supported.", __func__, attribute_values[i]); + parse_context->state = PARSER_ERROR; + break; + } + } + } + } else if (strcmp (name, "country") == 0) { + parse_context->state = PARSER_COUNTRY; + } +} + +static void +parser_country_start (ParseContext *parse_context, + const char *name, + const char **attribute_names, + const char **attribute_values) +{ + if (strcmp (name, "provider") == 0) + parse_context->state = PARSER_PROVIDER; +} + +static void +parser_provider_start (ParseContext *parse_context, + const char *name, + const char **attribute_names, + const char **attribute_values) +{ + parse_context->mccmnc_matched = FALSE; + if (strcmp (name, "gsm") == 0) + parse_context->state = PARSER_METHOD_GSM; + else if (strcmp (name, "cdma") == 0) + parse_context->state = PARSER_METHOD_CDMA; +} + +static void +parser_gsm_start (ParseContext *parse_context, + const char *name, + const char **attribute_names, + const char **attribute_values) +{ + int i; + + if (strcmp (name, "network-id") == 0) { + const char *mcc = NULL, *mnc = NULL; + + for (i = 0; attribute_names && attribute_names[i]; i++) { + if (strcmp (attribute_names[i], "mcc") == 0) + mcc = attribute_values[i]; + else if (strcmp (attribute_names[i], "mnc") == 0) + mnc = attribute_values[i]; + if (mcc && strlen (mcc) && mnc && strlen (mnc)) { + char *mccmnc = g_strdup_printf ("%s%s", mcc, mnc); + + if (strcmp (mccmnc, parse_context->mccmnc) == 0) + parse_context->mccmnc_matched = TRUE; + g_free (mccmnc); + break; + } + } + } else if (strcmp (name, "apn") == 0) { + parse_context->found_internet_apn = FALSE; + g_clear_pointer (&parse_context->apn, g_free); + g_clear_pointer (&parse_context->username, g_free); + g_clear_pointer (&parse_context->password, g_free); + g_clear_pointer (&parse_context->gateway, g_free); + g_clear_pointer (&parse_context->auth_method, g_free); + g_slist_free_full (parse_context->dns, g_free); + parse_context->dns = NULL; + + for (i = 0; attribute_names && attribute_names[i]; i++) { + if (strcmp (attribute_names[i], "value") == 0) { + parse_context->state = PARSER_METHOD_GSM_APN; + parse_context->apn = g_strstrip (g_strdup (attribute_values[i])); + break; + } + } + } +} + +static void +parser_gsm_apn_start (ParseContext *parse_context, + const char *name, + const char **attribute_names, + const char **attribute_values) +{ + int i; + + if (strcmp (name, "usage") == 0) { + for (i = 0; attribute_names && attribute_names[i]; i++) { + if ( (strcmp (attribute_names[i], "type") == 0) + && (strcmp (attribute_values[i], "internet") == 0)) { + parse_context->found_internet_apn = TRUE; + break; + } + } + } else if (strcmp (name, "authentication") == 0) { + for (i = 0; attribute_names && attribute_names[i]; i++) { + if (strcmp (attribute_names[i], "method") == 0) { + g_clear_pointer (&parse_context->auth_method, g_free); + parse_context->auth_method = g_strstrip (g_strdup (attribute_values[i])); + break; + } + } + } +} + +static void +parser_start_element (GMarkupParseContext *context, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + gpointer user_data, + GError **error) +{ + ParseContext *parse_context = user_data; + + g_clear_pointer (&parse_context->text_buffer, g_free); + + switch (parse_context->state) { + case PARSER_TOPLEVEL: + parser_toplevel_start (parse_context, element_name, attribute_names, attribute_values); + break; + case PARSER_COUNTRY: + parser_country_start (parse_context, element_name, attribute_names, attribute_values); + break; + case PARSER_PROVIDER: + parser_provider_start (parse_context, element_name, attribute_names, attribute_values); + break; + case PARSER_METHOD_GSM: + parser_gsm_start (parse_context, element_name, attribute_names, attribute_values); + break; + case PARSER_METHOD_GSM_APN: + parser_gsm_apn_start (parse_context, element_name, attribute_names, attribute_values); + break; + case PARSER_METHOD_CDMA: + break; + case PARSER_ERROR: + break; + case PARSER_DONE: + break; + } +} + +static void +parser_country_end (ParseContext *parse_context, + const char *name) +{ + if (strcmp (name, "country") == 0) { + g_clear_pointer (&parse_context->text_buffer, g_free); + parse_context->state = PARSER_TOPLEVEL; + } +} + +static void +parser_provider_end (ParseContext *parse_context, + const char *name) +{ + if (strcmp (name, "provider") == 0) { + g_clear_pointer (&parse_context->text_buffer, g_free); + parse_context->state = PARSER_COUNTRY; + } +} + +static void +parser_gsm_end (ParseContext *parse_context, + const char *name) +{ + if (strcmp (name, "gsm") == 0) { + g_clear_pointer (&parse_context->text_buffer, g_free); + parse_context->state = PARSER_PROVIDER; + } +} + +static void +parser_gsm_apn_end (ParseContext *parse_context, + const char *name) +{ + if (strcmp (name, "username") == 0) { + g_clear_pointer (&parse_context->username, g_free); + parse_context->username = g_steal_pointer (&parse_context->text_buffer); + } else if (strcmp (name, "password") == 0) { + g_clear_pointer (&parse_context->password, g_free); + parse_context->password = g_steal_pointer (&parse_context->text_buffer); + } else if (strcmp (name, "dns") == 0) { + parse_context->dns = g_slist_prepend (parse_context->dns, + g_steal_pointer (&parse_context->text_buffer)); + } else if (strcmp (name, "gateway") == 0) { + g_clear_pointer (&parse_context->gateway, g_free); + parse_context->gateway = g_steal_pointer (&parse_context->text_buffer); + } else if (strcmp (name, "apn") == 0) { + g_clear_pointer (&parse_context->text_buffer, g_free); + + if (parse_context->mccmnc_matched && parse_context->found_internet_apn) + parse_context->state = PARSER_DONE; + else + parse_context->state = PARSER_METHOD_GSM; + + } +} + +static void +parser_cdma_end (ParseContext *parse_context, + const char *name) +{ + if (strcmp (name, "cdma") == 0) { + g_clear_pointer (&parse_context->text_buffer, g_free); + parse_context->state = PARSER_PROVIDER; + } +} + +static void +parser_end_element (GMarkupParseContext *context, + const char *element_name, + gpointer user_data, + GError **error) +{ + ParseContext *parse_context = user_data; + + switch (parse_context->state) { + case PARSER_TOPLEVEL: + break; + case PARSER_COUNTRY: + parser_country_end (parse_context, element_name); + break; + case PARSER_PROVIDER: + parser_provider_end (parse_context, element_name); + break; + case PARSER_METHOD_GSM: + parser_gsm_end (parse_context, element_name); + break; + case PARSER_METHOD_GSM_APN: + parser_gsm_apn_end (parse_context, element_name); + break; + case PARSER_METHOD_CDMA: + parser_cdma_end (parse_context, element_name); + break; + case PARSER_ERROR: + break; + case PARSER_DONE: + break; + } +} + +static void +parser_text (GMarkupParseContext *context, + const char *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + ParseContext *parse_context = user_data; + + g_free (parse_context->text_buffer); + parse_context->text_buffer = g_strdup (text); +} + +static const GMarkupParser parser = { + .start_element = parser_start_element, + .end_element = parser_end_element, + .text = parser_text, + .passthrough = NULL, + .error = NULL, +}; + +/*****************************************************************************/ + +static void +finish_parse_context (ParseContext *parse_context, GError *error) +{ + if (parse_context->callback) { + if (error) { + parse_context->callback (NULL, NULL, NULL, NULL, NULL, + NULL, error, + parse_context->user_data); + } else { + parse_context->callback (parse_context->apn, + parse_context->username, + parse_context->password, + parse_context->gateway, + parse_context->auth_method, + parse_context->dns, + error, + parse_context->user_data); + } + } + + g_free (parse_context->mccmnc); + g_markup_parse_context_free (parse_context->ctx); + + g_free (parse_context->text_buffer); + g_free (parse_context->apn); + g_free (parse_context->username); + g_free (parse_context->password); + g_free (parse_context->gateway); + g_free (parse_context->auth_method); + g_slist_free_full (parse_context->dns, g_free); + + g_slice_free (ParseContext, parse_context); +} + +static void +read_next_chunk (GInputStream *stream, ParseContext *parse_context); + +static void +stream_read_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GInputStream *stream = G_INPUT_STREAM (source_object); + ParseContext *parse_context = user_data; + gssize len; + GError *error = NULL; + + len = g_input_stream_read_finish (stream, res, &error); + if (len == -1) { + g_prefix_error (&error, "Error reading service provider database: "); + finish_parse_context (parse_context, error); + g_clear_error (&error); + return; + } + + if (len == 0) { + g_set_error (&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "Operator ID '%s' not found in service provider database", + parse_context->mccmnc); + finish_parse_context (parse_context, error); + g_clear_error (&error); + return; + } + + if (!g_markup_parse_context_parse (parse_context->ctx, parse_context->buffer, len, &error)) { + g_prefix_error (&error, "Error parsing service provider database: "); + finish_parse_context (parse_context, error); + g_clear_error (&error); + return; + } + + if (parse_context->state == PARSER_DONE) { + finish_parse_context (parse_context, NULL); + return; + } + + read_next_chunk (stream, parse_context); +} + +static void +read_next_chunk (GInputStream *stream, ParseContext *parse_context) +{ + g_input_stream_read_async (stream, + parse_context->buffer, + sizeof (parse_context->buffer), + G_PRIORITY_DEFAULT, + parse_context->cancellable, + stream_read_cb, + parse_context); +} + +static void +file_read_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GFile *file = G_FILE (source_object); + ParseContext *parse_context = user_data; + GFileInputStream *stream; + gs_free_error GError *error = NULL; + + stream = g_file_read_finish (file, res, &error); + if (!stream) { + g_prefix_error (&error, "Error opening service provider database: "); + finish_parse_context (parse_context, error); + return; + } + + read_next_chunk (G_INPUT_STREAM (stream), parse_context); + + g_object_unref (stream); +} + +/*****************************************************************************/ + +void +nm_service_providers_find_gsm_apn (const char *service_providers, + const char *mccmnc, + GCancellable *cancellable, + NMServiceProvidersGsmApnCallback callback, + gpointer user_data) +{ + GFile *file; + ParseContext *parse_context; + + parse_context = g_slice_new0 (ParseContext); + parse_context->mccmnc = g_strdup (mccmnc); + parse_context->cancellable = cancellable; + parse_context->callback = callback; + parse_context->user_data = user_data; + parse_context->ctx = g_markup_parse_context_new (&parser, 0, parse_context, NULL); + + file = g_file_new_for_path (service_providers); + + g_file_read_async (file, G_PRIORITY_DEFAULT, cancellable, file_read_cb, parse_context); + + g_object_unref (file); +} diff --git a/src/devices/wwan/nm-service-providers.h b/src/devices/wwan/nm-service-providers.h new file mode 100644 index 00000000..35ad2fc1 --- /dev/null +++ b/src/devices/wwan/nm-service-providers.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_SERVICE_PROVIDERS_H__ +#define __NETWORKMANAGER_SERVICE_PROVIDERS_H__ + +typedef void (*NMServiceProvidersGsmApnCallback) (const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, + const GSList *dns, + GError *error, + gpointer user_data); + +void nm_service_providers_find_gsm_apn (const char *service_providers, + const char *mccmnc, + GCancellable *cancellable, + NMServiceProvidersGsmApnCallback callback, + gpointer user_data); + +#endif /* __NETWORKMANAGER_SERVICE_PROVIDERS_H__ */ diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index a0e5c160..9a85f936 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -77,11 +63,10 @@ modem_added_cb (NMModemManager *manager, gpointer user_data) { NMWwanFactory *self = NM_WWAN_FACTORY (user_data); - NMDevice *device; + gs_unref_object NMDevice *device = NULL; const char *driver; - /* Do nothing if the modem was consumed by some other plugin */ - if (nm_device_factory_emit_component_added (NM_DEVICE_FACTORY (self), G_OBJECT (modem))) + if (nm_modem_is_claimed (modem)) return; driver = nm_modem_get_driver (modem); @@ -90,17 +75,16 @@ modem_added_cb (NMModemManager *manager, * it. The rfcomm port (and thus the modem) gets created automatically * by the Bluetooth code during the connection process. */ - if (driver && strstr (driver, "bluetooth")) { - nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", - nm_modem_get_control_port (modem)); + if ( driver + && strstr (driver, "bluetooth")) { + nm_log_dbg (LOGD_MB, "WWAN factory ignores bluetooth modem '%s' which should be handled by bluetooth plugin", + nm_modem_get_control_port (modem)); return; } /* Make the new modem device */ device = nm_device_modem_new (modem); - g_assert (device); g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); - g_object_unref (device); } static NMDevice * diff --git a/src/devices/wwan/tests/test-service-providers.c b/src/devices/wwan/tests/test-service-providers.c new file mode 100644 index 00000000..33402cd5 --- /dev/null +++ b/src/devices/wwan/tests/test-service-providers.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat + */ + +#include "nm-default.h" + +#include "nm-service-providers.h" + +#include "nm-test-utils-core.h" + +static void +test_positive_cb (const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, + const GSList *dns, + GError *error, + gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_main_loop_quit (loop); + g_assert_no_error (error); + g_assert_cmpstr (apn, ==, "gprs.example.com"); + g_assert_cmpstr (username, ==, "praise"); + g_assert_cmpstr (password, ==, "santa"); + g_assert_cmpstr (gateway, ==, "192.0.2.3"); + g_assert_cmpstr (auth_method, ==, "pap"); + + g_assert_nonnull (dns); + g_assert_cmpstr (dns->data, ==, "192.0.2.2"); + dns = dns->next; + g_assert_nonnull (dns); + g_assert_cmpstr (dns->data, ==, "192.0.2.1"); + g_assert_null (dns->next); +} + +static void +test_positive (void) +{ + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + + nm_service_providers_find_gsm_apn (NM_BUILD_SRCDIR"/src/devices/wwan/tests/test-service-providers.xml", + "13337", NULL, test_positive_cb, loop); + g_main_loop_run (loop); + g_main_loop_unref (loop); +} + +/*****************************************************************************/ + +static void +test_negative_cb (const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, + const GSList *dns, + GError *error, + gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_main_loop_quit (loop); + g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN); +} + +static void +test_negative (void) +{ + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + + nm_service_providers_find_gsm_apn (NM_BUILD_SRCDIR"/src/devices/wwan/tests/test-service-providers.xml", + "78130", NULL, test_negative_cb, loop); + g_main_loop_run (loop); + g_main_loop_unref (loop); +} + +/*****************************************************************************/ + +static void +test_nonexistent_cb (const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, + const GSList *dns, + GError *error, + gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_main_loop_quit (loop); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_AGAIN); +} + +static void +test_nonexistent (void) +{ + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + + nm_service_providers_find_gsm_apn ("nonexistent.xml", "13337", NULL, + test_nonexistent_cb, loop); + g_main_loop_run (loop); + g_main_loop_unref (loop); +} + +/*****************************************************************************/ + +NMTST_DEFINE (); + +int +main (int argc, char **argv) +{ + nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT"); + + g_test_add_func ("/service-providers/positive", test_positive); + g_test_add_func ("/service-providers/negative", test_negative); + g_test_add_func ("/service-providers/nonexistent", test_nonexistent); + + return g_test_run (); +} + diff --git a/src/devices/wwan/tests/test-service-providers.xml b/src/devices/wwan/tests/test-service-providers.xml new file mode 100644 index 00000000..f0ca2deb --- /dev/null +++ b/src/devices/wwan/tests/test-service-providers.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding='utf-8'?> +<!DOCTYPE serviceproviders SYSTEM "serviceproviders.2.dtd"> + +<serviceproviders format="2.0"> + +<country code="feh"> + <provider> + <name>Sophia</name> + <gsm> + <network-id mcc="666" mnc="999"/> + <apn value="access.example.com"> + <plan type="postpaid"/> + <usage type="internet"/> + <name>APN</name> + <dns>192.0.2.1</dns> + <dns>192.0.2.2</dns> + </apn> + </gsm> + </provider> +</country> + +<country code="meh"> + <provider> + <name>Demiurge</name> + <gsm> + <network-id mcc="133" mnc="37"/> + <network-id mcc="133" mnc="666"/> + <apn value="mms"> + <usage type="mms"/> + <name>Unsolicited Nudes MMS</name> + <username>mms</username> + <password>mms</password> + <mmsc>http://mms.example.com/</mmsc> + <mmsproxy>192.0.2.1:8080</mmsproxy> + </apn> + <apn value="gprs.example.com"> + <plan type="postpaid"/> + <usage type="internet"/> + <name>GPRS</name> + <username>praise</username> + <password>santa</password> + <dns>192.0.2.1</dns> + <dns>192.0.2.2</dns> + <gateway>192.0.2.3</gateway> + <authentication method="pap"/> + </apn> + <apn value="second.example.com"> + <plan type="postpaid"/> + <usage type="internet"/> + <name>Second</name> + <username>worship</username> + <password>doom</password> + </apn> + </gsm> + </provider> + + <provider> + <name>Personal</name> + <gsm> + <network-id mcc="666" mnc="999"/> + <apn value="access.example.com"> + <plan type="postpaid"/> + <usage type="internet"/> + <name>APN</name> + <dns>192.0.2.1</dns> + <dns>192.0.2.2</dns> + </apn> + </gsm> + </provider> +</country> + +</serviceproviders> + diff --git a/src/dhcp/meson.build b/src/dhcp/meson.build index c1f28be0..609fe663 100644 --- a/src/dhcp/meson.build +++ b/src/dhcp/meson.build @@ -1,6 +1,6 @@ name = 'nm-dhcp-helper' -cflags = [ +c_flags = [ '-DG_LOG_DOMAIN="@0@"'.format(name), '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', ] @@ -8,8 +8,8 @@ cflags = [ executable( name, name + '.c', - dependencies: libnm_core_dep, - c_args: cflags, + dependencies: glib_nm_default_dep, + c_args: c_flags, link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, install: true, diff --git a/src/dhcp/nm-dhcp-client-logging.h b/src/dhcp/nm-dhcp-client-logging.h index d9b53f58..4e69c698 100644 --- a/src/dhcp/nm-dhcp-client-logging.h +++ b/src/dhcp/nm-dhcp-client-logging.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index 9f585c5d..0a07b26c 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -1,19 +1,6 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -59,7 +46,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpClient, PROP_ROUTE_TABLE, PROP_TIMEOUT, PROP_UUID, + PROP_IAID, + PROP_IAID_EXPLICIT, PROP_HOSTNAME, + PROP_HOSTNAME_FLAGS, ); typedef struct _NMDhcpClientPrivate { @@ -78,12 +68,15 @@ typedef struct _NMDhcpClientPrivate { guint32 route_table; guint32 route_metric; guint32 timeout; + guint32 iaid; NMDhcpState state; + NMDhcpHostnameFlags hostname_flags; bool info_only:1; bool use_fqdn:1; + bool iaid_explicit:1; } NMDhcpClientPrivate; -G_DEFINE_TYPE_EXTENDED (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {}) +G_DEFINE_ABSTRACT_TYPE (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) #define NM_DHCP_CLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMDhcpClient, NM_IS_DHCP_CLIENT) @@ -199,6 +192,22 @@ nm_dhcp_client_get_timeout (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->timeout; } +guint32 +nm_dhcp_client_get_iaid (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), 0); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->iaid; +} + +gboolean +nm_dhcp_client_get_iaid_explicit (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->iaid_explicit; +} + GBytes * nm_dhcp_client_get_client_id (NMDhcpClient *self) { @@ -279,6 +288,14 @@ nm_dhcp_client_get_hostname (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname; } +NMDhcpHostnameFlags +nm_dhcp_client_get_hostname_flags (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NM_DHCP_HOSTNAME_FLAG_NONE); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname_flags; +} + gboolean nm_dhcp_client_get_info_only (NMDhcpClient *self) { @@ -419,6 +436,17 @@ nm_dhcp_client_set_state (NMDhcpClient *self, if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND)) return; + if (_LOGI_ENABLED ()) { + gs_free const char **keys = NULL; + guint i, nkeys; + + keys = nm_utils_strdict_get_keys (options, TRUE, &nkeys); + for (i = 0; i < nkeys; i++) { + _LOGI ("option %-20s => '%s'", keys[i], + (char *) g_hash_table_lookup (options, keys[i])); + } + } + if ( priv->addr_family == AF_INET6 && new_state == NM_DHCP_STATE_BOUND) { char *start, *iaid; @@ -686,7 +714,7 @@ nm_dhcp_client_stop (NMDhcpClient *self, gboolean release) _LOGI ("canceled DHCP transaction, DHCP client pid %d", old_pid); else _LOGI ("canceled DHCP transaction"); - g_assert (priv->pid == -1); + nm_assert (priv->pid == -1); nm_dhcp_client_set_state (self, NM_DHCP_STATE_DONE, NULL, NULL); } @@ -807,6 +835,15 @@ maybe_add_option (NMDhcpClient *self, } } +void +nm_dhcp_client_emit_ipv6_prefix_delegated (NMDhcpClient *self, + const NMPlatformIP6Address *prefix) +{ + g_signal_emit (G_OBJECT (self), + signals[SIGNAL_PREFIX_DELEGATED], 0, + prefix); +} + gboolean nm_dhcp_client_handle_event (gpointer unused, const char *iface, @@ -853,15 +890,6 @@ nm_dhcp_client_handle_event (gpointer unused, g_variant_unref (value); } - if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP6)) { - GHashTableIter hash_iter; - gpointer key, val; - - g_hash_table_iter_init (&hash_iter, str_options); - while (g_hash_table_iter_next (&hash_iter, &key, &val)) - _LOGD ("option '%s'=>'%s'", (const char *) key, (const char *) val); - } - /* Create the IP config */ if (g_hash_table_size (str_options) > 0) { if (priv->addr_family == AF_INET) { @@ -887,9 +915,7 @@ nm_dhcp_client_handle_event (gpointer unused, /* If we got an IPv6 prefix to delegate, we don't change the state * of the DHCP client instance. Instead, we just signal the prefix * to the device. */ - g_signal_emit (G_OBJECT (self), - signals[SIGNAL_PREFIX_DELEGATED], 0, - &prefix); + nm_dhcp_client_emit_ipv6_prefix_delegated (self, &prefix); } else { /* Fail if no valid IP config was received */ if ( new_state == NM_DHCP_STATE_BOUND @@ -932,6 +958,12 @@ get_property (GObject *object, guint prop_id, case PROP_UUID: g_value_set_string (value, priv->uuid); break; + case PROP_IAID: + g_value_set_uint (value, priv->iaid); + break; + case PROP_IAID_EXPLICIT: + g_value_set_boolean (value, priv->iaid_explicit); + break; case PROP_HOSTNAME: g_value_set_string (value, priv->hostname); break; @@ -1001,10 +1033,22 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->uuid = g_value_dup_string (value); break; + case PROP_IAID: + /* construct-only */ + priv->iaid = g_value_get_uint (value); + break; + case PROP_IAID_EXPLICIT: + /* construct-only */ + priv->iaid_explicit = g_value_get_boolean (value); + break; case PROP_HOSTNAME: /* construct-only */ priv->hostname = g_value_dup_string (value); break; + case PROP_HOSTNAME_FLAGS: + /* construct-only */ + priv->hostname_flags = g_value_get_uint (value); + break; case PROP_ROUTE_TABLE: priv->route_table = g_value_get_uint (value); break; @@ -1120,12 +1164,30 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IAID] = + g_param_spec_uint (NM_DHCP_CLIENT_IAID, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IAID_EXPLICIT] = + g_param_spec_boolean (NM_DHCP_CLIENT_IAID_EXPLICIT, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_HOSTNAME] = g_param_spec_string (NM_DHCP_CLIENT_HOSTNAME, "", "", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_HOSTNAME_FLAGS] = + g_param_spec_uint (NM_DHCP_CLIENT_HOSTNAME_FLAGS, "", "", + 0, G_MAXUINT32, NM_DHCP_HOSTNAME_FLAG_NONE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint (NM_DHCP_CLIENT_ROUTE_TABLE, "", "", 0, G_MAXUINT32, RT_TABLE_MAIN, diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index 9eb76f33..6a431fa8 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -46,6 +34,9 @@ #define NM_DHCP_CLIENT_ROUTE_TABLE "route-table" #define NM_DHCP_CLIENT_TIMEOUT "timeout" #define NM_DHCP_CLIENT_UUID "uuid" +#define NM_DHCP_CLIENT_IAID "iaid" +#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit" +#define NM_DHCP_CLIENT_HOSTNAME_FLAGS "hostname-flags" #define NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED "state-changed" #define NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED "prefix-delegated" @@ -142,10 +133,16 @@ void nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric); guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self); +guint32 nm_dhcp_client_get_iaid (NMDhcpClient *self); + +gboolean nm_dhcp_client_get_iaid_explicit (NMDhcpClient *self); + GBytes *nm_dhcp_client_get_client_id (NMDhcpClient *self); const char *nm_dhcp_client_get_hostname (NMDhcpClient *self); +NMDhcpHostnameFlags nm_dhcp_client_get_hostname_flags (NMDhcpClient *self); + gboolean nm_dhcp_client_get_info_only (NMDhcpClient *self); gboolean nm_dhcp_client_get_use_fqdn (NMDhcpClient *self); @@ -202,20 +199,28 @@ void nm_dhcp_client_set_client_id_bin (NMDhcpClient *self, const guint8 *client_id, gsize len); +void nm_dhcp_client_emit_ipv6_prefix_delegated (NMDhcpClient *self, + const NMPlatformIP6Address *prefix); + /***************************************************************************** * Client data *****************************************************************************/ typedef struct { - GType (*get_type)(void); + GType (*get_type) (void); + GType (*get_type_per_addr_family) (int addr_family); const char *name; const char *(*get_path) (void); + bool experimental:1; } NMDhcpClientFactory; +GType nm_dhcp_nettools_get_type (void); + extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon; extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient; extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd; extern const NMDhcpClientFactory _nm_dhcp_client_factory_internal; +extern const NMDhcpClientFactory _nm_dhcp_client_factory_systemd; extern const NMDhcpClientFactory _nm_dhcp_client_factory_nettools; #endif /* __NETWORKMANAGER_DHCP_CLIENT_H__ */ diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index 98f8c13a..f31c493c 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -1,18 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2011 Red Hat, Inc. */ @@ -106,21 +93,11 @@ grab_request_options (GPtrArray *store, const char* line) } static void -add_hostname4 (GString *str, const char *hostname, gboolean use_fqdn) -{ - if (hostname) { - if (use_fqdn) { - g_string_append_printf (str, FQDN_FORMAT "\n", hostname); - g_string_append (str, - "send fqdn.encoded on;\n" - "send fqdn.server-update on;\n"); - } else - g_string_append_printf (str, HOSTNAME4_FORMAT "\n", hostname); - } -} - -static void -add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean use_fqdn) +add_ip4_config (GString *str, + GBytes *client_id, + const char *hostname, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags) { if (client_id) { const char *p; @@ -128,7 +105,7 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean guint i; p = g_bytes_get_data (client_id, &l); - g_assert (p); + nm_assert (p); /* Allow type 0 (non-hardware address) to be represented as a string * as long as all the characters are printable. @@ -156,7 +133,27 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean g_string_append (str, "; # added by NetworkManager\n"); } - add_hostname4 (str, hostname, use_fqdn); + if (hostname) { + if (use_fqdn) { + g_string_append_printf (str, FQDN_FORMAT "\n", hostname); + + g_string_append_printf (str, FQDN_TAG_PREFIX "encoded %s;\n", + (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) + ? "on" + : "off"); + + g_string_append_printf (str, FQDN_TAG_PREFIX "server-update %s;\n", + (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + ? "on" + : "off"); + + g_string_append_printf (str, FQDN_TAG_PREFIX "no-client-update %s;\n", + (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) + ? "on" + : "off"); + } else + g_string_append_printf (str, HOSTNAME4_FORMAT "\n", hostname); + } g_string_append_c (str, '\n'); @@ -172,12 +169,16 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean } static void -add_hostname6 (GString *str, const char *hostname) +add_hostname6 (GString *str, + const char *hostname, + NMDhcpHostnameFlags hostname_flags) { if (hostname) { g_string_append_printf (str, FQDN_FORMAT "\n", hostname); - g_string_append (str, - "send fqdn.server-update on;\n"); + if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + g_string_append (str, FQDN_TAG_PREFIX "server-update on;\n"); + if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) + g_string_append (str, FQDN_TAG_PREFIX "no-client-update on;\n"); g_string_append_c (str, '\n'); } } @@ -284,6 +285,7 @@ nm_dhcp_dhclient_create_config (const char *interface, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id) @@ -450,7 +452,7 @@ nm_dhcp_dhclient_create_config (const char *interface, } if (addr_family == AF_INET) { - add_ip4_config (new_contents, client_id, hostname, use_fqdn); + add_ip4_config (new_contents, client_id, hostname, use_fqdn, hostname_flags); add_request (reqs, "rfc3442-classless-static-routes"); add_request (reqs, "ms-classless-static-routes"); add_request (reqs, "static-routes"); @@ -458,7 +460,7 @@ nm_dhcp_dhclient_create_config (const char *interface, add_request (reqs, "ntp-servers"); add_request (reqs, "root-path"); } else { - add_hostname6 (new_contents, hostname); + add_hostname6 (new_contents, hostname, hostname_flags); add_request (reqs, "dhcp6.name-servers"); add_request (reqs, "dhcp6.domain-search"); diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/dhcp/nm-dhcp-dhclient-utils.h index 8ca893c3..0cf53887 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.h +++ b/src/dhcp/nm-dhcp-dhclient-utils.h @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. */ @@ -28,6 +16,7 @@ char *nm_dhcp_dhclient_create_config (const char *interface, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id); diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c index 54b50479..869966fb 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/dhcp/nm-dhcp-dhclient.c @@ -1,19 +1,5 @@ -/* nm-dhcp-dhclient.c - dhclient specific hooks for NetworkManager - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2012 Red Hat, Inc. */ @@ -38,7 +24,6 @@ #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-utils.h" -#include "nm-config.h" #include "nm-dhcp-dhclient-utils.h" #include "nm-dhcp-manager.h" #include "NetworkManagerUtils.h" @@ -118,35 +103,14 @@ get_dhclient_leasefile (int addr_family, const char *uuid, char **out_preferred_path) { - gs_free char *rundir_path = NULL; gs_free char *path = NULL; - /* First, see if the lease file is in /run */ - rundir_path = g_strdup_printf (NMRUNDIR "/dhclient%s-%s-%s.lease", - _addr_family_to_path_part (addr_family), - uuid, - iface); - - if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) { - NM_SET_OUT (out_preferred_path, g_strdup (rundir_path)); - return g_steal_pointer (&rundir_path); - } - - /* /var/lib/NetworkManager is the preferred leasefile path */ - path = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s-%s.lease", - _addr_family_to_path_part (addr_family), - uuid, - iface); - - if (g_file_test (path, G_FILE_TEST_EXISTS)) { + if (nm_dhcp_utils_get_leasefile_path (addr_family, "dhclient", iface, uuid, &path)) { NM_SET_OUT (out_preferred_path, g_strdup (path)); return g_steal_pointer (&path); } - if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) - NM_SET_OUT (out_preferred_path, g_steal_pointer (&rundir_path)); - else - NM_SET_OUT (out_preferred_path, g_steal_pointer (&path)); + NM_SET_OUT (out_preferred_path, g_steal_pointer (&path)); /* If the leasefile we're looking for doesn't exist yet in the new location * (eg, /var/lib/NetworkManager) then look in old locations to maintain @@ -182,6 +146,7 @@ merge_dhclient_config (NMDhcpDhclient *self, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *orig_path, GBytes **out_new_client_id, GError **error) @@ -210,10 +175,11 @@ merge_dhclient_config (NMDhcpDhclient *self, hostname, timeout, use_fqdn, + hostname_flags, orig_path, orig, out_new_client_id); - g_assert (new); + nm_assert (new); return g_file_set_contents (conf_file, new, @@ -301,6 +267,7 @@ create_dhclient_config (NMDhcpDhclient *self, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, GBytes **out_new_client_id) { gs_free char *orig = NULL; @@ -328,6 +295,7 @@ create_dhclient_config (NMDhcpDhclient *self, hostname, timeout, use_fqdn, + hostname_flags, orig, out_new_client_id, &error)) { @@ -527,6 +495,7 @@ ip4_start (NMDhcpClient *client, nm_dhcp_client_get_hostname (client), nm_dhcp_client_get_timeout (client), nm_dhcp_client_get_use_fqdn (client), + nm_dhcp_client_get_hostname_flags (client), &new_client_id); if (!priv->conf_file) { nm_utils_error_set_literal (error, @@ -558,6 +527,9 @@ ip6_start (NMDhcpClient *client, NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); + if (nm_dhcp_client_get_iaid_explicit (client)) + _LOGW ("dhclient does not support specifying an IAID for DHCPv6, it will be ignored"); + priv->conf_file = create_dhclient_config (self, AF_INET6, nm_dhcp_client_get_iface (client), @@ -567,6 +539,7 @@ ip6_start (NMDhcpClient *client, nm_dhcp_client_get_hostname (client), nm_dhcp_client_get_timeout (client), TRUE, + nm_dhcp_client_get_hostname_flags (client), NULL); if (!priv->conf_file) { nm_utils_error_set_literal (error, @@ -723,7 +696,7 @@ nm_dhcp_dhclient_class_init (NMDhcpDhclientClass *dhclient_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient = { - .name = "dhclient", + .name = "dhclient", .get_type = nm_dhcp_dhclient_get_type, .get_path = nm_dhcp_dhclient_get_path, }; diff --git a/src/dhcp/nm-dhcp-dhcpcanon.c b/src/dhcp/nm-dhcp-dhcpcanon.c index 2d2113cc..f9cc0f0a 100644 --- a/src/dhcp/nm-dhcp-dhcpcanon.c +++ b/src/dhcp/nm-dhcp-dhcpcanon.c @@ -1,19 +1,5 @@ -/* nm-dhcp-dhcpcanon.c - dhcpcanon specific hooks for NetworkManager - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 juga <juga at riseup dot net> */ @@ -248,7 +234,7 @@ nm_dhcp_dhcpcanon_class_init (NMDhcpDhcpcanonClass *dhcpcanon_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon = { - .name = "dhcpcanon", + .name = "dhcpcanon", .get_type = nm_dhcp_dhcpcanon_get_type, .get_path = nm_dhcp_dhcpcanon_get_path, }; diff --git a/src/dhcp/nm-dhcp-dhcpcd.c b/src/dhcp/nm-dhcp-dhcpcd.c index c300bbe2..1690bce5 100644 --- a/src/dhcp/nm-dhcp-dhcpcd.c +++ b/src/dhcp/nm-dhcp-dhcpcd.c @@ -1,22 +1,7 @@ -/* nm-dhcp-dhcpcd.c - dhcpcd specific hooks for NetworkManager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Roy Marples * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> - * - * 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. - * */ #include "nm-default.h" @@ -242,7 +227,7 @@ nm_dhcp_dhcpcd_class_init (NMDhcpDhcpcdClass *dhcpcd_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd = { - .name = "dhcpcd", + .name = "dhcpcd", .get_type = nm_dhcp_dhcpcd_get_type, .get_path = nm_dhcp_dhcpcd_get_path, }; diff --git a/src/dhcp/nm-dhcp-helper-api.h b/src/dhcp/nm-dhcp-helper-api.h index c1a3c71c..a03049aa 100644 --- a/src/dhcp/nm-dhcp-helper-api.h +++ b/src/dhcp/nm-dhcp-helper-api.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2016 Red Hat, Inc. */ #ifndef __NM_DHCP_HELPER_API_H__ diff --git a/src/dhcp/nm-dhcp-helper.c b/src/dhcp/nm-dhcp-helper.c index 9acc4045..17f9db7f 100644 --- a/src/dhcp/nm-dhcp-helper.c +++ b/src/dhcp/nm-dhcp-helper.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2013 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-listener.c b/src/dhcp/nm-dhcp-listener.c index 88aafeb0..a54b9643 100644 --- a/src/dhcp/nm-dhcp-listener.c +++ b/src/dhcp/nm-dhcp-listener.c @@ -1,19 +1,6 @@ -/* 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 2014 - 2016 Red Hat, Inc. - * +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 - 2016 Red Hat, Inc. */ #include "nm-default.h" @@ -38,7 +25,7 @@ /*****************************************************************************/ -const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5] = { +const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = { /* the order here matters, as we will try the plugins in this order to find * the first available plugin. */ @@ -52,6 +39,7 @@ const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5] = { &_nm_dhcp_client_factory_dhcpcd, #endif &_nm_dhcp_client_factory_internal, + &_nm_dhcp_client_factory_systemd, &_nm_dhcp_client_factory_nettools, }; diff --git a/src/dhcp/nm-dhcp-listener.h b/src/dhcp/nm-dhcp-listener.h index d9724062..c2b90dc3 100644 --- a/src/dhcp/nm-dhcp-listener.h +++ b/src/dhcp/nm-dhcp-listener.h @@ -1,18 +1,6 @@ -/* 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 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DHCP_LISTENER_H__ diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c index 304a7b99..10ed9589 100644 --- a/src/dhcp/nm-dhcp-manager.c +++ b/src/dhcp/nm-dhcp-manager.c @@ -1,22 +1,7 @@ -/* nm-dhcp-manager.c - Handle the DHCP daemon for NetworkManager - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. - * */ #include "nm-default.h" @@ -32,6 +17,7 @@ #include <stdio.h> #include "nm-glib-aux/nm-dedup-multi.h" +#include "systemd/nm-sd-utils-shared.h" #include "nm-config.h" #include "NetworkManagerUtils.h" @@ -89,10 +75,11 @@ _client_factory_available (const NMDhcpClientFactory *client_factory) return NULL; } -static const NMDhcpClientFactory * -_client_factory_get_effective (const NMDhcpClientFactory *client_factory, - int addr_family) +static GType +_client_factory_get_gtype (const NMDhcpClientFactory *client_factory, + int addr_family) { + GType gtype; nm_auto_unref_gtypeclass NMDhcpClientClass *klass = NULL; nm_assert (client_factory); @@ -118,23 +105,38 @@ _client_factory_get_effective (const NMDhcpClientFactory *client_factory, * to those plugins. But we don't intend to do so. The internal plugin is the way forward and * not extending other plugins. */ + if (client_factory->get_type_per_addr_family) + gtype = client_factory->get_type_per_addr_family (addr_family); + else + gtype = client_factory->get_type (); + if (client_factory == &_nm_dhcp_client_factory_internal) { - /* already using internal plugin. Nothing to do. */ - return client_factory; + /* we are already using the internal plugin. Nothing to do. */ + goto out; } - klass = g_type_class_ref (client_factory->get_type ()); + klass = g_type_class_ref (gtype); nm_assert (NM_IS_DHCP_CLIENT_CLASS (klass)); if (addr_family == AF_INET6) { - return klass->ip6_start - ? client_factory - : &_nm_dhcp_client_factory_internal; + if (!klass->ip6_start) + gtype = _client_factory_get_gtype (&_nm_dhcp_client_factory_internal, addr_family); + } else { + if (!klass->ip4_start) + gtype = _client_factory_get_gtype (&_nm_dhcp_client_factory_internal, addr_family); } - return klass->ip4_start - ? client_factory - : &_nm_dhcp_client_factory_internal; + +out: + nm_assert (g_type_is_a (gtype, NM_TYPE_DHCP_CLIENT)); + nm_assert (({ + nm_auto_unref_gtypeclass NMDhcpClientClass *k = g_type_class_ref (gtype); + + (addr_family == AF_INET6 && k->ip6_start) + || (addr_family == AF_INET && k->ip4_start); + })); + + return gtype; } /*****************************************************************************/ @@ -211,10 +213,13 @@ client_start (NMDhcpManager *self, const struct in6_addr *ipv6_ll_addr, GBytes *dhcp_client_id, gboolean enforce_duid, + guint32 iaid, + gboolean iaid_explicit, guint32 timeout, const char *dhcp_anycast_addr, const char *hostname, gboolean hostname_use_fqdn, + NMDhcpHostnameFlags hostname_flags, gboolean info_only, NMSettingIP6ConfigPrivacy privacy, const char *last_ip4_address, @@ -225,7 +230,7 @@ client_start (NMDhcpManager *self, NMDhcpClient *client; gboolean success = FALSE; gsize hwaddr_len; - const NMDhcpClientFactory *client_factory; + GType gtype; g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); g_return_val_if_fail (iface, NULL); @@ -251,12 +256,21 @@ client_start (NMDhcpManager *self, g_return_val_if_reached (NULL) ; } + if (hostname) { + if ( (hostname_use_fqdn && !nm_sd_dns_name_is_valid (hostname)) + || (!hostname_use_fqdn && !nm_sd_hostname_is_valid (hostname, FALSE))) { + nm_log_warn (LOGD_DHCP , "dhcp%c: %s '%s' is invalid, will be ignored", + nm_utils_addr_family_to_char (addr_family), + hostname_use_fqdn ? "FQDN" : "hostname", + hostname); + hostname = NULL; + } + } + nm_assert (g_bytes_get_size (hwaddr) == g_bytes_get_size (bcast_hwaddr)); priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - client_factory = _client_factory_get_effective (priv->client_factory, addr_family); - /* Kill any old client instance */ client = get_client_for_ifindex (self, addr_family, ifindex); if (client) { @@ -271,7 +285,14 @@ client_start (NMDhcpManager *self, g_object_unref (client); } - client = g_object_new (client_factory->get_type (), + gtype = _client_factory_get_gtype (priv->client_factory, addr_family); + + nm_log_trace (LOGD_DHCP , "dhcp%c: creating IPv%c DHCP client of type %s", + nm_utils_addr_family_to_char (addr_family), + nm_utils_addr_family_to_char (addr_family), + g_type_name (gtype)); + + client = g_object_new (gtype, NM_DHCP_CLIENT_MULTI_IDX, multi_idx, NM_DHCP_CLIENT_ADDR_FAMILY, addr_family, NM_DHCP_CLIENT_INTERFACE, iface, @@ -279,10 +300,13 @@ client_start (NMDhcpManager *self, NM_DHCP_CLIENT_HWADDR, hwaddr, NM_DHCP_CLIENT_BROADCAST_HWADDR, bcast_hwaddr, NM_DHCP_CLIENT_UUID, uuid, + NM_DHCP_CLIENT_IAID, (guint) iaid, + NM_DHCP_CLIENT_IAID_EXPLICIT, iaid_explicit, NM_DHCP_CLIENT_HOSTNAME, hostname, NM_DHCP_CLIENT_ROUTE_TABLE, (guint) route_table, NM_DHCP_CLIENT_ROUTE_METRIC, (guint) route_metric, NM_DHCP_CLIENT_TIMEOUT, (guint) timeout, + NM_DHCP_CLIENT_HOSTNAME_FLAGS, (guint) hostname_flags, NM_DHCP_CLIENT_FLAGS, (guint) (0 | (hostname_use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : 0) | (info_only ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY : 0) @@ -357,6 +381,7 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, gboolean send_hostname, const char *dhcp_hostname, const char *dhcp_fqdn, + NMDhcpHostnameFlags hostname_flags, GBytes *dhcp_client_id, guint32 timeout, const char *dhcp_anycast_addr, @@ -408,10 +433,13 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, NULL, dhcp_client_id, FALSE, + 0, + FALSE, timeout, dhcp_anycast_addr, hostname, use_fqdn, + hostname_flags, FALSE, 0, last_ip_address, @@ -433,8 +461,11 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, guint32 route_metric, gboolean send_hostname, const char *dhcp_hostname, + NMDhcpHostnameFlags hostname_flags, GBytes *duid, gboolean enforce_duid, + guint32 iaid, + gboolean iaid_explicit, guint32 timeout, const char *dhcp_anycast_addr, gboolean info_only, @@ -465,10 +496,13 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, ll_addr, duid, enforce_duid, + iaid, + iaid_explicit, timeout, dhcp_anycast_addr, hostname, TRUE, + hostname_flags, info_only, privacy, NULL, @@ -529,9 +563,10 @@ nm_dhcp_manager_init (NMDhcpManager *self) if (!f) continue; - nm_log_dbg (LOGD_DHCP, "dhcp-init: enabled DHCP client '%s' (%s)%s", - f->name, g_type_name (f->get_type ()), - _client_factory_available (f) ? "" : " (not available)"); + nm_log_dbg (LOGD_DHCP, "dhcp-init: enabled DHCP client '%s'%s%s", + f->name, + _client_factory_available (f) ? "" : " (not available)", + f->experimental ? " (undocumented internal plugin)" : ""); } /* Client-specific setup */ diff --git a/src/dhcp/nm-dhcp-manager.h b/src/dhcp/nm-dhcp-manager.h index ff0d6f54..fb1c9834 100644 --- a/src/dhcp/nm-dhcp-manager.h +++ b/src/dhcp/nm-dhcp-manager.h @@ -1,19 +1,5 @@ -/* nm-dhcp-manager.c - Handle the DHCP daemon for NetworkManager - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -56,6 +42,7 @@ NMDhcpClient * nm_dhcp_manager_start_ip4 (NMDhcpManager *manager, gboolean send_hostname, const char *dhcp_hostname, const char *dhcp_fqdn, + NMDhcpHostnameFlags hostname_flags, GBytes *dhcp_client_id, guint32 timeout, const char *dhcp_anycast_addr, @@ -74,8 +61,11 @@ NMDhcpClient * nm_dhcp_manager_start_ip6 (NMDhcpManager *manager, guint32 route_metric, gboolean send_hostname, const char *dhcp_hostname, + NMDhcpHostnameFlags hostname_flags, GBytes *duid, gboolean enforce_duid, + guint32 iaid, + gboolean iaid_explicit, guint32 timeout, const char *dhcp_anycast_addr, gboolean info_only, @@ -86,7 +76,7 @@ NMDhcpClient * nm_dhcp_manager_start_ip6 (NMDhcpManager *manager, /* For testing only */ extern const char* nm_dhcp_helper_path; -extern const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5]; +extern const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6]; void nmtst_dhcp_manager_unget (gpointer singleton_instance); diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c index a71a7a13..e557c004 100644 --- a/src/dhcp/nm-dhcp-nettools.c +++ b/src/dhcp/nm-dhcp-nettools.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2014-2019 Red Hat, Inc. + * Copyright (C) 2014 - 2019 Red Hat, Inc. */ #include "nm-default.h" @@ -42,6 +29,7 @@ #include "nm-dhcp-client-logging.h" #include "n-dhcp4/src/n-dhcp4.h" #include "systemd/nm-sd-utils-shared.h" +#include "systemd/nm-sd-utils-dhcp.h" /*****************************************************************************/ @@ -55,8 +43,6 @@ typedef struct _NMDhcpNettools NMDhcpNettools; typedef struct _NMDhcpNettoolsClass NMDhcpNettoolsClass; -static GType nm_dhcp_nettools_get_type (void); - /*****************************************************************************/ typedef struct { @@ -65,6 +51,7 @@ typedef struct { NDhcp4ClientLease *lease; GIOChannel *channel; guint event_id; + char *lease_file; } NMDhcpNettoolsPrivate; struct _NMDhcpNettools { @@ -85,13 +72,6 @@ G_DEFINE_TYPE (NMDhcpNettools, nm_dhcp_nettools, NM_TYPE_DHCP_CLIENT) #define DHCP_MAX_FQDN_LENGTH 255 enum { - DHCP_FQDN_FLAG_S = (1 << 0), - DHCP_FQDN_FLAG_O = (1 << 1), - DHCP_FQDN_FLAG_E = (1 << 2), - DHCP_FQDN_FLAG_N = (1 << 3), -}; - -enum { NM_IN_ADDR_CLASS_A, NM_IN_ADDR_CLASS_B, NM_IN_ADDR_CLASS_C, @@ -354,28 +334,21 @@ lease_get_u16 (NDhcp4ClientLease *lease, return TRUE; } -#define LOG_LEASE(domain, ...) \ - G_STMT_START { \ - _LOG2I ((domain), (iface), " "__VA_ARGS__); \ - } G_STMT_END - static gboolean lease_parse_address (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options, GError **error) { char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - const gint64 ts = nm_utils_get_monotonic_timestamp_ns (); - const gint64 ts_clock_boottime = nm_utils_monotonic_timestamp_as_boottime (ts, 1); struct in_addr a_address; struct in_addr a_netmask; struct in_addr a_next_server; guint32 a_plen; guint64 nettools_lifetime; - gint64 a_lifetime; - gint64 a_expiry; + guint32 a_lifetime; + guint32 a_timestamp; + guint64 a_expiry; n_dhcp4_client_lease_get_yiaddr (lease, &a_address); if (a_address.s_addr == INADDR_ANY) { @@ -383,29 +356,47 @@ lease_parse_address (NDhcp4ClientLease *lease, return FALSE; } - /* n_dhcp4_client_lease_get_lifetime() never fails */ n_dhcp4_client_lease_get_lifetime (lease, &nettools_lifetime); - /* FIXME: n_dhcp4_client_lease_get_lifetime() returns the time in nsec of CLOCK_BOOTTIME. - * We want to retrieve the original lifetime value in seconds, so we approximate it in a_lifetime. - * Use a nettools API to retrieve the original value as passed by the server. - */ + if (nettools_lifetime == G_MAXUINT64) { + a_timestamp = 0; a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - a_expiry = NM_PLATFORM_LIFETIME_PERMANENT; + a_expiry = G_MAXUINT64; } else { - gint64 ts_time = time (NULL); - - a_lifetime = ((gint64) nettools_lifetime - ts_clock_boottime) / NM_UTILS_NS_PER_SECOND; - /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */ - if (a_lifetime < 0) - a_lifetime = 0; - else if (a_lifetime > NM_PLATFORM_LIFETIME_PERMANENT) - a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT - 1; - - if (ts_time > NM_PLATFORM_LIFETIME_PERMANENT - a_lifetime) - a_expiry = NM_PLATFORM_LIFETIME_PERMANENT - 1; - else - a_expiry = ts_time + a_lifetime; + guint64 nettools_basetime; + guint64 lifetime; + gint64 ts; + + n_dhcp4_client_lease_get_basetime (lease, &nettools_basetime); + + /* usually we shouldn't assert against external libraries like n-dhcp4. + * Here we still do it... it seems safe enough. */ + nm_assert (nettools_basetime > 0); + nm_assert (nettools_lifetime >= nettools_basetime); + nm_assert (((nettools_lifetime - nettools_basetime) % NM_UTILS_NS_PER_SECOND) == 0); + nm_assert ((nettools_lifetime - nettools_basetime) / NM_UTILS_NS_PER_SECOND <= G_MAXUINT32); + + if (nettools_lifetime <= nettools_basetime) { + /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */ + lifetime = 0; + } else { + lifetime = nettools_lifetime - nettools_basetime; + + /* we "ceil" the value to the next second. In practice, we don't expect any sub-second values + * from n-dhcp4 anyway, so this should have no effect. */ + lifetime += NM_UTILS_NS_PER_SECOND - 1; + } + + ts = nm_utils_monotonic_timestamp_from_boottime (nettools_basetime, 1); + + /* the timestamp must be positive, because we only started nettools DHCP client + * after obtaining the first monotonic timestamp. Hence, the lease must have been + * received afterwards. */ + nm_assert (ts >= NM_UTILS_NS_PER_SECOND); + + a_timestamp = ts / NM_UTILS_NS_PER_SECOND; + a_lifetime = NM_MIN (lifetime / NM_UTILS_NS_PER_SECOND, NM_PLATFORM_LIFETIME_PERMANENT - 1); + a_expiry = time (NULL) + ((lifetime - (nm_utils_clock_gettime_ns (CLOCK_BOOTTIME) - nettools_basetime)) / NM_UTILS_NS_PER_SECOND); } if (!lease_get_in_addr (lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &a_netmask)) { @@ -416,7 +407,6 @@ lease_parse_address (NDhcp4ClientLease *lease, nm_utils_inet4_ntop (a_address.s_addr, addr_str); a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr); - LOG_LEASE (LOGD_DHCP4, "address %s/%u", addr_str, a_plen); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, @@ -426,20 +416,17 @@ lease_parse_address (NDhcp4ClientLease *lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, nm_utils_inet4_ntop (a_netmask.s_addr, addr_str)); - LOG_LEASE (LOGD_DHCP4, "%s '%u' seconds (at %lld)", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME), - (guint) a_lifetime, - (long long) a_expiry); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, (guint64) a_lifetime); - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_EXPIRY, - (guint64) a_expiry); + if (a_expiry != G_MAXUINT64) { + nm_dhcp_option_add_option_u64 (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_EXPIRY, + a_expiry); + } n_dhcp4_client_lease_get_siaddr (lease, &a_next_server); @@ -457,7 +444,7 @@ lease_parse_address (NDhcp4ClientLease *lease, .peer_address = a_address.s_addr, .plen = a_plen, .addr_source = NM_IP_CONFIG_SOURCE_DHCP, - .timestamp = ts / NM_UTILS_NS_PER_SECOND, + .timestamp = a_timestamp, .lifetime = a_lifetime, .preferred = a_lifetime, })); @@ -467,7 +454,6 @@ lease_parse_address (NDhcp4ClientLease *lease, static void lease_parse_domain_name_servers (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -498,7 +484,6 @@ lease_parse_domain_name_servers (NDhcp4ClientLease *lease, nm_ip4_config_add_nameserver (ip4_config, addr.s_addr); } - LOG_LEASE (LOGD_DHCP4, "nameserver '%s'", str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, @@ -507,7 +492,6 @@ lease_parse_domain_name_servers (NDhcp4ClientLease *lease, static void lease_parse_routes (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options, guint32 route_table, @@ -537,11 +521,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, nm_utils_inet4_ntop (dest.s_addr, dest_str); nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - LOG_LEASE (LOGD_DHCP4, - "classless static route %s/%d gw %s", - dest_str, - (int) plen, - gateway_str); g_string_append_printf (nm_gstring_add_space_delimiter (str), "%s/%d %s", dest_str, @@ -586,11 +565,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, nm_utils_inet4_ntop (dest.s_addr, dest_str); nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - LOG_LEASE (LOGD_DHCP4, - "static route %s/%d gw %s", - dest_str, - (int) plen, - gateway_str); g_string_append_printf (nm_gstring_add_space_delimiter (str), "%s/%d %s", dest_str, @@ -667,7 +641,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, }), NULL); } - LOG_LEASE (LOGD_DHCP4, "router %s", str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER, @@ -677,7 +650,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, static void lease_parse_mtu (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -689,7 +661,6 @@ lease_parse_mtu (NDhcp4ClientLease *lease, if (mtu < 68) return; - LOG_LEASE (LOGD_DHCP4, "mtu %u", mtu); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, @@ -699,7 +670,6 @@ lease_parse_mtu (NDhcp4ClientLease *lease, static void lease_parse_metered (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -715,13 +685,12 @@ lease_parse_metered (NDhcp4ClientLease *lease, metered = !!memmem (data, n_data, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED")); } - LOG_LEASE (LOGD_DHCP4, "%s", metered ? "metered" : "unmetered"); + /* TODO: expose the vendor specific option when present */ nm_ip4_config_set_metered (ip4_config, metered); } static void lease_parse_ntps (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { nm_auto_free_gstring GString *str = NULL; @@ -742,13 +711,14 @@ lease_parse_ntps (NDhcp4ClientLease *lease, g_string_append (nm_gstring_add_space_delimiter (str), addr_str); } - LOG_LEASE (LOGD_DHCP4, "ntp server '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NTP_SERVER, + str->str); } static void lease_parse_hostname (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { nm_auto_free_gstring GString *str = NULL; @@ -765,13 +735,14 @@ lease_parse_hostname (NDhcp4ClientLease *lease, if (is_localhost(str->str)) return; - LOG_LEASE (LOGD_DHCP4, "hostname '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + str->str); } static void lease_parse_domainname (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -798,13 +769,14 @@ lease_parse_domainname (NDhcp4ClientLease *lease, g_string_append (nm_gstring_add_space_delimiter (str), *d); nm_ip4_config_add_domain (ip4_config, *d); } - LOG_LEASE (LOGD_DHCP4, "domain name '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + str->str); } static void lease_parse_search_domains (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -832,7 +804,6 @@ lease_parse_search_domains (NDhcp4ClientLease *lease, g_string_append (nm_gstring_add_space_delimiter (str), domain->str); nm_ip4_config_add_search (ip4_config, domain->str); } - LOG_LEASE (LOGD_DHCP4, "domain search '%s'", str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, @@ -841,7 +812,6 @@ lease_parse_search_domains (NDhcp4ClientLease *lease, static void lease_parse_root_path (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { nm_auto_free_gstring GString *str = NULL; @@ -854,16 +824,17 @@ lease_parse_root_path (NDhcp4ClientLease *lease, return; str = g_string_new_len ((char *)data, n_data); - LOG_LEASE (LOGD_DHCP4, "root path '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + str->str); } static void lease_parse_wpad (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; + gs_free char *wpad = NULL; uint8_t *data; size_t n_data; int r; @@ -872,12 +843,44 @@ lease_parse_wpad (NDhcp4ClientLease *lease, if (r) return; - str = g_string_new_len ((char *)data, n_data); - LOG_LEASE (LOGD_DHCP4, "wpad '%s'", str->str); + nm_utils_buf_utf8safe_escape ((char *)data, n_data, 0, &wpad); + if (wpad == NULL) + wpad = g_strndup ((char *)data, n_data); + nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, - str->str); + wpad); +} + +static void +lease_parse_private_options (NDhcp4ClientLease *lease, + GHashTable *options) +{ + int i; + + for (i = NM_DHCP_OPTION_DHCP4_PRIVATE_224; i <= NM_DHCP_OPTION_DHCP4_PRIVATE_254; i++) { + gs_free char *option_string = NULL; + guint8 *data; + gsize n_data; + int r; + + /* We manage private options 249 (private classless static route) and 252 (wpad) in a special + * way, so skip them as we here just manage all (the other) private options as raw data */ + if (NM_IN_SET (i, NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY)) + continue; + + r = n_dhcp4_client_lease_query (lease, i, &data, &n_data); + if (r) + continue; + + option_string = nm_utils_bin2hexstr_full (data, n_data, ':', FALSE, NULL); + nm_dhcp_option_take_option (options, + _nm_dhcp_option_dhcp4_options, + i, + g_steal_pointer (&option_string)); + } } static NMIP4Config * @@ -896,22 +899,23 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, g_return_val_if_fail (lease != NULL, NULL); ip4_config = nm_ip4_config_new (multi_idx, ifindex); - options = out_options ? nm_dhcp_option_create_options_dict () : NULL; + options = nm_dhcp_option_create_options_dict (); - if (!lease_parse_address (lease, iface, ip4_config, options, error)) + if (!lease_parse_address (lease, ip4_config, options, error)) return NULL; - lease_parse_routes (lease, iface, ip4_config, options, route_table, route_metric); - lease_parse_domain_name_servers (lease, iface, ip4_config, options); - lease_parse_domainname (lease, iface, ip4_config, options); - lease_parse_search_domains (lease, iface, ip4_config, options); - lease_parse_mtu (lease, iface, ip4_config, options); - lease_parse_metered (lease, iface, ip4_config, options); + lease_parse_routes (lease, ip4_config, options, route_table, route_metric); + lease_parse_domain_name_servers (lease, ip4_config, options); + lease_parse_domainname (lease, ip4_config, options); + lease_parse_search_domains (lease, ip4_config, options); + lease_parse_mtu (lease, ip4_config, options); + lease_parse_metered (lease, ip4_config, options); - lease_parse_hostname (lease, iface, options); - lease_parse_ntps (lease, iface, options); - lease_parse_root_path (lease, iface, options); - lease_parse_wpad (lease, iface, options); + lease_parse_hostname (lease, options); + lease_parse_ntps (lease, options); + lease_parse_root_path (lease, options); + lease_parse_wpad (lease, options); + lease_parse_private_options (lease, options); NM_SET_OUT (out_options, g_steal_pointer (&options)); return g_steal_pointer (&ip4_config); @@ -920,8 +924,34 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, /*****************************************************************************/ static void +lease_save (NDhcp4ClientLease *lease, const char *lease_file) +{ + struct in_addr a_address; + nm_auto_free_gstring GString *new_contents = NULL; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + nm_assert (lease); + nm_assert (lease_file); + + new_contents = g_string_new ("# This is private data. Do not parse.\n"); + + n_dhcp4_client_lease_get_yiaddr (lease, &a_address); + if (a_address.s_addr == INADDR_ANY) + return; + + g_string_append_printf (new_contents, + "ADDRESS=%s\n", nm_utils_inet4_ntop (a_address.s_addr, sbuf)); + + g_file_set_contents (lease_file, + new_contents->str, + -1, + NULL); +} + +static void bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease) { + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); gs_unref_object NMIP4Config *ip4_config = NULL; gs_unref_hashtable GHashTable *options = NULL; @@ -945,6 +975,7 @@ bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease) } nm_dhcp_option_add_requests_to_options (options, _nm_dhcp_option_dhcp4_options); + lease_save (lease, priv->lease_file); nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_BOUND, @@ -1015,6 +1046,27 @@ dhcp4_event_cb (GIOChannel *source, return G_SOURCE_CONTINUE; } +G_GNUC_PRINTF (3, 4) +static void +nettools_log (int level, void *data, const char *fmt, ...) +{ + NMDhcpNettools *self = data; + NMLogLevel nm_level; + gs_free char *msg = NULL; + va_list ap; + + nm_level = nm_log_level_from_syslog (level); + if (nm_logging_enabled (nm_level, LOGD_DHCP4)) { + va_start (ap, fmt); + msg = g_strdup_vprintf (fmt, ap); + va_end (ap); + nm_log (nm_level, LOGD_DHCP4, NULL , NULL, + "dhcp4 (%s): %s", + nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)), + msg); + } +} + static gboolean nettools_create (NMDhcpNettools *self, const char *dhcp_anycast_addr, @@ -1084,11 +1136,15 @@ nettools_create (NMDhcpNettools *self, return FALSE; } + n_dhcp4_client_config_set_log_level (config, nm_log_level_to_syslog (nm_logging_get_level (LOGD_DHCP4))); + n_dhcp4_client_config_set_log_func (config, nettools_log, self); n_dhcp4_client_config_set_ifindex (config, nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self))); n_dhcp4_client_config_set_transport (config, transport); n_dhcp4_client_config_set_mac (config, hwaddr_arr, hwaddr_len); n_dhcp4_client_config_set_broadcast_mac (config, bcast_hwaddr_arr, bcast_hwaddr_len); - r = n_dhcp4_client_config_set_client_id (config, client_id_arr, client_id_len); + r = n_dhcp4_client_config_set_client_id (config, + client_id_arr, + NM_MIN (client_id_len, 1 + _NM_SD_MAX_CLIENT_ID_LEN)); if (r) { nm_utils_error_set_errno (error, r, "failed to set client-id: %s"); return FALSE; @@ -1157,6 +1213,22 @@ decline (NMDhcpClient *client, return TRUE; } +static guint8 +fqdn_flags_to_wire (NMDhcpHostnameFlags flags) +{ + guint r = 0; + + /* RFC 4702 section 2.1 */ + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + r |= (1 << 0); + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) + r |= (1 << 2); + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) + r |= (1 << 3); + + return r; +} + static gboolean ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, @@ -1166,6 +1238,7 @@ ip4_start (NMDhcpClient *client, nm_auto (n_dhcp4_client_probe_config_freep) NDhcp4ClientProbeConfig *config = NULL; NMDhcpNettools *self = NM_DHCP_NETTOOLS (client); NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); + gs_free char *lease_file = NULL; struct in_addr last_addr = { 0 }; const char *hostname; int r, i; @@ -1187,11 +1260,32 @@ ip4_start (NMDhcpClient *client, */ n_dhcp4_client_probe_config_set_start_delay (config, 1); - if (last_ip4_address) { + nm_dhcp_utils_get_leasefile_path (AF_INET, + "internal", + nm_dhcp_client_get_iface (client), + nm_dhcp_client_get_uuid (client), + &lease_file); + + if (last_ip4_address) inet_pton (AF_INET, last_ip4_address, &last_addr); - n_dhcp4_client_probe_config_set_requested_ip (config, last_addr); + else { + /* + * TODO: we stick to the systemd-networkd lease file format. Quite easy for now to + * just use the functions in systemd code. Anyway, as in the end we just use the + * ip address from all the options found in the lease, write a function that parses + * the lease file just for the assigned address and returns it in &last_address. + * Then drop reference to systemd-networkd structures and functions. + */ + nm_auto (sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + + dhcp_lease_load (&lease, lease_file); + if (lease) + sd_dhcp_lease_get_address (lease, &last_addr); } + if (last_addr.s_addr) + n_dhcp4_client_probe_config_set_requested_ip (config, last_addr); + /* Add requested options */ for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { if (_nm_dhcp_option_dhcp4_options[i].include) { @@ -1204,26 +1298,38 @@ ip4_start (NMDhcpClient *client, hostname = nm_dhcp_client_get_hostname (client); if (hostname) { if (nm_dhcp_client_get_use_fqdn (client)) { - uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; - - buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */ - DHCP_FQDN_FLAG_E; /* Canonical wire format */ - buffer[1] = 0; /* RCODE1 (deprecated) */ - buffer[2] = 0; /* RCODE2 (deprecated) */ - - r = nm_sd_dns_name_to_wire_format (hostname, - buffer + 3, - sizeof (buffer) - 3, - FALSE); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to convert DHCP FQDN: %s"); - return FALSE; + uint8_t buffer[255]; + NMDhcpHostnameFlags flags; + size_t fqdn_len; + + flags = nm_dhcp_client_get_hostname_flags (client); + buffer[0] = fqdn_flags_to_wire (flags); + buffer[1] = 0; /* RCODE1 (deprecated) */ + buffer[2] = 0; /* RCODE2 (deprecated) */ + + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) { + r = nm_sd_dns_name_to_wire_format (hostname, + buffer + 3, + sizeof (buffer) - 3, + FALSE); + if (r <= 0) { + nm_utils_error_set_errno (error, r, "failed to convert DHCP FQDN: %s"); + return FALSE; + } + fqdn_len = r; + } else { + fqdn_len = strlen (hostname); + if (fqdn_len > sizeof (buffer) - 3) { + nm_utils_error_set (error, r, "failed to set DHCP FQDN: name too long"); + return FALSE; + } + memcpy (buffer + 3, hostname, fqdn_len); } r = n_dhcp4_client_probe_config_append_option (config, NM_DHCP_OPTION_DHCP4_CLIENT_FQDN, buffer, - 3 + r); + 3 + fqdn_len); if (r) { nm_utils_error_set_errno (error, r, "failed to set DHCP FQDN: %s"); return FALSE; @@ -1240,6 +1346,9 @@ ip4_start (NMDhcpClient *client, } } + g_free (priv->lease_file); + priv->lease_file = g_steal_pointer (&lease_file); + r = n_dhcp4_client_probe (priv->client, &priv->probe, config); if (r) { nm_utils_error_set_errno (error, r, "failed to start DHCP client: %s"); @@ -1279,6 +1388,7 @@ dispose (GObject *object) { NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE ((NMDhcpNettools *) object); + nm_clear_pointer (&priv->lease_file, g_free); nm_clear_pointer (&priv->channel, g_io_channel_unref); nm_clear_g_source (&priv->event_id); nm_clear_pointer (&priv->lease, n_dhcp4_client_lease_unref); @@ -1303,7 +1413,7 @@ nm_dhcp_nettools_class_init (NMDhcpNettoolsClass *class) } const NMDhcpClientFactory _nm_dhcp_client_factory_nettools = { - .name = "nettools", - .get_type = nm_dhcp_nettools_get_type, - .get_path = NULL, + .name = "nettools", + .get_type = nm_dhcp_nettools_get_type, + .experimental = TRUE, }; diff --git a/src/dhcp/nm-dhcp-options.c b/src/dhcp/nm-dhcp-options.c index 22e7d90e..4c003f31 100644 --- a/src/dhcp/nm-dhcp-options.c +++ b/src/dhcp/nm-dhcp-options.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" @@ -237,6 +223,7 @@ nm_dhcp_option_take_option (GHashTable *options, nm_assert (options); nm_assert (requests); nm_assert (value); + nm_assert (g_utf8_validate (value, -1, NULL)); g_hash_table_insert (options, (gpointer) nm_dhcp_option_request_string (requests, option), diff --git a/src/dhcp/nm-dhcp-options.h b/src/dhcp/nm-dhcp-options.h index f56edb19..bf9ccd57 100644 --- a/src/dhcp/nm-dhcp-options.h +++ b/src/dhcp/nm-dhcp-options.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_DHCP_OPTIONS_H__ diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c index 96409345..1518d465 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/dhcp/nm-dhcp-systemd.c @@ -1,18 +1,5 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Copyright (C) 2014 Red Hat, Inc. */ @@ -30,7 +17,6 @@ #include "nm-std-aux/unaligned.h" #include "nm-utils.h" -#include "nm-config.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-options.h" #include "nm-core-utils.h" @@ -81,13 +67,6 @@ G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) /*****************************************************************************/ -#define LOG_LEASE(domain, ...) \ -G_STMT_START { \ - if (log_lease) { \ - _LOG2D ((domain), (iface), " "__VA_ARGS__); \ - } \ -} G_STMT_END - static NMIP4Config * lease_to_ip4_config (NMDedupMultiIndex *multi_idx, const char *iface, @@ -95,7 +74,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, sd_dhcp_lease *lease, guint32 route_table, guint32 route_metric, - gboolean log_lease, GHashTable **out_options, GError **error) { @@ -151,25 +129,17 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, options = out_options ? nm_dhcp_option_create_options_dict () : NULL; nm_utils_inet4_ntop (a_address.s_addr, addr_str); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS), - addr_str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, + addr_str); a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr); - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SUBNET_MASK), - (guint) a_plen); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, nm_utils_inet4_ntop (a_netmask.s_addr, addr_str)); - LOG_LEASE (LOGD_DHCP4, "%s '%u' seconds (at %lld)", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME), - (guint) a_lifetime, - (long long) (ts_time + a_lifetime)); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, @@ -200,9 +170,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, if (sd_dhcp_lease_get_server_identifier (lease, &server_id) >= 0) { nm_utils_inet4_ntop (server_id.s_addr, addr_str); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SERVER_ID), - addr_str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SERVER_ID, @@ -211,9 +178,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, if (sd_dhcp_lease_get_broadcast (lease, &broadcast) >= 0) { nm_utils_inet4_ntop (broadcast.s_addr, addr_str); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_BROADCAST), - addr_str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_BROADCAST, @@ -235,9 +199,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, @@ -251,9 +212,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, g_string_append (nm_gstring_add_space_delimiter (str), search_domains[i]); nm_ip4_config_add_search (ip4_config, search_domains[i]); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, @@ -264,10 +222,10 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, gs_strfreev char **domains = NULL; char **d; - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME), - s); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + s); /* Multiple domains sometimes stuffed into option 15 "Domain Name". * As systemd escapes such characters, split them at \\032. */ @@ -277,10 +235,10 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_hostname (lease, &s) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME), - s); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME, s); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + s); } num = sd_dhcp_lease_get_routes (lease, &routes); @@ -333,14 +291,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, nm_utils_inet4_ntop (network_net, network_net_str); nm_utils_inet4_ntop (r_gateway.s_addr, gateway_str); - LOG_LEASE (LOGD_DHCP4, - "%sstatic_route %s/%d gw %s", - option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE - ? "rfc3442_classless_" - : "", - network_net_str, - (int) r_plen, - gateway_str); g_string_append_printf (nm_gstring_add_space_delimiter ( option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE ? str_classless : str_static), @@ -442,17 +392,14 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, }), NULL); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER), - str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROUTER, + str->str); } if ( sd_dhcp_lease_get_mtu (lease, &mtu) >= 0 && mtu) { - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU), - mtu); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, @@ -467,9 +414,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str); g_string_append (nm_gstring_add_space_delimiter (str), addr_str); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER, @@ -477,16 +421,13 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_root_path (lease, &s) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH), - s); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + s); } if (sd_dhcp_lease_get_t1 (lease, &renewal) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME), - renewal); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, @@ -494,9 +435,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_t2 (lease, &rebinding) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME), - rebinding); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, @@ -504,9 +442,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_timezone (lease, &s) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE), - s); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, @@ -525,9 +460,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, option_string = nm_utils_bin2hexstr_full (private_options[i].data, private_options[i].data_len, ':', FALSE, NULL); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, private_options[i].code), - option_string); if (!options) { g_free (option_string); continue; @@ -544,37 +476,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, /*****************************************************************************/ -static char * -get_leasefile_path (int addr_family, const char *iface, const char *uuid) -{ - char *rundir_path; - char *statedir_path; - - rundir_path = g_strdup_printf (NMRUNDIR "/internal%s-%s-%s.lease", - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) - return rundir_path; - - statedir_path = g_strdup_printf (NMSTATEDIR "/internal%s-%s-%s.lease", - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if ( g_file_test (statedir_path, G_FILE_TEST_EXISTS) - || nm_config_get_configure_and_quit (nm_config_get ()) != NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) { - g_free (rundir_path); - return statedir_path; - } else { - g_free (statedir_path); - return rundir_path; - } -} - -/*****************************************************************************/ - static void bound4_handle (NMDhcpSystemd *self) { @@ -600,7 +501,6 @@ bound4_handle (NMDhcpSystemd *self) lease, nm_dhcp_client_get_route_table (NM_DHCP_CLIENT (self)), nm_dhcp_client_get_route_metric (NM_DHCP_CLIENT (self)), - TRUE, &options, &error); if (!ip4_config) { @@ -713,9 +613,11 @@ ip4_start (NMDhcpClient *client, return FALSE; } - lease_file = get_leasefile_path (AF_INET, - nm_dhcp_client_get_iface (client), - nm_dhcp_client_get_uuid (client)); + nm_dhcp_utils_get_leasefile_path (AF_INET, + "internal", + nm_dhcp_client_get_iface (client), + nm_dhcp_client_get_uuid (client), + &lease_file); if (last_ip4_address) inet_pton (AF_INET, last_ip4_address, &last_addr); @@ -814,9 +716,9 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, const char *iface, int ifindex, sd_dhcp6_lease *lease, - gboolean log_lease, gboolean info_only, GHashTable **out_options, + gint32 ts, GError **error) { gs_unref_object NMIP6Config *ip6_config = NULL; @@ -827,7 +729,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, char **domains; nm_auto_free_gstring GString *str = NULL; int num, i; - const gint32 ts = nm_utils_get_monotonic_timestamp_s (); g_return_val_if_fail (lease, NULL); @@ -838,7 +739,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, sd_dhcp6_lease_reset_address_iter (lease); nm_gstring_prepare (&str); while (sd_dhcp6_lease_get_address (lease, &tmp_addr, &lft_pref, &lft_valid) >= 0) { - char sbuf[400]; const NMPlatformIP6Address address = { .plen = 128, .address = tmp_addr, @@ -852,10 +752,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, nm_utils_inet6_ntop (&tmp_addr, addr_str); g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - - LOG_LEASE (LOGD_DHCP6, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS), - nm_platform_ip6_address_to_string (&address, sbuf, sizeof (sbuf))); }; if (str->len) nm_dhcp_option_add_option (options, @@ -880,9 +776,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, g_string_append (nm_gstring_add_space_delimiter (str), addr_str); nm_ip6_config_add_nameserver (ip6_config, &dns[i]); } - LOG_LEASE (LOGD_DHCP6, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DNS_SERVERS), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, @@ -896,9 +789,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, g_string_append (nm_gstring_add_space_delimiter (str), domains[i]); nm_ip6_config_add_search (ip6_config, domains[i]); } - LOG_LEASE (LOGD_DHCP6, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, @@ -913,10 +803,12 @@ static void bound6_handle (NMDhcpSystemd *self) { NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); + const gint32 ts = nm_utils_get_monotonic_timestamp_s (); const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); gs_unref_object NMIP6Config *ip6_config = NULL; gs_unref_hashtable GHashTable *options = NULL; gs_free_error GError *error = NULL; + NMPlatformIP6Address prefix = { 0 }; sd_dhcp6_lease *lease; if ( sd_dhcp6_client_get_lease (priv->client6, &lease) < 0 @@ -932,9 +824,9 @@ bound6_handle (NMDhcpSystemd *self) iface, nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self)), lease, - TRUE, nm_dhcp_client_get_info_only (NM_DHCP_CLIENT (self)), &options, + ts, &error); if (!ip6_config) { @@ -947,6 +839,16 @@ bound6_handle (NMDhcpSystemd *self) NM_DHCP_STATE_BOUND, NM_IP_CONFIG_CAST (ip6_config), options); + + sd_dhcp6_lease_reset_pd_prefix_iter (lease); + while (!sd_dhcp6_lease_get_pd (lease, + &prefix.address, + &prefix.plen, + &prefix.preferred, + &prefix.lifetime)) { + prefix.timestamp = ts; + nm_dhcp_client_emit_ipv6_prefix_delegated (NM_DHCP_CLIENT (self), &prefix); + } } static void @@ -990,7 +892,6 @@ ip6_start (NMDhcpClient *client, nm_auto (sd_dhcp6_client_unrefp) sd_dhcp6_client *sd_client = NULL; GBytes *hwaddr; const char *hostname; - const char *iface; int r, i; const guint8 *duid_arr; gsize duid_len; @@ -1015,22 +916,13 @@ ip6_start (NMDhcpClient *client, return FALSE; } - if (needed_prefixes > 0) { - _LOGW ("dhcp-client6: prefix delegation not yet supported, won't supply %d prefixes", - needed_prefixes); - } - _LOGT ("dhcp-client6: set %p", sd_client); if (nm_dhcp_client_get_info_only (client)) sd_dhcp6_client_set_information_request (sd_client, 1); - iface = nm_dhcp_client_get_iface (client); - r = sd_dhcp6_client_set_iaid (sd_client, - nm_utils_create_dhcp_iaid (TRUE, - (const guint8 *) iface, - strlen (iface))); + nm_dhcp_client_get_iaid (client)); if (r < 0) { nm_utils_error_set_errno (error, r, "failed to set IAID: %s"); return FALSE; @@ -1082,6 +974,18 @@ ip6_start (NMDhcpClient *client, } } + if (needed_prefixes > 0) { + if (needed_prefixes > 1) + _LOGW ("dhcp-client6: only one prefix request is supported"); + /* FIXME: systemd-networkd API only allows to request a + * single prefix */ + r = sd_dhcp6_client_set_prefix_delegation (sd_client, TRUE); + if (r < 0) { + nm_utils_error_set_errno (error, r, "failed to enable prefix delegation: %s"); + return FALSE; + } + } + r = sd_dhcp6_client_set_local_address (sd_client, ll_addr); if (r < 0) { nm_utils_error_set_errno (error, r, "failed to set local address: %s"); @@ -1182,8 +1086,25 @@ nm_dhcp_systemd_class_init (NMDhcpSystemdClass *sdhcp_class) client_class->stop = stop; } +const NMDhcpClientFactory _nm_dhcp_client_factory_systemd = { + .name = "systemd", + .get_type = nm_dhcp_systemd_get_type, + .experimental = TRUE, +}; + +/*****************************************************************************/ + +static GType +_get_type_per_addr_family (int addr_family) +{ + nm_assert_addr_family (addr_family); + + if (addr_family == AF_INET) + return nm_dhcp_nettools_get_type (); + return nm_dhcp_systemd_get_type (); +} + const NMDhcpClientFactory _nm_dhcp_client_factory_internal = { - .name = "internal", - .get_type = nm_dhcp_systemd_get_type, - .get_path = NULL, + .name = "internal", + .get_type_per_addr_family = _get_type_per_addr_family, }; diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c index 3f9368f2..c5da3e02 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/dhcp/nm-dhcp-utils.c @@ -1,19 +1,6 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -25,6 +12,7 @@ #include "nm-dhcp-utils.h" #include "nm-utils.h" +#include "nm-config.h" #include "NetworkManagerUtils.h" #include "platform/nm-platform.h" #include "nm-dhcp-client-logging.h" @@ -762,3 +750,55 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) return bytes; } +/** + * nm_dhcp_utils_get_leasefile_path: + * @addr_family: the IP address family + * @plugin_name: the name of the plugin part of the lease file name + * @iface: the interface name to which the lease relates to + * @uuid: uuid of the connection to which the lease relates to + * @out_leasefile_path: will store the computed lease file path + * + * Constructs the lease file name on the basis of the calling plugin, + * interface name and connection uuid. Then returns in @out_leasefile_path + * the full path of the lease filename. + * + * Returns: TRUE if the lease file already exists, FALSE otherwise. + */ +gboolean +nm_dhcp_utils_get_leasefile_path (int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char **out_leasefile_path) +{ + gs_free char *rundir_path = NULL; + gs_free char *statedir_path = NULL; + + rundir_path = g_strdup_printf (NMRUNDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer (&rundir_path); + return TRUE; + } + + statedir_path = g_strdup_printf (NMSTATEDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test (statedir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer (&statedir_path); + return TRUE; + } + + if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) + *out_leasefile_path = g_steal_pointer (&rundir_path); + else + *out_leasefile_path = g_steal_pointer (&statedir_path); + return FALSE; +} diff --git a/src/dhcp/nm-dhcp-utils.h b/src/dhcp/nm-dhcp-utils.h index 39ae7693..e4c33314 100644 --- a/src/dhcp/nm-dhcp-utils.h +++ b/src/dhcp/nm-dhcp-utils.h @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -40,7 +28,13 @@ NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options) char *nm_dhcp_utils_duid_to_string (GBytes *duid); -GBytes * nm_dhcp_utils_client_id_string_to_bytes (const char *client_id); +GBytes *nm_dhcp_utils_client_id_string_to_bytes (const char *client_id); + +gboolean nm_dhcp_utils_get_leasefile_path (int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char **out_leasefile_path); #endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */ diff --git a/src/dhcp/tests/meson.build b/src/dhcp/tests/meson.build index 43b33951..031e2efd 100644 --- a/src/dhcp/tests/meson.build +++ b/src/dhcp/tests/meson.build @@ -7,7 +7,8 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c index 9e51fceb..761f9cdb 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/dhcp/tests/test-dhcp-dhclient.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -43,6 +29,7 @@ test_config (const char *orig, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *dhcp_client_id, GBytes *expected_new_client_id, const char *iface, @@ -64,6 +51,7 @@ test_config (const char *orig, hostname, timeout, use_fqdn, + hostname_flags, "/path/to/dhclient.conf", orig, &new_client_id); @@ -108,7 +96,11 @@ static const char *orig_missing_expected = \ static void test_orig_missing (void) { - test_config (NULL, orig_missing_expected, AF_INET, NULL, 0, FALSE, NULL, NULL, "eth0", NULL); + test_config (NULL, + orig_missing_expected, + AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, NULL, "eth0", NULL); } /*****************************************************************************/ @@ -139,6 +131,7 @@ test_override_client_id (void) { test_config (override_client_id_orig, override_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, "11:22:33:44:55:66", NULL, "eth0", @@ -169,6 +162,7 @@ test_quote_client_id (void) { test_config (NULL, quote_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, "abcd", NULL, "eth0", @@ -199,6 +193,7 @@ test_quote_client_id_2 (void) { test_config (NULL, quote_client_id_expected_2, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, "a\\bc", NULL, "eth0", @@ -229,6 +224,7 @@ test_hex_zero_client_id (void) { test_config (NULL, hex_zero_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, "00:11:22:33", NULL, "eth0", @@ -259,6 +255,7 @@ test_ascii_client_id (void) { test_config (NULL, ascii_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, "qb:cd:ef:12:34:56", NULL, "eth0", @@ -289,6 +286,7 @@ test_hex_single_client_id (void) { test_config (NULL, hex_single_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, "ab:cd:e:12:34:56", NULL, "eth0", @@ -327,6 +325,7 @@ test_existing_hex_client_id (void) new_client_id = g_bytes_new (bytes, sizeof (bytes)); test_config (existing_hex_client_id_orig, existing_hex_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, new_client_id, "eth0", @@ -364,6 +363,7 @@ test_existing_escaped_client_id (void) new_client_id = g_bytes_new ("$test\xfe", 6); test_config (existing_escaped_client_id_orig, existing_escaped_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, new_client_id, "eth0", @@ -405,6 +405,7 @@ test_existing_ascii_client_id (void) new_client_id = g_bytes_new (buf, sizeof (buf)); test_config (existing_ascii_client_id_orig, existing_ascii_client_id_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, new_client_id, "eth0", @@ -417,7 +418,8 @@ static const char *fqdn_expected = \ "\n" "send fqdn.fqdn \"foo.bar.com\"; # added by NetworkManager\n" "send fqdn.encoded on;\n" - "send fqdn.server-update on;\n" + "send fqdn.server-update off;\n" + "send fqdn.no-client-update on;\n" "\n" "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" @@ -435,7 +437,10 @@ test_fqdn (void) { test_config (NULL, fqdn_expected, AF_INET, "foo.bar.com", 0, - TRUE, NULL, + TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED + | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, + NULL, NULL, "eth0", NULL); @@ -452,8 +457,9 @@ static const char *fqdn_options_override_expected = \ "# Merged from /path/to/dhclient.conf\n" "\n" "send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n" - "send fqdn.encoded on;\n" + "send fqdn.encoded off;\n" "send fqdn.server-update on;\n" + "send fqdn.no-client-update off;\n" "\n" "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" @@ -476,6 +482,7 @@ test_fqdn_options_override (void) test_config (fqdn_options_override_orig, fqdn_options_override_expected, AF_INET, "example2.com", 0, + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, TRUE, NULL, NULL, "eth0", @@ -510,6 +517,7 @@ test_override_hostname (void) { test_config (override_hostname_orig, override_hostname_expected, AF_INET, "blahblah", 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", @@ -538,6 +546,7 @@ test_override_hostname6 (void) { test_config (override_hostname6_orig, override_hostname6_expected, AF_INET6, "blahblah.local", 0, TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, NULL, NULL, "eth0", @@ -550,7 +559,7 @@ static const char *nonfqdn_hostname6_expected = \ "# Created by NetworkManager\n" "\n" "send fqdn.fqdn \"blahblah\"; # added by NetworkManager\n" - "send fqdn.server-update on;\n" + "send fqdn.no-client-update on;\n" "\n" "also request dhcp6.name-servers;\n" "also request dhcp6.domain-search;\n" @@ -563,6 +572,7 @@ test_nonfqdn_hostname6 (void) /* Non-FQDN hostname can now be used with dhclient */ test_config (NULL, nonfqdn_hostname6_expected, AF_INET6, "blahblah", 0, TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, NULL, NULL, "eth0", @@ -599,6 +609,7 @@ test_existing_alsoreq (void) { test_config (existing_alsoreq_orig, existing_alsoreq_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", @@ -638,6 +649,7 @@ test_existing_req (void) { test_config (existing_req_orig, existing_req_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", @@ -678,6 +690,7 @@ test_existing_multiline_alsoreq (void) { test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", @@ -917,6 +930,7 @@ test_interface1 (void) { test_config (interface1_orig, interface1_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", @@ -963,6 +977,7 @@ test_interface2 (void) { test_config (interface2_orig, interface2_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth1", @@ -1074,6 +1089,7 @@ test_structured (void) new_client_id = g_bytes_new (bytes, sizeof (bytes) - 1); test_config (orig, expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, new_client_id, "eth0", @@ -1129,6 +1145,7 @@ test_config_req_intf (void) test_config (orig, expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", diff --git a/src/dhcp/tests/test-dhcp-utils.c b/src/dhcp/tests/test-dhcp-utils.c index e4d4c348..d0389069 100644 --- a/src/dhcp/tests/test-dhcp-utils.c +++ b/src/dhcp/tests/test-dhcp-utils.c @@ -1,19 +1,6 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2014 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index 13576c92..a5028e42 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> - * - * 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. - * */ #include "nm-default.h" @@ -29,6 +15,7 @@ #include <sys/stat.h> #include <linux/if.h> +#include "nm-glib-aux/nm-dbus-aux.h" #include "nm-core-internal.h" #include "platform/nm-platform.h" #include "nm-utils.h" @@ -37,21 +24,644 @@ #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" -#define PIDFILE NMRUNDIR "/dnsmasq.pid" -#define CONFDIR NMCONFDIR "/dnsmasq.d" +#define PIDFILE NMRUNDIR "/dnsmasq.pid" +#define CONFDIR NMCONFDIR "/dnsmasq.d" #define DNSMASQ_DBUS_SERVICE "org.freedesktop.NetworkManager.dnsmasq" -#define DNSMASQ_DBUS_PATH "/uk/org/thekelleys/dnsmasq" +#define DNSMASQ_DBUS_PATH "/uk/org/thekelleys/dnsmasq" + +#define RATELIMIT_INTERVAL_MSEC 30000 +#define RATELIMIT_BURST 5 + +#define _NMLOG_DOMAIN LOGD_DNS /*****************************************************************************/ +#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "dnsmasq", __VA_ARGS__) + +#define WAIT_MSEC_AFTER_SIGTERM 1000 +G_STATIC_ASSERT (WAIT_MSEC_AFTER_SIGTERM <= NM_SHUTDOWN_TIMEOUT_MS); + +#define WAIT_MSEC_AFTER_SIGKILL 400 +G_STATIC_ASSERT (WAIT_MSEC_AFTER_SIGKILL + 100 <= NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG); + +typedef void (*GlPidSpawnAsyncNotify) (GCancellable *cancellable, + GPid pid, + const int *p_exit_code, + GError *error, + gpointer notify_user_data); + typedef struct { - GDBusProxy *dnsmasq; - GCancellable *dnsmasq_cancellable; - GCancellable *update_cancellable; - gboolean running; + NMShutdownWaitObjHandle *shutdown_wait_handle; + guint64 p_start_time; + gint64 started_at; + GPid pid; + bool sigkilled:1; +} GlPidKillExternalData; + +typedef struct { + const char *dm_binary; + GlPidSpawnAsyncNotify notify; + gpointer notify_user_data; + GCancellable *cancellable; +} GlPidSpawnAsyncData; + +static struct { + + GlPidKillExternalData *kill_external_data; + + GlPidSpawnAsyncData *spawn_data; + + NMShutdownWaitObjHandle *terminate_handle; + + GPid pid; + + guint terminate_timeout_id; + + guint watch_id; + + /* whether the external process (with the pid from PIDFILE) was already killed. + * This only happens once, once we do that, we remember to not do it again. + * The reason is that later one, when we want to kill the process it's a + * child process. So, we wait for the exit code. */ + bool kill_external_done:1; + + bool terminate_sigkill:1; +} gl_pid; + +/*****************************************************************************/ + +static void _gl_pid_spawn_next_step (void); +static void _gl_pid_spawn_cancelled_cb (GCancellable *cancellable, + GlPidSpawnAsyncData *sdata); + +/*****************************************************************************/ + +static gboolean +_gl_pid_unlink_pidfile (gboolean do_unlink) +{ + int errsv; + + if (do_unlink) { + if (unlink (PIDFILE) == 0) + _LOGD ("spawn: delete PID file %s", PIDFILE); + else { + errsv = errno; + if (errsv != ENOENT) + _LOGD ("spawn: delete PID file %s failed: %s (%d)", PIDFILE, nm_strerror_native (errsv), errsv); + } + } + return TRUE; +} + +static gboolean +_gl_pid_kill_external_timeout_cb (gpointer user_data) +{ + guint64 p_start_time; + char p_state = '\0'; + gint64 now; + + p_start_time = nm_utils_get_start_time_for_pid (gl_pid.kill_external_data->pid, &p_state, NULL); + if ( p_start_time == 0 + || p_start_time != gl_pid.kill_external_data->p_start_time + || nm_utils_process_state_is_dead (p_state)) { + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s is gone", gl_pid.kill_external_data->pid, PIDFILE); + goto process_gone; + } + + now = nm_utils_get_monotonic_timestamp_ms (); + + if (gl_pid.kill_external_data->started_at + WAIT_MSEC_AFTER_SIGTERM < now) { + if (!gl_pid.kill_external_data->sigkilled) { + _LOGD ("spawn: send SIGKILL to process %"G_PID_FORMAT" from pidfile %s", gl_pid.kill_external_data->pid, PIDFILE); + gl_pid.kill_external_data->sigkilled = TRUE; + kill (gl_pid.kill_external_data->pid, SIGKILL); + } else if (gl_pid.kill_external_data->started_at + WAIT_MSEC_AFTER_SIGTERM + WAIT_MSEC_AFTER_SIGKILL < now) { + _LOGW ("spawn: process %"G_PID_FORMAT" from pidfile %s is still here after trying to kill it. Wait no longer", gl_pid.kill_external_data->pid, PIDFILE); + goto process_gone; + } + } + + return G_SOURCE_CONTINUE; + +process_gone: + nm_shutdown_wait_obj_unregister (gl_pid.kill_external_data->shutdown_wait_handle); + g_slice_free (GlPidKillExternalData, g_steal_pointer (&gl_pid.kill_external_data)); + + _gl_pid_unlink_pidfile (TRUE); + + _gl_pid_spawn_next_step (); + + return G_SOURCE_REMOVE; +} + +static gboolean +_gl_pid_kill_external (void) +{ + gs_free char *contents = NULL; + gs_free char *cmdline_contents = NULL; + gs_free_error GError *error = NULL; + gint64 pid64; + GPid pid = 0; + guint64 p_start_time = 0; + char proc_path[256]; + gboolean do_kill = FALSE; + char p_state = '\0'; + gboolean do_unlink = TRUE; + int errsv; + + if (gl_pid.kill_external_done) { + if (gl_pid.kill_external_data) { + _LOGD ("spawn: waiting for external process %"G_PID_FORMAT" from pidfile %s quit", gl_pid.kill_external_data->pid, PIDFILE); + return FALSE; + } + return TRUE; + } + + if (!g_file_get_contents (PIDFILE, &contents, NULL, &error)) { + if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + do_unlink = FALSE; + _LOGD ("spawn: failure to read pidfile %s: %s", PIDFILE, error->message); + g_clear_error (&error); + goto handle_kill; + } + + pid64 = _nm_utils_ascii_str_to_int64 (contents, 10, 2, G_MAXINT64, -1); + if ( pid64 == -1 + || (pid = (GPid) pid64) != pid64) { + _LOGD ("spawn: pidfile %s does not contain a valid process identifier", PIDFILE); + goto handle_kill; + } + + G_STATIC_ASSERT_EXPR (sizeof (pid) == sizeof (pid_t)); + + p_start_time = nm_utils_get_start_time_for_pid (pid, &p_state, NULL); + if (p_start_time == 0) { + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s seems to no longer exist", pid, PIDFILE); + goto handle_kill; + } + + nm_sprintf_buf (proc_path, "/proc/%"G_PID_FORMAT"/cmdline", pid); + if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL)) { + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s seems to no longer exist", pid, PIDFILE); + goto handle_kill; + } + + if (!strstr (cmdline_contents, "/dnsmasq")) { + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s seems to no longer to be a dnsmasq process", pid, PIDFILE); + goto handle_kill; + } + + do_kill = TRUE; + +handle_kill: + + gl_pid.kill_external_done = TRUE; + + if (!do_kill) + return _gl_pid_unlink_pidfile (do_unlink); + + if (nm_utils_process_state_is_dead (p_state)) { + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s is already a zombie", pid, PIDFILE); + return _gl_pid_unlink_pidfile (do_unlink); + } + + if (kill (pid, SIGTERM) != 0) { + errsv = errno; + if (errsv == ESRCH) + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s no longer exists", pid, PIDFILE); + else + _LOGD ("spawn: process %"G_PID_FORMAT" from pidfile %s failed with \"%s\" (%d)", pid, PIDFILE, nm_strerror_native (errsv), errsv); + return _gl_pid_unlink_pidfile (do_unlink); + } + + _LOGD ("spawn: waiting for process %"G_PID_FORMAT" from pidfile %s to terminate after SIGTERM", pid, PIDFILE); + + gl_pid.kill_external_data = g_slice_new (GlPidKillExternalData); + *gl_pid.kill_external_data = (GlPidKillExternalData) { + .shutdown_wait_handle = nm_shutdown_wait_obj_register_handle_full (g_strdup_printf ("kill-external-dnsmasq-process-%"G_PID_FORMAT, pid), TRUE), + .started_at = nm_utils_get_monotonic_timestamp_ms (), + .pid = pid, + .p_start_time = p_start_time, + }; + g_timeout_add (50, _gl_pid_kill_external_timeout_cb, NULL); + return FALSE; +} + +/*****************************************************************************/ + +static gboolean +_gl_pid_spawn_clear_pid (void) +{ + gboolean was_stopping = !!gl_pid.terminate_handle; + + gl_pid.pid = 0; + gl_pid.terminate_sigkill = FALSE; + nm_clear_g_source (&gl_pid.watch_id); + nm_clear_g_source (&gl_pid.terminate_timeout_id); + nm_clear_pointer (&gl_pid.terminate_handle, nm_shutdown_wait_obj_unregister); + return was_stopping; +} + +static void +_gl_pid_spawn_register_for_termination (void) +{ + if ( gl_pid.pid > 0 + && !gl_pid.terminate_handle) { + /* Create a shtudown handle as a reminder that the currently running process must be terminated + * first. This also happens to block shutdown... */ + gl_pid.terminate_handle = nm_shutdown_wait_obj_register_handle_full (g_strdup_printf ("kill-dnsmasq-process-%"G_PID_FORMAT, gl_pid.pid), TRUE); + } +} + +/** + * _gl_pid_spawn_notify: + * @sdata: the notify data. @sdata might be destroyed by the function, + * depending on the other arguments (which indicate whether the + * task is complete). + * @pid: the PID to notify (argument for GlPidSpawnAsyncNotify) + * @p_exit_code: the exit code to notify (argument for GlPidSpawnAsyncNotify) + * @error: error reason to notify (argument for GlPidSpawnAsyncNotify) + * + * The GlPidSpawnAsyncNotify callback passed to _gl_pid_spawn() is used + * for two purposes: + * + * - signal that the dnsmasq process was spawned (or failed to be spawned). + * - signal that the dnsmasq process quit (if it was spawned sucessfully before). + * + * Depending on the arguments, the callee can see what's the case. + */ +static void +_gl_pid_spawn_notify (GlPidSpawnAsyncData *sdata, + GPid pid, + const int *p_exit_code, + GError *error) +{ + gboolean destroy = TRUE; + + nm_assert (sdata); + + if (error) { + nm_assert (pid == 0); + nm_assert (!p_exit_code); + if (!nm_utils_error_is_cancelled (error, FALSE)) + _LOGD ("spawn: dnsmasq failed: %s", error->message); + } else if (p_exit_code) { + /* the only caller already logged about this condition extensively. */ + nm_assert (pid > 0); + } else { + nm_assert (pid > 0); + _LOGD ("spawn: dnsmasq started with pid %"G_PID_FORMAT, pid); + destroy = FALSE; + } + + nm_assert ((!!destroy) == (sdata != gl_pid.spawn_data)); + + if (destroy) + g_signal_handlers_disconnect_by_func (sdata->cancellable, _gl_pid_spawn_cancelled_cb, sdata); + + sdata->notify (sdata->cancellable, + pid, + p_exit_code, + error, + sdata->notify_user_data); + + if (destroy) { + g_clear_object (&sdata->cancellable); + nm_g_slice_free (sdata); + } +} + +static void +_gl_pid_spawn_cancelled_cb (GCancellable *cancellable, + GlPidSpawnAsyncData *sdata) +{ + gs_free_error GError *error = NULL; + + if (sdata == gl_pid.spawn_data) { + gl_pid.spawn_data = NULL; + + /* When the cancellable gets cancelled, we terminate the current dnsmasq instance + * in the background. The only way for keeping dnsmasq running while unregistering + * the callback is by calling _gl_pid_spawn() without a new callback. */ + _gl_pid_spawn_register_for_termination (); + } else + nm_assert_not_reached (); + + if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) + nm_assert_not_reached (); + + _gl_pid_spawn_notify (sdata, 0, NULL, error); + + _gl_pid_spawn_next_step (); +} + +static gboolean +_gl_pid_spawn_terminate_timeout_cb (gpointer user_data) +{ + nm_assert (gl_pid.terminate_timeout_id != 0); + nm_assert (gl_pid.pid > 0); + nm_assert (gl_pid.terminate_handle); + nm_assert (gl_pid.watch_id != 0); + + gl_pid.terminate_timeout_id = 0; + + if (!gl_pid.terminate_sigkill) { + gl_pid.terminate_sigkill = TRUE; + _LOGD ("spawn: send SIGKILL signal to dnsmasq process %"G_PID_FORMAT" as it did not exit yet", gl_pid.pid); + kill (gl_pid.pid, SIGKILL); + gl_pid.terminate_timeout_id = g_timeout_add (WAIT_MSEC_AFTER_SIGKILL, _gl_pid_spawn_terminate_timeout_cb, NULL); + } else { + _LOGE ("spawn: process %"G_PID_FORMAT" did not exit even after SIGTERM and SIGKILL", gl_pid.pid); + + /* we don't unregister the watch. Just forget about it. We still want to reap the child eventually. */ + gl_pid.watch_id = 0; + + _gl_pid_spawn_clear_pid (); + _gl_pid_spawn_next_step (); + } + + return G_SOURCE_REMOVE; +} + +static void +_gl_pid_spawn_watch_cb (GPid pid, + int status, + gpointer user_data) +{ + int err; + gboolean was_stopping; + + nm_assert (pid > 0); + + if (WIFEXITED (status)) { + err = WEXITSTATUS (status); + if (err) { + char sbuf[100]; + + _LOGW ("spawn: dnsmasq process %"G_PID_FORMAT" exited with error: %s", + pid, nm_utils_dnsmasq_status_to_string (err, sbuf, sizeof (sbuf))); + } else + _LOGD ("spawn: dnsmasq process %"G_PID_FORMAT" exited normally", pid); + } else if (WIFSTOPPED (status)) + _LOGW ("spawn: dnsmasq process %"G_PID_FORMAT" stopped unexpectedly with signal %d", pid, WSTOPSIG (status)); + else if (WIFSIGNALED (status)) + _LOGW ("spawn: dnsmasq process %"G_PID_FORMAT" died with signal %d", pid, WTERMSIG (status)); + else + _LOGW ("spawn: dnsmasq process %"G_PID_FORMAT" died from an unknown cause (status %d)", pid, status); + + if (gl_pid.pid != pid) { + /* this can only happen, if we timed out and no longer care about this PID. + * We still kept the watch-id active, to reap the process. Nothing to do. */ + return; + } + + nm_assert (gl_pid.watch_id != 0); + + gl_pid.watch_id = 0; + + _gl_pid_unlink_pidfile (TRUE); + + was_stopping = _gl_pid_spawn_clear_pid (); + + if (gl_pid.spawn_data) { + if (was_stopping) { + /* The current process was scheduled to be terminated. That means the pending + * spawn_data is not for that former instance, but for starting a new one. + * This spawn-request is not yet complete, instead it's just about to start. */ + } else + _gl_pid_spawn_notify (g_steal_pointer (&gl_pid.spawn_data), pid, &status, NULL); + } + + _gl_pid_spawn_next_step (); +} + +/** + * _gl_pid_spawn_next_step: + * + * The state about a running dnsmasq process is tracked in @gl_pid. There are + * various things that can happen + * + * - user calls _gl_pid_spawn() -- which might terminate an existing run first. + * - user might cancel the GCancellable -- which would abort the spawning or + * kill the current instance. + * - the child process might exit. + * + * In all these cases, we call _gl_pid_spawn_next_step() to check what to do next. + */ +static void +_gl_pid_spawn_next_step (void) +{ + gs_free_error GError *error = NULL; + const char *argv[15]; + GPid pid = 0; + guint argv_idx; + + if (!_gl_pid_kill_external ()) { + /* we need to wait to kill the instance from the PID file first. */ + return; + } + + if (gl_pid.terminate_handle) { + + nm_assert (gl_pid.pid > 0); + + if (gl_pid.terminate_timeout_id == 0) { + _LOGD ("spawn: send SIGTERM signal to process %"G_PID_FORMAT, gl_pid.pid); + gl_pid.terminate_timeout_id = g_timeout_add (WAIT_MSEC_AFTER_SIGTERM, _gl_pid_spawn_terminate_timeout_cb, NULL); + kill (gl_pid.pid, SIGTERM); + } + + /* we can only wait for the process to exit. */ + return; + } + + if (!gl_pid.spawn_data) { + /* we are not requested to spawn another process. */ + nm_assert (gl_pid.pid == 0); + return; + } + + if (gl_pid.pid > 0) { + /* the process we desire is already running. All good. */ + return; + } + + argv_idx = 0; + argv[argv_idx++] = gl_pid.spawn_data->dm_binary; + argv[argv_idx++] = "--no-resolv"; /* Use only commandline */ + argv[argv_idx++] = "--keep-in-foreground"; + argv[argv_idx++] = "--no-hosts"; /* don't use /etc/hosts to resolve */ + argv[argv_idx++] = "--bind-interfaces"; + argv[argv_idx++] = "--pid-file=" PIDFILE; + argv[argv_idx++] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */ + argv[argv_idx++] = "--cache-size=400"; + argv[argv_idx++] = "--clear-on-reload"; /* clear cache when dns server changes */ + argv[argv_idx++] = "--conf-file=/dev/null"; /* avoid loading /etc/dnsmasq.conf */ + argv[argv_idx++] = "--proxy-dnssec"; /* Allow DNSSEC to pass through */ + argv[argv_idx++] = "--enable-dbus=" DNSMASQ_DBUS_SERVICE; + + /* dnsmasq exits if the conf dir is not present */ + if (g_file_test (CONFDIR, G_FILE_TEST_IS_DIR)) + argv[argv_idx++] = "--conf-dir=" CONFDIR; + + argv[argv_idx++] = NULL; + nm_assert (argv_idx <= G_N_ELEMENTS (argv)); + + if (!_LOGD_ENABLED ()) + _LOGI ("starting %s", gl_pid.spawn_data->dm_binary); + else { + gs_free char *cmdline = NULL; + + _LOGD ("spawn: starting dnsmasq: %s", + (cmdline = g_strjoinv (" ", (char **) argv))); + } + + if (!g_spawn_async (NULL, + (char **) argv, + NULL, + G_SPAWN_DO_NOT_REAP_CHILD, + nm_utils_setpgid, + NULL, + &pid, + &error)) { + _gl_pid_spawn_notify (g_steal_pointer (&gl_pid.spawn_data), 0, NULL, error); + return; + } + + gl_pid.pid = pid; + gl_pid.watch_id = g_child_watch_add (pid, _gl_pid_spawn_watch_cb, NULL); + + _gl_pid_spawn_notify (gl_pid.spawn_data, pid, NULL, NULL); +} + +/** + * _gl_pid_spawn: + * @dm_binary: the binary name for dnsmasq to spawn. We could + * detect it ad-hoc right when needing it. But that would be + * asynchronously, and if dnsmasq is not in $PATH, we want to + * fail right away (synchrounously). Hence, @dm_binary is + * an argument. + * @cancellable: abort the operation. This will invoke the callback + * a last time. Also, if the dnsmasq process is currently running, + * it will be terminated in the background. To unregister a notify + * call without killing the dnsmasq process, call _gl_pid_spawn() + * again with all arguments %NULL. + * @notify: the callback when the process is started successfully + * and when the process terminates. + * @notify_user_data: user-data for callback. + * + * If a dnsmasq process is already running (from a previous call of + * _gl_pid_spawn()), that one will be replaced. Meaning, the other notify + * callback will be invoked with NM_UTILS_ERROR/NM_UTILS_ERROR_CANCELLED_DISPOSING. + * If you the @dm_binary argument, the previously running process will + * also be terminated first, before spawning a new instance. + * However, you may also pass all arguments as %NULL. In that case, the + * previous @notify will be completed (and forgotten), but the dnsmasq + * process will be left running in the background. + * + * So, you can: + * + * - call _gl_pid_spawn() with a @dm_binary argument. The previous + * notify() completes with NM_UTILS_ERROR_CANCELLED_DISPOSING and + * the dnsmasq process gets killed. + * - cancel the GCancellable, in this case the notify() completes + * with G_IO_ERROR_CANCELLED and the dnsmasq process gets killed. + * - call _gl_pid_spawn() with all arguments %NULL. In that case + * the previous notify() completes with NM_UTILS_ERROR_CANCELLED_DISPOSING + * but the dnsmasq process keeps running in the background. + * + * The callback is used in two cases. + * - When spawning the process it will be invoked always exactly once. + * In this case the callback might be invoked synchronously or + * asynchronously. + * This either provides a PID or a failure reason. In case of a + * failure, that's the end and the process is not running. + * - if the process could be spawned, the child process with the + * provided PID gets monitored. When the process exits, the callback + * will be invoked again, with a failure reason. This is always done + * asynchronously. + */ +static void +_gl_pid_spawn (const char *dm_binary, + GCancellable *cancellable, + GlPidSpawnAsyncNotify notify, + gpointer notify_user_data) +{ + GlPidSpawnAsyncData *sdata_replace; + + sdata_replace = g_steal_pointer (&gl_pid.spawn_data); + + if (dm_binary) { + nm_assert (notify); + nm_assert (G_IS_CANCELLABLE (cancellable)); + gl_pid.spawn_data = g_slice_new (GlPidSpawnAsyncData); + *gl_pid.spawn_data = (GlPidSpawnAsyncData) { + .dm_binary = dm_binary, + .notify = notify, + .notify_user_data = notify_user_data, + .cancellable = g_object_ref (cancellable), + }; + g_signal_connect (cancellable, "cancelled", G_CALLBACK (_gl_pid_spawn_cancelled_cb), gl_pid.spawn_data); + + /* If dnsmasq is running, we terminate it and start a new instance. + * + * If the user would not provide a new callback, this would mean to fail/abort + * the currently subscribed notification (below). But it would leave the dnsmasq + * instance running in the background. + * This allows the user to say to not care about the current instance + * anymore, but still leave it running. + * + * To kill the dnsmasq process without scheduling a new one, cancel the cancellable + * instead. */ + _gl_pid_spawn_register_for_termination (); + } else { + nm_assert (!notify); + nm_assert (!cancellable); + nm_assert (!notify_user_data); + } + + if (sdata_replace) { + gs_free_error GError *error = NULL; + + /* we don't mark the error as G_IO_ERROR/G_IO_ERROR_CANCELLED. That + * is reserved for cancelling the cancellable. However, the current + * request was obsoleted/replaced by a new one, so we fail it with + * NM_UTILS_ERROR/NM_UTILS_ERROR_CANCELLED_DISPOSING. */ + nm_utils_error_set_cancelled (&error, TRUE, NULL); + _gl_pid_spawn_notify (sdata_replace, 0, NULL, error); + } + + _gl_pid_spawn_next_step (); +} + +/*****************************************************************************/ + +typedef struct { + + GDBusConnection *dbus_connection; GVariant *set_server_ex_args; + + GCancellable *update_cancellable; + + GCancellable *main_cancellable; + + char *name_owner; + + gint64 burst_start_at; + + GPid process_pid; + + guint name_owner_changed_id; + guint main_timeout_id; + + guint burst_retry_timeout_id; + + guint8 burst_count; + + bool is_stopped:1; + } NMDnsDnsmasqPrivate; struct _NMDnsDnsmasq { @@ -69,11 +679,15 @@ G_DEFINE_TYPE (NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN) /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_DNS +#undef _NMLOG #define _NMLOG(level, ...) __NMLOG_DEFAULT_WITH_ADDR (level, _NMLOG_DOMAIN, "dnsmasq", __VA_ARGS__) /*****************************************************************************/ +static gboolean start_dnsmasq (NMDnsDnsmasq *self, gboolean force_start, GError **error); + +/*****************************************************************************/ + static void add_dnsmasq_nameserver (NMDnsDnsmasq *self, GVariantBuilder *servers, @@ -192,19 +806,42 @@ add_ip_config (NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfig } } +static GVariant * +create_update_args (NMDnsDnsmasq *self, + const NMGlobalDnsConfig *global_config, + const CList *ip_config_lst_head, + const char *hostname) +{ + GVariantBuilder servers; + const NMDnsIPConfigData *ip_data; + + g_variant_builder_init (&servers, G_VARIANT_TYPE ("aas")); + + if (global_config) + add_global_config (self, &servers, global_config); + else { + c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) + add_ip_config (self, &servers, ip_data); + } + + return g_variant_new ("(aas)", &servers); +} + +/*****************************************************************************/ + static void -dnsmasq_update_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) +dnsmasq_update_done (GObject *source_object, GAsyncResult *res, gpointer user_data) { NMDnsDnsmasq *self; gs_free_error GError *error = NULL; gs_unref_variant GVariant *response = NULL; - response = g_dbus_proxy_call_finish (proxy, res, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; + response = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); - self = NM_DNS_DNSMASQ (user_data); + if (nm_utils_error_is_cancelled (error, FALSE)) + return; + self = user_data; if (!response) _LOGW ("dnsmasq update failed: %s", error->message); else @@ -216,238 +853,287 @@ send_dnsmasq_update (NMDnsDnsmasq *self) { NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - if (!priv->set_server_ex_args) - return; + if ( !priv->name_owner + || !priv->set_server_ex_args) + return; - if (priv->running) { - _LOGD ("trying to update dnsmasq nameservers"); - - nm_clear_g_cancellable (&priv->update_cancellable); - priv->update_cancellable = g_cancellable_new (); - - g_dbus_proxy_call (priv->dnsmasq, - "SetServersEx", - priv->set_server_ex_args, - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->update_cancellable, - (GAsyncReadyCallback) dnsmasq_update_done, - self); - g_clear_pointer (&priv->set_server_ex_args, g_variant_unref); - } else - _LOGD ("dnsmasq not found on the bus. The nameserver update will be sent when dnsmasq appears"); + _LOGD ("trying to update dnsmasq nameservers"); + + nm_clear_g_cancellable (&priv->update_cancellable); + priv->update_cancellable = g_cancellable_new (); + + g_dbus_connection_call (priv->dbus_connection, + priv->name_owner, + DNSMASQ_DBUS_PATH, + DNSMASQ_DBUS_SERVICE, + "SetServersEx", + priv->set_server_ex_args, + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 20000, + priv->update_cancellable, + dnsmasq_update_done, + self); } +/*****************************************************************************/ + static void -name_owner_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) +_main_cleanup (NMDnsDnsmasq *self, gboolean emit_failed) { - NMDnsDnsmasq *self = NM_DNS_DNSMASQ (user_data); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - gs_free char *owner = NULL; - owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)); - if (owner) { - _LOGI ("dnsmasq appeared as %s", owner); - priv->running = TRUE; + if (!priv->main_cancellable) + return; + + priv->process_pid = 0; + nm_clear_g_free (&priv->name_owner); + + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); + + nm_clear_g_source (&priv->main_timeout_id); + nm_clear_g_cancellable (&priv->update_cancellable); + + /* cancelling the main_cancellable will also cause _gl_pid_spawn*() to terminate the + * process in the background. */ + nm_clear_g_cancellable (&priv->main_cancellable); + + if ( !priv->is_stopped + && priv->burst_retry_timeout_id == 0) { + start_dnsmasq (self, FALSE, NULL); send_dnsmasq_update (self); - } else { - if (priv->running) { - _LOGI ("dnsmasq disappeared"); - priv->running = FALSE; - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); - } else { - /* The only reason for which (!priv->running) here - * is that the dnsmasq process quit. We don't care - * of that here, the manager handles child restarts - * by itself. */ - } } } static void -dnsmasq_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data) +name_owner_changed (NMDnsDnsmasq *self, + const char *name_owner) { - NMDnsDnsmasq *self; - NMDnsDnsmasqPrivate *priv; - gs_free_error GError *error = NULL; - gs_free char *owner = NULL; - GDBusProxy *proxy; + NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - proxy = g_dbus_proxy_new_finish (res, &error); - if ( !proxy - && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + name_owner = nm_str_not_empty (name_owner); + + if (nm_streq0 (priv->name_owner, name_owner)) return; - self = NM_DNS_DNSMASQ (user_data); + g_free (priv->name_owner); + priv->name_owner = g_strdup (name_owner); - if (!proxy) { - _LOGW ("failed to connect to dnsmasq via DBus: %s", error->message); - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); + if (!name_owner) { + _LOGT ("D-Bus name for dnsmasq disappeared"); + _main_cleanup (self, TRUE); return; } - priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); + _LOGT ("D-Bus name for dnsmasq got owner %s", name_owner); + nm_clear_g_source (&priv->main_timeout_id); + send_dnsmasq_update (self); +} + +static void +name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + NMDnsDnsmasq *self = user_data; + const char *new_owner; - priv->dnsmasq = proxy; - nm_clear_g_cancellable (&priv->dnsmasq_cancellable); + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) + return; - _LOGD ("dnsmasq proxy creation successful"); + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); - g_signal_connect (priv->dnsmasq, "notify::g-name-owner", - G_CALLBACK (name_owner_changed), self); - owner = g_dbus_proxy_get_name_owner (priv->dnsmasq); - priv->running = (owner != NULL); + name_owner_changed (self, new_owner); +} - if (priv->running) - send_dnsmasq_update (self); +static void +get_name_owner_cb (const char *name_owner, + GError *error, + gpointer user_data) +{ + if ( !name_owner + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + name_owner_changed (user_data, name_owner); +} + +static gboolean +spawn_timeout_cb (gpointer user_data) +{ + NMDnsDnsmasq *self = user_data; + + _LOGW ("timeout waiting for dnsmasq to appear on D-Bus"); + _main_cleanup (self, TRUE); + return G_SOURCE_REMOVE; } static void -start_dnsmasq (NMDnsDnsmasq *self) +spawn_notify (GCancellable *cancellable, + GPid pid, + const int *p_exit_code, + GError *error, + gpointer notify_user_data) { - NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - const char *dm_binary; - const char *argv[15]; - GPid pid = 0; - guint idx = 0; + NMDnsDnsmasq *self; + NMDnsDnsmasqPrivate *priv; - if (priv->running) { - /* the dnsmasq process is running. Nothing to do. */ + if (nm_utils_error_is_cancelled (error, FALSE)) return; - } - if (nm_dns_plugin_child_pid ((NMDnsPlugin *) self) > 0) { - /* if we already have a child process spawned, don't do - * it again. */ + self = notify_user_data; + priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); + if ( error + || p_exit_code) { + _main_cleanup (self, TRUE); return; } + nm_assert (pid > 0); + priv->process_pid = pid; + + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + DNSMASQ_DBUS_SERVICE, + name_owner_changed_cb, + self, + NULL); + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + DNSMASQ_DBUS_SERVICE, + -1, + priv->main_cancellable, + get_name_owner_cb, + self); +} + +static gboolean +_burst_retry_timeout_cb (gpointer user_data) +{ + NMDnsDnsmasq *self = user_data; + NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); + + priv->burst_retry_timeout_id = 0; + + start_dnsmasq (self, TRUE, NULL); + send_dnsmasq_update (self); + return G_SOURCE_REMOVE; +} + +static gboolean +start_dnsmasq (NMDnsDnsmasq *self, gboolean force_start, GError **error) +{ + NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); + const char *dm_binary; + gint64 now; + + if (G_LIKELY (priv->main_cancellable)) { + /* The process is already running or about to be started. Nothing to do. */ + return TRUE; + } + dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, NULL); if (!dm_binary) { - _LOGW ("could not find dnsmasq binary"); - return; + /* We resolve the binary name before trying to start it asynchronously. + * The reason is, that if dnsmasq is not installed, we want to fail early, + * so that NMDnsManager can fallback to a non-caching implementation. */ + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "could not find dnsmasq binary"); + return FALSE; } - argv[idx++] = dm_binary; - argv[idx++] = "--no-resolv"; /* Use only commandline */ - argv[idx++] = "--keep-in-foreground"; - argv[idx++] = "--no-hosts"; /* don't use /etc/hosts to resolve */ - argv[idx++] = "--bind-interfaces"; - argv[idx++] = "--pid-file=" PIDFILE; - argv[idx++] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */ - argv[idx++] = "--cache-size=400"; - argv[idx++] = "--clear-on-reload"; /* clear cache when dns server changes */ - argv[idx++] = "--conf-file=/dev/null"; /* avoid loading /etc/dnsmasq.conf */ - argv[idx++] = "--proxy-dnssec"; /* Allow DNSSEC to pass through */ - argv[idx++] = "--enable-dbus=" DNSMASQ_DBUS_SERVICE; - - /* dnsmasq exits if the conf dir is not present */ - if (g_file_test (CONFDIR, G_FILE_TEST_IS_DIR)) - argv[idx++] = "--conf-dir=" CONFDIR; + if (!priv->dbus_connection) { + priv->dbus_connection = nm_g_object_ref (NM_MAIN_DBUS_CONNECTION_GET); + if (!priv->dbus_connection) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "no D-Bus connection available to talk to dnsmasq"); + return FALSE; + } + } - argv[idx++] = NULL; - nm_assert (idx <= G_N_ELEMENTS (argv)); + now = nm_utils_get_monotonic_timestamp_ms (); + if ( force_start + || priv->burst_start_at == 0 + || priv->burst_start_at + RATELIMIT_INTERVAL_MSEC <= now) { + priv->burst_start_at = now; + priv->burst_count = 1; + nm_clear_g_source (&priv->burst_retry_timeout_id); + _LOGT ("rate-limit: start burst interval of %d seconds %s", + RATELIMIT_INTERVAL_MSEC / 1000, + force_start ? " (force)" : ""); + } else if (priv->burst_count < RATELIMIT_BURST) { + nm_assert (priv->burst_retry_timeout_id == 0); + priv->burst_count++; + _LOGT ("rate-limit: %u try within burst interval of %d seconds", + (guint) priv->burst_count, + RATELIMIT_INTERVAL_MSEC / 1000); + } else { + if (priv->burst_retry_timeout_id == 0) { + _LOGW ("dnsmasq dies and gets respawned too quickly. Back off. Something is very wrong"); + priv->burst_retry_timeout_id = g_timeout_add_seconds ((2 * RATELIMIT_INTERVAL_MSEC) / 1000, _burst_retry_timeout_cb, self); + } else + _LOGT ("rate-limit: currently rate-limited from restart"); + return TRUE; + } - /* And finally spawn dnsmasq */ - pid = nm_dns_plugin_child_spawn (NM_DNS_PLUGIN (self), argv, PIDFILE, "bin/dnsmasq"); - if (!pid) - return; + priv->main_timeout_id = g_timeout_add (10000, + spawn_timeout_cb, + self); - if ( priv->dnsmasq - || priv->dnsmasq_cancellable) { - /* we already have a proxy or are about to create it. - * We are done. */ - return; - } + priv->main_cancellable = g_cancellable_new (); - priv->dnsmasq_cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - DNSMASQ_DBUS_SERVICE, - DNSMASQ_DBUS_PATH, - DNSMASQ_DBUS_SERVICE, - priv->dnsmasq_cancellable, - dnsmasq_proxy_cb, - self); + _gl_pid_spawn (dm_binary, + priv->main_cancellable, + spawn_notify, + self); + return TRUE; } static gboolean update (NMDnsPlugin *plugin, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname) + const char *hostname, + GError **error) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - GVariantBuilder servers; - const NMDnsIPConfigData *ip_data; - - start_dnsmasq (self); - - g_variant_builder_init (&servers, G_VARIANT_TYPE ("aas")); - if (global_config) - add_global_config (self, &servers, global_config); - else { - c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) - add_ip_config (self, &servers, ip_data); - } + if (!start_dnsmasq (self, TRUE, error)) + return FALSE; - g_clear_pointer (&priv->set_server_ex_args, g_variant_unref); - priv->set_server_ex_args = g_variant_ref_sink (g_variant_new ("(aas)", &servers)); + nm_clear_pointer (&priv->set_server_ex_args, g_variant_unref); + priv->set_server_ex_args = g_variant_ref_sink (create_update_args (self, + global_config, + ip_config_lst_head, + hostname)); send_dnsmasq_update (self); - return TRUE; } /*****************************************************************************/ static void -child_quit (NMDnsPlugin *plugin, int status) +stop (NMDnsPlugin *plugin) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - gboolean failed = TRUE; - int err; - - if (WIFEXITED (status)) { - err = WEXITSTATUS (status); - if (err) { - _LOGW ("dnsmasq exited with error: %s", - nm_utils_dnsmasq_status_to_string (err, NULL, 0)); - } else { - _LOGD ("dnsmasq exited normally"); - failed = FALSE; - } - } else if (WIFSTOPPED (status)) - _LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); - else if (WIFSIGNALED (status)) - _LOGW ("dnsmasq died with signal %d", WTERMSIG (status)); - else - _LOGW ("dnsmasq died from an unknown cause"); - - priv->running = FALSE; - - if (failed) - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); -} - -/*****************************************************************************/ -static gboolean -is_caching (NMDnsPlugin *plugin) -{ - return TRUE; -} + priv->is_stopped = TRUE; + priv->burst_start_at = 0; + nm_clear_g_source (&priv->burst_retry_timeout_id); -static const char * -get_name (NMDnsPlugin *plugin) -{ - return "dnsmasq"; + /* Cancelling the cancellable will also terminate the + * process (in the background). */ + _main_cleanup (self, FALSE); } /*****************************************************************************/ @@ -466,16 +1152,20 @@ nm_dns_dnsmasq_new (void) static void dispose (GObject *object) { - NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE ((NMDnsDnsmasq *) object); + NMDnsDnsmasq *self = NM_DNS_DNSMASQ (object); + NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - nm_clear_g_cancellable (&priv->dnsmasq_cancellable); - nm_clear_g_cancellable (&priv->update_cancellable); + priv->is_stopped = TRUE; - g_clear_object (&priv->dnsmasq); + nm_clear_g_source (&priv->burst_retry_timeout_id); + + _main_cleanup (self, FALSE); g_clear_pointer (&priv->set_server_ex_args, g_variant_unref); G_OBJECT_CLASS (nm_dns_dnsmasq_parent_class)->dispose (object); + + g_clear_object (&priv->dbus_connection); } static void @@ -486,8 +1176,8 @@ nm_dns_dnsmasq_class_init (NMDnsDnsmasqClass *dns_class) object_class->dispose = dispose; - plugin_class->child_quit = child_quit; - plugin_class->is_caching = is_caching; - plugin_class->update = update; - plugin_class->get_name = get_name; + plugin_class->plugin_name = "dnsmasq"; + plugin_class->is_caching = TRUE; + plugin_class->stop = stop; + plugin_class->update = update; } diff --git a/src/dns/nm-dns-dnsmasq.h b/src/dns/nm-dns-dnsmasq.h index 7623d167..579e7686 100644 --- a/src/dns/nm-dns-dnsmasq.h +++ b/src/dns/nm-dns-dnsmasq.h @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. */ diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 2c55bee9..c7ca0b47 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -1,23 +1,8 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com> * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. - * and others */ #include "nm-default.h" @@ -63,10 +48,6 @@ #define NETCONFIG_PATH "/sbin/netconfig" #endif -#define PLUGIN_RATELIMIT_INTERVAL 30 -#define PLUGIN_RATELIMIT_BURST 5 -#define PLUGIN_RATELIMIT_DELAY 300 - /*****************************************************************************/ typedef enum { @@ -1441,13 +1422,15 @@ update_dns (NMDnsManager *self, nm_dns_plugin_update (priv->sd_resolve_plugin, global_config, _ip_config_lst_head (self), - priv->hostname); + priv->hostname, + NULL); } /* Let any plugins do their thing first */ if (priv->plugin) { NMDnsPlugin *plugin = priv->plugin; const char *plugin_name = nm_dns_plugin_get_name (plugin); + gs_free_error GError *plugin_error = NULL; if (nm_dns_plugin_is_caching (plugin)) { if (no_caching) { @@ -1462,8 +1445,9 @@ update_dns (NMDnsManager *self, if (!nm_dns_plugin_update (plugin, global_config, _ip_config_lst_head (self), - priv->hostname)) { - _LOGW ("update-dns: plugin %s update failed", plugin_name); + priv->hostname, + &plugin_error)) { + _LOGW ("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message); /* If the plugin failed to update, we shouldn't write out a local * caching DNS configuration to resolv.conf. @@ -1567,66 +1551,7 @@ update_dns (NMDnsManager *self, return !update || result == SR_SUCCESS; } -static void -plugin_failed (NMDnsPlugin *plugin, gpointer user_data) -{ - NMDnsManager *self = NM_DNS_MANAGER (user_data); - GError *error = NULL; - - /* Errors with non-caching plugins aren't fatal */ - if (!nm_dns_plugin_is_caching (plugin)) - return; - - /* Disable caching until the next DNS update */ - if (!update_dns (self, TRUE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } -} - -static gboolean -plugin_child_quit_update_dns (gpointer user_data) -{ - GError *error = NULL; - NMDnsManager *self = NM_DNS_MANAGER (user_data); - - /* Let the plugin try to spawn the child again */ - if (!update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } - - return G_SOURCE_REMOVE; -} - -static void -plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data) -{ - NMDnsManager *self = NM_DNS_MANAGER (user_data); - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - gint64 ts = nm_utils_get_monotonic_timestamp_ms (); - - _LOGW ("plugin %s child quit unexpectedly", nm_dns_plugin_get_name (plugin)); - - if ( !priv->plugin_ratelimit.ts - || (ts - priv->plugin_ratelimit.ts) / 1000 > PLUGIN_RATELIMIT_INTERVAL) { - priv->plugin_ratelimit.ts = ts; - priv->plugin_ratelimit.num_restarts = 0; - } else { - priv->plugin_ratelimit.num_restarts++; - if (priv->plugin_ratelimit.num_restarts > PLUGIN_RATELIMIT_BURST) { - plugin_failed (plugin, self); - _LOGW ("plugin %s child respawning too fast, delaying update for %u seconds", - nm_dns_plugin_get_name (plugin), PLUGIN_RATELIMIT_DELAY); - priv->plugin_ratelimit.timer = g_timeout_add_seconds (PLUGIN_RATELIMIT_DELAY, - plugin_child_quit_update_dns, - self); - return; - } - } - - plugin_child_quit_update_dns (self); -} +/*****************************************************************************/ static void _ip_config_dns_priority_changed (gpointer config, @@ -1856,15 +1781,14 @@ _clear_plugin (NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + priv->plugin_ratelimit.ts = 0; + nm_clear_g_source (&priv->plugin_ratelimit.timer); + if (priv->plugin) { - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self); - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self); nm_dns_plugin_stop (priv->plugin); g_clear_object (&priv->plugin); return TRUE; } - priv->plugin_ratelimit.ts = 0; - nm_clear_g_source (&priv->plugin_ratelimit.timer); return FALSE; } @@ -2083,12 +2007,6 @@ again: } else if (nm_clear_g_object (&priv->sd_resolve_plugin)) systemd_resolved_changed = TRUE; - if ( plugin_changed - && priv->plugin) { - g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); - g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self); - } - g_object_freeze_notify (G_OBJECT (self)); if (!nm_streq0 (priv->mode, mode)) { diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h index 1cb2c669..2a0c9dee 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/dns/nm-dns-manager.h @@ -1,23 +1,8 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com> * Copyright (C) 2004 - 2013 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. - * and others */ #ifndef __NETWORKMANAGER_DNS_MANAGER_H__ diff --git a/src/dns/nm-dns-plugin.c b/src/dns/nm-dns-plugin.c index 582abc62..c8876f1e 100644 --- a/src/dns/nm-dns-plugin.c +++ b/src/dns/nm-dns-plugin.c @@ -1,19 +1,6 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 - 2012 Red Hat, Inc. - * */ #include "nm-default.h" @@ -30,14 +17,6 @@ /*****************************************************************************/ -enum { - FAILED, - CHILD_QUIT, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - typedef struct _NMDnsPluginPrivate { GPid pid; guint watch_id; @@ -45,7 +24,7 @@ typedef struct _NMDnsPluginPrivate { char *pidfile; } NMDnsPluginPrivate; -G_DEFINE_TYPE_EXTENDED (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {}) +G_DEFINE_ABSTRACT_TYPE (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT) #define NM_DNS_PLUGIN_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMDnsPlugin, NM_IS_DNS_PLUGIN) @@ -77,188 +56,46 @@ gboolean nm_dns_plugin_update (NMDnsPlugin *self, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname) + const char *hostname, + GError **error) { g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE); return NM_DNS_PLUGIN_GET_CLASS (self)->update (self, global_config, ip_config_lst_head, - hostname); -} - -static gboolean -is_caching (NMDnsPlugin *self) -{ - return FALSE; + hostname, + error); } gboolean nm_dns_plugin_is_caching (NMDnsPlugin *self) { - return NM_DNS_PLUGIN_GET_CLASS (self)->is_caching (self); + return NM_DNS_PLUGIN_GET_CLASS (self)->is_caching; } const char * nm_dns_plugin_get_name (NMDnsPlugin *self) { - g_assert (NM_DNS_PLUGIN_GET_CLASS (self)->get_name); - return NM_DNS_PLUGIN_GET_CLASS (self)->get_name (self); -} + NMDnsPluginClass *klass; -/*****************************************************************************/ + g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), NULL); -static void -_clear_pidfile (NMDnsPlugin *self) -{ - NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); - - if (priv->pidfile) { - unlink (priv->pidfile); - g_clear_pointer (&priv->pidfile, g_free); - } -} - -static void -kill_existing (const char *progname, const char *pidfile, const char *kill_match) -{ - long pid; - gs_free char *contents = NULL; - gs_free char *cmdline_contents = NULL; - guint64 start_time; - char proc_path[256]; - gs_free_error GError *error = NULL; - - if (!pidfile) - return; - - if (!kill_match) - g_return_if_reached (); - - if (!g_file_get_contents (pidfile, &contents, NULL, &error)) { - if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) - return; - goto out; - } - - pid = _nm_utils_ascii_str_to_int64 (contents, 10, 2, INT_MAX, -1); - if (pid == -1) - goto out; - - start_time = nm_utils_get_start_time_for_pid (pid, NULL, NULL); - if (start_time == 0) - goto out; - - nm_sprintf_buf (proc_path, "/proc/%ld/cmdline", pid); - if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL)) - goto out; - - if (!strstr (cmdline_contents, kill_match)) - goto out; - - nm_utils_kill_process_sync (pid, start_time, SIGKILL, _NMLOG_DOMAIN, - progname ?: "<dns-process>", - 0, 0, 1000); - -out: - unlink (pidfile); -} - -static void -watch_cb (GPid pid, int status, gpointer user_data) -{ - NMDnsPlugin *self = NM_DNS_PLUGIN (user_data); - NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); - - priv->pid = 0; - priv->watch_id = 0; - g_clear_pointer (&priv->progname, g_free); - _clear_pidfile (self); - - g_signal_emit (self, signals[CHILD_QUIT], 0, status); -} - -GPid -nm_dns_plugin_child_pid (NMDnsPlugin *self) -{ - NMDnsPluginPrivate *priv; - - g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), 0); - - priv = NM_DNS_PLUGIN_GET_PRIVATE (self); - return priv->pid; -} - -GPid -nm_dns_plugin_child_spawn (NMDnsPlugin *self, - const char **argv, - const char *pidfile, - const char *kill_match) -{ - NMDnsPluginPrivate *priv; - GError *error = NULL; - GPid pid; - gs_free char *cmdline = NULL; - gs_free char *progname = NULL; - - g_return_val_if_fail (argv && argv[0], 0); - g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), 0); - - priv = NM_DNS_PLUGIN_GET_PRIVATE (self); - - g_return_val_if_fail (!priv->pid, 0); - nm_assert (!priv->progname); - nm_assert (!priv->watch_id); - nm_assert (!priv->pidfile); - - progname = g_path_get_basename (argv[0]); - kill_existing (progname, pidfile, kill_match); - - _LOGI ("starting %s...", progname); - _LOGD ("command line: %s", - (cmdline = g_strjoinv (" ", (char **) argv))); - - if (!g_spawn_async (NULL, (char **) argv, NULL, - G_SPAWN_DO_NOT_REAP_CHILD, - nm_utils_setpgid, NULL, - &pid, - &error)) { - _LOGW ("failed to spawn %s: %s", - progname, error->message); - g_clear_error (&error); - return 0; - } - - _LOGD ("%s started with pid %d", progname, pid); - priv->watch_id = g_child_watch_add (pid, (GChildWatchFunc) watch_cb, self); - priv->pid = pid; - priv->progname = g_steal_pointer (&progname); - priv->pidfile = g_strdup (pidfile); - - return pid; -} - -gboolean -nm_dns_plugin_child_kill (NMDnsPlugin *self) -{ - NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); - - nm_clear_g_source (&priv->watch_id); - if (priv->pid) { - nm_utils_kill_child_sync (priv->pid, SIGTERM, _NMLOG_DOMAIN, - priv->progname ?: "<dns-process>", NULL, 1000, 0); - priv->pid = 0; - g_clear_pointer (&priv->progname, g_free); - } - _clear_pidfile (self); - - return TRUE; + klass = NM_DNS_PLUGIN_GET_CLASS (self); + nm_assert (klass->plugin_name); + return klass->plugin_name; } void nm_dns_plugin_stop (NMDnsPlugin *self) { - nm_dns_plugin_child_kill (self); + NMDnsPluginClass *klass; + + g_return_if_fail (NM_IS_DNS_PLUGIN (self)); + + klass = NM_DNS_PLUGIN_GET_CLASS (self); + if (klass->stop) + klass->stop (self); } /*****************************************************************************/ @@ -266,49 +103,9 @@ nm_dns_plugin_stop (NMDnsPlugin *self) static void nm_dns_plugin_init (NMDnsPlugin *self) { - self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DNS_PLUGIN, NMDnsPluginPrivate); -} - -static void -dispose (GObject *object) -{ - NMDnsPlugin *self = NM_DNS_PLUGIN (object); - - nm_dns_plugin_stop (self); - - G_OBJECT_CLASS (nm_dns_plugin_parent_class)->dispose (object); } static void nm_dns_plugin_class_init (NMDnsPluginClass *plugin_class) { - GObjectClass *object_class = G_OBJECT_CLASS (plugin_class); - - g_type_class_add_private (plugin_class, sizeof (NMDnsPluginPrivate)); - - object_class->dispose = dispose; - - plugin_class->is_caching = is_caching; - - /* Emitted by the plugin and consumed by NMDnsManager when - * some error happens with the nameserver subprocess. Causes NM to fall - * back to writing out a non-local-caching resolv.conf until the next - * DNS update. - */ - signals[FAILED] = - g_signal_new (NM_DNS_PLUGIN_FAILED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[CHILD_QUIT] = - g_signal_new (NM_DNS_PLUGIN_CHILD_QUIT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDnsPluginClass, child_quit), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); } diff --git a/src/dns/nm-dns-plugin.h b/src/dns/nm-dns-plugin.h index 98bda7cf..78823739 100644 --- a/src/dns/nm-dns-plugin.h +++ b/src/dns/nm-dns-plugin.h @@ -1,22 +1,10 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. */ -#ifndef __NETWORKMANAGER_DNS_PLUGIN_H__ -#define __NETWORKMANAGER_DNS_PLUGIN_H__ +#ifndef __NM_DNS_PLUGIN_H__ +#define __NM_DNS_PLUGIN_H__ #include "nm-dns-manager.h" #include "nm-config-data.h" @@ -28,21 +16,13 @@ #define NM_IS_DNS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DNS_PLUGIN)) #define NM_DNS_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass)) -#define NM_DNS_PLUGIN_FAILED "failed" -#define NM_DNS_PLUGIN_CHILD_QUIT "child-quit" - -struct _NMDnsPluginPrivate; - typedef struct { GObject parent; - struct _NMDnsPluginPrivate *_priv; } NMDnsPlugin; typedef struct { GObjectClass parent; - /* Methods */ - /* Called when DNS information is changed. 'configs' is an array * of pointers to NMDnsIPConfigData sorted by priority. * 'global_config' is the optional global DNS @@ -51,25 +31,19 @@ typedef struct { gboolean (*update) (NMDnsPlugin *self, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname); + const char *hostname, + GError **error); - /* Subclasses should override and return TRUE if they start a local - * caching nameserver that listens on localhost and would block any - * other local caching nameserver from operating. - */ - gboolean (*is_caching) (NMDnsPlugin *self); - - /* Subclasses should override this and return their plugin name */ - const char *(*get_name) (NMDnsPlugin *self); + void (*stop) (NMDnsPlugin *self); - /* Signals */ + const char *plugin_name; - /* Emitted by the plugin base class when the nameserver subprocess - * quits. This signal is consumed by the plugin subclasses and not - * by NMDnsManager. If the subclass decides the exit status (as returned - * by waitpid(2)) is fatal it should then emit the 'failed' signal. + /* Types should set to TRUE if they start a local caching nameserver + * that listens on localhost and would block any other local caching + * nameserver from operating. */ - void (*child_quit) (NMDnsPlugin *self, int status); + bool is_caching:1; + } NMDnsPluginClass; GType nm_dns_plugin_get_type (void); @@ -81,25 +55,9 @@ const char *nm_dns_plugin_get_name (NMDnsPlugin *self); gboolean nm_dns_plugin_update (NMDnsPlugin *self, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname); + const char *hostname, + GError **error); void nm_dns_plugin_stop (NMDnsPlugin *self); -/* For subclasses/plugins */ - -/* Spawn a child process and watch for it to quit. 'argv' is the NULL-terminated - * argument vector to spawn the child with, where argv[0] is the full path to - * the child's executable. If 'pidfile' is given the process owning the PID - * contained in 'pidfile' will be killed if its command line matches 'kill_match' - * and the pidfile will be deleted. - */ -GPid nm_dns_plugin_child_spawn (NMDnsPlugin *self, - const char **argv, - const char *pidfile, - const char *kill_match); - -GPid nm_dns_plugin_child_pid (NMDnsPlugin *self); - -gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self); - -#endif /* __NETWORKMANAGER_DNS_PLUGIN_H__ */ +#endif /* __NM_DNS_PLUGIN_H__ */ diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c index 69b3e45e..4ab13a91 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/dns/nm-dns-systemd-resolved.c @@ -1,21 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> * Copyright (C) 2016 Sjoerd Simons <sjoerd@luon.net> - * - * 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. - * */ #include "nm-default.h" @@ -351,7 +337,8 @@ static gboolean update (NMDnsPlugin *plugin, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname) + const char *hostname, + GError **error) { NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED (plugin); gs_unref_hashtable GHashTable *interfaces = NULL; @@ -401,20 +388,6 @@ update (NMDnsPlugin *plugin, /*****************************************************************************/ -static gboolean -is_caching (NMDnsPlugin *plugin) -{ - return TRUE; -} - -static const char * -get_name (NMDnsPlugin *plugin) -{ - return "systemd-resolved"; -} - -/*****************************************************************************/ - static void name_owner_changed (NMDnsSystemdResolved *self, const char *owner) @@ -566,7 +539,7 @@ nm_dns_systemd_resolved_class_init (NMDnsSystemdResolvedClass *dns_class) object_class->dispose = dispose; - plugin_class->is_caching = is_caching; - plugin_class->update = update; - plugin_class->get_name = get_name; + plugin_class->plugin_name = "systemd-resolved"; + plugin_class->is_caching = TRUE; + plugin_class->update = update; } diff --git a/src/dns/nm-dns-systemd-resolved.h b/src/dns/nm-dns-systemd-resolved.h index 14e31e2b..31698519 100644 --- a/src/dns/nm-dns-systemd-resolved.h +++ b/src/dns/nm-dns-systemd-resolved.h @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons <sjoerd@luon.net> */ diff --git a/src/dns/nm-dns-unbound.c b/src/dns/nm-dns-unbound.c index 9e10950a..ca681f37 100644 --- a/src/dns/nm-dns-unbound.c +++ b/src/dns/nm-dns-unbound.c @@ -1,21 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2014 Red Hat, Inc. * Author: Pavel Å imerda <psimerda@redhat.com> */ + #include "nm-default.h" #include "nm-dns-unbound.h" @@ -40,9 +28,11 @@ static gboolean update (NMDnsPlugin *plugin, const NMGlobalDnsConfig *global_config, const CList *ip_config_lst_head, - const char *hostname) + const char *hostname, + GError **error) { char *argv[] = { DNSSEC_TRIGGER_PATH, "--async", "--update", NULL }; + gs_free_error GError *local = NULL; int status; /* TODO: We currently call a script installed with the dnssec-trigger @@ -54,23 +44,21 @@ update (NMDnsPlugin *plugin, * without calling custom scripts. The dnssec-trigger functionality * may be eventually merged into NetworkManager. */ - if (!g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, NULL)) + if (!g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &local)) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "error spawning dns-trigger: %s", + local->message); return FALSE; - return (status == 0); -} - -static gboolean -is_caching (NMDnsPlugin *plugin) -{ + } + if (status != 0) { + nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, + "dns-trigger exited with error code %d", + status); + return FALSE; + } return TRUE; } -static const char * -get_name (NMDnsPlugin *plugin) -{ - return "unbound"; -} - /*****************************************************************************/ static void @@ -89,7 +77,7 @@ nm_dns_unbound_class_init (NMDnsUnboundClass *klass) { NMDnsPluginClass *plugin_class = NM_DNS_PLUGIN_CLASS (klass); - plugin_class->update = update; - plugin_class->is_caching = is_caching; - plugin_class->get_name = get_name; + plugin_class->plugin_name = "unbound"; + plugin_class->is_caching = TRUE; + plugin_class->update = update; } diff --git a/src/dns/nm-dns-unbound.h b/src/dns/nm-dns-unbound.h index 743699ea..51737b16 100644 --- a/src/dns/nm-dns-unbound.h +++ b/src/dns/nm-dns-unbound.h @@ -1,19 +1,8 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ + #ifndef __NETWORKMANAGER_DNS_UNBOUND_H__ #define __NETWORKMANAGER_DNS_UNBOUND_H__ diff --git a/src/dnsmasq/nm-dnsmasq-manager.c b/src/dnsmasq/nm-dnsmasq-manager.c index b60b2952..735605ee 100644 --- a/src/dnsmasq/nm-dnsmasq-manager.c +++ b/src/dnsmasq/nm-dnsmasq-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2012 Red Hat, Inc. */ diff --git a/src/dnsmasq/nm-dnsmasq-manager.h b/src/dnsmasq/nm-dnsmasq-manager.h index 7d4d9c9b..0a616b2a 100644 --- a/src/dnsmasq/nm-dnsmasq-manager.h +++ b/src/dnsmasq/nm-dnsmasq-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/dnsmasq/nm-dnsmasq-utils.c b/src/dnsmasq/nm-dnsmasq-utils.c index 089b8ce0..01d59ecc 100644 --- a/src/dnsmasq/nm-dnsmasq-utils.c +++ b/src/dnsmasq/nm-dnsmasq-utils.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/dnsmasq/nm-dnsmasq-utils.h b/src/dnsmasq/nm-dnsmasq-utils.h index 393e7236..a6a0342f 100644 --- a/src/dnsmasq/nm-dnsmasq-utils.h +++ b/src/dnsmasq/nm-dnsmasq-utils.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/dnsmasq/tests/meson.build b/src/dnsmasq/tests/meson.build index 09ef52e5..6e429899 100644 --- a/src/dnsmasq/tests/meson.build +++ b/src/dnsmasq/tests/meson.build @@ -3,7 +3,8 @@ test_unit = 'test-dnsmasq-utils' exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( diff --git a/src/dnsmasq/tests/test-dnsmasq-utils.c b/src/dnsmasq/tests/test-dnsmasq-utils.c index 6d8e5a1f..432a5727 100644 --- a/src/dnsmasq/tests/test-dnsmasq-utils.c +++ b/src/dnsmasq/tests/test-dnsmasq-utils.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2013 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/initrd/meson.build b/src/initrd/meson.build index fa8c016b..09036f27 100644 --- a/src/initrd/meson.build +++ b/src/initrd/meson.build @@ -1,26 +1,29 @@ sources = files( 'nmi-cmdline-reader.c', + 'nmi-dt-reader.c', 'nmi-ibft-reader.c', ) -nm_cflags = ['-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_DAEMON'] - libnmi_core = static_library( 'nmi-core', - c_args: nm_cflags, sources: sources, - include_directories: src_inc, - dependencies: libnm_core_dep, + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, ) name = 'nm-initrd-generator' + +links = [ + libnetwork_manager_base, + libnmi_core, +] + executable( name, name + '.c', - c_args: nm_cflags, - include_directories: src_inc, - dependencies: [ libnm_core_dep ], - link_with: [libnetwork_manager_base, libnmi_core], + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, + link_with: links, link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, install: true, diff --git a/src/initrd/nm-initrd-generator.c b/src/initrd/nm-initrd-generator.c index 0ff3428e..f3f53acf 100644 --- a/src/initrd/nm-initrd-generator.c +++ b/src/initrd/nm-initrd-generator.c @@ -1,20 +1,5 @@ -/* NetworkManager initrd configuration generator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ @@ -63,7 +48,12 @@ output_conn (gpointer key, gpointer value, gpointer user_data) filename = nm_keyfile_utils_create_filename (basename, TRUE); full_filename = g_build_filename (connections_dir, filename, NULL); - if (!nm_utils_file_set_contents (full_filename, data, len, 0600, &error)) + if (!nm_utils_file_set_contents (full_filename, + data, + len, + 0600, + NULL, + &error)) goto err_out; } else g_print ("\n*** Connection '%s' ***\n\n%s", basename, data); diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h index 7ff9a92e..cba383d1 100644 --- a/src/initrd/nm-initrd-generator.h +++ b/src/initrd/nm-initrd-generator.h @@ -1,20 +1,5 @@ -/* NetworkManager initrd configuration generator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2014, 2018 Red Hat, Inc. */ @@ -41,6 +26,8 @@ GHashTable *nmi_ibft_read (const char *sysfs_dir); gboolean nmi_ibft_update_connection_from_nic (NMConnection *connection, GHashTable *nic, GError **error); +NMConnection *nmi_dt_reader_parse (const char *sysfs_dir); + GHashTable *nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv); #endif /* __NM_INITRD_GENERATOR_H__ */ diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index c305cd4d..c32ef1cf 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -1,20 +1,5 @@ -/* NetworkManager initrd configuration generator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ @@ -74,6 +59,7 @@ add_conn (GHashTable *connections, g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, NULL); setting = nm_setting_connection_new (); @@ -270,7 +256,8 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) } } - if (ifname == NULL && g_strcmp0 (kind, "ibft") == 0) { + if (ifname == NULL && ( g_strcmp0 (kind, "fw") == 0 + || g_strcmp0 (kind, "ibft") == 0)) { GHashTableIter iter; const char *mac; GHashTable *nic; @@ -302,6 +289,13 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) connection); } + connection = nmi_dt_reader_parse (sysfs_dir); + if (connection) { + g_hash_table_insert (connections, + g_strdup ("ofw"), + connection); + } + return; } diff --git a/src/initrd/nmi-dt-reader.c b/src/initrd/nmi-dt-reader.c new file mode 100644 index 00000000..a8677ed9 --- /dev/null +++ b/src/initrd/nmi-dt-reader.c @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2019 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-initrd-generator.h" + +#include <arpa/inet.h> + +#include "nm-core-internal.h" + +/*****************************************************************************/ + +#define _NMLOG(level, domain, ...) \ + nm_log ((level), (domain), NULL, NULL, \ + "dt-reader: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + +/*****************************************************************************/ + +static gboolean +dt_get_property (const char *base, + const char *dev, + const char *prop, + char **contents, + size_t *length) +{ + gs_free char *filename = g_build_filename (base, dev, prop, NULL); + gs_free_error GError *error = NULL; + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) + return FALSE; + + if (!contents) + return TRUE; + + if (!g_file_get_contents (filename, contents, length, &error)) { + _LOGW (LOGD_CORE, "%s: Can not read the %s property: %s", + dev, prop, error->message); + return FALSE; + } + + return TRUE; +} + +static NMIPAddress * +dt_get_ipaddr_property (const char *base, + const char *dev, + const char *prop, + int *family) +{ + gs_free char *buf = NULL; + size_t len; + int f; + + if (!dt_get_property (base, dev, prop, &buf, &len)) + return NULL; + + f = nm_utils_addr_family_from_size (len); + if ( f == AF_UNSPEC + || ( *family != AF_UNSPEC + && *family != f)) { + _LOGW (LOGD_CORE, "%s: Address %s has unrecognized length (%zd)", + dev, prop, len); + return NULL; + } + + *family = f; + return nm_ip_address_new_binary (f, buf, 0, NULL); +} + +static char * +dt_get_hwaddr_property (const char *base, + const char *dev, + const char *prop) +{ + gs_free guint8 *buf = NULL; + size_t len; + + if (!dt_get_property (base, dev, prop, (char **) &buf, &len)) + return NULL; + + if (len != ETH_ALEN) { + _LOGW (LOGD_CORE, "%s: MAC address %s has unrecognized length (%zd)", + dev, prop, len); + return NULL; + } + + return g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x", + buf[0], buf[1], buf[2], + buf[3], buf[4], buf[4]); +} + +static NMIPAddress * +str_addr (const char *str, int *family) +{ + NMIPAddr addr_bin; + + if (!nm_utils_parse_inaddr_bin_full (*family, + TRUE, + str, + family, + &addr_bin)) { + _LOGW (LOGD_CORE, "Malformed IP address: '%s'", str); + return NULL; + } + return nm_ip_address_new_binary (*family, &addr_bin, 0, NULL); +} + +NMConnection * +nmi_dt_reader_parse (const char *sysfs_dir) +{ + gs_unref_object NMConnection *connection = NULL; + gs_free char *base = NULL; + gs_free char *bootpath = NULL; + gs_strfreev char **tokens = NULL; + char *path = NULL; + gboolean bootp = FALSE; + const char *s_ipaddr = NULL; + const char *s_netmask = NULL; + const char *s_gateway = NULL; + nm_auto_unref_ip_address NMIPAddress *ipaddr = NULL; + nm_auto_unref_ip_address NMIPAddress *gateway = NULL; + const char *duplex = NULL; + gs_free char *hwaddr = NULL; + gs_free char *local_hwaddr = NULL; + gs_free char *hostname = NULL; + guint32 speed = 0; + int prefix = -1; + NMSettingIPConfig *s_ip = NULL; + NMSetting *s_ip4 = NULL; + NMSetting *s_ip6 = NULL; + NMSetting *s_wired = NULL; + int family = AF_UNSPEC; + int i = 0; + char *c; + gs_free_error GError *error = NULL; + + base = g_build_filename (sysfs_dir, "firmware", "devicetree", + "base", NULL); + + if (!dt_get_property (base, "chosen", "bootpath", &bootpath, NULL)) + return NULL; + + c = strchr (bootpath, ':'); + if (c) { + *c = '\0'; + path = c + 1; + } else { + path = ""; + } + + dt_get_property (base, "chosen", "client-name", &hostname, NULL); + + local_hwaddr = dt_get_hwaddr_property (base, bootpath, "local-mac-address"); + hwaddr = dt_get_hwaddr_property (base, bootpath, "mac-address"); + if (g_strcmp0 (local_hwaddr, hwaddr) == 0) + g_clear_pointer (&local_hwaddr, g_free); + + tokens = g_strsplit (path, ",", 0); + + /* + * Ethernet device settings. Defined by "Open Firmware, + * Recommended Practice: Device Support Extensions, Version 1.0 [1] + * [1] https://www.devicetree.org/open-firmware/practice/devicex/dse1_0a.ps + */ + + for (i = 0; tokens[i]; i++) { + /* Skip these. They have magical meaning for OpenFirmware. */ + if ( strcmp (tokens[i], "nfs") == 0 + || strcmp (tokens[i], "last") == 0) + continue; + if (strcmp (tokens[i], "promiscuous") == 0) { + /* Ignore. */ + continue; + } + + if (g_str_has_prefix (tokens[i], "speed=")) { + speed = _nm_utils_ascii_str_to_int64 (tokens[i] + 6, + 10, 0, G_MAXUINT32, 0); + continue; + } + + if (g_str_has_prefix (tokens[i], "duplex=auto")) { + continue; + } else if ( g_str_has_prefix (tokens[i], "duplex=half") + || g_str_has_prefix (tokens[i], "duplex=full")) { + duplex = tokens[i] + 7; + continue; + } + + break; + } + + /* + * Network boot configuration. Defined by "Open Firmware, + * Recommended Practice: TFTP Booting Extension, Version 1.0 [1] + * [1] https://www.devicetree.org/open-firmware/practice/obp-tftp/tftp1_0.pdf + */ + + for (; tokens[i]; i++) { + if ( strcmp (tokens[i], "bootp") == 0 + || strcmp (tokens[i], "dhcp") == 0 + || strcmp (tokens[i], "rarp") == 0) { + bootp = TRUE; + continue; + } + break; + } + + /* s-iaddr, or perhaps a raw absolute filename */ + if (tokens[i] && tokens[i][0] != '/') + i++; + + /* filename */ + if (tokens[i]) + i++; + + /* c-iaddr */ + if (tokens[i]) { + s_ipaddr = tokens[i]; + i++; + } + + /* g-iaddr */ + if (tokens[i]) { + s_gateway = tokens[i]; + i++; + } + + if (tokens[i] && ( strchr (tokens[i], '.') + || strchr (tokens[i], ':'))) { + /* yaboot claims the mask can be specified here, + * though it doesn't support it. */ + s_netmask = tokens[i]; + i++; + } + + /* bootp-retries */ + if (tokens[i]) + i++; + + /* tftp-retries */ + if (tokens[i]) + i++; + + if (tokens[i]) { + /* yaboot accepts a mask here */ + s_netmask = tokens[i]; + i++; + } + + connection = nm_simple_connection_new (); + + nm_connection_add_setting (connection, + g_object_new (NM_TYPE_SETTING_CONNECTION, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_ID, "OpenFirmware Connection", + NULL)); + + s_ip4 = nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, s_ip4); + + s_ip6 = nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, s_ip6); + + g_object_set (s_ip6, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NULL); + + if (!bootp && dt_get_property (base, "chosen", "bootp-response", NULL, NULL)) + bootp = TRUE; + + if (!bootp) { + nm_auto_unref_ip_address NMIPAddress *netmask = NULL; + + netmask = dt_get_ipaddr_property (base, "chosen", "netmask-ip", &family); + gateway = dt_get_ipaddr_property (base, "chosen", "gateway-ip", &family); + if (gateway) + s_gateway = nm_ip_address_get_address (gateway); + ipaddr = dt_get_ipaddr_property (base, "chosen", "client-ip", &family); + + if (family == AF_UNSPEC) { + nm_assert (netmask == NULL); + nm_assert (gateway == NULL); + nm_assert (ipaddr == NULL); + + netmask = str_addr (s_netmask, &family); + ipaddr = str_addr (s_ipaddr, &family); + + prefix = _nm_utils_ascii_str_to_int64 (s_netmask, 10, 0, 128, -1); + } + + if (prefix == -1 && family == AF_INET && netmask) { + guint32 netmask_v4; + + nm_ip_address_get_address_binary (netmask, &netmask_v4); + prefix = nm_utils_ip4_netmask_to_prefix (netmask_v4); + } + + if (prefix == -1) + _LOGW (LOGD_CORE, "Unable to determine the network prefix"); + else + nm_ip_address_set_prefix (ipaddr, prefix); + } + + if (!ipaddr) { + family = AF_UNSPEC; + bootp = TRUE; + } + + if (bootp) { + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname, + NULL); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, hostname, + NULL); + } else { + switch (family) { + case AF_INET: + s_ip = (NMSettingIPConfig *) s_ip4; + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DISABLED, + NULL); + break; + case AF_INET6: + s_ip = (NMSettingIPConfig *) s_ip6; + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NULL); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NULL); + break; + default: + g_return_val_if_reached (NULL); + } + + nm_setting_ip_config_add_address (s_ip, ipaddr); + g_object_set (s_ip, NM_SETTING_IP_CONFIG_GATEWAY, s_gateway, NULL); + } + + if (duplex || speed || hwaddr || local_hwaddr) { + s_wired = nm_setting_wired_new (); + nm_connection_add_setting (connection, s_wired); + + g_object_set (s_wired, + NM_SETTING_WIRED_SPEED, speed, + NM_SETTING_WIRED_DUPLEX, duplex, + NM_SETTING_WIRED_MAC_ADDRESS, hwaddr, + NM_SETTING_WIRED_CLONED_MAC_ADDRESS, local_hwaddr, + NULL); + } + + if (!nm_connection_normalize (connection, NULL, NULL, &error)) { + _LOGW (LOGD_CORE, "Generated an invalid connection: %s", + error->message); + g_clear_pointer (&connection, g_object_unref); + } + + return g_steal_pointer (&connection); +} diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c index 2db38e2c..ffce98fc 100644 --- a/src/initrd/nmi-ibft-reader.c +++ b/src/initrd/nmi-ibft-reader.c @@ -1,21 +1,6 @@ -/* NetworkManager initrd configuration generator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2014 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2014 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -172,6 +157,10 @@ ip_setting_add_from_block (GHashTable *nic, if (!s_ip6) { s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); nm_connection_add_setting (connection, (NMSetting *) s_ip6); + + g_object_set (s_ip6, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NULL); } family = guess_ip_address_family (s_ipaddr); diff --git a/src/initrd/tests/meson.build b/src/initrd/tests/meson.build index 20cf6af2..5dd2873c 100644 --- a/src/initrd/tests/meson.build +++ b/src/initrd/tests/meson.build @@ -1,20 +1,20 @@ +c_flags = test_c_flags + ['-DTEST_INITRD_DIR="@0@"'.format(meson.current_source_dir())] + test_units = [ + 'test-dt-reader', 'test-ibft-reader', 'test-cmdline-reader', ] -cflags = [ - '-DTEST_INITRD_DIR="@0@"'.format(meson.current_source_dir()), -] - foreach test_unit : test_units exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, - c_args: cflags, + dependencies: libnetwork_manager_test_dep, + c_args: c_flags, link_with: libnmi_core, ) + test( 'initrd/' + test_unit, test_script, diff --git a/src/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath b/src/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath new file mode 100644 index 00000000..6f069ae0 --- /dev/null +++ b/src/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request new file mode 100644 index 00000000..034d423e --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response new file mode 100644 index 00000000..25982d6f --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath new file mode 100644 index 00000000..db880702 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip new file mode 100644 index 00000000..7bde8641 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip @@ -0,0 +1 @@ +ÿÿÿÿ \ No newline at end of file diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip new file mode 100644 index 00000000..f108ba9b --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip @@ -0,0 +1,2 @@ + ++ \ No newline at end of file diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name new file mode 100644 index 00000000..fe0f76b8 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name new file mode 100644 index 00000000..b34f9f96 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip new file mode 100644 index 00000000..f0361835 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip @@ -0,0 +1,2 @@ + ++þ \ No newline at end of file diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name new file mode 100644 index 00000000..f3e58052 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip new file mode 100644 index 00000000..d441cd83 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path new file mode 100644 index 00000000..f76dd238 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip new file mode 100644 index 00000000..a2a4b2e8 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip @@ -0,0 +1,2 @@ + +& \ No newline at end of file diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file new file mode 100644 index 00000000..c0e0e330 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options new file mode 100644 index 00000000..f76dd238 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type new file mode 100644 index 00000000..df3c9d9f --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address new file mode 100644 index 00000000..c983e752 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address @@ -0,0 +1 @@ +¬>åØ \ No newline at end of file diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address new file mode 100644 index 00000000..c983e752 --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address @@ -0,0 +1 @@ +¬>åØ \ No newline at end of file diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name new file mode 100644 index 00000000..88eaddfe --- /dev/null +++ b/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name Binary files differdiff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index a28c634d..1d4bb9a6 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -1,21 +1,6 @@ -/* NetworkManager initrd configuration generator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/initrd/tests/test-dt-reader.c b/src/initrd/tests/test-dt-reader.c new file mode 100644 index 00000000..9a4dc735 --- /dev/null +++ b/src/initrd/tests/test-dt-reader.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2014 - 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> +#include <netinet/ether.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> + +#include "nm-core-internal.h" +#include "NetworkManagerUtils.h" + +#include "../nm-initrd-generator.h" + +#include "nm-test-utils-core.h" + +static void +test_read_dt_ofw (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + const char *mac_address; + + connection = nmi_dt_reader_parse (TEST_INITRD_DIR "/sysfs-dt"); + g_assert (connection); + nmtst_assert_connection_verifies (connection); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "OpenFirmware Connection"); + g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0); + g_assert (nm_setting_connection_get_autoconnect (s_con)); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert (s_wired); + mac_address = nm_setting_wired_get_mac_address (s_wired); + g_assert (mac_address); + g_assert (nm_utils_hwaddr_matches (mac_address, -1, "ac:7f:3e:e5:d8:d8", -1)); + g_assert (!nm_setting_wired_get_duplex (s_wired)); + g_assert_cmpint (nm_setting_wired_get_speed (s_wired), ==, 0); + g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert_cmpstr (nm_setting_ip_config_get_dhcp_hostname (s_ip4), ==, "demiurge"); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + + g_object_unref (connection); +} + +static void +test_read_dt_slof (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMIPAddress *ip4_addr; + + connection = nmi_dt_reader_parse (TEST_INITRD_DIR "/sysfs-dt-tftp"); + g_assert (connection); + nmtst_assert_connection_verifies (connection); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "OpenFirmware Connection"); + g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0); + g_assert (nm_setting_connection_get_autoconnect (s_con)); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert (s_wired); + g_assert (!nm_setting_wired_get_mac_address (s_wired)); + g_assert_cmpstr (nm_setting_wired_get_duplex (s_wired), ==, "half"); + g_assert_cmpint (nm_setting_wired_get_speed (s_wired), ==, 10); + g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); + + g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1); + ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0); + g_assert (ip4_addr); + g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.32.2"); + g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 16); + + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.32.1"); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DISABLED); + + g_object_unref (connection); +} + +static void +test_read_dt_none (void) +{ + NMConnection *connection; + + connection = nmi_dt_reader_parse (TEST_INITRD_DIR "/sysfs"); + g_assert (!connection); +} + +NMTST_DEFINE (); + +int main (int argc, char **argv) +{ + nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT"); + + g_test_add_func ("/initrd/dt/ofw", test_read_dt_ofw); + g_test_add_func ("/initrd/dt/slof", test_read_dt_slof); + g_test_add_func ("/initrd/dt/none", test_read_dt_none); + + return g_test_run (); +} diff --git a/src/initrd/tests/test-ibft-reader.c b/src/initrd/tests/test-ibft-reader.c index a49d0abf..932c1a48 100644 --- a/src/initrd/tests/test-ibft-reader.c +++ b/src/initrd/tests/test-ibft-reader.c @@ -1,21 +1,6 @@ -/* NetworkManager initrd configuration generator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2014 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2014 - 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/main-utils.c b/src/main-utils.c index 38fd519a..80222495 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ diff --git a/src/main-utils.h b/src/main-utils.h index d4da6052..58240686 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/main.c b/src/main.c index f1e9690f..262b6484 100644 --- a/src/main.c +++ b/src/main.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ @@ -102,7 +88,7 @@ _init_nm_debug (NMConfig *config) debug = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_DEBUG, - NM_MANAGER_RELOAD_FLAGS_NONE); + NM_CONFIG_GET_VALUE_NONE); flags = nm_utils_parse_debug_string (env, keys, G_N_ELEMENTS (keys)); flags |= nm_utils_parse_debug_string (debug, keys, G_N_ELEMENTS (keys)); @@ -168,6 +154,7 @@ print_config (NMConfigCmdLineOptions *config_cli) gs_unref_object NMConfig *config = NULL; gs_free_error GError *error = NULL; NMConfigData *config_data; + const char *const*warnings; nm_logging_setup ("OFF", "ALL", NULL, NULL); @@ -179,7 +166,14 @@ print_config (NMConfigCmdLineOptions *config_cli) config_data = nm_config_get_data (config); fprintf (stdout, "# NetworkManager configuration: %s\n", nm_config_data_get_config_description (config_data)); - nm_config_data_log (config_data, "", "", stdout); + nm_config_data_log (config_data, "", "", nm_config_get_no_auto_default_file (config), stdout); + + warnings = nm_config_get_warnings (config); + if (warnings && warnings[0]) + fprintf (stdout, "\n"); + for ( ; warnings && warnings[0]; warnings++) + fprintf (stdout, "# WARNING: %s\n", warnings[0]); + return 0; } @@ -386,7 +380,7 @@ main (int argc, char *argv[]) nm_config_get_first_start (config) ? "for the first time" : "after a restart"); nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); - nm_config_data_log (nm_config_get_data (config), "CONFIG: ", " ", NULL); + nm_config_data_log (nm_config_get_data (config), "CONFIG: ", " ", nm_config_get_no_auto_default_file (config), NULL); if (error_invalid_logging_config) { nm_log_warn (LOGD_CORE, "config: invalid logging configuration: %s", error_invalid_logging_config->message); @@ -424,10 +418,7 @@ main (int argc, char *argv[]) NM_UTILS_KEEP_ALIVE (config, nm_netns_get (), "NMConfig-depends-on-NMNetns"); - nm_auth_manager_setup (nm_config_data_get_value_boolean (nm_config_get_data_orig (config), - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT, - NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_BOOL)); + nm_auth_manager_setup (nm_config_data_get_main_auth_polkit (nm_config_get_data_orig (config))); manager = nm_manager_setup (); diff --git a/src/meson.build b/src/meson.build index f3f5ee58..748fa519 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,11 @@ src_inc = include_directories('.') +daemon_nm_default_dep = declare_dependency( + sources: libnm_core_enum_sources[1], + include_directories: src_inc, + dependencies: libnm_core_nm_default_dep, +) + install_data( 'org.freedesktop.NetworkManager.conf', install_dir: dbus_conf_dir, @@ -9,15 +15,7 @@ subdir('systemd') core_plugins = [] -nm_cflags = ['-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_DAEMON'] - -nm_dep = declare_dependency( - include_directories: src_inc, - dependencies: libnm_core_dep, - compile_args: nm_cflags, -) - -cflags = nm_cflags +daemon_c_flags = ['-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_DAEMON'] sources = files( 'dhcp/nm-dhcp-client.c', @@ -49,10 +47,13 @@ sources = files( ) deps = [ + daemon_nm_default_dep, + libn_dhcp4_dep, + libnm_core_dep, + libnm_systemd_shared_dep, + libnm_udev_aux_dep, libsystemd_dep, libudev_dep, - libnm_core_dep, - shared_n_dhcp4_dep, ] if enable_wext @@ -63,8 +64,7 @@ libnetwork_manager_base = static_library( nm_name + 'Base', sources: sources, dependencies: deps, - c_args: cflags, - link_with: libnm_core, + c_args: daemon_c_flags, ) sources = files( @@ -151,14 +151,20 @@ sources = files( ) nm_deps = [ + daemon_nm_default_dep, dl_dep, + libn_acd_dep, libndp_dep, libudev_dep, - libnm_core_dep, - shared_n_acd_dep, logind_dep, ] +nm_links = [ + libnetwork_manager_base, + libnm_systemd_core, + libnm_systemd_shared, +] + if enable_concheck nm_deps += libcurl_dep endif @@ -179,19 +185,15 @@ libnetwork_manager = static_library( nm_name, sources: sources, dependencies: nm_deps, - c_args: cflags, - link_with: [ - libnetwork_manager_base, - libnm_systemd_core, - libnm_systemd_shared, - ], + c_args: daemon_c_flags, + link_with: nm_links, ) deps = [ + daemon_nm_default_dep, dl_dep, libndp_dep, libudev_dep, - libnm_core_dep, ] name = 'nm-iface-helper' @@ -200,12 +202,8 @@ executable( name, name + '.c', dependencies: deps, - c_args: cflags, - link_with: [ - libnetwork_manager_base, - libnm_systemd_core, - libnm_systemd_shared, - ], + c_args: daemon_c_flags, + link_with: nm_links, link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, install: true, @@ -213,46 +211,30 @@ executable( ) if enable_tests + test_c_flags = daemon_c_flags + ['-DNETWORKMANAGER_COMPILATION_TEST'] + if require_root_tests + test_c_flags += ['-DREQUIRE_ROOT_TESTS=1'] + endif + sources = files( 'ndisc/nm-fake-ndisc.c', 'platform/tests/test-common.c', 'platform/nm-fake-platform.c', ) - deps = [ - libudev_dep, - libnm_core_dep, - ] - - test_cflags = ['-DNETWORKMANAGER_COMPILATION_TEST'] - if require_root_tests - test_cflags += ['-DREQUIRE_ROOT_TESTS=1'] - endif - libnetwork_manager_test = static_library( nm_name + 'Test', sources: sources, - dependencies: deps, - c_args: cflags + test_cflags, + dependencies: daemon_nm_default_dep, + c_args: test_c_flags, link_with: libnetwork_manager, ) - test_nm_dep = declare_dependency( - dependencies: nm_dep, - compile_args: test_cflags, + libnetwork_manager_test_dep = declare_dependency( + dependencies: daemon_nm_default_dep, link_with: libnetwork_manager_test, ) - test_nm_dep_fake = declare_dependency( - dependencies: test_nm_dep, - compile_args: ['-DSETUP=nm_fake_platform_setup'] - ) - - test_nm_dep_linux = declare_dependency( - dependencies: test_nm_dep, - compile_args: ['-DSETUP=nm_linux_platform_setup'] - ) - subdir('dnsmasq/tests') subdir('ndisc/tests') subdir('platform/tests') @@ -272,7 +254,7 @@ subdir('settings/plugins') # NetworkManager binary -create_exports_networkmanager = join_paths(meson.source_root(), 'tools', 'create-exports-NetworkManager.sh') +create_exports_networkmanager = join_paths(source_root, 'tools', 'create-exports-NetworkManager.sh') symbol_map_name = 'NetworkManager.ver' # libNetworkManager.a, as built by meson doesn't contain all symbols @@ -283,29 +265,30 @@ symbol_map_name = 'NetworkManager.ver' network_manager_sym = executable( 'nm-full-symbols', 'main.c', - c_args: nm_cflags, - link_args: '-Wl,--no-gc-sections', dependencies: nm_deps, + c_args: daemon_c_flags, + link_args: '-Wl,--no-gc-sections', link_whole: [libnetwork_manager, libnetwork_manager_base, libnm_core], - install: false, ) # this uses symbols from nm-full-symbols instead of libNetworkManager.a ver_script = custom_target( symbol_map_name, - input: meson.source_root(), output: symbol_map_name, - depends: [ network_manager_sym, core_plugins ], - command: [create_exports_networkmanager, '--called-from-build', '@INPUT@'], + depends: [network_manager_sym, core_plugins], + command: [create_exports_networkmanager, '--called-from-build', source_root], ) -ldflags = ['-rdynamic', '-Wl,--version-script,@0@'.format(ver_script.full_path())] +ldflags = [ + '-rdynamic', + '-Wl,--version-script,@0@'.format(ver_script.full_path()), +] network_manager = executable( nm_name, 'main.c', dependencies: nm_deps, - c_args: nm_cflags, + c_args: daemon_c_flags, link_with: libnetwork_manager, link_args: ldflags, link_depends: ver_script, @@ -314,16 +297,20 @@ network_manager = executable( ) if enable_tests - foreach plugin : core_plugins - test ('sym/' + plugin.full_path().split('/')[-1], - network_manager, - args: '--version', - env: ['LD_BIND_NOW=1', 'LD_PRELOAD=' + plugin.full_path()]) + foreach plugin: core_plugins + plugin_path = plugin.full_path() + + test( + 'sym/' + plugin_path.split('/')[-1], + network_manager, + args: '--version', + env: ['LD_BIND_NOW=1', 'LD_PRELOAD=' + plugin_path], + ) endforeach endif test( 'check-config-options', - find_program(join_paths(meson.source_root(), 'tools', 'check-config-options.sh')), - args: [meson.source_root()] + find_program(join_paths(source_root, 'tools', 'check-config-options.sh')), + args: source_root, ) diff --git a/src/ndisc/nm-fake-ndisc.c b/src/ndisc/nm-fake-ndisc.c index dadd1743..020764d3 100644 --- a/src/ndisc/nm-fake-ndisc.c +++ b/src/ndisc/nm-fake-ndisc.c @@ -1,19 +1,5 @@ -/* nm-fake-ndisc.c - Fake implementation of neighbor discovery - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/nm-fake-ndisc.h b/src/ndisc/nm-fake-ndisc.h index 5cf65bc1..39b88184 100644 --- a/src/ndisc/nm-fake-ndisc.h +++ b/src/ndisc/nm-fake-ndisc.h @@ -1,19 +1,5 @@ -/* nm-fake-ndisc.h - Fake implementation of neighbor discovery - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c index 9352a753..8077099f 100644 --- a/src/ndisc/nm-lndp-ndisc.c +++ b/src/ndisc/nm-lndp-ndisc.c @@ -1,19 +1,5 @@ -/* nm-lndp-ndisc.c - Router discovery implementation using libndp - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/nm-lndp-ndisc.h b/src/ndisc/nm-lndp-ndisc.h index f95d5d0c..22f21e41 100644 --- a/src/ndisc/nm-lndp-ndisc.h +++ b/src/ndisc/nm-lndp-ndisc.h @@ -1,19 +1,5 @@ -/* nm-lndp-ndisc.h - Implementation of neighbor discovery using libndp - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/nm-ndisc-private.h b/src/ndisc/nm-ndisc-private.h index 450def27..d31ab31f 100644 --- a/src/ndisc/nm-ndisc-private.h +++ b/src/ndisc/nm-ndisc-private.h @@ -1,20 +1,6 @@ -/* nm-ndisc.h - Perform IPv6 neighbor discovery - * - * 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 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_NDISC_PRIVATE_H__ diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c index a8fabb56..41201e24 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/ndisc/nm-ndisc.c @@ -1,19 +1,5 @@ -/* nm-ndisc.c - Perform IPv6 neighbor discovery - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h index 8e07ca41..92295ac6 100644 --- a/src/ndisc/nm-ndisc.h +++ b/src/ndisc/nm-ndisc.h @@ -1,19 +1,5 @@ -/* nm-ndisc.h - Perform IPv6 neighbor discovery - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/tests/meson.build b/src/ndisc/tests/meson.build index 99cf664e..c81e24ad 100644 --- a/src/ndisc/tests/meson.build +++ b/src/ndisc/tests/meson.build @@ -3,7 +3,8 @@ test_unit = 'test-ndisc-fake' exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep_fake, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( @@ -18,5 +19,6 @@ test = 'test-ndisc-linux' exe = executable( test, test + '.c', - dependencies: test_nm_dep_linux, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) diff --git a/src/ndisc/tests/test-ndisc-fake.c b/src/ndisc/tests/test-ndisc-fake.c index f752376d..8bdc053d 100644 --- a/src/ndisc/tests/test-ndisc-fake.c +++ b/src/ndisc/tests/test-ndisc-fake.c @@ -1,19 +1,5 @@ -/* ndisc.c - test program - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/ndisc/tests/test-ndisc-linux.c b/src/ndisc/tests/test-ndisc-linux.c index 715d4037..e9ceaa2b 100644 --- a/src/ndisc/tests/test-ndisc-linux.c +++ b/src/ndisc/tests/test-ndisc-linux.c @@ -1,19 +1,5 @@ -/* ndisc.c - test program - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/nm-act-request.c b/src/nm-act-request.c index 763b1503..ef36a40d 100644 --- a/src/nm-act-request.c +++ b/src/nm-act-request.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ diff --git a/src/nm-act-request.h b/src/nm-act-request.h index 055b2591..07fd5731 100644 --- a/src/nm-act-request.h +++ b/src/nm-act-request.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2005 - 2012 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2005 - 2012 Red Hat, Inc. */ #ifndef __NM_ACT_REQUEST_H__ diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index b937f732..bf50e55d 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2014 Red Hat, Inc. */ @@ -721,7 +707,7 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device) G_CALLBACK (device_metered_changed), self); if (priv->activation_type != NM_ACTIVATION_TYPE_EXTERNAL) { - priv->pending_activation_id = g_strdup_printf (NM_PENDING_ACTIONPREFIX_ACTIVATION"%p", (void *)self); + priv->pending_activation_id = g_strdup_printf (NM_PENDING_ACTIONPREFIX_ACTIVATION"%"G_GUINT64_FORMAT, priv->version_id); nm_device_add_pending_action (device, priv->pending_activation_id, TRUE); } } else { diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index d9d28378..bf38a1b0 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2012 Red Hat, Inc. */ diff --git a/src/nm-audit-manager.c b/src/nm-audit-manager.c index fe7645f8..b219b35a 100644 --- a/src/nm-audit-manager.c +++ b/src/nm-audit-manager.c @@ -1,20 +1,6 @@ -/* NetworkManager audit support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/nm-audit-manager.h b/src/nm-audit-manager.h index b4ad5db9..d8310eaf 100644 --- a/src/nm-audit-manager.h +++ b/src/nm-audit-manager.h @@ -1,20 +1,6 @@ -/* NetworkManager audit support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Red Hat, Inc. */ #ifndef __NM_AUDIT_MANAGER_H__ diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c index 0663e207..3f248aee 100644 --- a/src/nm-auth-manager.c +++ b/src/nm-auth-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -56,7 +42,7 @@ typedef struct { guint changed_signal_id; bool disposing:1; bool shutting_down:1; - bool polkit_enabled_construct_only:1; + NMAuthPolkitMode auth_polkit_mode:3; } NMAuthManagerPrivate; struct _NMAuthManager { @@ -124,11 +110,6 @@ typedef enum { POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION = (1<<0), } PolkitCheckAuthorizationFlags; -typedef enum { - IDLE_REASON_AUTHORIZED, - IDLE_REASON_NO_DBUS, -} IdleReason; - struct _NMAuthManagerCallId { CList calls_lst; NMAuthManager *self; @@ -137,7 +118,7 @@ struct _NMAuthManagerCallId { gpointer user_data; guint64 call_numid; guint idle_id; - IdleReason idle_reason:8; + bool idle_is_authorized:1; }; #define cancellation_id_to_str_a(call_numid) \ @@ -276,25 +257,16 @@ static gboolean _call_on_idle (gpointer user_data) { NMAuthManagerCallId *call_id = user_data; - gs_free_error GError *error = NULL; - gboolean is_authorized = FALSE; + gboolean is_authorized; gboolean is_challenge = FALSE; - const char *error_msg = NULL; + is_authorized = call_id->idle_is_authorized; call_id->idle_id = 0; - if (call_id->idle_reason == IDLE_REASON_AUTHORIZED) { - is_authorized = TRUE; - _LOG2T (call_id, "completed: authorized=%d, challenge=%d (simulated)", - is_authorized, is_challenge); - } else { - nm_assert (call_id->idle_reason == IDLE_REASON_NO_DBUS); - error_msg = "failure creating GDBusProxy for authorization request"; - _LOG2T (call_id, "completed: failed due to no D-Bus proxy"); - } - if (error_msg) - g_set_error_literal (&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, error_msg); - _call_id_invoke_callback (call_id, is_authorized, is_challenge, error); + _LOG2T (call_id, "completed: authorized=%d, challenge=%d (simulated)", + is_authorized, is_challenge); + + _call_id_invoke_callback (call_id, is_authorized, is_challenge, NULL); return G_SOURCE_REMOVE; } @@ -342,24 +314,24 @@ nm_auth_manager_check_authorization (NMAuthManager *self, call_id = g_slice_new (NMAuthManagerCallId); *call_id = (NMAuthManagerCallId) { - .self = g_object_ref (self), - .callback = callback, - .user_data = user_data, - .call_numid = ++priv->call_numid_counter, + .self = g_object_ref (self), + .callback = callback, + .user_data = user_data, + .call_numid = ++priv->call_numid_counter, + .idle_is_authorized = TRUE, }; c_list_link_tail (&priv->calls_lst_head, &call_id->calls_lst); - if (!priv->dbus_connection) { - _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding due to polkit authorization disabled)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf))); - call_id->idle_reason = IDLE_REASON_AUTHORIZED; - call_id->idle_id = g_idle_add (_call_on_idle, call_id); - } else if (nm_auth_subject_is_internal (subject)) { + if (nm_auth_subject_is_internal (subject)) { _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for internal request)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf))); - call_id->idle_reason = IDLE_REASON_AUTHORIZED; call_id->idle_id = g_idle_add (_call_on_idle, call_id); } else if (nm_auth_subject_get_unix_process_uid (subject) == 0) { _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for root)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf))); - call_id->idle_reason = IDLE_REASON_AUTHORIZED; + call_id->idle_id = g_idle_add (_call_on_idle, call_id); + } else if (priv->auth_polkit_mode != NM_AUTH_POLKIT_MODE_USE_POLKIT) { + _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (PolicyKit disabled and always %s authorization to non-root user)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)), + priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ALLOW_ALL ? "grant" : "deny"); + call_id->idle_is_authorized = (priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ALLOW_ALL); call_id->idle_id = g_idle_add (_call_on_idle, call_id); } else { GVariant *parameters; @@ -494,11 +466,17 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE ((NMAuthManager *) object); + int v_int; switch (prop_id) { case PROP_POLKIT_ENABLED: /* construct-only */ - priv->polkit_enabled_construct_only = !!g_value_get_boolean (value); + v_int = g_value_get_int (value); + g_return_if_fail (NM_IN_SET (v_int, NM_AUTH_POLKIT_MODE_ROOT_ONLY, + NM_AUTH_POLKIT_MODE_ALLOW_ALL, + NM_AUTH_POLKIT_MODE_USE_POLKIT)); + priv->auth_polkit_mode = v_int; + nm_assert (priv->auth_polkit_mode == v_int); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -514,6 +492,7 @@ nm_auth_manager_init (NMAuthManager *self) NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self); c_list_init (&priv->calls_lst_head); + priv->auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; } static void @@ -526,8 +505,11 @@ constructed (GObject *object) G_OBJECT_CLASS (nm_auth_manager_parent_class)->constructed (object); - if (!priv->polkit_enabled_construct_only) { - create_message = "polkit disabled"; + if (priv->auth_polkit_mode != NM_AUTH_POLKIT_MODE_USE_POLKIT) { + if (priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ROOT_ONLY) + create_message = "polkit disabled, root-only"; + else + create_message = "polkit disabled, allow-all"; goto out; } @@ -536,7 +518,8 @@ constructed (GObject *object) if (!priv->dbus_connection) { /* This warrants an info level message. */ logl = LOGL_INFO; - create_message = "D-Bus connection not available. Polkit is disabled and all requests are authenticated."; + create_message = "D-Bus connection not available. Polkit is disabled and only root will be authorized."; + priv->auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; goto out; } @@ -560,14 +543,17 @@ out: } NMAuthManager * -nm_auth_manager_setup (gboolean polkit_enabled) +nm_auth_manager_setup (NMAuthPolkitMode auth_polkit_mode) { NMAuthManager *self; g_return_val_if_fail (!singleton_instance, singleton_instance); + nm_assert (NM_IN_SET (auth_polkit_mode, NM_AUTH_POLKIT_MODE_ROOT_ONLY, + NM_AUTH_POLKIT_MODE_ALLOW_ALL, + NM_AUTH_POLKIT_MODE_USE_POLKIT)); self = g_object_new (NM_TYPE_AUTH_MANAGER, - NM_AUTH_MANAGER_POLKIT_ENABLED, polkit_enabled, + NM_AUTH_MANAGER_POLKIT_ENABLED, (int) auth_polkit_mode, NULL); _LOGD ("set instance"); @@ -612,11 +598,11 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass) object_class->dispose = dispose; obj_properties[PROP_POLKIT_ENABLED] = - g_param_spec_boolean (NM_AUTH_MANAGER_POLKIT_ENABLED, "", "", - FALSE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); + g_param_spec_int (NM_AUTH_MANAGER_POLKIT_ENABLED, "", "", + NM_AUTH_POLKIT_MODE_ROOT_ONLY, NM_AUTH_POLKIT_MODE_USE_POLKIT, NM_AUTH_POLKIT_MODE_USE_POLKIT, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/nm-auth-manager.h b/src/nm-auth-manager.h index 86746d09..33e3bb2c 100644 --- a/src/nm-auth-manager.h +++ b/src/nm-auth-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -21,6 +7,7 @@ #define NM_AUTH_MANAGER_H #include "nm-auth-subject.h" +#include "nm-config-data.h" /*****************************************************************************/ @@ -63,7 +50,7 @@ typedef struct _NMAuthManagerClass NMAuthManagerClass; GType nm_auth_manager_get_type (void); -NMAuthManager *nm_auth_manager_setup (gboolean polkit_enabled); +NMAuthManager *nm_auth_manager_setup (NMAuthPolkitMode auth_polkit_mode); NMAuthManager *nm_auth_manager_get (void); void nm_auth_manager_force_shutdown (NMAuthManager *self); diff --git a/src/nm-auth-subject.c b/src/nm-auth-subject.c index fd39bff1..ecf6b013 100644 --- a/src/nm-auth-subject.c +++ b/src/nm-auth-subject.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 - 2014 Red Hat, Inc. */ diff --git a/src/nm-auth-subject.h b/src/nm-auth-subject.h index 7af76018..7a75aca9 100644 --- a/src/nm-auth-subject.h +++ b/src/nm-auth-subject.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c index 7235cba1..a5b951ab 100644 --- a/src/nm-auth-utils.c +++ b/src/nm-auth-utils.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. */ diff --git a/src/nm-auth-utils.h b/src/nm-auth-utils.h index 5201d260..808d20fd 100644 --- a/src/nm-auth-utils.h +++ b/src/nm-auth-utils.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. */ diff --git a/src/nm-checkpoint-manager.c b/src/nm-checkpoint-manager.c index 7c50d61f..8cc8e609 100644 --- a/src/nm-checkpoint-manager.c +++ b/src/nm-checkpoint-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ @@ -223,7 +209,7 @@ nm_checkpoint_manager_destroy (NMCheckpointManager *self, g_return_val_if_fail (path && path[0] == '/', FALSE); g_return_val_if_fail (!error || !*error, FALSE); - if (nm_streq (path, "/")) { + if (!nm_dbus_path_not_empty (path)) { nm_checkpoint_manager_destroy_all (self); return TRUE; } diff --git a/src/nm-checkpoint-manager.h b/src/nm-checkpoint-manager.h index 46590a0c..c0549317 100644 --- a/src/nm-checkpoint-manager.h +++ b/src/nm-checkpoint-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index 9bc979bb..734a40e1 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/nm-checkpoint.h b/src/nm-checkpoint.h index 708d8dd6..6d27a43f 100644 --- a/src/nm-checkpoint.h +++ b/src/nm-checkpoint.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 5655c8fd..c787aa98 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> */ @@ -95,8 +81,12 @@ typedef struct { int autoconnect_retries_default; struct { + + /* from /var/lib/NetworkManager/no-auto-default.state */ char **arr; GSList *specs; + + /* from main.no-auto-default setting in NetworkManager.conf. */ GSList *specs_config; } no_auto_default; @@ -396,6 +386,61 @@ _nm_config_data_get_keyfile_user (const NMConfigData *self) /*****************************************************************************/ +static NMAuthPolkitMode +nm_auth_polkit_mode_from_string (const char *str) +{ + int as_bool; + + if (!str) + return NM_AUTH_POLKIT_MODE_UNKNOWN; + + if (nm_streq (str, "root-only")) + return NM_AUTH_POLKIT_MODE_ROOT_ONLY; + + as_bool = _nm_utils_ascii_str_to_bool (str, -1); + if (as_bool != -1) { + return as_bool + ? NM_AUTH_POLKIT_MODE_USE_POLKIT + : NM_AUTH_POLKIT_MODE_ALLOW_ALL; + } + + return NM_AUTH_POLKIT_MODE_UNKNOWN; +} + +static NMAuthPolkitMode +_config_data_get_main_auth_polkit (const NMConfigData *self, + gboolean *out_invalid_config) +{ + NMAuthPolkitMode auth_polkit_mode; + const char *str; + + str = nm_config_data_get_value (self, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT, + NM_CONFIG_GET_VALUE_STRIP + | NM_CONFIG_GET_VALUE_NO_EMPTY); + auth_polkit_mode = nm_auth_polkit_mode_from_string (str); + if (auth_polkit_mode == NM_AUTH_POLKIT_MODE_UNKNOWN) { + NM_SET_OUT (out_invalid_config, (str != NULL)); + auth_polkit_mode = nm_auth_polkit_mode_from_string (NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT); + if (auth_polkit_mode == NM_AUTH_POLKIT_MODE_UNKNOWN) { + nm_assert_not_reached (); + auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; + } + } else + NM_SET_OUT (out_invalid_config, FALSE); + + return auth_polkit_mode; +} + +NMAuthPolkitMode +nm_config_data_get_main_auth_polkit (const NMConfigData *self) +{ + return _config_data_get_main_auth_polkit (self, NULL); +} + +/*****************************************************************************/ + /** * nm_config_data_get_groups: * @self: the #NMConfigData instance @@ -614,6 +659,7 @@ void nm_config_data_log (const NMConfigData *self, const char *prefix, const char *key_prefix, + const char *no_auto_default_file, /* FILE* */ gpointer print_stream) { const NMConfigDataPrivate *priv; @@ -706,6 +752,16 @@ nm_config_data_log (const NMConfigData *self, } } + _LOG (stream, prefix, ""); + _LOG (stream, prefix, "# no-auto-default file \"%s\"", no_auto_default_file); + { + gs_free char *msg = NULL; + + msg = nm_utils_g_slist_strlist_join (priv->no_auto_default.specs, ","); + if (msg) + _LOG (stream, prefix, "# no-auto-default specs \"%s\"", msg); + } + #undef _LOG } @@ -1551,6 +1607,26 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) /*****************************************************************************/ +void +nm_config_data_get_warnings (const NMConfigData *self, + GPtrArray *warnings) +{ + gboolean invalid; + + nm_assert (NM_IS_CONFIG_DATA (self)); + nm_assert (warnings); + + _config_data_get_main_auth_polkit (self, &invalid); + if (invalid) { + g_ptr_array_add (warnings, + g_strdup_printf ("invalid setting for %s.%s (should be one of \"true\", \"false\", \"root-only\")", + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT)); + } +} + +/*****************************************************************************/ + static void get_property (GObject *object, guint prop_id, @@ -1662,7 +1738,7 @@ set_property (GObject *object, specs = g_slist_prepend (specs, spec); } - priv->no_auto_default.arr = nm_utils_strv_dup (value_arr, j); + priv->no_auto_default.arr = nm_utils_strv_dup (value_arr, j, TRUE); priv->no_auto_default.specs = g_slist_reverse (specs); } break; diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 8f925a6c..2a3f2a89 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -1,25 +1,33 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ #ifndef NM_CONFIG_DATA_H #define NM_CONFIG_DATA_H +/*****************************************************************************/ + +typedef enum { + + /* an invalid mode. */ + NM_AUTH_POLKIT_MODE_UNKNOWN, + + /* don't use PolicyKit, but only allow root user (uid 0). */ + NM_AUTH_POLKIT_MODE_ROOT_ONLY, + + /* don't use PolicyKit, but allow all requests. */ + NM_AUTH_POLKIT_MODE_ALLOW_ALL, + + /* use PolicyKit to authorize requests. Root user (uid 0) always + * gets a free pass, without consulting PolicyKit. If PolicyKit is not + * running, authorization will fail for non root users. */ + NM_AUTH_POLKIT_MODE_USE_POLKIT, + +} NMAuthPolkitMode; + +/*****************************************************************************/ + #define NM_TYPE_CONFIG_DATA (nm_config_data_get_type ()) #define NM_CONFIG_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG_DATA, NMConfigData)) #define NM_CONFIG_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONFIG_DATA, NMConfigDataClass)) @@ -38,25 +46,6 @@ #define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" #define NM_CONFIG_DATA_DNS_MODE "dns" -/* The flags for Reload. Currently these are internal defines, - * only their numeric value matters and must be stable as - * they are public API! Also, the enum must fit in uint32. */ -enum { /*< skip >*/ - NM_MANAGER_RELOAD_FLAGS_NONE = 0, - - /* reload the configuration from disk */ - NM_MANAGER_RELOAD_FLAGS_CONF = (1LL << 0), - - /* write DNS configuration to resolv.conf */ - NM_MANAGER_RELOAD_FLAGS_DNS_RC = (1LL << 1), - - /* restart the DNS plugin (includes DNS_RC) */ - NM_MANAGER_RELOAD_FLAGS_DNS_FULL = (1LL << 2), - - _NM_MANAGER_RELOAD_FLAGS_ALL, - NM_MANAGER_RELOAD_FLAGS_ALL = ((_NM_MANAGER_RELOAD_FLAGS_ALL - 1) << 1) - 1, -}; - typedef enum { /*< flags >*/ NM_CONFIG_GET_VALUE_NONE = 0, @@ -143,9 +132,10 @@ NMConfigData *nm_config_data_new_update_no_auto_default (const NMConfigData *bas NMConfigChangeFlags nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data); void nm_config_data_log (const NMConfigData *self, - const char *prefix, - const char *key_prefix, - /* FILE* */ gpointer print_stream); + const char *prefix, + const char *key_prefix, + const char *no_auto_default_file, + /* FILE* */ gpointer print_stream); const char *nm_config_data_get_config_main_file (const NMConfigData *config_data); const char *nm_config_data_get_config_description (const NMConfigData *config_data); @@ -164,6 +154,8 @@ const char *nm_config_data_get_connectivity_response (const NMConfigData *config int nm_config_data_get_autoconnect_retries_default (const NMConfigData *config_data); +NMAuthPolkitMode nm_config_data_get_main_auth_polkit (const NMConfigData *config_data); + const char *const*nm_config_data_get_no_auto_default (const NMConfigData *config_data); gboolean nm_config_data_get_no_auto_default_for_device (const NMConfigData *self, NMDevice *device); @@ -242,6 +234,9 @@ void nm_global_dns_config_free (NMGlobalDnsConfig *dns_config); NMGlobalDnsConfig *nm_global_dns_config_from_dbus (const GValue *value, GError **error); void nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value); +void nm_config_data_get_warnings (const NMConfigData *self, + GPtrArray *warnings); + /* private accessors */ GKeyFile *_nm_config_data_get_keyfile (const NMConfigData *self); GKeyFile *_nm_config_data_get_keyfile_user (const NMConfigData *self); diff --git a/src/nm-config.c b/src/nm-config.c index d1279814..a7bb3503 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> */ @@ -344,6 +330,12 @@ nm_config_get_first_start (NMConfig *config) return NM_CONFIG_GET_PRIVATE (config)->cli.first_start; } +const char * +nm_config_get_no_auto_default_file (NMConfig *config) +{ + return NM_CONFIG_GET_PRIVATE (config)->no_auto_default_file; +} + /*****************************************************************************/ static char ** @@ -1218,7 +1210,7 @@ read_entire_config (const NMConfigCmdLineOptions *cli, const char *system_config_dir, char **out_config_main_file, char **out_config_description, - char ***out_warnings, + GPtrArray *warnings, GError **error) { gs_unref_keyfile GKeyFile *keyfile = NULL; @@ -1228,14 +1220,13 @@ read_entire_config (const NMConfigCmdLineOptions *cli, guint i; gs_free char *o_config_main_file = NULL; const char *run_config_dir = ""; - gs_unref_ptrarray GPtrArray *warnings = NULL; - g_return_val_if_fail (config_dir, NULL); - g_return_val_if_fail (system_config_dir, NULL); - g_return_val_if_fail (!out_config_main_file || !*out_config_main_file, FALSE); - g_return_val_if_fail (!out_config_description || !*out_config_description, NULL); - g_return_val_if_fail (!error || !*error, FALSE); - g_return_val_if_fail (out_warnings && !*out_warnings, FALSE); + nm_assert (config_dir); + nm_assert (system_config_dir); + nm_assert (!out_config_main_file || !*out_config_main_file); + nm_assert (!out_config_description || !*out_config_description); + nm_assert (!error || !*error); + nm_assert (warnings); if ( (""RUN_CONFIG_DIR)[0] == '/' && !nm_streq (RUN_CONFIG_DIR, system_config_dir) @@ -1244,7 +1235,6 @@ read_entire_config (const NMConfigCmdLineOptions *cli, /* create a default configuration file. */ keyfile = nm_config_create_keyfile (); - warnings = g_ptr_array_new_with_free_func (g_free); system_confs = _get_config_dir_files (system_config_dir); confs = _get_config_dir_files (config_dir); @@ -1334,10 +1324,6 @@ read_entire_config (const NMConfigCmdLineOptions *cli, } NM_SET_OUT (out_config_main_file, g_steal_pointer (&o_config_main_file)); - g_ptr_array_add (warnings, NULL); - *out_warnings = (char **) g_ptr_array_free (warnings, warnings->len == 1); - g_steal_pointer (&warnings); - return g_steal_pointer (&keyfile); } @@ -2580,7 +2566,7 @@ nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags, gboolean emi char *config_description = NULL; gs_strfreev char **no_auto_default = NULL; gboolean intern_config_needs_rewrite; - gs_strfreev char **warnings = NULL; + gs_unref_ptrarray GPtrArray *warnings = NULL; guint i; g_return_if_fail (NM_IS_CONFIG (self)); @@ -2597,6 +2583,8 @@ nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags, gboolean emi return; } + warnings = g_ptr_array_new_with_free_func (g_free); + /* pass on the original command line options. This means, that * options specified at command line cannot ever be reloaded from * file. That seems desirable. @@ -2606,7 +2594,7 @@ nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags, gboolean emi priv->system_config_dir, &config_main_file, &config_description, - &warnings, + warnings, &error); if (!keyfile) { _LOGE ("Failed to reload the configuration: %s", error->message); @@ -2615,11 +2603,6 @@ nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags, gboolean emi return; } - if (emit_warnings && warnings) { - for (i = 0; warnings[i]; i++) - _LOGW ("%s", warnings[i]); - } - no_auto_default = no_auto_default_from_file (priv->no_auto_default_file); keyfile_intern = intern_config_read (priv->intern_config_file, @@ -2636,6 +2619,13 @@ nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags, gboolean emi (const char *const*) no_auto_default, keyfile, keyfile_intern); + + if (emit_warnings) { + nm_config_data_get_warnings (priv->config_data_orig, warnings); + for (i = 0; i < warnings->len; i++) + _LOGW ("%s", (const char *) warnings->pdata[i]); + } + g_free (config_main_file); g_free (config_description); g_key_file_unref (keyfile); @@ -2703,7 +2693,7 @@ _set_config_data (NMConfig *self, NMConfigData *new_data, NMConfigChangeFlags re _LOGI ("signal: %s (%s)", nm_config_change_flags_to_string (changes, NULL, 0), nm_config_data_get_config_description (new_data)); - nm_config_data_log (new_data, "CONFIG: ", " ", NULL); + nm_config_data_log (new_data, "CONFIG: ", " ", priv->no_auto_default_file, NULL); priv->config_data = new_data; } else if (had_new_data) _LOGI ("signal: %s (no changes from disk)", nm_config_change_flags_to_string (changes, NULL, 0)); @@ -2787,7 +2777,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) gs_free char *config_main_file = NULL; gs_free char *config_description = NULL; gs_strfreev char **no_auto_default = NULL; - gs_strfreev char **warnings = NULL; + gs_unref_ptrarray GPtrArray *warnings = NULL; gs_free char *configure_and_quit = NULL; gboolean intern_config_needs_rewrite; const char *s; @@ -2814,12 +2804,14 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) else priv->intern_config_file = g_strdup (DEFAULT_INTERN_CONFIG_FILE); + warnings = g_ptr_array_new_with_free_func (g_free); + keyfile = read_entire_config (&priv->cli, priv->config_dir, priv->system_config_dir, &config_main_file, &config_description, - &warnings, + warnings, error); if (!keyfile) return FALSE; @@ -2865,8 +2857,13 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) keyfile, keyfile_intern); + nm_config_data_get_warnings (priv->config_data_orig, warnings); + priv->config_data = g_object_ref (priv->config_data_orig); - priv->warnings = g_steal_pointer (&warnings); + if (warnings->len > 0) { + g_ptr_array_add (warnings, NULL); + priv->warnings = (char **) g_ptr_array_free (g_steal_pointer (&warnings), FALSE); + } return TRUE; } diff --git a/src/nm-config.h b/src/nm-config.h index 32ce236f..d9460ebb 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> */ @@ -163,6 +149,8 @@ gboolean nm_config_get_is_debug (NMConfig *config); gboolean nm_config_get_first_start (NMConfig *config); +const char *nm_config_get_no_auto_default_file (NMConfig *config); + void nm_config_set_values (NMConfig *self, GKeyFile *keyfile_intern_new, gboolean allow_write, @@ -231,7 +219,6 @@ extern char *_nm_config_match_env; #define NM_CONFIG_DEVICE_STATE_DIR ""NMRUNDIR"/devices" -#define NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_BOOL (nm_streq (""NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "true")) #define NM_CONFIG_DEFAULT_LOGGING_AUDIT_BOOL (nm_streq (""NM_CONFIG_DEFAULT_LOGGING_AUDIT, "true")) typedef enum { diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 694733f6..ccac6376 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de> * Copyright (C) 2011 Dan Williams <dcbw@redhat.com> * Copyright (C) 2016 - 2018 Red Hat, Inc. @@ -27,6 +13,7 @@ #include <curl/curl.h> #endif #include <linux/rtnetlink.h> +#include <glib-unix.h> #include "c-list/src/c-list.h" #include "nm-core-internal.h" @@ -327,7 +314,6 @@ _con_curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask) { NMConnectivityCheckHandle *cb_data; CURLMsg *msg; - CURLcode eret; int m_left; long response_code; CURLMcode ret; @@ -336,12 +322,13 @@ _con_curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask) ret = curl_multi_socket_action (mhandle, sockfd, ev_bitmask, &running_handles); if (ret != CURLM_OK) { - _LOGD ("connectivity check failed: (%d) %s", ret, curl_easy_strerror (ret)); + _LOGD ("connectivity check failed: (%d) %s", ret, curl_multi_strerror (ret)); success = FALSE; } while ((msg = curl_multi_info_read (mhandle, &m_left))) { const char *response; + CURLcode eret; if (msg->msg != CURLMSG_DONE) continue; @@ -422,10 +409,9 @@ _con_curl_timeout_cb (gpointer user_data) { NMConnectivityCheckHandle *cb_data = user_data; - cb_data->concheck.curl_timer = 0; _con_curl_check_connectivity (cb_data->concheck.curl_mhandle, CURL_SOCKET_TIMEOUT, 0); _complete_queued (cb_data->self); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } static int @@ -441,7 +427,8 @@ multi_timer_cb (CURLM *multi, long timeout_ms, void *userdata) typedef struct { NMConnectivityCheckHandle *cb_data; - GIOChannel *ch; + + GSource *source; /* this is a very simplistic weak-pointer. If ConCurlSockData gets * destroyed, it will set *destroy_notify to TRUE. @@ -450,15 +437,15 @@ typedef struct { * safely access @fdp after _con_curl_check_connectivity(). */ gboolean *destroy_notify; - guint ev; } ConCurlSockData; static gboolean -_con_curl_socketevent_cb (GIOChannel *ch, GIOCondition condition, gpointer user_data) +_con_curl_socketevent_cb (int fd, + GIOCondition condition, + gpointer user_data) { ConCurlSockData *fdp = user_data; NMConnectivityCheckHandle *cb_data = fdp->cb_data; - int fd = g_io_channel_unix_get_fd (ch); int action = 0; gboolean fdp_destroyed = FALSE; gboolean success; @@ -482,12 +469,12 @@ _con_curl_socketevent_cb (GIOChannel *ch, GIOCondition condition, gpointer user_ nm_assert (fdp->destroy_notify == &fdp_destroyed); fdp->destroy_notify = NULL; if (!success) - fdp->ev = 0; + nm_clear_g_source_inst (&fdp->source); } _complete_queued (cb_data->self); - return success ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } static int @@ -495,7 +482,6 @@ multi_socket_cb (CURL *e_handle, curl_socket_t fd, int what, void *userdata, voi { NMConnectivityCheckHandle *cb_data = userdata; ConCurlSockData *fdp = socketp; - GIOCondition condition = 0; (void) _NM_ENSURE_TYPE (int, fd); @@ -503,19 +489,21 @@ multi_socket_cb (CURL *e_handle, curl_socket_t fd, int what, void *userdata, voi if (fdp) { if (fdp->destroy_notify) *fdp->destroy_notify = TRUE; + nm_clear_g_source_inst (&fdp->source); curl_multi_assign (cb_data->concheck.curl_mhandle, fd, NULL); - nm_clear_g_source (&fdp->ev); - g_io_channel_unref (fdp->ch); g_slice_free (ConCurlSockData, fdp); } } else { + GIOCondition condition; + if (!fdp) { - fdp = g_slice_new0 (ConCurlSockData); - fdp->cb_data = cb_data; - fdp->ch = g_io_channel_unix_new (fd); + fdp = g_slice_new (ConCurlSockData); + *fdp = (ConCurlSockData) { + .cb_data = cb_data, + }; curl_multi_assign (cb_data->concheck.curl_mhandle, fd, fdp); } else - nm_clear_g_source (&fdp->ev); + nm_clear_g_source_inst (&fdp->source); if (what == CURL_POLL_IN) condition = G_IO_IN; @@ -523,9 +511,14 @@ multi_socket_cb (CURL *e_handle, curl_socket_t fd, int what, void *userdata, voi condition = G_IO_OUT; else if (what == CURL_POLL_INOUT) condition = G_IO_IN | G_IO_OUT; + else + condition = 0; - if (condition) - fdp->ev = g_io_add_watch (fdp->ch, condition, _con_curl_socketevent_cb, fdp); + if (condition) { + fdp->source = g_unix_fd_source_new (fd, condition); + g_source_set_callback (fdp->source, G_SOURCE_FUNC (_con_curl_socketevent_cb), fdp, NULL); + g_source_attach (fdp->source, NULL); + } } return CURLM_OK; diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h index 00d0e642..db113f74 100644 --- a/src/nm-connectivity.h +++ b/src/nm-connectivity.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de> * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index d896d4d3..fb92289f 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -1,21 +1,7 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2004 - 2018 Red Hat, Inc. - * Copyright 2005 - 2008 Novell, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2004 - 2018 Red Hat, Inc. + * Copyright (C) 2005 - 2008 Novell, Inc. */ #include "nm-default.h" @@ -245,102 +231,6 @@ nm_ethernet_address_is_valid (gconstpointer addr, gssize len) return TRUE; } -gconstpointer -nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen) -{ - g_return_val_if_fail (dst, NULL); - - switch (family) { - case AF_INET: - g_return_val_if_fail (plen <= 32, NULL); - - if (!src) { - /* allow "self-assignment", by specifying %NULL as source. */ - src = dst; - } - - *((guint32 *) dst) = nm_utils_ip4_address_clear_host_address (*((guint32 *) src), plen); - break; - case AF_INET6: - nm_utils_ip6_address_clear_host_address (dst, src, plen); - break; - default: - g_return_val_if_reached (NULL); - } - return dst; -} - -/* nm_utils_ip4_address_clear_host_address: - * @addr: source ip6 address - * @plen: prefix length of network - * - * returns: the input address, with the host address set to 0. - */ -in_addr_t -nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen) -{ - return addr & _nm_utils_ip4_prefix_to_netmask (plen); -} - -/* nm_utils_ip6_address_clear_host_address: - * @dst: destination output buffer, will contain the network part of the @src address - * @src: source ip6 address - * @plen: prefix length of network - * - * Note: this function is self assignment safe, to update @src inplace, set both - * @dst and @src to the same destination or set @src NULL. - */ -const struct in6_addr * -nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen) -{ - g_return_val_if_fail (plen <= 128, NULL); - g_return_val_if_fail (dst, NULL); - - if (!src) - src = dst; - - if (plen < 128) { - guint nbytes = plen / 8; - guint nbits = plen % 8; - - if (nbytes && dst != src) - memcpy (dst, src, nbytes); - if (nbits) { - dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits))); - nbytes++; - } - if (nbytes <= 15) - memset (&dst->s6_addr[nbytes], 0, 16 - nbytes); - } else if (src != dst) - *dst = *src; - - return dst; -} - -int -nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen) -{ - int nbytes; - guint8 va, vb, m; - - if (plen >= 128) - NM_CMP_DIRECT_MEMCMP (addr_a, addr_b, sizeof (struct in6_addr)); - else { - nbytes = plen / 8; - if (nbytes) - NM_CMP_DIRECT_MEMCMP (addr_a, addr_b, nbytes); - - plen = plen % 8; - if (plen != 0) { - m = ~((1 << (8 - plen)) - 1); - va = ((((const guint8 *) addr_a))[nbytes]) & m; - vb = ((((const guint8 *) addr_b))[nbytes]) & m; - NM_CMP_DIRECT (va, vb); - } - } - return 0; -} - /*****************************************************************************/ void @@ -1113,7 +1003,7 @@ const char *const NM_PATHS_DEFAULT[] = { }; const char * -nm_utils_find_helper(const char *progname, const char *try_first, GError **error) +nm_utils_find_helper (const char *progname, const char *try_first, GError **error) { return nm_utils_file_search_in_paths (progname, try_first, NM_PATHS_DEFAULT, G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, error); } @@ -2431,8 +2321,8 @@ again: * where our configured SYSCONFDIR is. Alternatively, it might be in * LOCALSTATEDIR /lib/dbus/machine-id. */ - if ( nm_utils_file_get_contents (-1, "/etc/machine-id", 100*1024, 0, &content, NULL, NULL) >= 0 - || nm_utils_file_get_contents (-1, LOCALSTATEDIR"/lib/dbus/machine-id", 100*1024, 0, &content, NULL, NULL) >= 0) { + if ( nm_utils_file_get_contents (-1, "/etc/machine-id", 100*1024, 0, &content, NULL, NULL, NULL) + || nm_utils_file_get_contents (-1, LOCALSTATEDIR"/lib/dbus/machine-id", 100*1024, 0, &content, NULL, NULL, NULL)) { g_strstrip (content); if (nm_utils_hexstr2bin_full (content, FALSE, @@ -2615,13 +2505,14 @@ _host_id_read (guint8 **out_host_id, GError *error = NULL; gboolean success; - if (nm_utils_file_get_contents (-1, - SECRET_KEY_FILE, - 10*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, - (char **) &file_content.str, - &file_content.len, - &error) < 0) { + if (!nm_utils_file_get_contents (-1, + SECRET_KEY_FILE, + 10*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, + &file_content.str, + &file_content.len, + NULL, + &error)) { if (!nm_utils_error_is_notfound (error)) { nm_log_warn (LOGD_CORE, "secret-key: failure reading secret key in \"%s\": %s (generate new key)", SECRET_KEY_FILE, error->message); @@ -2699,6 +2590,7 @@ _host_id_read (guint8 **out_host_id, (const char *) new_content, len, 0600, + NULL, &error)) { nm_log_warn (LOGD_CORE, "secret-key: failure to persist secret key in \"%s\" (%s) (use non-persistent key)", SECRET_KEY_FILE, error->message); @@ -2809,9 +2701,14 @@ again: NMUuid uuid; gboolean is_fake = FALSE; - nm_utils_file_get_contents (-1, "/proc/sys/kernel/random/boot_id", 0, + nm_utils_file_get_contents (-1, + "/proc/sys/kernel/random/boot_id", + 0, NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, NULL, NULL); + &contents, + NULL, + NULL, + NULL); if ( !contents || !_nm_utils_uuid_parse (nm_strstrip (contents), &uuid)) { /* generate a random UUID instead. */ @@ -3625,12 +3522,7 @@ nm_utils_create_dhcp_iaid (gboolean legacy_unstable_byteorder, /** * nm_utils_dhcp_client_id_systemd_node_specific_full: - * @legacy_unstable_byteorder: historically, the code would generate a iaid - * dependent on host endianness. This is undesirable, if backward compatibility - * are not a concern, generate stable endianness. - * @interface_id: a binary identifier that is hashed into the DUID. - * Comonly this is the interface-name, but it may be the MAC address. - * @interface_id_len: the length of @interface_id. + * @iaid: the IAID (identity association identifier) in native byte order * @machine_id: the binary identifier for the machine. It is hashed * into the DUID. It commonly is /etc/machine-id (parsed in binary as NMUuid). * @machine_id_len: the length of the @machine_id. @@ -3642,9 +3534,7 @@ nm_utils_create_dhcp_iaid (gboolean legacy_unstable_byteorder, * Returns: a %GBytes of generated client-id. This function cannot fail. */ GBytes * -nm_utils_dhcp_client_id_systemd_node_specific_full (gboolean legacy_unstable_byteorder, - const guint8 *interface_id, - gsize interface_id_len, +nm_utils_dhcp_client_id_systemd_node_specific_full (guint32 iaid, const guint8 *machine_id, gsize machine_id_len) { @@ -3665,24 +3555,15 @@ nm_utils_dhcp_client_id_systemd_node_specific_full (gboolean legacy_unstable_byt } duid; } *client_id; guint64 u64; - guint32 u32; - g_return_val_if_fail (interface_id, NULL); - g_return_val_if_fail (interface_id_len > 0, NULL); g_return_val_if_fail (machine_id, NULL); g_return_val_if_fail (machine_id_len > 0, NULL); client_id = g_malloc (sizeof (*client_id)); client_id->type = 255; - - u32 = nm_utils_create_dhcp_iaid (legacy_unstable_byteorder, - interface_id, - interface_id_len); - unaligned_write_be32 (&client_id->iaid, u32); - + unaligned_write_be32 (&client_id->iaid, iaid); unaligned_write_be16 (&client_id->duid.type, DUID_TYPE_EN); - unaligned_write_be32 (&client_id->duid.en.pen, SYSTEMD_PEN); u64 = htole64 (c_siphash_hash (HASH_KEY, machine_id, machine_id_len)); @@ -3693,14 +3574,9 @@ nm_utils_dhcp_client_id_systemd_node_specific_full (gboolean legacy_unstable_byt } GBytes * -nm_utils_dhcp_client_id_systemd_node_specific (gboolean legacy_unstable_byteorder, - const char *ifname) +nm_utils_dhcp_client_id_systemd_node_specific (guint32 iaid) { - g_return_val_if_fail (ifname && ifname[0], NULL); - - return nm_utils_dhcp_client_id_systemd_node_specific_full (legacy_unstable_byteorder, - (const guint8 *) ifname, - strlen (ifname), + return nm_utils_dhcp_client_id_systemd_node_specific_full (iaid, (const guint8 *) nm_utils_machine_id_bin (), sizeof (NMUuid)); } @@ -3751,66 +3627,6 @@ nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings) /*****************************************************************************/ -static gboolean -debug_key_matches (const char *key, - const char *token, - guint length) -{ - /* may not call GLib functions: see note in g_parse_debug_string() */ - for (; length; length--, key++, token++) { - char k = (*key == '_') ? '-' : g_ascii_tolower (*key ); - char t = (*token == '_') ? '-' : g_ascii_tolower (*token); - - if (k != t) - return FALSE; - } - - return *key == '\0'; -} - -/** - * nm_utils_parse_debug_string: - * @string: the string to parse - * @keys: the debug keys - * @nkeys: number of entries in @keys - * - * Similar to g_parse_debug_string(), but does not special - * case "help" or "all". - * - * Returns: the flags - */ -guint -nm_utils_parse_debug_string (const char *string, - const GDebugKey *keys, - guint nkeys) -{ - guint i; - guint result = 0; - const char *q; - - if (string == NULL) - return 0; - - while (*string) { - q = strpbrk (string, ":;, \t"); - if (!q) - q = string + strlen (string); - - for (i = 0; i < nkeys; i++) { - if (debug_key_matches (keys[i].key, string, q - string)) - result |= keys[i].value; - } - - string = q; - if (*string) - string++; - } - - return result; -} - -/*****************************************************************************/ - void nm_utils_ifname_cpy (char *dst, const char *name) { diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index a0efb3b8..7d63d06a 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -1,21 +1,7 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2004 - 2016 Red Hat, Inc. - * Copyright 2005 - 2008 Novell, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2004 - 2016 Red Hat, Inc. + * Copyright (C) 2005 - 2008 Novell, Inc. */ #ifndef __NM_CORE_UTILS_H__ @@ -402,14 +388,11 @@ guint32 nm_utils_create_dhcp_iaid (gboolean legacy_unstable_byteorder, const guint8 *interface_id, gsize interface_id_len); -GBytes *nm_utils_dhcp_client_id_systemd_node_specific_full (gboolean legacy_unstable_byteorder, - const guint8 *interface_id, - gsize interface_id_len, +GBytes *nm_utils_dhcp_client_id_systemd_node_specific_full (guint32 iaid, const guint8 *machine_id, gsize machine_id_len); -GBytes *nm_utils_dhcp_client_id_systemd_node_specific (gboolean legacy_unstable_byteorder, - const char *ifname); +GBytes *nm_utils_dhcp_client_id_systemd_node_specific (guint32 iaid); /*****************************************************************************/ @@ -439,10 +422,6 @@ void _nm_utils_set_testing (NMUtilsTestFlags flags); void nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings); -guint nm_utils_parse_debug_string (const char *string, - const GDebugKey *keys, - guint nkeys); - void nm_utils_ifname_cpy (char *dst, const char *name); guint32 nm_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp, diff --git a/src/nm-dbus-manager.c b/src/nm-dbus-manager.c index a14ea120..3f6f8115 100644 --- a/src/nm-dbus-manager.c +++ b/src/nm-dbus-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -772,86 +758,6 @@ nm_dbus_manager_get_unix_user (NMDBusManager *self, /*****************************************************************************/ -const char * -nm_dbus_manager_connection_get_private_name (NMDBusManager *self, - GDBusConnection *connection) -{ - NMDBusManagerPrivate *priv; - PrivateServer *s; - const char *owner; - - g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), FALSE); - g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE); - - if (g_dbus_connection_get_unique_name (connection)) { - /* Shortcut. The connection is not a private connection. */ - return NULL; - } - - priv = NM_DBUS_MANAGER_GET_PRIVATE (self); - c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) { - if ((owner = private_server_get_connection_owner (s, connection))) - return owner; - } - g_return_val_if_reached (NULL); -} - -/** - * nm_dbus_manager_new_proxy: - * @self: the #NMDBusManager - * @connection: the GDBusConnection for which this connection should be created - * @proxy_type: the type of #GDBusProxy to create - * @name: any name on the message bus - * @path: name of the object instance to call methods on - * @iface: name of the interface to call methods on - * - * Creates a new proxy (of type @proxy_type) for a name on a given bus. Since - * the process which called the D-Bus method could be coming from a private - * connection or the system bus connection, different proxies must be created - * for each case. This function abstracts that. - * - * Returns: a #GDBusProxy capable of calling D-Bus methods of the calling process - */ -GDBusProxy * -nm_dbus_manager_new_proxy (NMDBusManager *self, - GDBusConnection *connection, - GType proxy_type, - const char *name, - const char *path, - const char *iface) -{ - const char *owner; - GDBusProxy *proxy; - GError *error = NULL; - - g_return_val_if_fail (g_type_is_a (proxy_type, G_TYPE_DBUS_PROXY), NULL); - g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); - - /* Might be a private connection, for which @name is fake */ - owner = nm_dbus_manager_connection_get_private_name (self, connection); - if (owner) { - g_return_val_if_fail (!g_strcmp0 (owner, name), NULL); - name = NULL; - } - - proxy = g_initable_new (proxy_type, NULL, &error, - "g-connection", connection, - "g-flags", (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS), - "g-name", name, - "g-object-path", path, - "g-interface-name", iface, - NULL); - if (!proxy) { - _LOGW ("could not create proxy for %s on connection %s: %s", - iface, name, error->message); - g_error_free (error); - } - return proxy; -} - -/*****************************************************************************/ - static const NMDBusInterfaceInfoExtended * _reg_data_get_interface_info (RegistrationData *reg_data) { @@ -1542,7 +1448,7 @@ static const GDBusSignalInfo signal_info_objmgr_interfaces_removed = NM_DEFINE_G ); static const GDBusInterfaceInfo interface_info_objmgr = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - "org.freedesktop.DBus.ObjectManager", + DBUS_INTERFACE_OBJECT_MANAGER, .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( NM_DEFINE_GDBUS_METHOD_INFO ( "GetManagedObjects", diff --git a/src/nm-dbus-manager.h b/src/nm-dbus-manager.h index c4a99563..a6094938 100644 --- a/src/nm-dbus-manager.h +++ b/src/nm-dbus-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2008 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -87,9 +73,6 @@ gboolean nm_dbus_manager_ensure_uid (NMDBusManager *self, GQuark error_domain, int error_code); -const char *nm_dbus_manager_connection_get_private_name (NMDBusManager *self, - GDBusConnection *connection); - gboolean nm_dbus_manager_get_unix_user (NMDBusManager *self, const char *sender, gulong *out_uid); @@ -105,11 +88,4 @@ void nm_dbus_manager_private_server_register (NMDBusManager *self, const char *path, const char *tag); -GDBusProxy *nm_dbus_manager_new_proxy (NMDBusManager *self, - GDBusConnection *connection, - GType proxy_type, - const char *name, - const char *path, - const char *iface); - #endif /* __NM_DBUS_MANAGER_H__ */ diff --git a/src/nm-dbus-object.c b/src/nm-dbus-object.c index abf1aa57..a829417c 100644 --- a/src/nm-dbus-object.c +++ b/src/nm-dbus-object.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/nm-dbus-object.h b/src/nm-dbus-object.h index 574107a1..8b36bce8 100644 --- a/src/nm-dbus-object.h +++ b/src/nm-dbus-object.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_DBUS_OBJECT_H__ diff --git a/src/nm-dbus-utils.c b/src/nm-dbus-utils.c index fe3eff7a..07fa909d 100644 --- a/src/nm-dbus-utils.c +++ b/src/nm-dbus-utils.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/nm-dbus-utils.h b/src/nm-dbus-utils.h index cf372e88..8ae6cb3a 100644 --- a/src/nm-dbus-utils.h +++ b/src/nm-dbus-utils.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_DBUS_UTILS_H__ diff --git a/src/nm-dcb.c b/src/nm-dcb.c index d6a9946b..d9ab2f57 100644 --- a/src/nm-dcb.c +++ b/src/nm-dcb.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/nm-dcb.h b/src/nm-dcb.h index 425e3e23..8c19d0dd 100644 --- a/src/nm-dcb.h +++ b/src/nm-dcb.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/nm-dhcp4-config.c b/src/nm-dhcp4-config.c index 8390a654..cdbe2071 100644 --- a/src/nm-dhcp4-config.c +++ b/src/nm-dhcp4-config.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/nm-dhcp4-config.h b/src/nm-dhcp4-config.h index 9853f4ff..3cad1e82 100644 --- a/src/nm-dhcp4-config.h +++ b/src/nm-dhcp4-config.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/nm-dhcp6-config.c b/src/nm-dhcp6-config.c index 5bbc20ef..676caa6d 100644 --- a/src/nm-dhcp6-config.c +++ b/src/nm-dhcp6-config.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/nm-dhcp6-config.h b/src/nm-dhcp6-config.h index ffe7b18d..e5697e04 100644 --- a/src/nm-dhcp6-config.h +++ b/src/nm-dhcp6-config.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index 652b9838..54b0567b 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2018 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ diff --git a/src/nm-dispatcher.h b/src/nm-dispatcher.h index 5c6c5805..93272dc4 100644 --- a/src/nm-dispatcher.h +++ b/src/nm-dispatcher.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ diff --git a/src/nm-firewall-manager.c b/src/nm-firewall-manager.c index 9b0d49c9..cf6494bd 100644 --- a/src/nm-firewall-manager.c +++ b/src/nm-firewall-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 - 2015 Red Hat, Inc. */ @@ -21,9 +7,16 @@ #include "nm-firewall-manager.h" -#include "NetworkManagerUtils.h" +#include "nm-glib-aux/nm-dbus-aux.h" #include "c-list/src/c-list.h" +#include "NetworkManagerUtils.h" +#include "nm-dbus-manager.h" + +#define FIREWALL_DBUS_SERVICE "org.fedoraproject.FirewallD1" +#define FIREWALL_DBUS_PATH "/org/fedoraproject/FirewallD1" +#define FIREWALL_DBUS_INTERFACE_ZONE "org.fedoraproject.FirewallD1.zone" + /*****************************************************************************/ enum { @@ -34,11 +27,16 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - GDBusProxy *proxy; - GCancellable *proxy_cancellable; + GDBusConnection *dbus_connection; + + GCancellable *get_name_owner_cancellable; + + CList pending_calls; - CList pending_calls; - bool running; + guint name_owner_changed_id; + + bool dbus_inited:1; + bool running:1; } NMFirewallManagerPrivate; struct _NMFirewallManager { @@ -61,27 +59,18 @@ NM_DEFINE_SINGLETON_GETTER (NMFirewallManager, nm_firewall_manager_get, NM_TYPE_ /*****************************************************************************/ typedef enum { - CB_INFO_OPS_ADD = 1, - CB_INFO_OPS_CHANGE, - CB_INFO_OPS_REMOVE, -} CBInfoOpsType; - -typedef enum { - CB_INFO_MODE_IDLE = 1, - CB_INFO_MODE_DBUS_WAITING, - CB_INFO_MODE_DBUS, - CB_INFO_MODE_DBUS_COMPLETED, -} CBInfoMode; + OPS_TYPE_ADD = 1, + OPS_TYPE_CHANGE, + OPS_TYPE_REMOVE, +} OpsType; struct _NMFirewallManagerCallId { CList lst; + NMFirewallManager *self; - CBInfoOpsType ops_type; - union { - const CBInfoMode mode; - CBInfoMode mode_mutable; - }; + char *iface; + NMFirewallManagerAddRemoveCallback callback; gpointer user_data; @@ -94,45 +83,57 @@ struct _NMFirewallManagerCallId { guint id; } idle; }; + + OpsType ops_type; + + bool is_idle:1; }; -typedef struct _NMFirewallManagerCallId CBInfo; /*****************************************************************************/ static const char * -_ops_type_to_string (CBInfoOpsType ops_type) +_ops_type_to_string (OpsType ops_type) { switch (ops_type) { - case CB_INFO_OPS_ADD: return "add"; - case CB_INFO_OPS_REMOVE: return "remove"; - case CB_INFO_OPS_CHANGE: return "change"; - default: g_return_val_if_reached ("unknown"); + case OPS_TYPE_ADD: return "add"; + case OPS_TYPE_REMOVE: return "remove"; + case OPS_TYPE_CHANGE: return "change"; } + nm_assert_not_reached (); + return NULL; } #define _NMLOG_DOMAIN LOGD_FIREWALL #define _NMLOG_PREFIX_NAME "firewall" -#define _NMLOG(level, info, ...) \ +#define _NMLOG(level, call_id, ...) \ G_STMT_START { \ if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \ - CBInfo *__info = (info); \ - char __prefix_name[30]; \ - char __prefix_info[64]; \ + NMFirewallManagerCallId *_call_id = (call_id); \ + char _prefix_name[30]; \ + char _prefix_info[100]; \ \ _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \ "%s: %s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ (self) != singleton_instance \ ? ({ \ - g_snprintf (__prefix_name, sizeof (__prefix_name), "%s[%p]", ""_NMLOG_PREFIX_NAME, (self)); \ - __prefix_name; \ + g_snprintf (_prefix_name, \ + sizeof (_prefix_name), \ + "%s["NM_HASH_OBFUSCATE_PTR_FMT"]", \ + ""_NMLOG_PREFIX_NAME,\ + NM_HASH_OBFUSCATE_PTR (self)); \ + _prefix_name; \ }) \ : _NMLOG_PREFIX_NAME, \ - __info \ + _call_id \ ? ({ \ - g_snprintf (__prefix_info, sizeof (__prefix_info), "[%p,%s%s:%s%s%s]: ", __info, \ - _ops_type_to_string (__info->ops_type), __info->mode == CB_INFO_MODE_IDLE ? "*" : "", \ - NM_PRINT_FMT_QUOTE_STRING (__info->iface)); \ - __prefix_info; \ + g_snprintf (_prefix_info, \ + sizeof (_prefix_info), \ + "["NM_HASH_OBFUSCATE_PTR_FMT",%s%s:%s%s%s]: ", \ + NM_HASH_OBFUSCATE_PTR (_call_id), \ + _ops_type_to_string (_call_id->ops_type), \ + _call_id->is_idle ? "*" : "", \ + NM_PRINT_FMT_QUOTE_STRING (_call_id->iface)); \ + _prefix_info; \ }) \ : "" \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ @@ -141,125 +142,152 @@ _ops_type_to_string (CBInfoOpsType ops_type) /*****************************************************************************/ +static gboolean +_get_running (NMFirewallManagerPrivate *priv) +{ + /* when starting, we need to asynchronously check whether there is + * a name owner. During that time we optimistially assume that the + * service is indeed running. That is the time when we queue the + * requests, and they will be started once the get-name-owner call + * returns. */ + return priv->running + || ( priv->dbus_connection + && !priv->dbus_inited); +} + gboolean nm_firewall_manager_get_running (NMFirewallManager *self) { g_return_val_if_fail (NM_IS_FIREWALL_MANAGER (self), FALSE); - return NM_FIREWALL_MANAGER_GET_PRIVATE (self)->running; + return _get_running (NM_FIREWALL_MANAGER_GET_PRIVATE (self)); } /*****************************************************************************/ -static CBInfo * +static NMFirewallManagerCallId * _cb_info_create (NMFirewallManager *self, - CBInfoOpsType ops_type, + OpsType ops_type, const char *iface, const char *zone, NMFirewallManagerAddRemoveCallback callback, gpointer user_data) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - CBInfo *info; - - info = g_slice_new0 (CBInfo); - info->self = g_object_ref (self); - info->ops_type = ops_type; - info->iface = g_strdup (iface); - info->callback = callback; - info->user_data = user_data; - - if (priv->running || priv->proxy_cancellable) { - info->mode_mutable = CB_INFO_MODE_DBUS_WAITING; - info->dbus.arg = g_variant_new ("(ss)", zone ?: "", iface); - } else - info->mode_mutable = CB_INFO_MODE_IDLE; + NMFirewallManagerCallId *call_id; - c_list_link_tail (&priv->pending_calls, &info->lst); + call_id = g_slice_new0 (NMFirewallManagerCallId); - return info; -} + call_id->self = g_object_ref (self); + call_id->ops_type = ops_type; + call_id->iface = g_strdup (iface); + call_id->callback = callback; + call_id->user_data = user_data; -static void -_cb_info_free (CBInfo *info) -{ - c_list_unlink_stale (&info->lst); - if (info->mode != CB_INFO_MODE_IDLE) { - if (info->dbus.arg) - g_variant_unref (info->dbus.arg); - g_clear_object (&info->dbus.cancellable); - } - g_free (info->iface); - if (info->self) - g_object_unref (info->self); - g_slice_free (CBInfo, info); -} + if (_get_running (priv)) { + call_id->is_idle = FALSE; + call_id->dbus.arg = g_variant_new ("(ss)", zone ?: "", iface); + } else + call_id->is_idle = TRUE; -static void -_cb_info_callback (CBInfo *info, - GError *error) -{ - if (info->callback) - info->callback (info->self, info, error, info->user_data); + c_list_link_tail (&priv->pending_calls, &call_id->lst); + + return call_id; } static void -_cb_info_complete_normal (CBInfo *info, GError *error) +_cb_info_complete (NMFirewallManagerCallId *call_id, + GError *error) { - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self); + c_list_unlink (&call_id->lst); - nm_assert (c_list_contains (&priv->pending_calls, &info->lst)); + if (call_id->callback) + call_id->callback (call_id->self, call_id, error, call_id->user_data); - c_list_unlink (&info->lst); - - _cb_info_callback (info, error); - _cb_info_free (info); + if (call_id->is_idle) + nm_clear_g_source (&call_id->idle.id); + else { + nm_g_variant_unref (call_id->dbus.arg); + nm_clear_g_cancellable (&call_id->dbus.cancellable); + } + g_free (call_id->iface); + g_object_unref (call_id->self); + nm_g_slice_free (call_id); } static gboolean -_handle_idle (gpointer user_data) +_handle_idle_cb (gpointer user_data) { NMFirewallManager *self; - CBInfo *info = user_data; + NMFirewallManagerCallId *call_id = user_data; + + nm_assert (call_id); + nm_assert (NM_IS_FIREWALL_MANAGER (call_id->self)); + nm_assert (call_id->is_idle); + nm_assert (c_list_contains (&NM_FIREWALL_MANAGER_GET_PRIVATE (call_id->self)->pending_calls, &call_id->lst)); - nm_assert (info && NM_IS_FIREWALL_MANAGER (info->self)); + self = call_id->self; - self = info->self; + _LOGD (call_id, "complete: fake success"); - _LOGD (info, "complete: fake success"); + call_id->idle.id = 0; - _cb_info_complete_normal (info, NULL); + _cb_info_complete (call_id, NULL); return G_SOURCE_REMOVE; } +static gboolean +_handle_idle_start (NMFirewallManager *self, + NMFirewallManagerCallId *call_id) +{ + if (!call_id->callback) { + /* if the user did not provide a callback and firewalld is not running, + * there is no point in scheduling an idle-request to fake success. Just + * return right away. */ + _LOGD (call_id, "complete: drop request simulating success"); + _cb_info_complete (call_id, NULL); + return FALSE; + } + call_id->idle.id = g_idle_add (_handle_idle_cb, call_id); + return TRUE; +} + static void -_handle_dbus (GObject *proxy, GAsyncResult *result, gpointer user_data) +_handle_dbus_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) { NMFirewallManager *self; - CBInfo *info = user_data; + NMFirewallManagerCallId *call_id; gs_free_error GError *error = NULL; gs_unref_variant GVariant *ret = NULL; - if (info->mode != CB_INFO_MODE_DBUS) { - _cb_info_free (info); + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) return; - } - self = info->self; + call_id = user_data; - ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + nm_assert (call_id); + nm_assert (NM_IS_FIREWALL_MANAGER (call_id->self)); + nm_assert (!call_id->is_idle); + nm_assert (c_list_contains (&NM_FIREWALL_MANAGER_GET_PRIVATE (call_id->self)->pending_calls, &call_id->lst)); + + self = call_id->self; if (error) { const char *non_error = NULL; g_dbus_error_strip_remote_error (error); - switch (info->ops_type) { - case CB_INFO_OPS_ADD: - case CB_INFO_OPS_CHANGE: + switch (call_id->ops_type) { + case OPS_TYPE_ADD: + case OPS_TYPE_CHANGE: non_error = "ZONE_ALREADY_SET"; break; - case CB_INFO_OPS_REMOVE: + case OPS_TYPE_REMOVE: non_error = "UNKNOWN_INTERFACE"; break; } @@ -267,118 +295,122 @@ _handle_dbus (GObject *proxy, GAsyncResult *result, gpointer user_data) && non_error && g_str_has_prefix (error->message, non_error) && NM_IN_SET (error->message[strlen (non_error)], '\0', ':')) { - _LOGD (info, "complete: request failed with a non-error (%s)", error->message); + _LOGD (call_id, "complete: request failed with a non-error (%s)", error->message); /* The operation failed with an error reason that we don't want * to propagate. Instead, signal success. */ g_clear_error (&error); } else - _LOGW (info, "complete: request failed (%s)", error->message); + _LOGW (call_id, "complete: request failed (%s)", error->message); } else - _LOGD (info, "complete: success"); + _LOGD (call_id, "complete: success"); + + g_clear_object (&call_id->dbus.cancellable); - _cb_info_complete_normal (info, error); + _cb_info_complete (call_id, error); } static void _handle_dbus_start (NMFirewallManager *self, - CBInfo *info) + NMFirewallManagerCallId *call_id) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); const char *dbus_method = NULL; GVariant *arg; - nm_assert (info); + nm_assert (call_id); nm_assert (priv->running); - nm_assert (info->mode == CB_INFO_MODE_DBUS_WAITING); + nm_assert (!call_id->is_idle); + nm_assert (c_list_contains (&priv->pending_calls, &call_id->lst)); - switch (info->ops_type) { - case CB_INFO_OPS_ADD: + switch (call_id->ops_type) { + case OPS_TYPE_ADD: dbus_method = "addInterface"; break; - case CB_INFO_OPS_CHANGE: + case OPS_TYPE_CHANGE: dbus_method = "changeZone"; break; - case CB_INFO_OPS_REMOVE: + case OPS_TYPE_REMOVE: dbus_method = "removeInterface"; break; } nm_assert (dbus_method); - arg = info->dbus.arg; - info->dbus.arg = NULL; + arg = g_steal_pointer (&call_id->dbus.arg); nm_assert (arg && g_variant_is_floating (arg)); - info->mode_mutable = CB_INFO_MODE_DBUS; - info->dbus.cancellable = g_cancellable_new (); - - g_dbus_proxy_call (priv->proxy, - dbus_method, - arg, - G_DBUS_CALL_FLAGS_NONE, 10000, - info->dbus.cancellable, - _handle_dbus, - info); + nm_assert (!call_id->dbus.cancellable); + + call_id->dbus.cancellable = g_cancellable_new (); + + g_dbus_connection_call (priv->dbus_connection, + FIREWALL_DBUS_SERVICE, + FIREWALL_DBUS_PATH, + FIREWALL_DBUS_INTERFACE_ZONE, + dbus_method, + arg, + NULL, + G_DBUS_CALL_FLAGS_NONE, + 10000, + call_id->dbus.cancellable, + _handle_dbus_cb, + call_id); } -static NMFirewallManagerCallId +static NMFirewallManagerCallId * _start_request (NMFirewallManager *self, - CBInfoOpsType ops_type, + OpsType ops_type, const char *iface, const char *zone, NMFirewallManagerAddRemoveCallback callback, gpointer user_data) { NMFirewallManagerPrivate *priv; - CBInfo *info; + NMFirewallManagerCallId *call_id; g_return_val_if_fail (NM_IS_FIREWALL_MANAGER (self), NULL); g_return_val_if_fail (iface && *iface, NULL); priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - info = _cb_info_create (self, ops_type, iface, zone, callback, user_data); + call_id = _cb_info_create (self, ops_type, iface, zone, callback, user_data); - _LOGD (info, "firewall zone %s %s:%s%s%s%s", - _ops_type_to_string (info->ops_type), + _LOGD (call_id, "firewall zone %s %s:%s%s%s%s", + _ops_type_to_string (call_id->ops_type), iface, NM_PRINT_FMT_QUOTED (zone, "\"", zone, "\"", "default"), - info->mode == CB_INFO_MODE_IDLE + call_id->is_idle ? " (not running, simulate success)" : (!priv->running ? " (waiting to initialize)" : "")); - if (info->mode == CB_INFO_MODE_DBUS_WAITING) { + if (!call_id->is_idle) { if (priv->running) - _handle_dbus_start (self, info); - if (!info->callback) { + _handle_dbus_start (self, call_id); + if (!call_id->callback) { /* if the user did not provide a callback, the call_id is useless. * Especially, the user cannot use the call-id to cancel the request, * because he cannot know whether the request is still pending. * * Hence, returning %NULL doesn't mean that the request could not be started - * (the request will always be started). */ + * (this function never fails and always starts a request). */ return NULL; } - } else if (info->mode == CB_INFO_MODE_IDLE) { - if (!info->callback) { + } else { + if (!_handle_idle_start (self, call_id)) { /* if the user did not provide a callback and firewalld is not running, * there is no point in scheduling an idle-request to fake success. Just * return right away. */ - _LOGD (info, "complete: drop request simulating success"); - _cb_info_complete_normal (info, NULL); return NULL; - } else - info->idle.id = g_idle_add (_handle_idle, info); - } else - nm_assert_not_reached (); + } + } - return info; + return call_id; } -NMFirewallManagerCallId +NMFirewallManagerCallId * nm_firewall_manager_add_or_change_zone (NMFirewallManager *self, const char *iface, const char *zone, @@ -387,14 +419,14 @@ nm_firewall_manager_add_or_change_zone (NMFirewallManager *self, gpointer user_data) { return _start_request (self, - add ? CB_INFO_OPS_ADD : CB_INFO_OPS_CHANGE, + add ? OPS_TYPE_ADD : OPS_TYPE_CHANGE, iface, zone, callback, user_data); } -NMFirewallManagerCallId +NMFirewallManagerCallId * nm_firewall_manager_remove_from_zone (NMFirewallManager *self, const char *iface, const char *zone, @@ -402,7 +434,7 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self, gpointer user_data) { return _start_request (self, - CB_INFO_OPS_REMOVE, + OPS_TYPE_REMOVE, iface, zone, callback, @@ -410,162 +442,165 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self, } void -nm_firewall_manager_cancel_call (NMFirewallManagerCallId call) +nm_firewall_manager_cancel_call (NMFirewallManagerCallId *call_id) { NMFirewallManager *self; NMFirewallManagerPrivate *priv; - CBInfo *info = call; gs_free_error GError *error = NULL; - g_return_if_fail (info); - g_return_if_fail (NM_IS_FIREWALL_MANAGER (info->self)); + g_return_if_fail (call_id); + g_return_if_fail (NM_IS_FIREWALL_MANAGER (call_id->self)); + g_return_if_fail (!c_list_is_empty (&call_id->lst)); - self = info->self; + self = call_id->self; priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - nm_assert (c_list_contains (&priv->pending_calls, &info->lst)); - - c_list_unlink (&info->lst); + nm_assert (c_list_contains (&priv->pending_calls, &call_id->lst)); nm_utils_error_set_cancelled (&error, FALSE, "NMFirewallManager"); - _LOGD (info, "complete: cancel (%s)", error->message); - - _cb_info_callback (info, error); + _LOGD (call_id, "complete: cancel (%s)", error->message); - if (info->mode == CB_INFO_MODE_DBUS_WAITING) - _cb_info_free (info); - else if (info->mode == CB_INFO_MODE_IDLE) { - g_source_remove (info->idle.id); - _cb_info_free (info); - } else { - info->mode_mutable = CB_INFO_MODE_DBUS_COMPLETED; - g_cancellable_cancel (info->dbus.cancellable); - g_clear_object (&info->self); - } + _cb_info_complete (call_id, error); } /*****************************************************************************/ -static gboolean -name_owner_changed (NMFirewallManager *self) +static void +name_owner_changed (NMFirewallManager *self, + const char *owner) { + _nm_unused gs_unref_object NMFirewallManager *self_keep_alive = g_object_ref (self); NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - gs_free char *owner = NULL; + gboolean was_running; gboolean now_running; + gboolean just_initied; + + owner = nm_str_not_empty (owner); + + if (!owner) + _LOGT (NULL, "D-Bus name for firewalld has no owner (firewall stopped)"); + else + _LOGT (NULL, "D-Bus name for firewalld has owner %s (firewall started)", owner); + + was_running = _get_running (priv); + just_initied = !priv->dbus_inited; + + priv->dbus_inited = TRUE; + priv->running = !!owner; + + now_running = _get_running (priv); + + if (just_initied) { + NMFirewallManagerCallId *call_id_safe; + NMFirewallManagerCallId *call_id; + + /* We kick of the requests that we have pending. Note that this is + * entirely asynchronous and also we don't invoke any callbacks for + * the user. + * Even _handle_idle_start() just schedules an idle handler. That is, + * because we don't want to callback to the user before emitting the + * DISCONNECTED signal below. Also, emitting callbacks means the user + * can call back to modify the list of pending-calls and we'd have + * to handle reentrancy. */ + c_list_for_each_entry_safe (call_id, call_id_safe, &priv->pending_calls, lst) { + + nm_assert (!call_id->is_idle); + nm_assert (call_id->dbus.arg); + + if (priv->running) { + _LOGD (call_id, "initalizing: make D-Bus call"); + _handle_dbus_start (self, call_id); + } else { + /* we don't want to invoke callbacks to the user right away. That is because + * the user might schedule/cancel more calls, which messes up the order. + * + * Instead, convert the pending calls to idle requests... */ + nm_clear_pointer (&call_id->dbus.arg, g_variant_unref); + call_id->is_idle = TRUE; + _LOGD (call_id, "initializing: fake success on idle"); + _handle_idle_start (self, call_id); + } + } + } - owner = g_dbus_proxy_get_name_owner (priv->proxy); - now_running = !!owner; - - if (now_running == priv->running) - return FALSE; - - priv->running = now_running; - _LOGD (NULL, "firewall %s", now_running ? "started" : "stopped"); - return TRUE; + if (was_running != now_running) + g_signal_emit (self, signals[STATE_CHANGED], 0, FALSE); } static void -name_owner_changed_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) +name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) { NMFirewallManager *self = user_data; + const char *new_owner; - nm_assert (NM_IS_FIREWALL_MANAGER (self)); - nm_assert (G_IS_DBUS_PROXY (object)); - nm_assert (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy == G_DBUS_PROXY (object)); + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) + return; - if (name_owner_changed (self)) - g_signal_emit (self, signals[STATE_CHANGED], 0, FALSE); + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + + name_owner_changed (self, new_owner); } static void -_proxy_new_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) +get_name_owner_cb (const char *name_owner, + GError *error, + gpointer user_data) { NMFirewallManager *self; NMFirewallManagerPrivate *priv; - GDBusProxy *proxy; - gs_free_error GError *error = NULL; - CBInfo *info; - CList *iter; - proxy = g_dbus_proxy_new_for_bus_finish (result, &error); - if ( !proxy + if ( !name_owner && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = user_data; priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - g_clear_object (&priv->proxy_cancellable); - if (!proxy) { - _LOGW (NULL, "could not connect to system D-Bus (%s)", error->message); - return; - } + g_clear_object (&priv->get_name_owner_cancellable); - priv->proxy = proxy; - g_signal_connect (priv->proxy, "notify::g-name-owner", - G_CALLBACK (name_owner_changed_cb), self); - - if (!name_owner_changed (self)) - _LOGD (NULL, "firewall %s", "initialized (not running)"); - -again: - c_list_for_each (iter, &priv->pending_calls) { - info = c_list_entry (iter, CBInfo, lst); - - if (info->mode != CB_INFO_MODE_DBUS_WAITING) - continue; - if (priv->running) { - _LOGD (info, "make D-Bus call"); - _handle_dbus_start (self, info); - } else { - _LOGD (info, "complete: fake success"); - c_list_unlink (&info->lst); - _cb_info_callback (info, NULL); - _cb_info_free (info); - goto again; - } - } - - /* we always emit a state-changed signal, even if the - * "running" property is still false. */ - g_signal_emit (self, signals[STATE_CHANGED], 0, TRUE); + name_owner_changed (self, name_owner); } /*****************************************************************************/ static void -nm_firewall_manager_init (NMFirewallManager * self) +nm_firewall_manager_init (NMFirewallManager *self) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); c_list_init (&priv->pending_calls); -} - -static void -constructed (GObject *object) -{ - NMFirewallManager *self = (NMFirewallManager *) object; - NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); - priv->proxy_cancellable = g_cancellable_new (); + priv->dbus_connection = nm_g_object_ref (NM_MAIN_DBUS_CONNECTION_GET); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - FIREWALL_DBUS_SERVICE, - FIREWALL_DBUS_PATH, - FIREWALL_DBUS_INTERFACE_ZONE, - priv->proxy_cancellable, - _proxy_new_cb, - self); + if (!priv->dbus_connection) { + _LOGD (NULL, "no D-Bus connection"); + return; + } - G_OBJECT_CLASS (nm_firewall_manager_parent_class)->constructed (object); + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + FIREWALL_DBUS_SERVICE, + name_owner_changed_cb, + self, + NULL); + + priv->get_name_owner_cancellable = g_cancellable_new (); + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + FIREWALL_DBUS_SERVICE, + -1, + priv->get_name_owner_cancellable, + get_name_owner_cb, + self); } static void @@ -578,10 +613,14 @@ dispose (GObject *object) * we don't expect pending operations at this point. */ nm_assert (c_list_is_empty (&priv->pending_calls)); - nm_clear_g_cancellable (&priv->proxy_cancellable); - g_clear_object (&priv->proxy); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); + + nm_clear_g_cancellable (&priv->get_name_owner_cancellable); G_OBJECT_CLASS (nm_firewall_manager_parent_class)->dispose (object); + + g_clear_object (&priv->dbus_connection); } static void @@ -589,7 +628,6 @@ nm_firewall_manager_class_init (NMFirewallManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->constructed = constructed; object_class->dispose = dispose; signals[STATE_CHANGED] = diff --git a/src/nm-firewall-manager.h b/src/nm-firewall-manager.h index ceca58be..689e6b06 100644 --- a/src/nm-firewall-manager.h +++ b/src/nm-firewall-manager.h @@ -1,30 +1,11 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_FIREWALL_MANAGER_H__ #define __NETWORKMANAGER_FIREWALL_MANAGER_H__ -#define FIREWALL_DBUS_SERVICE "org.fedoraproject.FirewallD1" -#define FIREWALL_DBUS_PATH "/org/fedoraproject/FirewallD1" -#define FIREWALL_DBUS_INTERFACE "org.fedoraproject.FirewallD1" -#define FIREWALL_DBUS_INTERFACE_ZONE "org.fedoraproject.FirewallD1.zone" - #define NM_TYPE_FIREWALL_MANAGER (nm_firewall_manager_get_type ()) #define NM_FIREWALL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_FIREWALL_MANAGER, NMFirewallManager)) #define NM_FIREWALL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_FIREWALL_MANAGER, NMFirewallManagerClass)) @@ -34,7 +15,7 @@ #define NM_FIREWALL_MANAGER_STATE_CHANGED "state-changed" -typedef struct _NMFirewallManagerCallId *NMFirewallManagerCallId; +typedef struct _NMFirewallManagerCallId NMFirewallManagerCallId; typedef struct _NMFirewallManager NMFirewallManager; typedef struct _NMFirewallManagerClass NMFirewallManagerClass; @@ -46,22 +27,22 @@ NMFirewallManager *nm_firewall_manager_get (void); gboolean nm_firewall_manager_get_running (NMFirewallManager *self); typedef void (*NMFirewallManagerAddRemoveCallback) (NMFirewallManager *self, - NMFirewallManagerCallId call_id, + NMFirewallManagerCallId *call_id, GError *error, gpointer user_data); -NMFirewallManagerCallId nm_firewall_manager_add_or_change_zone (NMFirewallManager *mgr, - const char *iface, - const char *zone, - gboolean add, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data); -NMFirewallManagerCallId nm_firewall_manager_remove_from_zone (NMFirewallManager *mgr, - const char *iface, - const char *zone, - NMFirewallManagerAddRemoveCallback callback, - gpointer user_data); - -void nm_firewall_manager_cancel_call (NMFirewallManagerCallId fw_call); +NMFirewallManagerCallId *nm_firewall_manager_add_or_change_zone (NMFirewallManager *mgr, + const char *iface, + const char *zone, + gboolean add, + NMFirewallManagerAddRemoveCallback callback, + gpointer user_data); +NMFirewallManagerCallId *nm_firewall_manager_remove_from_zone (NMFirewallManager *mgr, + const char *iface, + const char *zone, + NMFirewallManagerAddRemoveCallback callback, + gpointer user_data); + +void nm_firewall_manager_cancel_call (NMFirewallManagerCallId *call_id); #endif /* __NETWORKMANAGER_FIREWALL_MANAGER_H__ */ diff --git a/src/nm-hostname-manager.c b/src/nm-hostname-manager.c index 86da0168..f44e169e 100644 --- a/src/nm-hostname-manager.c +++ b/src/nm-hostname-manager.c @@ -1,20 +1,6 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/nm-hostname-manager.h b/src/nm-hostname-manager.h index 84ee7cb2..b826b14b 100644 --- a/src/nm-hostname-manager.h +++ b/src/nm-hostname-manager.h @@ -1,25 +1,10 @@ -/* NetworkManager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Søren Sandmann <sandmann@daimi.au.dk> * Dan Williams <dcbw@redhat.com> * Tambet Ingo <tambet@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007 - 2011, 2017 Red Hat, Inc. - * (C) Copyright 2008 Novell, Inc. + * Copyright (C) 2007 - 2011, 2017 Red Hat, Inc. + * Copyright (C) 2008 Novell, Inc. */ #ifndef __NM_HOSTNAME_MANAGER_H__ diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index afe3fc5d..bfb7af57 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -40,6 +26,7 @@ #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" #include "nm-utils.h" +#include "nm-core-internal.h" #include "nm-setting-ip6-config.h" #include "systemd/nm-sd.h" @@ -111,6 +98,7 @@ dhcp4_state_changed (NMDhcpClient *client, static NMIP4Config *last_config = NULL; NMIP4Config *existing; gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; + gs_free_error GError *error = NULL; g_return_if_fail (!ip4_config || NM_IS_IP4_CONFIG (ip4_config)); @@ -136,6 +124,9 @@ dhcp4_state_changed (NMDhcpClient *client, NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN)) _LOGW (LOGD_DHCP4, "failed to apply DHCPv4 config"); + if (!last_config && !nm_dhcp_client_accept (client, &error)) + _LOGW (LOGD_DHCP4, "failed to accept lease: %s", error->message); + nm_platform_ip4_dev_route_blacklist_set (NM_PLATFORM_GET, gl.ifindex, ip4_dev_route_blacklist); @@ -530,6 +521,7 @@ main (int argc, char *argv[]) !!global_opt.dhcp4_hostname, global_opt.dhcp4_hostname, global_opt.dhcp4_fqdn, + NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4, client_id, NM_DHCP_TIMEOUT_DEFAULT, NULL, @@ -605,9 +597,10 @@ main (int argc, char *argv[]) /*****************************************************************************/ -const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5] = { +const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = { + /* For nm-iface-helper there is no option to choose a DHCP plugin. + * It just uses the "internal" one. */ &_nm_dhcp_client_factory_internal, - &_nm_dhcp_client_factory_nettools, }; /*****************************************************************************/ diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 6dd08434..cd14fb8f 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -1,19 +1,5 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -718,12 +704,22 @@ nm_ip4_config_add_dependent_routes (NMIP4Config *self, /* The destination network depends on the peer-address. */ network = nm_utils_ip4_address_clear_host_address (my_addr->peer_address, my_addr->plen); + if (my_addr->external) + continue; + if (_ipv4_is_zeronet (network)) { /* Kernel doesn't add device-routes for destinations that * start with 0.x.y.z. Skip them. */ continue; } + if ( my_addr->plen == 32 + && my_addr->address == my_addr->peer_address) { + /* Kernel doesn't add device-routes for /32 addresses unless + * they have a peer. */ + continue; + } + r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL); route = NMP_OBJECT_CAST_IP4_ROUTE (r); @@ -866,8 +862,13 @@ _nm_ip_config_merge_route_attributes (int addr_family, GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0); r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN)); - if (addr_family == AF_INET) + if (addr_family == AF_INET) { + guint8 scope; + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0); + GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_SCOPE, scope, BYTE, byte, RT_SCOPE_NOWHERE); + r4->scope_inv = nm_platform_route_scope_inv (scope); + } GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE); @@ -993,8 +994,6 @@ nm_ip4_config_merge_setting (NMIP4Config *self, route.plen = nm_ip_route_get_prefix (s_route); nm_assert (route.plen <= 32); - if (route.plen == 0) - continue; nm_ip_route_get_next_hop_binary (s_route, &route.gateway); if (nm_ip_route_get_metric (s_route) == -1) @@ -1179,8 +1178,17 @@ nm_ip4_config_merge (NMIP4Config *dst, g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &address) - _add_address (dst, NMP_OBJECT_UP_CAST (address), NULL); + nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &address) { + if ( NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) + && !address->external) { + NMPlatformIP4Address a; + + a = *address; + a.external = TRUE; + _add_address (dst, NULL, &a); + } else + _add_address (dst, NMP_OBJECT_UP_CAST (address), NULL); + } /* nameservers */ if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index fe0a085b..01a42e54 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -1,20 +1,6 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2008–2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_IP4_CONFIG_H__ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 1810d511..12553657 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -494,6 +480,8 @@ nm_ip6_config_add_dependent_routes (NMIP6Config *self, gboolean has_peer; int routes_n, routes_i; + if (my_addr->external) + continue; if (NM_FLAGS_HAS (my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE)) continue; if (my_addr->plen == 0) @@ -672,8 +660,6 @@ nm_ip6_config_merge_setting (NMIP6Config *self, route.plen = nm_ip_route_get_prefix (s_route); nm_assert (route.plen <= 128); - if (route.plen == 0) - continue; nm_ip_route_get_next_hop_binary (s_route, &route.gateway); if (nm_ip_route_get_metric (s_route) == -1) @@ -865,8 +851,17 @@ nm_ip6_config_merge (NMIP6Config *dst, g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &address) - _add_address (dst, NMP_OBJECT_UP_CAST (address), NULL); + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &address) { + if ( NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) + && !address->external) { + NMPlatformIP6Address a; + + a = *address; + a.external = TRUE; + _add_address (dst, NULL, &a); + } else + _add_address (dst, NMP_OBJECT_UP_CAST (address), NULL); + } /* nameservers */ if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 6c7b4cf4..a9fa8f14 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -1,20 +1,6 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2008–2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_IP6_CONFIG_H__ diff --git a/src/nm-keep-alive.c b/src/nm-keep-alive.c index ba080a81..7a382f17 100644 --- a/src/nm-keep-alive.c +++ b/src/nm-keep-alive.c @@ -1,22 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * NetworkManager -- Inhibition management - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/nm-keep-alive.h b/src/nm-keep-alive.h index fcee9d6d..6efec5f5 100644 --- a/src/nm-keep-alive.h +++ b/src/nm-keep-alive.h @@ -1,22 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * NetworkManager -- Inhibition management - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_KEEP_ALIVE_H__ diff --git a/src/nm-logging.c b/src/nm-logging.c index ea505a81..34dd2797 100644 --- a/src/nm-logging.c +++ b/src/nm-logging.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2012 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -36,6 +22,7 @@ #include <systemd/sd-journal.h> #endif +#include "nm-glib-aux/nm-logging-base.h" #include "nm-glib-aux/nm-time-utils.h" #include "nm-errors.h" @@ -99,22 +86,6 @@ typedef struct { } LogDesc; typedef struct { - const char *name; - const char *level_str; - - /* nm-logging uses syslog internally. Note that the three most-verbose syslog levels - * are LOG_DEBUG, LOG_INFO and LOG_NOTICE. Journal already highlights LOG_NOTICE - * as special. - * - * On the other hand, we have three levels LOGL_TRACE, LOGL_DEBUG and LOGL_INFO, - * which are regular messages not to be highlighted. For that reason, we must map - * LOGL_TRACE and LOGL_DEBUG both to syslog level LOG_DEBUG. */ - int syslog_level; - - GLogLevelFlags g_log_level; -} LogLevelDesc; - -typedef struct { char *logging_domains_to_string; } GlobalMain; @@ -172,16 +143,6 @@ NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL] = { /*****************************************************************************/ -static const LogLevelDesc level_desc[_LOGL_N] = { - [LOGL_TRACE] = { "TRACE", "<trace>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, }, - [LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, }, - [LOGL_INFO] = { "INFO", "<info>", LOG_INFO, G_LOG_LEVEL_INFO, }, - [LOGL_WARN] = { "WARN", "<warn>", LOG_WARNING, G_LOG_LEVEL_MESSAGE, }, - [LOGL_ERR] = { "ERR", "<error>", LOG_ERR, G_LOG_LEVEL_MESSAGE, }, - [_LOGL_OFF] = { "OFF", NULL, 0, 0, }, - [_LOGL_KEEP] = { "KEEP", NULL, 0, 0, }, -}; - static const LogDesc domain_desc[] = { { LOGD_PLATFORM, "PLATFORM" }, { LOGD_RFKILL, "RFKILL" }, @@ -285,14 +246,8 @@ match_log_level (const char *level, NMLogLevel *out_level, GError **error) { - int i; - - for (i = 0; i < G_N_ELEMENTS (level_desc); i++) { - if (!g_ascii_strcasecmp (level_desc[i].name, level)) { - *out_level = i; - return TRUE; - } - } + if (_nm_log_parse_level (level, out_level)) + return TRUE; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, _("Unknown log level '%s'"), level); diff --git a/src/nm-logging.h b/src/nm-logging.h index c604f493..54887b0f 100644 --- a/src/nm-logging.h +++ b/src/nm-logging.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2012 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -84,9 +70,10 @@ LOGD_IP_from_af (int addr_family) (domain), \ (ifname), \ (con_uuid), \ - "%s[%p] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + "%s["NM_HASH_OBFUSCATE_PTR_FMT"] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ (prefix) ?: "", \ - self _NM_UTILS_MACRO_REST(__VA_ARGS__)) + NM_HASH_OBFUSCATE_PTR (self) \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)) static inline gboolean _nm_log_ptr_is_debug (NMLogLevel level) @@ -190,114 +177,6 @@ gboolean nm_logging_syslog_enabled (void); /*****************************************************************************/ -/* This is the default definition of _NMLOG_ENABLED(). Special implementations - * might want to undef this and redefine it. */ -#define _NMLOG_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG_DOMAIN)) ) - -#define _LOGT(...) _NMLOG (LOGL_TRACE, __VA_ARGS__) -#define _LOGD(...) _NMLOG (LOGL_DEBUG, __VA_ARGS__) -#define _LOGI(...) _NMLOG (LOGL_INFO , __VA_ARGS__) -#define _LOGW(...) _NMLOG (LOGL_WARN , __VA_ARGS__) -#define _LOGE(...) _NMLOG (LOGL_ERR , __VA_ARGS__) - -#define _LOGT_ENABLED(...) _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__) -#define _LOGD_ENABLED(...) _NMLOG_ENABLED (LOGL_DEBUG, ##__VA_ARGS__) -#define _LOGI_ENABLED(...) _NMLOG_ENABLED (LOGL_INFO , ##__VA_ARGS__) -#define _LOGW_ENABLED(...) _NMLOG_ENABLED (LOGL_WARN , ##__VA_ARGS__) -#define _LOGE_ENABLED(...) _NMLOG_ENABLED (LOGL_ERR , ##__VA_ARGS__) - -#define _LOGT_err(errsv, ...) _NMLOG_err (errsv, LOGL_TRACE, __VA_ARGS__) -#define _LOGD_err(errsv, ...) _NMLOG_err (errsv, LOGL_DEBUG, __VA_ARGS__) -#define _LOGI_err(errsv, ...) _NMLOG_err (errsv, LOGL_INFO , __VA_ARGS__) -#define _LOGW_err(errsv, ...) _NMLOG_err (errsv, LOGL_WARN , __VA_ARGS__) -#define _LOGE_err(errsv, ...) _NMLOG_err (errsv, LOGL_ERR , __VA_ARGS__) - -/* _LOGT() and _LOGt() both log with level TRACE, but the latter is disabled by default, - * unless building with --with-more-logging. */ -#if NM_MORE_LOGGING -#define _LOGt_ENABLED(...) _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__) -#define _LOGt(...) _NMLOG (LOGL_TRACE, __VA_ARGS__) -#define _LOGt_err(errsv, ...) _NMLOG_err (errsv, LOGL_TRACE, __VA_ARGS__) -#else -/* still call the logging macros to get compile time checks, but they will be optimized out. */ -#define _LOGt_ENABLED(...) ( FALSE && (_NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) ) -#define _LOGt(...) G_STMT_START { if (FALSE) { _NMLOG (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END -#define _LOGt_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END -#endif - -/*****************************************************************************/ - -/* Some implementation define a second set of logging macros, for a separate - * use. As with the _LOGD() macro family above, the exact implementation - * depends on the file that uses them. - * Still, it encourages a common pattern to have the common set of macros - * like _LOG2D(), _LOG2I(), etc. and have _LOG2t() which by default - * is disabled at compile time. */ - -#define _NMLOG2_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG2_DOMAIN)) ) - -#define _LOG2T(...) _NMLOG2 (LOGL_TRACE, __VA_ARGS__) -#define _LOG2D(...) _NMLOG2 (LOGL_DEBUG, __VA_ARGS__) -#define _LOG2I(...) _NMLOG2 (LOGL_INFO , __VA_ARGS__) -#define _LOG2W(...) _NMLOG2 (LOGL_WARN , __VA_ARGS__) -#define _LOG2E(...) _NMLOG2 (LOGL_ERR , __VA_ARGS__) - -#define _LOG2T_ENABLED(...) _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__) -#define _LOG2D_ENABLED(...) _NMLOG2_ENABLED (LOGL_DEBUG, ##__VA_ARGS__) -#define _LOG2I_ENABLED(...) _NMLOG2_ENABLED (LOGL_INFO , ##__VA_ARGS__) -#define _LOG2W_ENABLED(...) _NMLOG2_ENABLED (LOGL_WARN , ##__VA_ARGS__) -#define _LOG2E_ENABLED(...) _NMLOG2_ENABLED (LOGL_ERR , ##__VA_ARGS__) - -#define _LOG2T_err(errsv, ...) _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__) -#define _LOG2D_err(errsv, ...) _NMLOG2_err (errsv, LOGL_DEBUG, __VA_ARGS__) -#define _LOG2I_err(errsv, ...) _NMLOG2_err (errsv, LOGL_INFO , __VA_ARGS__) -#define _LOG2W_err(errsv, ...) _NMLOG2_err (errsv, LOGL_WARN , __VA_ARGS__) -#define _LOG2E_err(errsv, ...) _NMLOG2_err (errsv, LOGL_ERR , __VA_ARGS__) - -#if NM_MORE_LOGGING -#define _LOG2t_ENABLED(...) _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__) -#define _LOG2t(...) _NMLOG2 (LOGL_TRACE, __VA_ARGS__) -#define _LOG2t_err(errsv, ...) _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__) -#else -/* still call the logging macros to get compile time checks, but they will be optimized out. */ -#define _LOG2t_ENABLED(...) ( FALSE && (_NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) ) -#define _LOG2t(...) G_STMT_START { if (FALSE) { _NMLOG2 (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END -#define _LOG2t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG2_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END -#endif - -#define _NMLOG3_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG3_DOMAIN)) ) - -#define _LOG3T(...) _NMLOG3 (LOGL_TRACE, __VA_ARGS__) -#define _LOG3D(...) _NMLOG3 (LOGL_DEBUG, __VA_ARGS__) -#define _LOG3I(...) _NMLOG3 (LOGL_INFO , __VA_ARGS__) -#define _LOG3W(...) _NMLOG3 (LOGL_WARN , __VA_ARGS__) -#define _LOG3E(...) _NMLOG3 (LOGL_ERR , __VA_ARGS__) - -#define _LOG3T_ENABLED(...) _NMLOG3_ENABLED (LOGL_TRACE, ##__VA_ARGS__) -#define _LOG3D_ENABLED(...) _NMLOG3_ENABLED (LOGL_DEBUG, ##__VA_ARGS__) -#define _LOG3I_ENABLED(...) _NMLOG3_ENABLED (LOGL_INFO , ##__VA_ARGS__) -#define _LOG3W_ENABLED(...) _NMLOG3_ENABLED (LOGL_WARN , ##__VA_ARGS__) -#define _LOG3E_ENABLED(...) _NMLOG3_ENABLED (LOGL_ERR , ##__VA_ARGS__) - -#define _LOG3T_err(errsv, ...) _NMLOG3_err (errsv, LOGL_TRACE, __VA_ARGS__) -#define _LOG3D_err(errsv, ...) _NMLOG3_err (errsv, LOGL_DEBUG, __VA_ARGS__) -#define _LOG3I_err(errsv, ...) _NMLOG3_err (errsv, LOGL_INFO , __VA_ARGS__) -#define _LOG3W_err(errsv, ...) _NMLOG3_err (errsv, LOGL_WARN , __VA_ARGS__) -#define _LOG3E_err(errsv, ...) _NMLOG3_err (errsv, LOGL_ERR , __VA_ARGS__) - -#if NM_MORE_LOGGING -#define _LOG3t_ENABLED(...) _NMLOG3_ENABLED (LOGL_TRACE, ##__VA_ARGS__) -#define _LOG3t(...) _NMLOG3 (LOGL_TRACE, __VA_ARGS__) -#define _LOG3t_err(errsv, ...) _NMLOG3_err (errsv, LOGL_TRACE, __VA_ARGS__) -#else -/* still call the logging macros to get compile time checks, but they will be optimized out. */ -#define _LOG3t_ENABLED(...) ( FALSE && (_NMLOG3_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) ) -#define _LOG3t(...) G_STMT_START { if (FALSE) { _NMLOG3 (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END -#define _LOG3t_err(errsv, ...) G_STMT_START { if (FALSE) { _NMLOG3_err (errsv, LOGL_TRACE, __VA_ARGS__); } } G_STMT_END -#endif - -/*****************************************************************************/ - #define __NMLOG_DEFAULT(level, domain, prefix, ...) \ G_STMT_START { \ nm_log ((level), (domain), NULL, NULL, \ diff --git a/src/nm-manager.c b/src/nm-manager.c index d112fcf7..132cf5a0 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2009 Novell, Inc. * Copyright (C) 2007 - 2017 Red Hat, Inc. */ @@ -25,6 +11,10 @@ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/sendfile.h> +#include <limits.h> #include "nm-glib-aux/nm-c-list.h" @@ -1168,16 +1158,16 @@ _reload_auth_cb (NMAuthChain *chain, NM_MANAGER_ERROR_PERMISSION_DENIED, "Not authorized to reload configuration"); } else { - if (NM_FLAGS_ANY (flags, ~NM_MANAGER_RELOAD_FLAGS_ALL)) { + if (NM_FLAGS_ANY (flags, ~NM_MANAGER_RELOAD_FLAG_ALL)) { /* invalid flags */ } else if (flags == 0) reload_type = NM_CONFIG_CHANGE_CAUSE_SIGHUP; else { - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_CONF)) + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_CONF)) reload_type |= NM_CONFIG_CHANGE_CAUSE_CONF; - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_DNS_RC)) + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_DNS_RC)) reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_RC; - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_DNS_FULL)) + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_DNS_FULL)) reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_FULL; } @@ -1729,7 +1719,10 @@ nm_manager_get_state (NMManager *manager) /*****************************************************************************/ static NMDevice * -find_parent_device_for_connection (NMManager *self, NMConnection *connection, NMDeviceFactory *cached_factory) +find_parent_device_for_connection (NMManager *self, + NMConnection *connection, + NMDeviceFactory *cached_factory, + const char **out_parent_spec) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMDeviceFactory *factory; @@ -1739,6 +1732,7 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM NMDevice *candidate; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + NM_SET_OUT (out_parent_spec, NULL); if (!cached_factory) { factory = nm_device_factory_manager_find_factory_for_connection (connection); @@ -1751,6 +1745,8 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM if (!parent_name) return NULL; + NM_SET_OUT (out_parent_spec, parent_name); + /* Try as an interface name of a parent device */ parent = find_device_by_iface (self, parent_name, NULL, NULL); if (parent) @@ -1792,6 +1788,9 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM * @self: the #NMManager * @connection: the #NMConnection to get the interface for * @out_parent: on success, the parent device if any + * @out_parent_spec: on return, a string specifying the parent device + * in the connection. This can be a device name, a MAC address or a + * connection UUID. * @error: an error if determining the virtual interface name failed * * Given @connection, returns the interface name that the connection @@ -1805,14 +1804,15 @@ char * nm_manager_get_connection_iface (NMManager *self, NMConnection *connection, NMDevice **out_parent, + const char **out_parent_spec, GError **error) { NMDeviceFactory *factory; char *iface = NULL; NMDevice *parent = NULL; - if (out_parent) - *out_parent = NULL; + NM_SET_OUT (out_parent, NULL); + NM_SET_OUT (out_parent_spec, NULL); factory = nm_device_factory_manager_find_factory_for_connection (connection); if (!factory) { @@ -1835,7 +1835,7 @@ nm_manager_get_connection_iface (NMManager *self, goto return_ifname_fom_connection; } - parent = find_parent_device_for_connection (self, connection, factory); + parent = find_parent_device_for_connection (self, connection, factory, out_parent_spec); iface = nm_device_factory_get_connection_iface (factory, connection, parent ? nm_device_get_ip_iface (parent) : NULL, @@ -1932,6 +1932,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) gs_free NMSettingsConnection **connections = NULL; guint i; gs_free char *iface = NULL; + const char *parent_spec; NMDevice *device = NULL, *parent = NULL; NMDevice *dev_candidate; GError *error = NULL; @@ -1940,7 +1941,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) g_return_val_if_fail (NM_IS_MANAGER (self), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - iface = nm_manager_get_connection_iface (self, connection, &parent, &error); + iface = nm_manager_get_connection_iface (self, connection, &parent, &parent_spec, &error); if (!iface) { _LOG3D (LOGD_DEVICE, connection, "can't get a name of a virtual device: %s", error->message); @@ -1948,6 +1949,11 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) return NULL; } + if (parent_spec && !parent) { + /* parent is not ready, wait */ + return NULL; + } + /* See if there's a device that is already compatible with this connection */ c_list_for_each_entry (dev_candidate, &priv->devices_lst_head, devices_lst) { if (nm_device_check_connection_compatible (dev_candidate, connection, NULL)) { @@ -2018,7 +2024,8 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) s_con = nm_connection_get_setting_connection (candidate); g_assert (s_con); - if (!nm_setting_connection_get_autoconnect (s_con)) + if ( !nm_setting_connection_get_autoconnect (s_con) + || nm_settings_connection_autoconnect_is_blocked (connections[i])) continue; /* Create any backing resources the device needs */ @@ -2061,10 +2068,10 @@ retry_connections_for_parent_device (NMManager *self, NMDevice *device) gs_free char *ifname = NULL; NMDevice *parent; - parent = find_parent_device_for_connection (self, connection, NULL); + parent = find_parent_device_for_connection (self, connection, NULL, NULL); if (parent == device) { /* Only try to activate devices that don't already exist */ - ifname = nm_manager_get_connection_iface (self, connection, &parent, &error); + ifname = nm_manager_get_connection_iface (self, connection, &parent, NULL, &error); if (ifname) { if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname)) connection_changed (self, sett_conn); @@ -2133,7 +2140,7 @@ connection_changed_on_idle (NMManager *self, if (priv->connection_changed_on_idle_id == 0) priv->connection_changed_on_idle_id = g_idle_add (connection_changed_on_idle_cb, self); - if (!nm_c_list_elem_find_first (&priv->connection_changed_on_idle_lst, sett_conn)) { + if (!nm_c_list_elem_find_first_ptr (&priv->connection_changed_on_idle_lst, sett_conn)) { c_list_link_tail (&priv->connection_changed_on_idle_lst, &nm_c_list_elem_new_stale (g_object_ref (sett_conn))->lst); } @@ -2690,6 +2697,34 @@ get_existing_connection (NMManager *self, } static gboolean +copy_lease (const char *src, const char *dst) +{ + nm_auto_close int src_fd = -1; + int dst_fd; + ssize_t res, size = SSIZE_MAX; + + src_fd = open (src, O_RDONLY|O_CLOEXEC); + if (src_fd < 0) + return FALSE; + + dst_fd = open (dst, O_CREAT|O_EXCL|O_CLOEXEC|O_WRONLY, 0644); + if (dst_fd < 0) + return FALSE; + + while ((res = sendfile (dst_fd, src_fd, NULL, size)) > 0) + size -= res; + + nm_close (dst_fd); + + if (res != 0) { + unlink (dst); + return FALSE; + } + + return TRUE; +} + +static gboolean recheck_assume_connection (NMManager *self, NMDevice *device) { @@ -2730,7 +2765,8 @@ recheck_assume_connection (NMManager *self, nm_settings_connection_get_uuid (sett_conn), nm_device_get_iface (device)); - if (rename (initramfs_lease, connection_lease) == 0) { + if (copy_lease (initramfs_lease, connection_lease)) { + unlink (initramfs_lease); /* * We've managed to steal the lease used by initramfs before it * killed off the dhclient. We need to take ownership of the configured @@ -3207,22 +3243,6 @@ factory_device_added_cb (NMDeviceFactory *factory, } } -static gboolean -factory_component_added_cb (NMDeviceFactory *factory, - GObject *component, - gpointer user_data) -{ - NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_notify_component_added (device, component)) - return TRUE; - } - return FALSE; -} - static void _register_device_factory (NMDeviceFactory *factory, gpointer user_data) { @@ -3232,10 +3252,18 @@ _register_device_factory (NMDeviceFactory *factory, gpointer user_data) NM_DEVICE_FACTORY_DEVICE_ADDED, G_CALLBACK (factory_device_added_cb), self); - g_signal_connect (factory, - NM_DEVICE_FACTORY_COMPONENT_ADDED, - G_CALLBACK (factory_component_added_cb), - self); +} + +/*****************************************************************************/ + +void +nm_manager_notify_device_availibility_maybe_changed (NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMDevice *device; + + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) + nm_device_notify_availability_maybe_changed (device); } /*****************************************************************************/ @@ -4574,6 +4602,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * NMAuthSubject *subject; GError *local = NULL; NMConnectionMultiConnect multi_connect; + const char *parent_spec; g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE); @@ -4626,7 +4655,14 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * parent = find_parent_device_for_connection (self, nm_settings_connection_get_connection (sett_conn), - NULL); + NULL, + &parent_spec); + + if (parent_spec && !parent) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "parent device '%s' not found", parent_spec); + return FALSE; + } if (parent && !nm_device_is_real (parent)) { NMSettingsConnection *parent_con; @@ -4638,6 +4674,15 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * return FALSE; } + if ( nm_active_connection_get_activation_reason (active) == NM_ACTIVATION_REASON_AUTOCONNECT + && nm_settings_connection_autoconnect_blocked_reason_get (parent_con, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "the parent connection of %s cannot autoactivate because it is blocked due to user request", + nm_device_get_iface (device)); + return FALSE; + } + parent_ac = nm_manager_activate_connection (self, parent_con, NULL, @@ -5181,7 +5226,7 @@ validate_activation_request (NMManager *self, } /* Look for an existing device with the connection's interface name */ - iface = nm_manager_get_connection_iface (self, connection, NULL, error); + iface = nm_manager_get_connection_iface (self, connection, NULL, NULL, error); if (!iface) return NULL; diff --git a/src/nm-manager.h b/src/nm-manager.h index 966abce0..ad06e318 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2010 Red Hat, Inc. */ @@ -77,6 +63,7 @@ GType nm_manager_get_type (void); NMManager * nm_manager_setup (void); NMManager * nm_manager_get (void); +#define NM_MANAGER_GET (nm_manager_get ()) gboolean nm_manager_start (NMManager *manager, GError **error); @@ -162,6 +149,7 @@ void nm_manager_device_route_metric_clear (NMManager *self, char * nm_manager_get_connection_iface (NMManager *self, NMConnection *connection, NMDevice **out_parent, + const char **out_parent_spec, GError **error); const char * nm_manager_iface_for_uuid (NMManager *self, @@ -203,4 +191,6 @@ void nm_manager_dbus_set_property_handle (NMDBusObject *obj, NMMetered nm_manager_get_metered (NMManager *self); +void nm_manager_notify_device_availibility_maybe_changed (NMManager *self); + #endif /* __NETWORKMANAGER_MANAGER_H__ */ diff --git a/src/nm-netns.c b/src/nm-netns.c index c1ced153..3652384a 100644 --- a/src/nm-netns.c +++ b/src/nm-netns.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/nm-netns.h b/src/nm-netns.h index 126ef375..c65dd907 100644 --- a/src/nm-netns.h +++ b/src/nm-netns.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/nm-pacrunner-manager.c b/src/nm-pacrunner-manager.c index 38b53eab..b5c7bc02 100644 --- a/src/nm-pacrunner-manager.c +++ b/src/nm-pacrunner-manager.c @@ -1,20 +1,6 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. */ #include "nm-default.h" diff --git a/src/nm-pacrunner-manager.h b/src/nm-pacrunner-manager.h index f3f41e9c..d45a4a0a 100644 --- a/src/nm-pacrunner-manager.h +++ b/src/nm-pacrunner-manager.h @@ -1,21 +1,7 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2016 Atul Anand <atulhjp@gmail.com>. - * Copyright 2016 - 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. + * Copyright (C) 2016 - 2017 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_PACRUNNER_MANAGER_H__ diff --git a/src/nm-policy.c b/src/nm-policy.c index 559babed..d322b2ef 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2013 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ @@ -179,7 +165,7 @@ static void _clear_ip6_subnet (gpointer key, gpointer value, gpointer user_data) { NMPlatformIP6Address *subnet = value; - NMDevice *device = nm_manager_get_device_by_ifindex (nm_manager_get (), + NMDevice *device = nm_manager_get_device_by_ifindex (NM_MANAGER_GET, GPOINTER_TO_INT (key)); if (device) { @@ -1886,7 +1872,7 @@ device_state_changed (NMDevice *device, switch (nm_device_state_reason_check (reason)) { case NM_DEVICE_STATE_REASON_USER_REQUESTED: - blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST; + blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST; break; case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED; diff --git a/src/nm-policy.h b/src/nm-policy.h index dea500bf..23c50cff 100644 --- a/src/nm-policy.h +++ b/src/nm-policy.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2004 - 2010 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ diff --git a/src/nm-proxy-config.c b/src/nm-proxy-config.c index 5a7a85c0..feee4afe 100644 --- a/src/nm-proxy-config.c +++ b/src/nm-proxy-config.c @@ -1,20 +1,6 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. */ #include "nm-default.h" diff --git a/src/nm-proxy-config.h b/src/nm-proxy-config.h index 050e0d98..a23b80dd 100644 --- a/src/nm-proxy-config.h +++ b/src/nm-proxy-config.h @@ -1,20 +1,6 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Atul Anand <atulhjp@gmail.com>. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. */ #ifndef __NETWORKMANAGER_PROXY_CONFIG_H__ diff --git a/src/nm-rfkill-manager.c b/src/nm-rfkill-manager.c index c276fc77..28666fa0 100644 --- a/src/nm-rfkill-manager.c +++ b/src/nm-rfkill-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2013 Red Hat, Inc. */ diff --git a/src/nm-rfkill-manager.h b/src/nm-rfkill-manager.h index 5f2d3adb..4a3242e4 100644 --- a/src/nm-rfkill-manager.h +++ b/src/nm-rfkill-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2013 Red Hat, Inc. */ diff --git a/src/nm-session-monitor.c b/src/nm-session-monitor.c index 8cb1b88d..5d5fe4c9 100644 --- a/src/nm-session-monitor.c +++ b/src/nm-session-monitor.c @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2015 Red Hat, Inc. * Author: David Zeuthen <davidz@redhat.com> * Author: Dan Williams <dcbw@redhat.com> * Author: Matthias Clasen diff --git a/src/nm-session-monitor.h b/src/nm-session-monitor.h index 43f9eef9..64f91942 100644 --- a/src/nm-session-monitor.h +++ b/src/nm-session-monitor.h @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 - 2010 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2010 Red Hat, Inc. * Author: David Zeuthen <davidz@redhat.com> * Author: Dan Williams <dcbw@redhat.com> */ diff --git a/src/nm-sleep-monitor.c b/src/nm-sleep-monitor.c index c97f6f7d..c16dc074 100644 --- a/src/nm-sleep-monitor.c +++ b/src/nm-sleep-monitor.c @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2012-2016 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 - 2016 Red Hat, Inc. * Author: Matthias Clasen <mclasen@redhat.com> */ diff --git a/src/nm-sleep-monitor.h b/src/nm-sleep-monitor.h index da1fd8cf..c2f3ab81 100644 --- a/src/nm-sleep-monitor.h +++ b/src/nm-sleep-monitor.h @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2012-2016 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 - 2016 Red Hat, Inc. * Author: Matthias Clasen <mclasen@redhat.com> */ diff --git a/src/nm-test-utils-core.h b/src/nm-test-utils-core.h index 1f4b87ef..e1d250dd 100644 --- a/src/nm-test-utils-core.h +++ b/src/nm-test-utils-core.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2014 - 2016 Red Hat, Inc. + * Copyright (C) 2014 - 2016 Red Hat, Inc. */ #ifndef __NM_TEST_UTILS_CORE_H__ diff --git a/src/nm-types.h b/src/nm-types.h index fae344f2..2f1ac2dc 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ @@ -218,11 +204,20 @@ typedef enum { NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1, } NMPObjectType; +/** + * NMIPConfigMergeFlags: + * @NM_IP_CONFIG_MERGE_DEFAULT: no flags set + * @NM_IP_CONFIG_MERGE_NO_ROUTES: don't merge routes + * @NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES: don't merge default routes + * @NM_IP_CONFIG_MERGE_NO_DNS: don't merge DNS information + * @NM_IP_CONFIG_MERGE_EXTERNAL: mark new addresses as external + */ typedef enum { NM_IP_CONFIG_MERGE_DEFAULT = 0, NM_IP_CONFIG_MERGE_NO_ROUTES = (1LL << 0), NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES = (1LL << 1), NM_IP_CONFIG_MERGE_NO_DNS = (1LL << 2), + NM_IP_CONFIG_MERGE_EXTERNAL = (1LL << 3), } NMIPConfigMergeFlags; /** diff --git a/src/platform/linux/nl802154.h b/src/platform/linux/nl802154.h index ddcee128..57646a39 100644 --- a/src/platform/linux/nl802154.h +++ b/src/platform/linux/nl802154.h @@ -3,7 +3,7 @@ /* * 802.15.4 netlink interface public header * - * Copyright 2014 Alexander Aring <aar@pengutronix.de> + * Copyright (C) 2014 Alexander Aring <aar@pengutronix.de> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 967aaee8..6aae808a 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -1,20 +1,6 @@ -/* nm-platform-fake.c - Fake platform interaction code for testing NetworkManager - * - * 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) 2012–2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 - 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/platform/nm-fake-platform.h b/src/platform/nm-fake-platform.h index d5be8c65..72245e67 100644 --- a/src/platform/nm-fake-platform.h +++ b/src/platform/nm-fake-platform.h @@ -1,19 +1,5 @@ -/* nm-fake-platform.h - Fake platform interaction code for testing NetworkManager - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index d222527d..305ae52e 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1,21 +1,8 @@ -/* nm-linux-platform.c - Linux kernel & udev network configuration layer - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ + #include "nm-default.h" #include "nm-linux-platform.h" @@ -868,14 +855,19 @@ _lookup_cached_link (const NMPCache *cache, static char * _linktype_read_devtype (int dirfd) { - char *contents = NULL; + gs_free char *contents = NULL; char *cont, *end; nm_assert (dirfd >= 0); - if (nm_utils_file_get_contents (dirfd, "uevent", 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, NULL, NULL) < 0) + if (!nm_utils_file_get_contents (dirfd, + "uevent", + 1*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + NULL, + NULL, + NULL)) return NULL; for (cont = contents; cont; cont = end) { end = strpbrk (cont, "\r\n"); @@ -884,10 +876,9 @@ _linktype_read_devtype (int dirfd) if (strncmp (cont, DEVTYPE_PREFIX, NM_STRLEN (DEVTYPE_PREFIX)) == 0) { cont += NM_STRLEN (DEVTYPE_PREFIX); memmove (contents, cont, strlen (cont) + 1); - return contents; + return g_steal_pointer (&contents); } } - g_free (contents); return NULL; } @@ -4398,12 +4389,17 @@ static void _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) { GError *error = NULL; - char *contents; + gs_free char *contents = NULL; gs_free char *value_escaped = g_strescape (value, NULL); - if (nm_utils_file_get_contents (dirfd, path, 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, NULL, &error) < 0) { + if (!nm_utils_file_get_contents (dirfd, + path, + 1*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + NULL, + NULL, + &error)) { _LOGD ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", pathid ?: path, value_escaped, error->message); g_clear_error (&error); return; @@ -4417,7 +4413,6 @@ _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, c _LOGD ("sysctl: setting '%s' to '%s' (current value is '%s')", pathid ?: path, value_escaped, contents_escaped); } - g_free (contents); } #define _log_dbg_sysctl_set(platform, pathid, dirfd, path, value) \ @@ -4833,7 +4828,7 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat { nm_auto_pop_netns NMPNetns *netns = NULL; GError *error = NULL; - char *contents; + gs_free char *contents = NULL; ASSERT_SYSCTL_ARGS (pathid, dirfd, path); @@ -4845,9 +4840,14 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat pathid = path; } - if (nm_utils_file_get_contents (dirfd, path, 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, NULL, &error) < 0) { + if (!nm_utils_file_get_contents (dirfd, + path, + 1*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + NULL, + NULL, + &error)) { NMLogLevel log_level = LOGL_ERR; int errsv = EBUSY; @@ -4871,7 +4871,7 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat _log_dbg_sysctl_get (platform, pathid, contents); /* errno is left undefined (as we don't return NULL). */ - return contents; + return g_steal_pointer (&contents); } /*****************************************************************************/ diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h index f08f91aa..90b9a17a 100644 --- a/src/platform/nm-linux-platform.h +++ b/src/platform/nm-linux-platform.h @@ -1,19 +1,5 @@ -/* nm-linux-platform.h - Linux kernel & udev network configuration layer - * - * 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c index da009d01..d133d351 100644 --- a/src/platform/nm-netlink.c +++ b/src/platform/nm-netlink.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h index c793f04a..0ac5b3b7 100644 --- a/src/platform/nm-netlink.h +++ b/src/platform/nm-netlink.h @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/platform/nm-platform-private.h b/src/platform/nm-platform-private.h index 5a24eda0..a072af05 100644 --- a/src/platform/nm-platform-private.h +++ b/src/platform/nm-platform-private.h @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index bc9ec11d..4f0da581 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index ae3f51e2..a62d828c 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 0a7acba9..6795dde7 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ @@ -4152,11 +4138,12 @@ nm_platform_ip4_address_sync (NMPlatform *self, } } ip4_addr_subnets_destroy_index (plat_subnets, plat_addresses); - ip4_addr_subnets_destroy_index (known_subnets, known_addresses); if (!known_addresses) return TRUE; + ip4_addr_subnets_destroy_index (known_subnets, known_addresses); + ifa_flags = nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) ? IFA_F_NOPREFIXROUTE : 0; @@ -6097,13 +6084,14 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); g_snprintf (buf, len, - "%s/%d lft %s pref %s%s%s%s%s%s src %s", + "%s/%d lft %s pref %s%s%s%s%s%s src %s%s", s_address, address->plen, str_lft_p, str_pref_p, str_time_p, str_peer ?: "", str_dev, _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), str_label, - nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source))); + nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source)), + address->external ? " ext" : ""); g_free (str_peer); return buf; } @@ -6204,12 +6192,13 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); g_snprintf (buf, len, - "%s/%d lft %s pref %s%s%s%s%s src %s", + "%s/%d lft %s pref %s%s%s%s%s src %s%s", s_address, address->plen, str_lft_p, str_pref_p, str_time_p, str_peer ?: "", str_dev, _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), - nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source))); + nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source)), + address->external ? " ext" : ""); g_free (str_peer); return buf; } @@ -7315,7 +7304,8 @@ nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashStat obj->n_ifa_flags, obj->plen, obj->address, - obj->peer_address); + obj->peer_address, + NM_HASH_COMBINE_BOOLS (guint8, obj->external)); nm_hash_update_strarr (h, obj->label); } @@ -7333,6 +7323,7 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A NM_CMP_FIELD (a, b, preferred); NM_CMP_FIELD (a, b, n_ifa_flags); NM_CMP_FIELD_STR (a, b, label); + NM_CMP_FIELD_UNSAFE (a, b, external); return 0; } @@ -7348,7 +7339,8 @@ nm_platform_ip6_address_hash_update (const NMPlatformIP6Address *obj, NMHashStat obj->n_ifa_flags, obj->plen, obj->address, - obj->peer_address); + obj->peer_address, + NM_HASH_COMBINE_BOOLS (guint8, obj->external)); } int @@ -7368,6 +7360,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A NM_CMP_FIELD (a, b, lifetime); NM_CMP_FIELD (a, b, preferred); NM_CMP_FIELD (a, b, n_ifa_flags); + NM_CMP_FIELD_UNSAFE (a, b, external); return 0; } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 44733809..4bd8e34d 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 - 2018 Red Hat, Inc. */ @@ -320,6 +306,8 @@ typedef enum { guint32 n_ifa_flags; \ \ guint8 plen; \ + \ + bool external:1; \ ; /** @@ -508,7 +496,7 @@ struct _NMPlatformIP4Route { /* The bitwise inverse of the route scope rtm_scope. It is inverted so that the * default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv() - * to convert back and forth between the inverese representation and the + * to convert back and forth between the inverse representation and the * real value. * * rtm_scope is part of the primary key for IPv4 routes. When deleting a route, diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c index b33d86fb..78f76cc7 100644 --- a/src/platform/nmp-netns.c +++ b/src/platform/nmp-netns.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/platform/nmp-netns.h b/src/platform/nmp-netns.h index 3c0ca74b..a74e2319 100644 --- a/src/platform/nmp-netns.h +++ b/src/platform/nmp-netns.h @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 5cbf9428..97aa4f28 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index cea5f958..d52cc132 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ diff --git a/src/platform/nmp-rules-manager.c b/src/platform/nmp-rules-manager.c index f982f04c..a1d724c5 100644 --- a/src/platform/nmp-rules-manager.c +++ b/src/platform/nmp-rules-manager.c @@ -1,19 +1,4 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ +// SPDX-License-Identifier: LGPL-2.1+ #include "nm-default.h" diff --git a/src/platform/nmp-rules-manager.h b/src/platform/nmp-rules-manager.h index 645df5c2..cf29ff45 100644 --- a/src/platform/nmp-rules-manager.h +++ b/src/platform/nmp-rules-manager.h @@ -1,19 +1,4 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - */ +// SPDX-License-Identifier: LGPL-2.1+ #ifndef __NMP_RULES_MANAGER_H__ #define __NMP_RULES_MANAGER_H__ diff --git a/src/platform/tests/meson.build b/src/platform/tests/meson.build index aaee8964..6f7173b6 100644 --- a/src/platform/tests/meson.build +++ b/src/platform/tests/meson.build @@ -1,21 +1,25 @@ +test_fake_c_flags = test_c_flags + ['-DSETUP=nm_fake_platform_setup'] +test_linux_c_flags = test_c_flags + ['-DSETUP=nm_linux_platform_setup'] + test_units = [ - [ 'test-address-fake', 'test-address.c', test_nm_dep_fake, default_test_timeout ], - [ 'test-address-linux', 'test-address.c', test_nm_dep_linux, default_test_timeout ], - [ 'test-cleanup-fake', 'test-cleanup.c', test_nm_dep_fake, default_test_timeout ], - [ 'test-cleanup-linux', 'test-cleanup.c', test_nm_dep_linux, default_test_timeout ], - [ 'test-link-fake', 'test-link.c', test_nm_dep_fake, default_test_timeout ], - [ 'test-link-linux', 'test-link.c', test_nm_dep_linux, 900 ], - [ 'test-nmp-object', 'test-nmp-object.c', test_nm_dep, default_test_timeout ], - [ 'test-platform-general', 'test-platform-general.c', test_nm_dep, default_test_timeout ], - [ 'test-route-fake', 'test-route.c', test_nm_dep_fake, default_test_timeout ], - [ 'test-route-linux', 'test-route.c', test_nm_dep_linux, default_test_timeout ], + ['test-address-fake', 'test-address.c', test_fake_c_flags, default_test_timeout], + ['test-address-linux', 'test-address.c', test_linux_c_flags, default_test_timeout], + ['test-cleanup-fake', 'test-cleanup.c', test_fake_c_flags, default_test_timeout], + ['test-cleanup-linux', 'test-cleanup.c', test_linux_c_flags, default_test_timeout], + ['test-link-fake', 'test-link.c', test_fake_c_flags, default_test_timeout], + ['test-link-linux', 'test-link.c', test_linux_c_flags, 900], + ['test-nmp-object', 'test-nmp-object.c', test_c_flags, default_test_timeout], + ['test-platform-general', 'test-platform-general.c', test_c_flags, default_test_timeout], + ['test-route-fake', 'test-route.c', test_fake_c_flags, default_test_timeout], + ['test-route-linux', 'test-route.c', test_linux_c_flags, default_test_timeout], ] foreach test_unit: test_units exe = executable( test_unit[0], test_unit[1], - dependencies: test_unit[2], + dependencies: libnetwork_manager_test_dep, + c_args: test_unit[2], ) test( 'platform/' + test_unit[0], @@ -25,8 +29,11 @@ foreach test_unit: test_units ) endforeach +name = 'monitor' + executable( - 'monitor', - 'monitor.c', - dependencies: test_nm_dep, + name, + name + '.c', + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c index 6a5e0e16..aec29b75 100644 --- a/src/platform/tests/monitor.c +++ b/src/platform/tests/monitor.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 3a3e9009..26072400 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2015 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 70d64c15..34175c01 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2016 Red Hat, Inc. + * Copyright (C) 2016 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index cd0bef45..b93213ef 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2016 - 2017 Red Hat, Inc. + * Copyright (C) 2016 - 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index e4eaec29..c571df6a 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2016 - 2017 Red Hat, Inc. + * Copyright (C) 2016 - 2017 Red Hat, Inc. */ #include <stdlib.h> diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 27ec3f07..37e1cde5 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2016 Red Hat, Inc. + * Copyright (C) 2016 Red Hat, Inc. */ #include "nm-default.h" @@ -476,9 +463,9 @@ _system (const char *cmd) static void test_bond (void) { - if (nmtstp_is_root_test () && - !g_file_test ("/proc/1/net/bonding", G_FILE_TEST_IS_DIR) && - _system("modprobe --show bonding") != 0) { + if ( nmtstp_is_root_test () + && !g_file_test ("/proc/1/net/bonding", G_FILE_TEST_IS_DIR) + && _system("modprobe --show bonding") != 0) { g_test_skip ("Skipping test for bonding: bonding module not available"); return; } @@ -489,6 +476,20 @@ test_bond (void) static void test_team (void) { + int r; + + if (nmtstp_is_root_test ()) { + r = nm_platform_link_team_add (NM_PLATFORM_GET, "nm-team-check", NULL); + + if (r < 0) { + g_assert_cmpint (r, ==, -EOPNOTSUPP); + g_test_skip ("Skipping test for teaming: team module not functioning"); + return; + } + + nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, "nm-team-check", FALSE); + } + test_software (NM_LINK_TYPE_TEAM, "team"); } @@ -2886,9 +2887,14 @@ test_sysctl_rename (void) case 0: { gs_free char *c = NULL; - if (nm_utils_file_get_contents (dirfd, "ifindex", 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &c, NULL, NULL) < 0) + if (!nm_utils_file_get_contents (dirfd, + "ifindex", + 1*1024*1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &c, + NULL, + NULL, + NULL)) g_assert_not_reached(); g_assert_cmpint (ifindex[0], ==, (int) _nm_utils_ascii_str_to_int64 (c, 10, 0, G_MAXINT, -1)); break; @@ -2952,9 +2958,14 @@ test_sysctl_netns_switch (void) { gs_free char *c = NULL; - if (nm_utils_file_get_contents (dirfd, "ifindex", 0, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &c, NULL, NULL) < 0) + if (!nm_utils_file_get_contents (dirfd, + "ifindex", + 0, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &c, + NULL, + NULL, + NULL)) g_assert_not_reached(); g_assert_cmpint (ifindex, ==, (int) _nm_utils_ascii_str_to_int64 (c, 10, 0, G_MAXINT, -1)); } @@ -2997,11 +3008,14 @@ test_sysctl_netns_switch (void) { gs_free char *c = NULL; - if (nm_utils_file_get_contents (-1, - nm_sprintf_bufa (100, "/sys/class/net/%s/ifindex", IFNAME), - 0, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &c, NULL, NULL) < 0) + if (!nm_utils_file_get_contents (-1, + nm_sprintf_bufa (100, "/sys/class/net/%s/ifindex", IFNAME), + 0, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &c, + NULL, + NULL, + NULL)) ifindex_tmp = -1; else ifindex_tmp = _nm_utils_ascii_str_to_int64 (c, 10, 0, G_MAXINT, -2); diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c index 08bde437..8ecfac8a 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/platform/tests/test-nmp-object.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 - 2017 Red Hat, Inc. */ diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c index 2b723810..255210f2 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/platform/tests/test-platform-general.c @@ -1,19 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 44bfbc58..f8b1bb9a 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2016 - 2017 Red Hat, Inc. + * Copyright (C) 2016 - 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c index 36901f83..afeb3b02 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/platform/wifi/nm-wifi-utils-nl80211.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. * Copyright (C) 2011 Intel Corporation. All rights reserved. @@ -913,6 +899,9 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) if (tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]) info->can_wowlan = TRUE; + if (tb[NL80211_ATTR_SUPPORT_IBSS_RSN]) + info->caps |= NM_WIFI_DEVICE_CAP_IBSS_RSN; + info->success = TRUE; return NL_SKIP; diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.h b/src/platform/wifi/nm-wifi-utils-nl80211.h index a4c9ca55..45876534 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.h +++ b/src/platform/wifi/nm-wifi-utils-nl80211.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 Intel Corporation. All rights reserved. * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/platform/wifi/nm-wifi-utils-private.h b/src/platform/wifi/nm-wifi-utils-private.h index 4cae22e5..53816744 100644 --- a/src/platform/wifi/nm-wifi-utils-private.h +++ b/src/platform/wifi/nm-wifi-utils-private.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ diff --git a/src/platform/wifi/nm-wifi-utils-wext.c b/src/platform/wifi/nm-wifi-utils-wext.c index d19cf8a5..68924a35 100644 --- a/src/platform/wifi/nm-wifi-utils-wext.c +++ b/src/platform/wifi/nm-wifi-utils-wext.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/platform/wifi/nm-wifi-utils-wext.h b/src/platform/wifi/nm-wifi-utils-wext.h index 70cae966..ce76f68d 100644 --- a/src/platform/wifi/nm-wifi-utils-wext.h +++ b/src/platform/wifi/nm-wifi-utils-wext.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ diff --git a/src/platform/wifi/nm-wifi-utils.c b/src/platform/wifi/nm-wifi-utils.c index 1e42db6a..39ce9b09 100644 --- a/src/platform/wifi/nm-wifi-utils.c +++ b/src/platform/wifi/nm-wifi-utils.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/platform/wifi/nm-wifi-utils.h b/src/platform/wifi/nm-wifi-utils.h index 2e89053b..bc0d88c8 100644 --- a/src/platform/wifi/nm-wifi-utils.h +++ b/src/platform/wifi/nm-wifi-utils.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/platform/wpan/nm-wpan-utils.c index 0afc2a4d..231e6e2c 100644 --- a/src/platform/wpan/nm-wpan-utils.c +++ b/src/platform/wpan/nm-wpan-utils.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/platform/wpan/nm-wpan-utils.h b/src/platform/wpan/nm-wpan-utils.h index 1b54ec49..deafeb97 100644 --- a/src/platform/wpan/nm-wpan-utils.h +++ b/src/platform/wpan/nm-wpan-utils.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/ppp/meson.build b/src/ppp/meson.build index 04c539e3..0c458768 100644 --- a/src/ppp/meson.build +++ b/src/ppp/meson.build @@ -1,39 +1,30 @@ name = 'nm-pppd-plugin' -deps = [ - dl_dep, - libnm_core_dep, +c_flags = [ + '-DG_LOG_DOMAIN="@0@"'.format(name), + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', ] nm_pppd_plugin = shared_module( name, name_prefix: '', sources: name + '.c', - include_directories: src_inc, - dependencies: deps, - c_args: [ - '-DG_LOG_DOMAIN="@0@"'.format(name), - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', - ], + dependencies: libnm_core_nm_default_dep, + c_args: c_flags, install: true, install_dir: pppd_plugin_dir, ) name = 'nm-ppp-plugin' -deps = [ - nm_dep, -] - linker_script = join_paths(meson.current_source_dir(), 'nm-ppp-plugin.ver') core_plugins += shared_module( name, sources: 'nm-ppp-manager.c', - dependencies: deps, - link_args: [ - '-Wl,--version-script,@0@'.format(linker_script), - ], + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, + link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, install: true, install_dir: nm_plugindir, diff --git a/src/ppp/nm-ppp-manager-call.c b/src/ppp/nm-ppp-manager-call.c index c134a2b2..11520ec9 100644 --- a/src/ppp/nm-ppp-manager-call.c +++ b/src/ppp/nm-ppp-manager-call.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/ppp/nm-ppp-manager-call.h b/src/ppp/nm-ppp-manager-call.h index 6561a388..96fb6483 100644 --- a/src/ppp/nm-ppp-manager-call.h +++ b/src/ppp/nm-ppp-manager-call.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index 3708b940..f649e0cb 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2012 Red Hat, Inc. */ @@ -1226,7 +1212,7 @@ _ppp_manager_stop (NMPPPManager *self, /* No PID. There is nothing to kill, however, invoke the callback in * an idle handler. * - * Note that we don't register nm_shutdown_wait_obj_register(). + * Note that we don't register nm_shutdown_wait_obj_register_object(). * In order for shutdown to work properly, the caller must always * explicitly cancel the action to go down. With the idle-handler, * cancelling the handle completes the request. */ @@ -1238,7 +1224,7 @@ _ppp_manager_stop (NMPPPManager *self, * until the process terminated. We do that, by registering an object * that delays shutdown. */ handle->shutdown_waitobj = g_object_new (G_TYPE_OBJECT, NULL); - nm_shutdown_wait_obj_register (handle->shutdown_waitobj, "ppp-manager-wait-kill-pppd"); + nm_shutdown_wait_obj_register_object (handle->shutdown_waitobj, "ppp-manager-wait-kill-pppd"); nm_utils_kill_child_async (nm_steal_int (&priv->pid), SIGTERM, LOGD_PPP, "pppd", NM_SHUTDOWN_TIMEOUT_MS, diff --git a/src/ppp/nm-ppp-manager.h b/src/ppp/nm-ppp-manager.h index d2285e3e..8657367f 100644 --- a/src/ppp/nm-ppp-manager.h +++ b/src/ppp/nm-ppp-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2016 Red Hat, Inc. */ diff --git a/src/ppp/nm-ppp-plugin-api.h b/src/ppp/nm-ppp-plugin-api.h index 7177a7d6..f2d4f7be 100644 --- a/src/ppp/nm-ppp-plugin-api.h +++ b/src/ppp/nm-ppp-plugin-api.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/ppp/nm-ppp-status.h b/src/ppp/nm-ppp-status.h index a57685a1..f817d7cb 100644 --- a/src/ppp/nm-ppp-status.h +++ b/src/ppp/nm-ppp-status.h @@ -1,21 +1,7 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2008-2016 Red Hat, Inc. + * Copyright (C) 2008 - 2016 Red Hat, Inc. */ #ifndef __NM_PPP_STATUS_H__ diff --git a/src/ppp/nm-pppd-plugin.c b/src/ppp/nm-pppd-plugin.c index f0b9027c..db9a2b67 100644 --- a/src/ppp/nm-pppd-plugin.c +++ b/src/ppp/nm-pppd-plugin.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/ppp/nm-pppd-plugin.h b/src/ppp/nm-pppd-plugin.h index e0d691bf..e69bc2ae 100644 --- a/src/ppp/nm-pppd-plugin.h +++ b/src/ppp/nm-pppd-plugin.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2014 Red Hat, Inc. */ diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index db0e021c..ecca0eb3 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 - 2013 Red Hat, Inc. */ @@ -93,13 +79,13 @@ NM_DEFINE_SINGLETON_GETTER (NMAgentManager, nm_agent_manager_get, NM_TYPE_AGENT_ if (!(self)) \ g_snprintf (__prefix1, sizeof (__prefix1), "%s%s", ""_NMLOG_PREFIX_NAME"", "[]"); \ else if ((self) != singleton_instance) \ - g_snprintf (__prefix1, sizeof (__prefix1), "%s[%p]", ""_NMLOG_PREFIX_NAME"", (self)); \ + g_snprintf (__prefix1, sizeof (__prefix1), "%s["NM_HASH_OBFUSCATE_PTR_FMT"]", ""_NMLOG_PREFIX_NAME"", NM_HASH_OBFUSCATE_PTR (self)); \ else \ g_strlcpy (__prefix1, _NMLOG_PREFIX_NAME, sizeof (__prefix1)); \ if (__agent) { \ g_snprintf (__prefix2, sizeof (__prefix2), \ - ": req[%p, %s]", \ - __agent, \ + ": agent["NM_HASH_OBFUSCATE_PTR_FMT",%s]", \ + NM_HASH_OBFUSCATE_PTR (__agent), \ nm_secret_agent_get_description (__agent)); \ } else \ __prefix2[0] = '\0'; \ @@ -109,9 +95,9 @@ NM_DEFINE_SINGLETON_GETTER (NMAgentManager, nm_agent_manager_get, NM_TYPE_AGENT_ } \ } G_STMT_END -#define LOG_REQ_FMT "[%p/%s%s%s%s%s%s]" +#define LOG_REQ_FMT "["NM_HASH_OBFUSCATE_PTR_FMT"/%s%s%s%s%s%s]" #define LOG_REQ_ARG(req) \ - (req), \ + NM_HASH_OBFUSCATE_PTR (req), \ NM_PRINT_FMT_QUOTE_STRING ((req)->detail), \ NM_PRINT_FMT_QUOTED (((req)->request_type == REQUEST_TYPE_CON_GET) && (req)->con.get.setting_name, \ "/\"", (req)->con.get.setting_name, "\"", \ @@ -539,12 +525,10 @@ request_free (Request *req) if (req->idle_id) g_source_remove (req->idle_id); - if (req->current && req->current_call_id) { - /* cancel-secrets invokes the done-callback synchronously -- in which case - * the handler just return. - * Hence, we can proceed to free @req... */ - nm_secret_agent_cancel_secrets (req->current, req->current_call_id); - } + /* cancel-secrets invokes the done-callback synchronously -- in which case + * the handler just return. + * Hence, we can proceed to free @req... */ + nm_secret_agent_cancel_call (req->current, req->current_call_id); g_object_unref (req->subject); @@ -742,12 +726,9 @@ request_next_agent (Request *req) self = req->self; - if (req->current) { - if (req->current_call_id) - nm_secret_agent_cancel_secrets (req->current, req->current_call_id); - g_clear_object (&req->current); - } + nm_secret_agent_cancel_call (req->current, req->current_call_id); nm_assert (!req->current_call_id); + g_clear_object (&req->current); if (req->pending) { /* Send the request to the next agent */ @@ -882,10 +863,8 @@ _con_get_request_done (NMSecretAgent *agent, req_complete_error (req, error); g_error_free (error); } else { - if (req->current_call_id) { - /* Tell the failed agent we're no longer interested. */ - nm_secret_agent_cancel_secrets (req->current, req->current_call_id); - } + /* Tell the failed agent we're no longer interested. */ + nm_secret_agent_cancel_call (req->current, req->current_call_id); /* Try the next agent */ request_next_agent (req); diff --git a/src/settings/nm-agent-manager.h b/src/settings/nm-agent-manager.h index 949ab6bc..5200d241 100644 --- a/src/settings/nm-agent-manager.h +++ b/src/settings/nm-agent-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 - 2011 Red Hat, Inc. */ diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c index 2aa1476d..74bd9b2f 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/settings/nm-secret-agent.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 - 2011 Red Hat, Inc. */ @@ -24,9 +10,9 @@ #include <sys/types.h> #include <pwd.h> +#include "nm-glib-aux/nm-c-list.h" #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-dbus-interface.h" -#include "nm-dbus-manager.h" #include "nm-core-internal.h" #include "nm-auth-subject.h" #include "nm-simple-connection.h" @@ -35,30 +21,32 @@ /*****************************************************************************/ +#define METHOD_GET_SECRETS "GetSecrets" +#define METHOD_CANCEL_GET_SECRETS "CancelGetSecrets" +#define METHOD_SAVE_SECRETS "SaveSecrets" +#define METHOD_DELETE_SECRETS "DeleteSecrets" + enum { DISCONNECTED, LAST_SIGNAL }; + static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { + CList permissions; char *description; NMAuthSubject *subject; char *identifier; char *owner_username; char *dbus_owner; - NMSecretAgentCapabilities capabilities; - GSList *permissions; - GDBusProxy *proxy; - NMDBusManager *bus_mgr; - GDBusConnection *connection; + GDBusConnection *dbus_connection; + GCancellable *name_owner_cancellable; CList requests; - union { - gulong obj_signal; - guint dbus_signal; - } on_disconnected_id; - bool connection_is_private:1; + NMSecretAgentCapabilities capabilities; + guint name_owner_changed_id; + bool shutdown_wait_obj_registered:1; } NMSecretAgentPrivate; struct _NMSecretAgent { @@ -81,25 +69,51 @@ G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT) #define _NMLOG(level, ...) \ G_STMT_START { \ if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \ - char __prefix[32]; \ + char _prefix[64]; \ \ - if ((self)) \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", ""_NMLOG_PREFIX_NAME"", (self)); \ - else \ - g_strlcpy (__prefix, _NMLOG_PREFIX_NAME, sizeof (__prefix)); \ - _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \ + if ((self)) { \ + g_snprintf (_prefix, \ + sizeof (_prefix), \ + _NMLOG_PREFIX_NAME"["NM_HASH_OBFUSCATE_PTR_FMT"]", \ + NM_HASH_OBFUSCATE_PTR (self)); \ + } else \ + g_strlcpy (_prefix, _NMLOG_PREFIX_NAME, sizeof (_prefix)); \ + \ + _nm_log ((level), \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + _prefix \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } \ } G_STMT_END -#define LOG_REQ_FMT "req[%p,%s,%s%s%s%s]" -#define LOG_REQ_ARG(req) (req), (req)->dbus_command, NM_PRINT_FMT_QUOTE_STRING ((req)->path), ((req)->cancellable ? "" : " (cancelled)") +#define _NMLOG2(level, call_id, ...) \ + G_STMT_START { \ + NMSecretAgentCallId *const _call_id = (call_id); \ + \ + nm_assert (_call_id); \ + \ + nm_log ((level), \ + (_NMLOG_DOMAIN), \ + NULL, \ + NULL, \ + "%s["NM_HASH_OBFUSCATE_PTR_FMT"] request ["NM_HASH_OBFUSCATE_PTR_FMT",%s,%s%s%s%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + NM_HASH_OBFUSCATE_PTR (_call_id->self), \ + NM_HASH_OBFUSCATE_PTR (_call_id), \ + _call_id->method_name, \ + NM_PRINT_FMT_QUOTE_STRING (_call_id->path), \ + (_call_id->cancellable ? "" : " (cancelled)") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END /*****************************************************************************/ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_capabilities_to_string, NMSecretAgentCapabilities, - NM_UTILS_FLAGS2STR (NM_SECRET_AGENT_CAPABILITY_NONE, "none"), + NM_UTILS_FLAGS2STR (NM_SECRET_AGENT_CAPABILITY_NONE, "none"), NM_UTILS_FLAGS2STR (NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, "vpn-hints"), ); @@ -107,69 +121,100 @@ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_capabilities_to_string, NMSecretAgentCapabili struct _NMSecretAgentCallId { CList lst; - NMSecretAgent *agent; + NMSecretAgent *self; GCancellable *cancellable; char *path; - const char *dbus_command; + const char *method_name; char *setting_name; - gboolean is_get_secrets; NMSecretAgentCallback callback; gpointer callback_data; }; static NMSecretAgentCallId * -request_new (NMSecretAgent *self, - const char *dbus_command, /* this must be a static string. */ - const char *path, - const char *setting_name, - NMSecretAgentCallback callback, - gpointer callback_data) +_call_id_new (NMSecretAgent *self, + const char *method_name, /* this must be a static string. */ + const char *path, + const char *setting_name, + NMSecretAgentCallback callback, + gpointer callback_data) { - NMSecretAgentCallId *r; - - r = g_slice_new0 (NMSecretAgentCallId); - r->agent = self; - r->path = g_strdup (path); - r->setting_name = g_strdup (setting_name); - r->dbus_command = dbus_command, - r->callback = callback; - r->callback_data = callback_data; - r->cancellable = g_cancellable_new (); - c_list_link_tail (&NM_SECRET_AGENT_GET_PRIVATE (self)->requests, - &r->lst); - _LOGt ("request "LOG_REQ_FMT": created", LOG_REQ_ARG (r)); - return r; + NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); + NMSecretAgentCallId *call_id; + + call_id = g_slice_new (NMSecretAgentCallId); + *call_id = (NMSecretAgentCallId) { + .self = g_object_ref (self), + .path = g_strdup (path), + .setting_name = g_strdup (setting_name), + .method_name = method_name, + .callback = callback, + .callback_data = callback_data, + .cancellable = g_cancellable_new (), + }; + c_list_link_tail (&priv->requests, &call_id->lst); + + _LOG2T (call_id, "new request..."); + + if (!priv->shutdown_wait_obj_registered) { + /* self has async requests (that keep self alive). As long as + * we have pending requests, shutdown is blocked. */ + priv->shutdown_wait_obj_registered = TRUE; + nm_shutdown_wait_obj_register_object (G_OBJECT (self), "secret-agent"); + } + + return call_id; } -#define request_new(self,dbus_command,path,setting_name,callback,callback_data) request_new(self,""dbus_command"",path,setting_name,callback,callback_data) + +#define _call_id_new(self, method_name, path, setting_name, callback, callback_data) _call_id_new(self, ""method_name"", path, setting_name, callback, callback_data) static void -request_free (NMSecretAgentCallId *r) +_call_id_free (NMSecretAgentCallId *call_id) { - NMSecretAgent *self = r->agent; - - _LOGt ("request "LOG_REQ_FMT": destroyed", LOG_REQ_ARG (r)); - c_list_unlink_stale (&r->lst); - g_free (r->path); - g_free (r->setting_name); - if (r->cancellable) - g_object_unref (r->cancellable); - g_slice_free (NMSecretAgentCallId, r); + c_list_unlink_stale (&call_id->lst); + g_free (call_id->path); + g_free (call_id->setting_name); + nm_g_object_unref (call_id->cancellable); + g_object_unref (call_id->self); + nm_g_slice_free (call_id); } -static gboolean -request_check_return (NMSecretAgentCallId *r) +static void +_call_id_invoke_callback (NMSecretAgentCallId *call_id, + GVariant *secrets, + GError *error, + gboolean cancelled, + gboolean free_call_id) { - if (!r->cancellable) - return FALSE; + gs_free_error GError *error_cancelled = NULL; - g_return_val_if_fail (NM_IS_SECRET_AGENT (r->agent), FALSE); + nm_assert (call_id); + nm_assert (!c_list_is_empty (&call_id->lst)); - nm_assert (c_list_contains (&NM_SECRET_AGENT_GET_PRIVATE (r->agent)->requests, - &r->lst)); + c_list_unlink (&call_id->lst); - c_list_unlink (&r->lst); + if (cancelled) { + nm_assert (!secrets); + nm_assert (!error); + if (call_id->callback) { + nm_utils_error_set_cancelled (&error_cancelled, FALSE, "NMSecretAgent"); + error = error_cancelled; + } + _LOG2T (call_id, "cancelled"); + } else if (error) { + nm_assert (!secrets); + _LOG2T (call_id, "completed with failure: %s", error->message); + } else { + nm_assert ( !secrets + || g_variant_is_of_type (secrets, G_VARIANT_TYPE ("a{sa{sv}}"))); + nm_assert ((!!secrets) == nm_streq0 (call_id->method_name, METHOD_GET_SECRETS)); + _LOG2T (call_id, "completed successfully"); + } + + if (call_id->callback) + call_id->callback (call_id->self, call_id, secrets, error, call_id->callback_data); - return TRUE; + if (free_call_id) + _call_id_free (call_id); } /*****************************************************************************/ @@ -200,6 +245,8 @@ nm_secret_agent_get_description (NMSecretAgent *agent) return priv->description; } +/*****************************************************************************/ + const char * nm_secret_agent_get_dbus_owner (NMSecretAgent *agent) { @@ -256,6 +303,8 @@ nm_secret_agent_get_subject (NMSecretAgent *agent) return NM_SECRET_AGENT_GET_PRIVATE (agent)->subject; } +/*****************************************************************************/ + /** * nm_secret_agent_add_permission: * @agent: A #NMSecretAgent. @@ -269,31 +318,25 @@ nm_secret_agent_add_permission (NMSecretAgent *agent, gboolean allowed) { NMSecretAgentPrivate *priv; - GSList *iter; + NMCListElem *elem; g_return_if_fail (agent != NULL); g_return_if_fail (permission != NULL); priv = NM_SECRET_AGENT_GET_PRIVATE (agent); - /* Check if the permission is already in the list */ - for (iter = priv->permissions; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (permission, iter->data) == 0) { - /* If the permission is no longer allowed, remove it from the - * list. If it is now allowed, do nothing since it's already - * in the list. - */ - if (allowed == FALSE) { - g_free (iter->data); - priv->permissions = g_slist_delete_link (priv->permissions, iter); - } - return; - } + elem = nm_c_list_elem_find_first (&priv->permissions, p, nm_streq (p, permission)); + + if (elem) { + if (!allowed) + nm_c_list_elem_free_full (elem, g_free); + return; } - /* New permission that's allowed */ - if (allowed) - priv->permissions = g_slist_prepend (priv->permissions, g_strdup (permission)); + if (allowed) { + c_list_link_tail (&priv->permissions, + &nm_c_list_elem_new_stale (g_strdup (permission))->lst); + } } /** @@ -310,51 +353,48 @@ nm_secret_agent_add_permission (NMSecretAgent *agent, gboolean nm_secret_agent_has_permission (NMSecretAgent *agent, const char *permission) { - NMSecretAgentPrivate *priv; - GSList *iter; - g_return_val_if_fail (agent != NULL, FALSE); g_return_val_if_fail (permission != NULL, FALSE); - priv = NM_SECRET_AGENT_GET_PRIVATE (agent); - - /* Check if the permission is already in the list */ - for (iter = priv->permissions; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (permission, iter->data) == 0) - return TRUE; - } - return FALSE; + return !!nm_c_list_elem_find_first (&NM_SECRET_AGENT_GET_PRIVATE (agent)->permissions, + p, nm_streq (p, permission)); } /*****************************************************************************/ static void -get_callback (GObject *proxy, - GAsyncResult *result, - gpointer user_data) +_dbus_call_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) { - NMSecretAgentCallId *r = user_data; - - if (request_check_return (r)) { - NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent); - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *ret = NULL; - gs_unref_variant GVariant *secrets = NULL; - - ret = _nm_dbus_proxy_call_finish (priv->proxy, result, G_VARIANT_TYPE ("(a{sa{sv}})"), &error); - if (!ret) - g_dbus_error_strip_remote_error (error); - else { + NMSecretAgentCallId *call_id; + gs_unref_variant GVariant *ret = NULL; + gs_unref_variant GVariant *secrets = NULL; + gs_free_error GError *error = NULL; + + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); + + if ( !ret + && nm_utils_error_is_cancelled (error, FALSE)) + return; + + call_id = user_data; + + if (!ret) + g_dbus_error_strip_remote_error (error); + else { + if (nm_streq (call_id->method_name, METHOD_GET_SECRETS)) { g_variant_get (ret, "(@a{sa{sv}})", &secrets); } - r->callback (r->agent, r, secrets, error, r->callback_data); } - request_free (r); + _call_id_invoke_callback (call_id, secrets, error, FALSE, TRUE); } +/*****************************************************************************/ + NMSecretAgentCallId * nm_secret_agent_get_secrets (NMSecretAgent *self, const char *path, @@ -367,160 +407,139 @@ nm_secret_agent_get_secrets (NMSecretAgent *self, { NMSecretAgentPrivate *priv; GVariant *dict; - NMSecretAgentCallId *r; + NMSecretAgentCallId *call_id; g_return_val_if_fail (NM_IS_SECRET_AGENT (self), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (path && *path, NULL); - g_return_val_if_fail (setting_name != NULL, NULL); + g_return_val_if_fail (setting_name, NULL); + g_return_val_if_fail (callback, NULL); priv = NM_SECRET_AGENT_GET_PRIVATE (self); - g_return_val_if_fail (priv->proxy != NULL, NULL); dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL); /* Mask off the private flags if present */ - flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM; - flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS; - - r = request_new (self, "GetSecrets", path, setting_name, callback, callback_data); - r->is_get_secrets = TRUE; - - g_dbus_proxy_call (priv->proxy, - "GetSecrets", - g_variant_new ("(@a{sa{sv}}os^asu)", - dict, - path, - setting_name, - hints ?: NM_PTRARRAY_EMPTY (const char *), - (guint32) flags), - G_DBUS_CALL_FLAGS_NONE, - 120000, - r->cancellable, - get_callback, - r); - - g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (priv->proxy), -1); - - return r; + flags &= ~( NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM + | NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS); + + call_id = _call_id_new (self, METHOD_GET_SECRETS, path, setting_name, callback, callback_data); + + g_dbus_connection_call (priv->dbus_connection, + priv->dbus_owner, + NM_DBUS_PATH_SECRET_AGENT, + NM_DBUS_INTERFACE_SECRET_AGENT, + call_id->method_name, + g_variant_new ("(@a{sa{sv}}os^asu)", + dict, + path, + setting_name, + hints ?: NM_PTRARRAY_EMPTY (const char *), + (guint32) flags), + G_VARIANT_TYPE ("(a{sa{sv}})"), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 120000, + call_id->cancellable, + _dbus_call_cb, + call_id); + + return call_id; } /*****************************************************************************/ static void -cancel_done (GObject *proxy, GAsyncResult *result, gpointer user_data) +_call_cancel_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) { - gs_free char *description = user_data; + NMSecretAgentCallId *call_id = user_data; gs_free_error GError *error = NULL; gs_unref_variant GVariant *ret = NULL; - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, G_VARIANT_TYPE ("()"), &error); - if (!ret) { - nm_log_dbg (LOGD_AGENTS, "%s%s%s: agent failed to cancel secrets: %s", - NM_PRINT_FMT_QUOTED (description, "(", description, ")", "???"), - error->message); - } -} - -static void -do_cancel_secrets (NMSecretAgent *self, NMSecretAgentCallId *r, gboolean disposing) -{ - NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); - GCancellable *cancellable; - NMSecretAgentCallback callback; - gpointer callback_data; + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); - g_return_if_fail (r->agent == self); - g_return_if_fail (r->cancellable); - - if ( r->is_get_secrets - && priv->proxy) { - /* for GetSecrets call, we must cancel the request. */ - g_dbus_proxy_call (G_DBUS_PROXY (priv->proxy), - "CancelGetSecrets", - g_variant_new ("(os)", - r->path, - r->setting_name), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - cancel_done, - g_strdup (nm_secret_agent_get_description (self))); + if (ret) + _LOG2T (call_id, "success cancelling GetSecrets"); + else if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + _LOG2T (call_id, "cancelling GetSecrets no longer works as service disconnected"); + else { + _LOG2T (call_id, "failed to cancel GetSecrets: %s", + error->message); } - cancellable = r->cancellable; - callback = r->callback; - callback_data = r->callback_data; - - /* During g_cancellable_cancel() the d-bus method might return synchronously. - * Clear r->cancellable first, so that it doesn't actually do anything. - * After that, @r might be already freed. */ - r->cancellable = NULL; - g_cancellable_cancel (cancellable); - g_object_unref (cancellable); - - /* Don't free the request @r. It will be freed when the d-bus call returns. - * Only clear r->cancellable to indicate that the request was cancelled. */ - - if (callback) { - gs_free_error GError *error = NULL; - - nm_utils_error_set_cancelled (&error, disposing, "NMSecretAgent"); - /* @r might be a dangling pointer at this point. However, that is no problem - * to pass it as (opaque) call_id. */ - callback (self, r, NULL, error, callback_data); - } + _call_id_free (call_id); } /** - * nm_secret_agent_cancel_secrets: - * @self: #NMSecretAgent instance - * @call_id: the call id to cancel + * nm_secret_agent_cancel_call: + * @self: the #NMSecretAgent instance for the @call_id. + * Maybe be %NULL if @call_id is %NULL. + * @call_id: (allow-none): the call id to cancel. May be %NULL for convenience, + * in which case it does nothing. * * It is an error to pass an invalid @call_id or a @call_id for an operation - * that already completed. NMSecretAgent will always invoke the callback, - * also for cancel() and dispose(). - * In case of nm_secret_agent_cancel_secrets() this will synchronously invoke the - * callback before nm_secret_agent_cancel_secrets() returns. + * that already completed. It is also an error to cancel the call from inside + * the callback, at that point the call is already completed. + * In case of nm_secret_agent_cancel_call() this will synchronously invoke the + * callback before nm_secret_agent_cancel_call() returns. */ void -nm_secret_agent_cancel_secrets (NMSecretAgent *self, NMSecretAgentCallId *call_id) +nm_secret_agent_cancel_call (NMSecretAgent *self, + NMSecretAgentCallId *call_id) { - NMSecretAgentCallId *r = call_id; - - g_return_if_fail (NM_IS_SECRET_AGENT (self)); - g_return_if_fail (r); - - nm_assert (c_list_contains (&NM_SECRET_AGENT_GET_PRIVATE (self)->requests, - &r->lst)); - - c_list_unlink (&r->lst); + NMSecretAgentPrivate *priv; + gboolean free_call_id = TRUE; - do_cancel_secrets (self, r, FALSE); -} + if (!call_id) { + /* for convenience, %NULL is accepted fine. */ + nm_assert (!self || NM_IS_SECRET_AGENT (self)); + return; + } -/*****************************************************************************/ + g_return_if_fail (NM_IS_SECRET_AGENT (call_id->self)); + g_return_if_fail (!c_list_is_empty (&call_id->lst)); -static void -agent_save_cb (GObject *proxy, - GAsyncResult *result, - gpointer user_data) -{ - NMSecretAgentCallId *r = user_data; + /* Theoretically, call-id already has a self pointer. But nm_secret_agent_cancel_call() has only + * one user: NMAgentManager. And that one has the self-pointer at hand, so the only purpose of + * the @self argument is to assert that we are cancelling the expected call. + * + * We could drop the @self argument, but that just remove an additional assert-check from + * our code, without making a simplification for the only caller of this function. */ + g_return_if_fail (self == call_id->self); - if (request_check_return (r)) { - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *ret = NULL; + priv = NM_SECRET_AGENT_GET_PRIVATE (self); - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, G_VARIANT_TYPE ("()"), &error); - if (!ret) - g_dbus_error_strip_remote_error (error); - r->callback (r->agent, r, NULL, error, r->callback_data); + nm_assert (c_list_contains (&priv->requests, + &call_id->lst)); + + nm_clear_g_cancellable (&call_id->cancellable); + + if (nm_streq (call_id->method_name, METHOD_GET_SECRETS)) { + g_dbus_connection_call (priv->dbus_connection, + priv->dbus_owner, + NM_DBUS_PATH_SECRET_AGENT, + NM_DBUS_INTERFACE_SECRET_AGENT, + METHOD_CANCEL_GET_SECRETS, + g_variant_new ("(os)", + call_id->path, + call_id->setting_name), + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + NM_SHUTDOWN_TIMEOUT_MS, + NULL, /* this operation is not cancellable. We rely on the timeout. */ + _call_cancel_cb, + call_id); + /* we keep call-id alive, but it will be unlinked from priv->requests. + * _call_cancel_cb() will finally free it later. */ + free_call_id = FALSE; } - request_free (r); + _call_id_invoke_callback (call_id, NULL, NULL, TRUE, free_call_id); } +/*****************************************************************************/ + NMSecretAgentCallId * nm_secret_agent_save_secrets (NMSecretAgent *self, const char *path, @@ -530,7 +549,7 @@ nm_secret_agent_save_secrets (NMSecretAgent *self, { NMSecretAgentPrivate *priv; GVariant *dict; - NMSecretAgentCallId *r; + NMSecretAgentCallId *call_id; g_return_val_if_fail (NM_IS_SECRET_AGENT (self), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); @@ -541,43 +560,28 @@ nm_secret_agent_save_secrets (NMSecretAgent *self, /* Caller should have ensured that only agent-owned secrets exist in 'connection' */ dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL); - r = request_new (self, "SaveSecrets", path, NULL, callback, callback_data); - g_dbus_proxy_call (priv->proxy, - "SaveSecrets", - g_variant_new ("(@a{sa{sv}}o)", - dict, - path), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* cancelling the request does *not* cancel the D-Bus call. */ - agent_save_cb, - r); - - return r; + call_id = _call_id_new (self, METHOD_SAVE_SECRETS, path, NULL, callback, callback_data); + + g_dbus_connection_call (priv->dbus_connection, + priv->dbus_owner, + NM_DBUS_PATH_SECRET_AGENT, + NM_DBUS_INTERFACE_SECRET_AGENT, + call_id->method_name, + g_variant_new ("(@a{sa{sv}}o)", + dict, + path), + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 60000, + call_id->cancellable, + _dbus_call_cb, + call_id); + + return call_id; } /*****************************************************************************/ -static void -agent_delete_cb (GObject *proxy, - GAsyncResult *result, - gpointer user_data) -{ - NMSecretAgentCallId *r = user_data; - - if (request_check_return (r)) { - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *ret = NULL; - - ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, G_VARIANT_TYPE ("()"), &error); - if (!ret) - g_dbus_error_strip_remote_error (error); - r->callback (r->agent, r, NULL, error, r->callback_data); - } - - request_free (r); -} - NMSecretAgentCallId * nm_secret_agent_delete_secrets (NMSecretAgent *self, const char *path, @@ -587,7 +591,7 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self, { NMSecretAgentPrivate *priv; GVariant *dict; - NMSecretAgentCallId *r; + NMSecretAgentCallId *call_id; g_return_val_if_fail (NM_IS_SECRET_AGENT (self), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); @@ -598,81 +602,90 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self, /* No secrets sent; agents must be smart enough to track secrets using the UUID or something */ dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); - r = request_new (self, "DeleteSecrets", path, NULL, callback, callback_data); - g_dbus_proxy_call (priv->proxy, - "DeleteSecrets", - g_variant_new ("(@a{sa{sv}}o)", - dict, - path), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* cancelling the request does *not* cancel the D-Bus call. */ - agent_delete_cb, - r); - return r; + call_id = _call_id_new (self, METHOD_DELETE_SECRETS, path, NULL, callback, callback_data); + + g_dbus_connection_call (priv->dbus_connection, + priv->dbus_owner, + NM_DBUS_PATH_SECRET_AGENT, + NM_DBUS_INTERFACE_SECRET_AGENT, + call_id->method_name, + g_variant_new ("(@a{sa{sv}}o)", + dict, + path), + G_VARIANT_TYPE ("()"), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 60000, + call_id->cancellable, + _dbus_call_cb, + call_id); + return call_id; } /*****************************************************************************/ static void -_on_disconnected_cleanup (NMSecretAgentPrivate *priv) +name_owner_changed (NMSecretAgent *self, + const char *owner) { - if (priv->connection_is_private) { - nm_clear_g_signal_handler (priv->bus_mgr, - &priv->on_disconnected_id.obj_signal); - } else { - nm_clear_g_dbus_connection_signal (priv->connection, - &priv->on_disconnected_id.dbus_signal); - } + NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); - g_clear_object (&priv->connection); - g_clear_object (&priv->proxy); - g_clear_object (&priv->bus_mgr); -} + nm_assert (!priv->name_owner_cancellable); -static void -_on_disconnected_private_connection (NMDBusManager *mgr, - GDBusConnection *connection, - NMSecretAgent *self) -{ - NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); + owner = nm_str_not_empty (owner); + + _LOGT ("name-owner-changed: %s%s%s", + NM_PRINT_FMT_QUOTED (owner, "has ", owner, "", "disconnected")); - if (priv->connection != connection) + if (owner) return; - _LOGt ("private connection disconnected"); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); - _on_disconnected_cleanup (priv); g_signal_emit (self, signals[DISCONNECTED], 0); } static void -_on_disconnected_name_owner_changed (GDBusConnection *connection, - const char *sender_name, - const char *object_path, - const char *interface_name, - const char *signal_name, - GVariant *parameters, - gpointer user_data) +name_owner_changed_cb (GDBusConnection *dbus_connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) { NMSecretAgent *self = NM_SECRET_AGENT (user_data); - NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); - const char *old_owner = NULL, *new_owner = NULL; + const char *new_owner = NULL; + + if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) { + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + } - g_variant_get (parameters, - "(&s&s&s)", - NULL, - &old_owner, - &new_owner); + nm_clear_g_cancellable (&NM_SECRET_AGENT_GET_PRIVATE (self)->name_owner_cancellable); - _LOGt ("name-owner-changed: %s%s%s => %s%s%s", - NM_PRINT_FMT_QUOTE_STRING (old_owner), - NM_PRINT_FMT_QUOTE_STRING (new_owner)); + name_owner_changed (self, new_owner); +} - if (!*new_owner) { - _on_disconnected_cleanup (priv); - g_signal_emit (self, signals[DISCONNECTED], 0); - } +static void +get_name_owner_cb (const char *name_owner, + GError *error, + gpointer user_data) +{ + NMSecretAgent *self; + + if ( !name_owner + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = user_data; + + g_clear_object (&NM_SECRET_AGENT_GET_PRIVATE (self)->name_owner_cancellable); + + name_owner_changed (self, name_owner); } /*****************************************************************************/ @@ -692,16 +705,16 @@ nm_secret_agent_new (GDBusMethodInvocation *context, char buf_subject[64]; char buf_caps[150]; gulong uid; - GDBusConnection *connection; + GDBusConnection *dbus_connection; g_return_val_if_fail (context != NULL, NULL); g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); g_return_val_if_fail (nm_auth_subject_is_unix_process (subject), NULL); g_return_val_if_fail (identifier != NULL, NULL); - connection = g_dbus_method_invocation_get_connection (context); + dbus_connection = g_dbus_method_invocation_get_connection (context); - g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); + g_return_val_if_fail (G_IS_DBUS_CONNECTION (dbus_connection), NULL); uid = nm_auth_subject_get_unix_process_uid (subject); @@ -715,16 +728,13 @@ nm_secret_agent_new (GDBusMethodInvocation *context, priv = NM_SECRET_AGENT_GET_PRIVATE (self); - priv->bus_mgr = g_object_ref (nm_dbus_manager_get ()); - priv->connection = g_object_ref (connection); - priv->connection_is_private = !!nm_dbus_manager_connection_get_private_name (priv->bus_mgr, connection); + priv->dbus_connection = g_object_ref (dbus_connection); - _LOGt ("constructed: %s, owner=%s%s%s (%s), private-connection=%d, unique-name=%s%s%s, capabilities=%s", + _LOGT ("constructed: %s, owner=%s%s%s (%s), unique-name=%s%s%s, capabilities=%s", (description = _create_description (dbus_owner, identifier, uid)), NM_PRINT_FMT_QUOTE_STRING (owner_username), nm_auth_subject_to_string (subject, buf_subject, sizeof (buf_subject)), - priv->connection_is_private, - NM_PRINT_FMT_QUOTE_STRING (g_dbus_connection_get_unique_name (priv->connection)), + NM_PRINT_FMT_QUOTE_STRING (g_dbus_connection_get_unique_name (priv->dbus_connection)), _capabilities_to_string (capabilities, buf_caps, sizeof (buf_caps))); priv->identifier = g_strdup (identifier); @@ -734,27 +744,19 @@ nm_secret_agent_new (GDBusMethodInvocation *context, priv->capabilities = capabilities; priv->subject = g_object_ref (subject); - priv->proxy = nm_dbus_manager_new_proxy (priv->bus_mgr, - priv->connection, - G_TYPE_DBUS_PROXY, - priv->dbus_owner, - NM_DBUS_PATH_SECRET_AGENT, - NM_DBUS_INTERFACE_SECRET_AGENT); - - /* we cannot subscribe to notify::g-name-owner because that doesn't work - * for unique names and it doesn't work for private connections. */ - if (priv->connection_is_private) { - priv->on_disconnected_id.obj_signal = g_signal_connect (priv->bus_mgr, - NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED, - G_CALLBACK (_on_disconnected_private_connection), - self); - } else { - priv->on_disconnected_id.dbus_signal = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->connection, - priv->dbus_owner, - _on_disconnected_name_owner_changed, - self, - NULL); - } + priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, + priv->dbus_owner, + name_owner_changed_cb, + self, + NULL); + + priv->name_owner_cancellable = g_cancellable_new (); + nm_dbus_connection_call_get_name_owner (priv->dbus_connection, + priv->dbus_owner, + -1, + priv->name_owner_cancellable, + get_name_owner_cb, + self); return self; } @@ -764,6 +766,7 @@ nm_secret_agent_init (NMSecretAgent *self) { NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); + c_list_init (&priv->permissions); c_list_init (&priv->requests); } @@ -772,18 +775,13 @@ dispose (GObject *object) { NMSecretAgent *self = NM_SECRET_AGENT (object); NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); - CList *iter; -again: - c_list_for_each (iter, &priv->requests) { - c_list_unlink (iter); - do_cancel_secrets (self, c_list_entry (iter, NMSecretAgentCallId, lst), TRUE); - goto again; - } + nm_assert (c_list_is_empty (&priv->requests)); - _on_disconnected_cleanup (priv); + nm_clear_g_dbus_connection_signal (priv->dbus_connection, + &priv->name_owner_changed_id); - g_clear_object (&priv->subject); + nm_clear_g_cancellable (&priv->name_owner_cancellable); G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object); } @@ -799,11 +797,15 @@ finalize (GObject *object) g_free (priv->owner_username); g_free (priv->dbus_owner); - g_slist_free_full (priv->permissions, g_free); + nm_c_list_elem_free_all (&priv->permissions, g_free); + + g_clear_object (&priv->subject); + + g_clear_object (&priv->dbus_connection); G_OBJECT_CLASS (nm_secret_agent_parent_class)->finalize (object); - _LOGt ("finalized"); + _LOGT ("finalized"); } static void @@ -823,4 +825,3 @@ nm_secret_agent_class_init (NMSecretAgentClass *config_class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } - diff --git a/src/settings/nm-secret-agent.h b/src/settings/nm-secret-agent.h index 209a1009..ea86e432 100644 --- a/src/settings/nm-secret-agent.h +++ b/src/settings/nm-secret-agent.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 - 2011 Red Hat, Inc. */ @@ -79,9 +65,6 @@ NMSecretAgentCallId *nm_secret_agent_get_secrets (NMSecretAgent *agent, NMSecretAgentCallback callback, gpointer callback_data); -void nm_secret_agent_cancel_secrets (NMSecretAgent *agent, - NMSecretAgentCallId *call_id); - NMSecretAgentCallId *nm_secret_agent_save_secrets (NMSecretAgent *agent, const char *path, NMConnection *connection, @@ -94,4 +77,7 @@ NMSecretAgentCallId *nm_secret_agent_delete_secrets (NMSecretAgent *agent, NMSecretAgentCallback callback, gpointer callback_data); +void nm_secret_agent_cancel_call (NMSecretAgent *self, + NMSecretAgentCallId *call_id); + #endif /* __NETWORKMANAGER_SECRET_AGENT_H__ */ diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index ed0cb8e8..ccbab807 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -1,21 +1,7 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2008 Novell, Inc. - * Copyright 2008 - 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2008 - 2014 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 61d5c246..dfc3786c 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -1,21 +1,7 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Novell, Inc. - * (C) Copyright 2008 - 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2008 - 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_SETTINGS_CONNECTION_H__ diff --git a/src/settings/nm-settings-plugin.c b/src/settings/nm-settings-plugin.c index 09010931..630532ef 100644 --- a/src/settings/nm-settings-plugin.c +++ b/src/settings/nm-settings-plugin.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2018 Red Hat, Inc. * Copyright (C) 2008 Novell, Inc. */ diff --git a/src/settings/nm-settings-plugin.h b/src/settings/nm-settings-plugin.h index 4df3472e..d27429db 100644 --- a/src/settings/nm-settings-plugin.h +++ b/src/settings/nm-settings-plugin.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2018 Red Hat, Inc. * Copyright (C) 2008 Novell, Inc. */ diff --git a/src/settings/nm-settings-storage.c b/src/settings/nm-settings-storage.c index 935b5b48..483773f6 100644 --- a/src/settings/nm-settings-storage.c +++ b/src/settings/nm-settings-storage.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/settings/nm-settings-storage.h b/src/settings/nm-settings-storage.h index c43145b5..62ee8876 100644 --- a/src/settings/nm-settings-storage.h +++ b/src/settings/nm-settings-storage.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2018 Red Hat, Inc. + * Copyright (C) 2018 Red Hat, Inc. */ #ifndef __NM_SETTINGS_STORAGE_H__ diff --git a/src/settings/nm-settings-utils.c b/src/settings/nm-settings-utils.c index 0d636537..c5ec6c31 100644 --- a/src/settings/nm-settings-utils.c +++ b/src/settings/nm-settings-utils.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2019 Red Hat, Inc. */ diff --git a/src/settings/nm-settings-utils.h b/src/settings/nm-settings-utils.h index a2a22dc4..1f9a6ea1 100644 --- a/src/settings/nm-settings-utils.h +++ b/src/settings/nm-settings-utils.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_SETTINGS_UTILS_H__ diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 6529cc58..f964fb16 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1,25 +1,10 @@ -/* NetworkManager system settings service - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Søren Sandmann <sandmann@daimi.au.dk> * Dan Williams <dcbw@redhat.com> * Tambet Ingo <tambet@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007 - 2011 Red Hat, Inc. - * (C) Copyright 2008 Novell, Inc. + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2008 Novell, Inc. */ #include "nm-default.h" @@ -2487,17 +2472,6 @@ nm_settings_add_connection_dbus (NMSettings *self, goto done; } - /* FIXME: The kernel doesn't support Ad-Hoc WPA connections well at this time, - * and turns them into open networks. It's been this way since at least - * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks. - */ - if (nm_utils_connection_is_adhoc_wpa (connection)) { - error = g_error_new_literal (NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "WPA Ad-Hoc disabled due to kernel bugs"); - goto done; - } - if (!nm_auth_is_subject_in_acl_set_error (connection, subject, NM_SETTINGS_ERROR, @@ -2776,9 +2750,10 @@ impl_settings_load_connections (NMDBusObject *obj, for (i = 0; i < n_entries; i++) { NMSettingsPluginConnectionLoadEntry *entry = &entries[i]; - if (!entry->handled) + if (!entry->handled) { _LOGW ("load: no settings plugin could load \"%s\"", entry->filename); - else if (entry->error) { + nm_assert (!entry->error); + } else if (entry->error) { _LOGW ("load: failure to load \"%s\": %s", entry->filename, entry->error->message); g_clear_error (&entry->error); } else @@ -2847,6 +2822,7 @@ impl_settings_reload_connections (NMDBusObject *obj, nm_audit_log_connection_op (NM_AUDIT_OP_CONNS_RELOAD, NULL, TRUE, NULL, invocation, NULL); + /* We MUST return %TRUE here, otherwise older libnm versions might misbehave. */ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE)); } @@ -3140,9 +3116,9 @@ add_plugin (NMSettings *self, priv->plugins = g_slist_append (priv->plugins, g_object_ref (plugin)); - nm_shutdown_wait_obj_register_full (G_OBJECT (plugin), - g_strdup_printf ("%s-settings-plugin", pname), - TRUE); + nm_shutdown_wait_obj_register_object_full (plugin, + g_strdup_printf ("%s-settings-plugin", pname), + TRUE); _LOGI ("Loaded settings plugin: %s (%s%s%s)", pname, @@ -3455,14 +3431,27 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self) */ if ( !NM_DEVICE_GET_CLASS (device)->new_default_connection || !nm_device_get_managed (device, FALSE) - || g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ()) - || have_connection_for_device (self, device) - || nm_config_get_no_auto_default_for_device (priv->config, device)) + || g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ())) return; + if (nm_config_get_no_auto_default_for_device (priv->config, device)) { + _LOGT ("auto-default: cannot create auto-default connection for device %s: disabled by \"no-auto-default\"", + nm_device_get_iface (device)); + return; + } + + if (have_connection_for_device (self, device)) { + _LOGT ("auto-default: cannot create auto-default connection for device %s: already has a profile", + nm_device_get_iface (device)); + return; + } + connection = nm_device_new_default_connection (device); - if (!connection) + if (!connection) { + _LOGT ("auto-default: cannot create auto-default connection for device %s", + nm_device_get_iface (device)); return; + } _LOGT ("auto-default: creating in-memory connection %s (%s) for device %s", nm_connection_get_uuid (connection), diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index d2bf72d6..aa7e36e0 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -1,25 +1,10 @@ -/* NetworkManager system settings service - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Søren Sandmann <sandmann@daimi.au.dk> * Dan Williams <dcbw@redhat.com> * Tambet Ingo <tambet@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007 - 2011 Red Hat, Inc. - * (C) Copyright 2008 Novell, Inc. + * Copyright (C) 2007 - 2011 Red Hat, Inc. + * Copyright (C) 2008 Novell, Inc. */ #ifndef __NM_SETTINGS_H__ diff --git a/src/settings/plugins/ifcfg-rh/meson.build b/src/settings/plugins/ifcfg-rh/meson.build index 58acdcfc..d9dd3edb 100644 --- a/src/settings/plugins/ifcfg-rh/meson.build +++ b/src/settings/plugins/ifcfg-rh/meson.build @@ -25,23 +25,24 @@ core_sources = files( 'shvar.c', ) -deps = [ - nm_dep, -] - libnms_ifcfg_rh_core = static_library( 'nms-ifcfg-rh-core', sources: core_sources, - dependencies: deps, + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, ) -sources = [dbus_sources] + core_sources + files('nms-ifcfg-rh-storage.c', 'nms-ifcfg-rh-plugin.c') +sources = [dbus_sources] + core_sources + files( + 'nms-ifcfg-rh-storage.c', + 'nms-ifcfg-rh-plugin.c', +) libnm_settings_plugin_ifcfg_rh = shared_module( 'nm-settings-plugin-ifcfg-rh', sources: sources, - dependencies: deps, - link_with: [libnms_ifcfg_rh_core], + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, + link_with: libnms_ifcfg_rh_core, link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, install: true, @@ -50,27 +51,17 @@ libnm_settings_plugin_ifcfg_rh = shared_module( core_plugins += libnm_settings_plugin_ifcfg_rh -# FIXME: check_so_symbols replacement -''' -run_target( - 'check-local-symbols-settings-ifcfg-rh', - command: [check_so_symbols, libnm_settings_plugin_ifcfg_rh.full_path()], - depends: libnm_settings_plugin_ifcfg_rh, -) - -check-local-symbols-settings-ifcfg-rh: src/settings/plugins/ifcfg-rh/libnm-settings-plugin-ifcfg-rh.la - $(call check_so_symbols,$(builddir)/src/settings/plugins/ifcfg-rh/.libs/libnm-settings-plugin-ifcfg-rh.so) -''' +data = [ + 'nm-ifdown', + 'nm-ifup', +] install_data( - ['nm-ifup', 'nm-ifdown'], + data, install_dir: nm_libexecdir, install_mode: 'rwxr-xr-x', ) -meson.add_install_script('sh', '-c', - 'mkdir -p $DESTDIR/@0@/sysconfig/network-scripts'.format(nm_sysconfdir)) - if enable_tests subdir('tests') endif diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h index ff01fc7a..6a01a5ac 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 - 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2013 Red Hat, Inc. */ #ifndef __COMMON_H__ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index cc4fe4ce..f57ca1a7 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -1,22 +1,7 @@ -/* NetworkManager system settings service - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Dan Williams <dcbw@redhat.com> * Søren Sandmann <sandmann@daimi.au.dk> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Copyright (C) 2007 - 2011 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h index 1db36083..14cadac6 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h @@ -1,22 +1,7 @@ -/* NetworkManager system settings service - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Dan Williams <dcbw@redhat.com> * Søren Sandmann <sandmann@daimi.au.dk> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Copyright (C) 2007 - 2008 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 68ebd781..a1d3236e 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2008 - 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -29,6 +15,7 @@ #include <sys/inotify.h> #include <sys/ioctl.h> #include <unistd.h> +#include <linux/rtnetlink.h> #include "nm-glib-aux/nm-secret-utils.h" #include "nm-connection.h" @@ -753,25 +740,36 @@ parse_route_line_is_comment (const char *line) /*****************************************************************************/ +typedef enum { + PARSE_LINE_AF_FLAG_FOR_IPV4 = 0x01, + PARSE_LINE_AF_FLAG_FOR_IPV6 = 0x02, +} ParseLineAFFlag; + typedef struct { const char *key; /* the element is not available in this case. */ - bool disabled:1; + ParseLineAFFlag disabled:3; + + bool disabled_with_options_route:1; /* whether the element is to be ignored. Ignord is different from * "disabled", because we still parse the option, but don't use it. */ - bool ignore:1; + ParseLineAFFlag ignore:3; bool int_base_16:1; + /* the type, one of PARSE_LINE_TYPE_* */ + char type; + +} ParseLineInfo; + +typedef struct { + /* whether the command line option was found, and @v is * initialized. */ bool has:1; - /* the type, one of PARSE_LINE_TYPE_* */ - char type; - union { guint8 uint8; guint32 uint32; @@ -786,7 +784,7 @@ typedef struct { } addr; } v; -} ParseLineInfo; +} ParseLineData; enum { /* route attributes */ @@ -794,6 +792,7 @@ enum { PARSE_LINE_ATTR_ROUTE_SRC, PARSE_LINE_ATTR_ROUTE_FROM, PARSE_LINE_ATTR_ROUTE_TOS, + PARSE_LINE_ATTR_ROUTE_SCOPE, PARSE_LINE_ATTR_ROUTE_ONLINK, PARSE_LINE_ATTR_ROUTE_WINDOW, PARSE_LINE_ATTR_ROUTE_CWND, @@ -817,6 +816,7 @@ enum { #define PARSE_LINE_TYPE_ADDR_WITH_PREFIX 'p' #define PARSE_LINE_TYPE_IFNAME 'i' #define PARSE_LINE_TYPE_FLAG 'f' +#define PARSE_LINE_TYPE_ROUTE_SCOPE 'S' /** * parse_route_line: @@ -847,29 +847,23 @@ parse_route_line (const char *line, NMIPRoute **out_route, GError **error) { - nm_auto_unref_ip_route NMIPRoute *route = NULL; - gs_free const char **words_free = NULL; - const char *const*words; - const char *s; - gsize i_words; - guint i; - char buf1[256]; - char buf2[256]; - ParseLineInfo infos[] = { + static const ParseLineInfo parse_infos[] = { [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, .type = PARSE_LINE_TYPE_UINT32, }, [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, .type = PARSE_LINE_TYPE_ADDR, }, [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM, .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, - .disabled = (addr_family != AF_INET6), }, + .disabled = PARSE_LINE_AF_FLAG_FOR_IPV4, }, [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS, .type = PARSE_LINE_TYPE_UINT8, .int_base_16 = TRUE, - .ignore = (addr_family != AF_INET), }, + .ignore = PARSE_LINE_AF_FLAG_FOR_IPV6, }, + [PARSE_LINE_ATTR_ROUTE_SCOPE] = { .key = NM_IP_ROUTE_ATTRIBUTE_SCOPE, + .type = PARSE_LINE_TYPE_ROUTE_SCOPE, + .ignore = PARSE_LINE_AF_FLAG_FOR_IPV6, }, [PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK, - .type = PARSE_LINE_TYPE_FLAG, - .ignore = (addr_family != AF_INET), }, + .type = PARSE_LINE_TYPE_FLAG, }, [PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW, .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, [PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND, @@ -883,19 +877,31 @@ parse_route_line (const char *line, [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to", .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, - .disabled = (options_route != NULL), }, + .disabled_with_options_route = TRUE, }, [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via", .type = PARSE_LINE_TYPE_ADDR, - .disabled = (options_route != NULL), }, + .disabled_with_options_route = TRUE, }, [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric", .type = PARSE_LINE_TYPE_UINT32, - .disabled = (options_route != NULL), }, + .disabled_with_options_route = TRUE, }, [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev", .type = PARSE_LINE_TYPE_IFNAME, - .ignore = TRUE, - .disabled = (options_route != NULL), }, + .ignore = PARSE_LINE_AF_FLAG_FOR_IPV4 | PARSE_LINE_AF_FLAG_FOR_IPV6, + .disabled_with_options_route = TRUE, }, }; + nm_auto_unref_ip_route NMIPRoute *route = NULL; + gs_free const char **words_free = NULL; + const char *const*words; + const char *s; + gsize i_words; + guint i; + char buf1[256]; + char buf2[256]; + ParseLineData parse_datas[G_N_ELEMENTS (parse_infos)] = { }; + const ParseLineAFFlag af_flag = (addr_family == AF_INET) + ? PARSE_LINE_AF_FLAG_FOR_IPV4 + : PARSE_LINE_AF_FLAG_FOR_IPV6; nm_assert (line); nm_assert_addr_family (addr_family); @@ -923,19 +929,22 @@ parse_route_line (const char *line, for (i_words = 0; words[i_words]; ) { const gsize i_words0 = i_words; const char *const w = words[i_words0]; - ParseLineInfo *info; + const ParseLineInfo *p_info; + ParseLineData *p_data; gboolean unqualified_addr = FALSE; - for (i = 0; i < G_N_ELEMENTS (infos); i++) { - info = &infos[i]; + for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { + p_info = &parse_infos[i]; + p_data = &parse_datas[i]; - if (info->disabled) + if ( (p_info->disabled & af_flag) + || (p_info->disabled_with_options_route && options_route)) continue; - if (!nm_streq (w, info->key)) + if (!nm_streq (w, p_info->key)) continue; - if (info->has) { + if (p_data->has) { /* iproute2 for most arguments allows specifying them multiple times. * Let's not do that. */ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -943,8 +952,8 @@ parse_route_line (const char *line, return -EINVAL; } - info->has = TRUE; - switch (info->type) { + p_data->has = TRUE; + switch (p_info->type) { case PARSE_LINE_TYPE_UINT8: i_words++; goto parse_line_type_uint8; @@ -966,16 +975,22 @@ parse_route_line (const char *line, case PARSE_LINE_TYPE_FLAG: i_words++; goto next; + case PARSE_LINE_TYPE_ROUTE_SCOPE: + i_words++; + goto parse_line_type_route_scope; default: nm_assert_not_reached (); } } /* "to" is also accepted unqualified... (once) */ - info = &infos[PARSE_LINE_ATTR_ROUTE_TO]; - if (!info->has && !info->disabled) { + p_info = &parse_infos[PARSE_LINE_ATTR_ROUTE_TO]; + p_data = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO]; + if ( !p_data->has + && !(p_info->disabled & af_flag) + && !(p_info->disabled_with_options_route && options_route)) { unqualified_addr = TRUE; - info->has = TRUE; + p_data->has = TRUE; goto parse_line_type_addr; } @@ -983,15 +998,44 @@ parse_route_line (const char *line, "Unrecognized argument (\"to\" is duplicate or \"%s\" is garbage)", w); return -EINVAL; +parse_line_type_route_scope: + s = words[i_words]; + if (!s) + goto err_word_missing_argument; + if (nm_streq (s, "global")) + p_data->v.uint8 = RT_SCOPE_UNIVERSE; + else if (nm_streq (s, "nowhere")) + p_data->v.uint8 = RT_SCOPE_NOWHERE; + else if (nm_streq (s, "host")) + p_data->v.uint8 = RT_SCOPE_HOST; + else if (nm_streq (s, "link")) + p_data->v.uint8 = RT_SCOPE_LINK; + else if (nm_streq (s, "site")) + p_data->v.uint8 = RT_SCOPE_SITE; + else { + p_data->v.uint8 = _nm_utils_ascii_str_to_int64 (s, + 0, + 0, + G_MAXUINT8, + 0);; + if (errno) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Argument for \"%s\" is not a valid number", w); + return -EINVAL; + } + } + i_words++; + goto next; + parse_line_type_uint8: s = words[i_words]; if (!s) goto err_word_missing_argument; - info->v.uint8 = _nm_utils_ascii_str_to_int64 (s, - info->int_base_16 ? 16 : 10, - 0, - G_MAXUINT8, - 0);; + p_data->v.uint8 = _nm_utils_ascii_str_to_int64 (s, + p_info->int_base_16 ? 16 : 10, + 0, + G_MAXUINT8, + 0);; if (errno) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Argument for \"%s\" is not a valid number", w); @@ -1005,17 +1049,17 @@ parse_line_type_uint32_with_lock: s = words[i_words]; if (!s) goto err_word_missing_argument; - if (info->type == PARSE_LINE_TYPE_UINT32_WITH_LOCK) { + if (p_info->type == PARSE_LINE_TYPE_UINT32_WITH_LOCK) { if (nm_streq (s, "lock")) { s = words[++i_words]; if (!s) goto err_word_missing_argument; - info->v.uint32_with_lock.lock = TRUE; + p_data->v.uint32_with_lock.lock = TRUE; } else - info->v.uint32_with_lock.lock = FALSE; - info->v.uint32_with_lock.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);; + p_data->v.uint32_with_lock.lock = FALSE; + p_data->v.uint32_with_lock.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0);; } else { - info->v.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0); + p_data->v.uint32 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT32, 0); } if (errno) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -1040,16 +1084,16 @@ parse_line_type_addr_with_prefix: { int prefix = -1; - if (info->type == PARSE_LINE_TYPE_ADDR) { + if (p_info->type == PARSE_LINE_TYPE_ADDR) { if (!nm_utils_parse_inaddr_bin (addr_family, s, NULL, - &info->v.addr.addr)) { - if ( info == &infos[PARSE_LINE_ATTR_ROUTE_VIA] + &p_data->v.addr.addr)) { + if ( p_info == &parse_infos[PARSE_LINE_ATTR_ROUTE_VIA] && nm_streq (s, "(null)")) { /* Due to a bug, would older versions of NM write "via (null)" * (rh#1452648). Workaround that, and accept it.*/ - memset (&info->v.addr.addr, 0, sizeof (info->v.addr.addr)); + memset (&p_data->v.addr.addr, 0, sizeof (p_data->v.addr.addr)); } else { if (unqualified_addr) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -1064,15 +1108,15 @@ parse_line_type_addr_with_prefix: } } } else { - nm_assert (info->type == PARSE_LINE_TYPE_ADDR_WITH_PREFIX); - if ( info == &infos[PARSE_LINE_ATTR_ROUTE_TO] + nm_assert (p_info->type == PARSE_LINE_TYPE_ADDR_WITH_PREFIX); + if ( p_info == &parse_infos[PARSE_LINE_ATTR_ROUTE_TO] && nm_streq (s, "default")) { - memset (&info->v.addr.addr, 0, sizeof (info->v.addr.addr)); + memset (&p_data->v.addr.addr, 0, sizeof (p_data->v.addr.addr)); prefix = 0; } else if (!nm_utils_parse_inaddr_prefix_bin (addr_family, s, NULL, - &info->v.addr.addr, + &p_data->v.addr.addr, &prefix)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Argument for \"%s\" is not ADDR/PREFIX format", w); @@ -1080,10 +1124,10 @@ parse_line_type_addr_with_prefix: } } if (prefix == -1) - info->v.addr.has_plen = FALSE; + p_data->v.addr.has_plen = FALSE; else { - info->v.addr.has_plen = TRUE; - info->v.addr.plen = prefix; + p_data->v.addr.has_plen = TRUE; + p_data->v.addr.plen = prefix; } } i_words++; @@ -1101,79 +1145,76 @@ next: route = options_route; nm_ip_route_ref (route); } else { - ParseLineInfo *info_to = &infos[PARSE_LINE_ATTR_ROUTE_TO]; - ParseLineInfo *info_via = &infos[PARSE_LINE_ATTR_ROUTE_VIA]; - ParseLineInfo *info_metric = &infos[PARSE_LINE_ATTR_ROUTE_METRIC]; + ParseLineData *data_to = &parse_datas[PARSE_LINE_ATTR_ROUTE_TO]; + ParseLineData *data_via = &parse_datas[PARSE_LINE_ATTR_ROUTE_VIA]; + ParseLineData *data_metric = &parse_datas[PARSE_LINE_ATTR_ROUTE_METRIC]; guint prefix; - if (!info_to->has) { + if (!data_to->has) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing destination prefix"); return -EINVAL; } - prefix = info_to->v.addr.has_plen - ? info_to->v.addr.plen + prefix = data_to->v.addr.has_plen + ? data_to->v.addr.plen : (addr_family == AF_INET ? 32 : 128); - if ( ( (addr_family == AF_INET && !info_to->v.addr.addr.addr4) - || (addr_family == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED (&info_to->v.addr.addr.addr6))) - && prefix == 0) { - /* we ignore default routes by returning -ERANGE. */ - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Ignore manual default route"); - return -ERANGE; - } - route = nm_ip_route_new_binary (addr_family, - &info_to->v.addr.addr, + &data_to->v.addr.addr, prefix, - info_via->has ? &info_via->v.addr.addr : NULL, - info_metric->has ? (gint64) info_metric->v.uint32 : (gint64) -1, + data_via->has ? &data_via->v.addr.addr : NULL, + data_metric->has ? (gint64) data_metric->v.uint32 : (gint64) -1, error); - info_to->has = FALSE; - info_via->has = FALSE; - info_metric->has = FALSE; + data_to->has = FALSE; + data_via->has = FALSE; + data_metric->has = FALSE; if (!route) return -EINVAL; } - for (i = 0; i < G_N_ELEMENTS (infos); i++) { - ParseLineInfo *info = &infos[i]; + for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { + const ParseLineInfo *p_info = &parse_infos[i]; + ParseLineData *p_data = &parse_datas[i]; - if (!info->has) + if (!p_data->has) continue; - if (info->ignore || info->disabled) + + if ( (p_info->ignore & af_flag) + || (p_info->disabled & af_flag) + || (p_info->disabled_with_options_route && options_route)) continue; - switch (info->type) { + + switch (p_info->type) { case PARSE_LINE_TYPE_UINT8: + case PARSE_LINE_TYPE_ROUTE_SCOPE: nm_ip_route_set_attribute (route, - info->key, - g_variant_new_byte (info->v.uint8)); + p_info->key, + g_variant_new_byte (p_data->v.uint8)); break; case PARSE_LINE_TYPE_UINT32: nm_ip_route_set_attribute (route, - info->key, - g_variant_new_uint32 (info->v.uint32)); + p_info->key, + g_variant_new_uint32 (p_data->v.uint32)); break; case PARSE_LINE_TYPE_UINT32_WITH_LOCK: - if (info->v.uint32_with_lock.lock) { + if (p_data->v.uint32_with_lock.lock) { nm_ip_route_set_attribute (route, - nm_sprintf_buf (buf1, "lock-%s", info->key), + nm_sprintf_buf (buf1, "lock-%s", p_info->key), g_variant_new_boolean (TRUE)); } nm_ip_route_set_attribute (route, - info->key, - g_variant_new_uint32 (info->v.uint32_with_lock.uint32)); + p_info->key, + g_variant_new_uint32 (p_data->v.uint32_with_lock.uint32)); break; case PARSE_LINE_TYPE_ADDR: case PARSE_LINE_TYPE_ADDR_WITH_PREFIX: nm_ip_route_set_attribute (route, - info->key, + p_info->key, g_variant_new_printf ("%s%s", - inet_ntop (addr_family, &info->v.addr.addr, buf1, sizeof (buf1)), - info->v.addr.has_plen - ? nm_sprintf_buf (buf2, "/%u", (unsigned) info->v.addr.plen) + inet_ntop (addr_family, &p_data->v.addr.addr, buf1, sizeof (buf1)), + p_data->v.addr.has_plen + ? nm_sprintf_buf (buf2, "/%u", (unsigned) p_data->v.addr.plen) : "")); break; case PARSE_LINE_TYPE_FLAG: @@ -1182,7 +1223,7 @@ next: * of this attribute, hence, the file format cannot encode * that configuration. */ nm_ip_route_set_attribute (route, - info->key, + p_info->key, g_variant_new_boolean (TRUE)); break; default: @@ -1244,7 +1285,7 @@ read_one_ip4_route (shvarFile *ifcfg, return FALSE; if (has_key) { prefix = nm_utils_ip4_netmask_to_prefix (netmask); - if (prefix == 0 || netmask != _nm_utils_ip4_prefix_to_netmask (prefix)) { + if (netmask != _nm_utils_ip4_prefix_to_netmask (prefix)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP4 netmask '%s' \"%s\"", netmask_tag, nm_utils_inet4_ntop (netmask, inet_buf)); return FALSE; @@ -1538,7 +1579,7 @@ make_ip4_setting (shvarFile *ifcfg, gboolean has_key; shvarFile *route_ifcfg; gboolean never_default; - gint64 timeout; + gint64 i64; int priority; const char *const *item; guint32 route_table; @@ -1641,6 +1682,14 @@ make_ip4_setting (shvarFile *ifcfg, NULL); } + i64 = svGetValueInt64 (ifcfg, "DHCP_HOSTNAME_FLAGS", 10, 0, G_MAXUINT32, -1); + if (i64 > -1) { + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, + (guint) i64, + NULL); + } + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, svGetValueBoolean (ifcfg, "DHCP_SEND_HOSTNAME", TRUE), NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, svGetValueInt64 (ifcfg, "IPV4_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0), @@ -1651,6 +1700,11 @@ make_ip4_setting (shvarFile *ifcfg, if (v) g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, v, NULL); + nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "DHCP_IAID", &value); + if (v) + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_IAID, v, NULL); + /* Read static IP addresses. * Read them even for AUTO method - in this case the addresses are * added to the automatic ones. Note that this is not currently supported by @@ -1806,14 +1860,14 @@ make_ip4_setting (shvarFile *ifcfg, } } - timeout = svGetValueInt64 (ifcfg, "ACD_TIMEOUT", 10, -1, NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, -2); - if (timeout == -2) { - timeout = svGetValueInt64 (ifcfg, "ARPING_WAIT", 10, -1, - NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX / 1000, -1); - if (timeout > 0) - timeout *= 1000; + i64 = svGetValueInt64 (ifcfg, "ACD_TIMEOUT", 10, -1, NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX, -2); + if (i64 == -2) { + i64 = svGetValueInt64 (ifcfg, "ARPING_WAIT", 10, -1, + NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX / 1000, -1); + if (i64 > 0) + i64 *= 1000; } - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (int) timeout, NULL); + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (int) i64, NULL); return NM_SETTING (g_steal_pointer (&s_ip4)); } @@ -1947,6 +2001,7 @@ make_ip6_setting (shvarFile *ifcfg, gs_free const char **list = NULL; const char *const *iter; guint32 i; + gint64 i64; int i_val; GError *local = NULL; int priority; @@ -2085,6 +2140,11 @@ make_ip6_setting (shvarFile *ifcfg, g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_DHCP_DUID, v, NULL); nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "DHCPV6_IAID", &value); + if (v) + g_object_set (s_ip6, NM_SETTING_IP_CONFIG_DHCP_IAID, v, NULL); + + nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "DHCPV6_HOSTNAME", &value); /* Use DHCP_HOSTNAME as fallback if it is in FQDN format and ipv6.method is * auto or dhcp: this is required to support old ifcfg files @@ -2102,6 +2162,15 @@ make_ip6_setting (shvarFile *ifcfg, g_object_set (s_ip6, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, svGetValueBoolean (ifcfg, "DHCPV6_SEND_HOSTNAME", TRUE), NULL); + + i64 = svGetValueInt64 (ifcfg, "DHCPV6_HOSTNAME_FLAGS", 10, 0, G_MAXUINT32, -1); + if (i64 > -1) { + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, + (guint) i64, + NULL); + } + /* Read static IP addresses. * Read them even for AUTO and DHCP methods - in this case the addresses are * added to the automatic ones. Note that this is not currently supported by @@ -2762,7 +2831,7 @@ add_one_wep_key (shvarFile *ifcfg, /* Hexadecimal WEP key */ if (NM_STRCHAR_ANY (value, ch, !g_ascii_isxdigit (ch))) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid hexadecimal WEP key."); + "Invalid hexadecimal WEP key"); return FALSE; } key = value; @@ -2771,7 +2840,7 @@ add_one_wep_key (shvarFile *ifcfg, /* ASCII key */ if (NM_STRCHAR_ANY (value + 2, ch, !g_ascii_isprint (ch))) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid ASCII WEP key."); + "Invalid ASCII WEP key"); return FALSE; } @@ -2787,7 +2856,7 @@ add_one_wep_key (shvarFile *ifcfg, if (!key) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid WEP key length."); + "Invalid WEP key length"); return FALSE; } @@ -2934,7 +3003,7 @@ make_wep_setting (shvarFile *ifcfg, if (auth_alg && !strcmp (auth_alg, "shared")) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "WEP Shared Key authentication is invalid for " - "unencrypted connections."); + "unencrypted connections"); return NULL; } @@ -2963,22 +3032,6 @@ fill_wpa_ciphers (shvarFile *ifcfg, list = nm_utils_strsplit_set (p, " "); for (iter = list; iter && *iter; iter++, i++) { - /* Ad-Hoc configurations cannot have pairwise ciphers, and can only - * have one group cipher. Ignore any additional group ciphers and - * any pairwise ciphers specified. - */ - if (adhoc) { - if (group && (i > 0)) { - PARSE_WARNING ("ignoring group cipher '%s' (only one group cipher allowed " - "in Ad-Hoc mode)", *iter); - continue; - } else if (!group) { - PARSE_WARNING ("ignoring pairwise cipher '%s' (pairwise not used " - "in Ad-Hoc mode)", *iter); - continue; - } - } - if (!strcmp (*iter, "CCMP")) { if (group) nm_setting_wireless_security_add_group (wsec, "ccmp"); @@ -3184,6 +3237,89 @@ eap_tls_reader (const char *eap_method, } static gboolean +parse_8021x_phase2_auth (shvarFile *ifcfg, + shvarFile *keys_ifcfg, + NMSetting8021x *s_8021x, + GError **error) +{ + gs_free char *inner_auth = NULL; + gs_free char *v_free = NULL; + const char *v; + gs_free const char **list = NULL; + const char *const *iter; + guint num_auth = 0; + guint num_autheap = 0; + + v = svGetValueStr (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", &v_free); + if (!v) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Missing IEEE_8021X_INNER_AUTH_METHODS"); + return FALSE; + } + + inner_auth = g_ascii_strdown (v, -1); + list = nm_utils_strsplit_set (inner_auth, " "); + for (iter = list; iter && *iter; iter++) { + if (NM_IN_STRSET (*iter, "pap", + "chap", + "mschap", + "mschapv2", + "gtc", + "otp", + "md5")) { + if (num_auth == 0) { + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) + return FALSE; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, *iter, NULL); + } + num_auth++; + } else if (nm_streq (*iter, "tls")) { + if (num_auth == 0) { + if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) + return FALSE; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL); + } + num_auth++; + } else if (NM_IN_STRSET (*iter, "eap-md5", + "eap-mschapv2", + "eap-otp", + "eap-gtc")) { + if (num_autheap == 0) { + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) + return FALSE; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + NM_STRLEN ("eap-")), NULL); + } + num_autheap++; + } else if (nm_streq (*iter, "eap-tls")) { + if (num_autheap == 0) { + if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) + return FALSE; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", NULL); + } + num_autheap++; + } else { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'", + *iter); + return FALSE; + } + } + + if (num_auth > 1) + PARSE_WARNING ("Discarded extra phase2 authentication methods"); + if (num_auth > 1) + PARSE_WARNING ("Discarded extra phase2 EAP authentication methods"); + + if (!num_auth && !num_autheap) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "No phase2 authentication method found"); + return FALSE; + } + + return TRUE; +} + +static gboolean eap_peap_reader (const char *eap_method, shvarFile *ifcfg, shvarFile *keys_ifcfg, @@ -3193,8 +3329,6 @@ eap_peap_reader (const char *eap_method, { gs_free char *value = NULL; const char *v; - gs_free const char **list = NULL; - const char *const *iter; if (!_cert_set_from_ifcfg (s_8021x, ifcfg, @@ -3232,46 +3366,8 @@ eap_peap_reader (const char *eap_method, if (v) g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, v, NULL); - nm_clear_g_free (&value); - v = svGetValueStr (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", &value); - if (!v) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing IEEE_8021X_INNER_AUTH_METHODS."); - return FALSE; - } - - /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (v, " "); - iter = list; - if (iter) { - if (NM_IN_STRSET (*iter, "MSCHAPV2", - "MD5", - "GTC")) { - if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) - return FALSE; - } else if (nm_streq (*iter, "TLS")) { - if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) - return FALSE; - } else { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.", - *iter); - return FALSE; - } - - { - gs_free char *lower = NULL; - - lower = g_ascii_strdown (*iter, -1); - g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, NULL); - } - } - - if (!nm_setting_802_1x_get_phase2_auth (s_8021x)) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "No valid IEEE_8021X_INNER_AUTH_METHODS found."); + if (!parse_8021x_phase2_auth (ifcfg, keys_ifcfg, s_8021x, error)) return FALSE; - } return TRUE; } @@ -3284,11 +3380,8 @@ eap_ttls_reader (const char *eap_method, gboolean phase2, GError **error) { - gs_free char *inner_auth = NULL; gs_free char *value = NULL; const char *v; - gs_free const char **list = NULL; - const char *const *iter; if (!_cert_set_from_ifcfg (s_8021x, ifcfg, @@ -3308,44 +3401,8 @@ eap_ttls_reader (const char *eap_method, if (v) g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, v, NULL); - nm_clear_g_free (&value); - v = svGetValueStr (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", &value); - if (!v) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing IEEE_8021X_INNER_AUTH_METHODS."); + if (!parse_8021x_phase2_auth (ifcfg, keys_ifcfg, s_8021x, error)) return FALSE; - } - - inner_auth = g_ascii_strdown (v, -1); - - /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (inner_auth, " "); - iter = list; - if (iter) { - if (NM_IN_STRSET (*iter, "mschapv2", - "mschap", - "pap", - "chap")) { - if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) - return FALSE; - g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, *iter, NULL); - } else if (nm_streq (*iter, "eap-tls")) { - if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) - return FALSE; - g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", NULL); - } else if (NM_IN_STRSET (*iter, "eap-mschapv2", - "eap-md5", - "eap-gtc")) { - if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) - return FALSE; - g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + NM_STRLEN ("eap-")), NULL); - } else { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.", - *iter); - return FALSE; - } - } return TRUE; } @@ -3358,17 +3415,13 @@ eap_fast_reader (const char *eap_method, gboolean phase2, GError **error) { - char *anon_ident = NULL; - char *pac_file = NULL; - char *real_pac_path = NULL; - char *inner_auth = NULL; - char *fast_provisioning = NULL; - char *lower; - gs_free const char **list = NULL; + gs_free char *anon_ident = NULL; + gs_free char *pac_file = NULL; + gs_free char *real_pac_path = NULL; + gs_free char *fast_provisioning = NULL; const char *const *iter; const char *pac_prov_str; gboolean allow_unauth = FALSE, allow_auth = FALSE; - gboolean success = FALSE; pac_file = svGetValueStr_cp (ifcfg, "IEEE_8021X_PAC_FILE"); if (pac_file) { @@ -3378,10 +3431,10 @@ eap_fast_reader (const char *eap_method, fast_provisioning = svGetValueStr_cp (ifcfg, "IEEE_8021X_FAST_PROVISIONING"); if (fast_provisioning) { - gs_free const char **list1 = NULL; + gs_free const char **list = NULL; - list1 = nm_utils_strsplit_set (fast_provisioning, " \t"); - for (iter = list1; iter && *iter; iter++) { + list = nm_utils_strsplit_set (fast_provisioning, " \t"); + for (iter = list; iter && *iter; iter++) { if (strcmp (*iter, "allow-unauth") == 0) allow_unauth = TRUE; else if (strcmp (*iter, "allow-auth") == 0) @@ -3398,56 +3451,18 @@ eap_fast_reader (const char *eap_method, if (!pac_file && !(allow_unauth || allow_auth)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "IEEE_8021X_PAC_FILE not provided and EAP-FAST automatic PAC provisioning disabled."); - goto done; + "IEEE_8021X_PAC_FILE not provided and EAP-FAST automatic PAC provisioning disabled"); + return FALSE; } anon_ident = svGetValueStr_cp (ifcfg, "IEEE_8021X_ANON_IDENTITY"); if (anon_ident) g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, anon_ident, NULL); - inner_auth = svGetValueStr_cp (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); - if (!inner_auth) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing IEEE_8021X_INNER_AUTH_METHODS."); - goto done; - } - - /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (inner_auth, " "); - iter = list; - if (iter) { - if ( !strcmp (*iter, "MSCHAPV2") - || !strcmp (*iter, "GTC")) { - if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) - goto done; - } else { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.", - *iter); - goto done; - } - - lower = g_ascii_strdown (*iter, -1); - g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, NULL); - g_free (lower); - } - - if (!nm_setting_802_1x_get_phase2_auth (s_8021x)) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "No valid IEEE_8021X_INNER_AUTH_METHODS found."); - goto done; - } - - success = TRUE; + if (!parse_8021x_phase2_auth (ifcfg, keys_ifcfg, s_8021x, error)) + return FALSE; -done: - g_free (inner_auth); - g_free (fast_provisioning); - g_free (real_pac_path); - g_free (pac_file); - g_free (anon_ident); - return success; + return TRUE; } typedef struct { @@ -3546,7 +3561,7 @@ fill_8021x (shvarFile *ifcfg, * used with TTLS or PEAP or whatever. */ if (wifi && eap->wifi_phase2_only) { - PARSE_WARNING ("ignored invalid IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.", + PARSE_WARNING ("ignored invalid IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi", lower); goto next; } @@ -3564,12 +3579,12 @@ next: } if (!found) - PARSE_WARNING ("ignored unknown IEEE_8021X_EAP_METHOD '%s'.", lower); + PARSE_WARNING ("ignored unknown IEEE_8021X_EAP_METHOD '%s'", lower); } if (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 0) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "No valid EAP methods found in IEEE_8021X_EAP_METHODS."); + "No valid EAP methods found in IEEE_8021X_EAP_METHODS"); return NULL; } @@ -3663,8 +3678,8 @@ make_wpa_setting (shvarFile *ifcfg, /* WPA and/or RSN */ if (adhoc) { - /* Ad-Hoc mode only supports WPA proto for now */ - nm_setting_wireless_security_add_proto (wsec, "wpa"); + /* Ad-Hoc mode only supports RSN proto */ + nm_setting_wireless_security_add_proto (wsec, "rsn"); } else { gs_free char *value2 = NULL; const char *v2; @@ -3698,9 +3713,7 @@ make_wpa_setting (shvarFile *ifcfg, } } - if (adhoc) - g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL); - else if (wpa_psk) + if (wpa_psk) g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL); else { nm_assert (wpa_sae); @@ -4145,7 +4158,7 @@ wireless_connection_from_ifcfg (const char *file, if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -4664,7 +4677,7 @@ make_wired_setting (shvarFile *ifcfg, g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_SETTING_MISSING, - "The setting is missing."); + "The setting is missing"); return NULL; } @@ -4690,7 +4703,7 @@ wired_connection_from_ifcfg (const char *file, con_setting = make_connection_setting (file, ifcfg, NM_SETTING_WIRED_SETTING_NAME, NULL, NULL); if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -4768,7 +4781,7 @@ parse_infiniband_p_key (shvarFile *ifcfg, if (!ret) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create InfiniBand setting."); + "Failed to create InfiniBand setting"); } return ret; } @@ -4842,7 +4855,7 @@ infiniband_connection_from_ifcfg (const char *file, con_setting = make_connection_setting (file, ifcfg, NM_SETTING_INFINIBAND_SETTING_NAME, NULL, NULL); if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -4946,7 +4959,7 @@ bond_connection_from_ifcfg (const char *file, con_setting = make_connection_setting (file, ifcfg, NM_SETTING_BOND_SETTING_NAME, NULL, _("Bond")); if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -5019,7 +5032,7 @@ team_connection_from_ifcfg (const char *file, con_setting = make_connection_setting (file, ifcfg, NM_SETTING_TEAM_SETTING_NAME, NULL, _("Team")); if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -5301,7 +5314,7 @@ bridge_connection_from_ifcfg (const char *file, con_setting = make_connection_setting (file, ifcfg, NM_SETTING_BRIDGE_SETTING_NAME, NULL, _("Bridge")); if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -5469,7 +5482,7 @@ make_vlan_setting (shvarFile *ifcfg, iface_name = svGetValueStr_cp (ifcfg, "DEVICE"); if (!iface_name && vlan_id < 0) { g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing DEVICE property; cannot determine VLAN ID."); + "Missing DEVICE property; cannot determine VLAN ID"); return NULL; } @@ -5512,7 +5525,7 @@ make_vlan_setting (shvarFile *ifcfg, if (vlan_id < 0) { g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to determine VLAN ID from DEVICE or VLAN_ID."); + "Failed to determine VLAN ID from DEVICE or VLAN_ID"); return NULL; } g_object_set (s_vlan, NM_SETTING_VLAN_ID, vlan_id, NULL); @@ -5583,7 +5596,7 @@ vlan_connection_from_ifcfg (const char *file, con_setting = make_connection_setting (file, ifcfg, NM_SETTING_VLAN_SETTING_NAME, NULL, "Vlan"); if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create connection setting."); + "Failed to create connection setting"); g_object_unref (connection); return NULL; } @@ -5726,7 +5739,7 @@ connection_from_file_full (const char *filename, ifcfg_name = utils_get_ifcfg_name (filename, TRUE); if (!ifcfg_name) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Ignoring connection '%s' because it's not an ifcfg file.", filename); + "Ignoring connection '%s' because it's not an ifcfg file", filename); return NULL; } @@ -5804,14 +5817,14 @@ connection_from_file_full (const char *filename, device = svGetValueStr_cp (main_ifcfg, "DEVICE"); if (!device) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "File '%s' had neither TYPE nor DEVICE keys.", filename); + "File '%s' had neither TYPE nor DEVICE keys", filename); return NULL; } if (!strcmp (device, "lo")) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Ignoring loopback device config."); + "Ignoring loopback device config"); g_free (device); return NULL; } diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h index 8008e052..9319a064 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c index 2841bedb..79101296 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c @@ -1,19 +1,5 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h index e1165f50..1b2b58e6 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h @@ -1,19 +1,5 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2019 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index cb1fc23a..ee389bd9 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 - 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2017 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 20d6f72d..035146ff 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 - 2017 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 - 2017 Red Hat, Inc. */ #ifndef _UTILS_H_ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 809d3769..d33845c2 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2009 - 2015 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2009 - 2015 Red Hat, Inc. */ #include "nm-default.h" @@ -305,6 +291,7 @@ write_blobs (GHashTable *blobs, GError **error) (const char *) g_bytes_get_data (blob, NULL), g_bytes_get_size (blob), 0600, + NULL, &write_error)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Could not write certificate to file \"%s\": %s", @@ -588,7 +575,7 @@ write_wireless_security_setting (NMConnection *connection, svUnsetValue (ifcfg, "KEY_MGMT"); wep = TRUE; *no_8021x = TRUE; - } else if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) { + } else if (!strcmp (key_mgmt, "wpa-psk")) { svSetValueStr (ifcfg, "KEY_MGMT", "WPA-PSK"); wpa = TRUE; *no_8021x = TRUE; @@ -1943,7 +1930,7 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) * it into an interface name, so that legacy tooling is not confused. */ if (!nm_utils_get_testing ()) { /* This is conditional for easier testing. */ - master_iface = nm_manager_iface_for_uuid (nm_manager_get (), master); + master_iface = nm_manager_iface_for_uuid (NM_MANAGER_GET, master); } if (!master_iface) { master_iface = master; @@ -2097,6 +2084,8 @@ get_route_attributes_string (NMIPRoute *route, int family) /* we also have a corresponding attribute with the numeric value. The * lock setting is handled above. */ } + } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SCOPE)) { + g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_byte (attr)); } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TOS)) { g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr)); } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TABLE)) { @@ -2449,6 +2438,7 @@ write_ip4_setting (NMConnection *connection, GString *searches; const char *method = NULL; gboolean has_netmask; + NMDhcpHostnameFlags flags; NM_SET_OUT (out_route_content_svformat, NULL); NM_SET_OUT (out_route_content, NULL); @@ -2609,6 +2599,12 @@ write_ip4_setting (NMConnection *connection, value = nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)); svSetValueStr (ifcfg, "DHCP_FQDN", value); + flags = nm_setting_ip_config_get_dhcp_hostname_flags (s_ip4); + svSetValueInt64_cond (ifcfg, + "DHCP_HOSTNAME_FLAGS", + flags != NM_DHCP_HOSTNAME_FLAG_NONE, + flags); + /* Missing DHCP_SEND_HOSTNAME means TRUE, and we prefer not write it explicitly * in that case, because it is NM-specific variable */ @@ -2618,6 +2614,9 @@ write_ip4_setting (NMConnection *connection, value = nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)); svSetValueStr (ifcfg, "DHCP_CLIENT_ID", value); + value = nm_setting_ip_config_get_dhcp_iaid (s_ip4); + svSetValueStr (ifcfg, "DHCP_IAID", value); + timeout = nm_setting_ip_config_get_dhcp_timeout (s_ip4); svSetValueInt64_cond (ifcfg, "IPV4_DHCP_TIMEOUT", @@ -2752,6 +2751,7 @@ write_ip4_aliases (NMConnection *connection, const char *base_ifcfg_path) static void write_ip6_setting_dhcp_hostname (NMSettingIPConfig *s_ip6, shvarFile *ifcfg) { + NMDhcpHostnameFlags flags; const char *hostname; hostname = nm_setting_ip_config_get_dhcp_hostname (s_ip6); @@ -2764,6 +2764,12 @@ write_ip6_setting_dhcp_hostname (NMSettingIPConfig *s_ip6, shvarFile *ifcfg) svUnsetValue (ifcfg, "DHCPV6_SEND_HOSTNAME"); else svSetValueStr (ifcfg, "DHCPV6_SEND_HOSTNAME", "no"); + + flags = nm_setting_ip_config_get_dhcp_hostname_flags (s_ip6); + svSetValueInt64_cond (ifcfg, + "DHCPV6_HOSTNAME_FLAGS", + flags != NM_DHCP_HOSTNAME_FLAG_NONE, + flags); } static gboolean @@ -2796,6 +2802,7 @@ write_ip6_setting (NMConnection *connection, svUnsetValue (ifcfg, "IPV6_AUTOCONF"); svUnsetValue (ifcfg, "DHCPV6C"); svUnsetValue (ifcfg, "DHCPv6_DUID"); + svUnsetValue (ifcfg, "DHCPv6_IAID"); svUnsetValue (ifcfg, "DHCPV6_HOSTNAME"); svUnsetValue (ifcfg, "DHCPV6_SEND_HOSTNAME"); svUnsetValue (ifcfg, "IPV6_DEFROUTE"); @@ -2845,6 +2852,8 @@ write_ip6_setting (NMConnection *connection, svSetValueStr (ifcfg, "DHCPV6_DUID", nm_setting_ip6_config_get_dhcp_duid (NM_SETTING_IP6_CONFIG (s_ip6))); + svSetValueStr (ifcfg, "DHCPV6_IAID", + nm_setting_ip_config_get_dhcp_iaid (s_ip6)); write_ip6_setting_dhcp_hostname (s_ip6, ifcfg); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h index 0902daee..c4903a46 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2009 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index d4bc71f3..16b2dd37 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -1,25 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * shvar.c - * - * Implementation of non-destructively reading/writing files containing - * only shell variable declarations and full-line comments. - * - * Copyright 1999,2000 Red Hat, Inc. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * + * Copyright (C) 1999, 2000 Red Hat, Inc. */ #include "nm-default.h" @@ -790,7 +771,7 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) shvarFile *s; gboolean closefd = FALSE; int errsv = 0; - char *arena; + gs_free char *arena = NULL; const char *p, *q; gs_free_error GError *local = NULL; nm_auto_close int fd = -1; @@ -816,13 +797,14 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) return NULL; } - if (nm_utils_fd_get_contents (closefd ? nm_steal_fd (&fd) : fd, - closefd, - 10 * 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &arena, - NULL, - &local) < 0) { + if (!nm_utils_fd_get_contents (closefd ? nm_steal_fd (&fd) : fd, + closefd, + 10 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &arena, + NULL, + NULL, + &local)) { if (create) return svFile_new (name); @@ -839,7 +821,6 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) c_list_link_tail (&s->lst_head, &line_new_parse (p, q - p)->lst); if (p[0]) c_list_link_tail (&s->lst_head, &line_new_parse (p, strlen (p))->lst); - g_free (arena); /* closefd is set if we opened the file read-only, so go ahead and * close it, because we can't write to it anyway */ diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index 2f6912b3..c3bbabab 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -1,32 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * shvar.h - * - * Interface for non-destructively reading/writing files containing - * only shell variable declarations and full-line comments. - * - * Includes explicit inheritance mechanism intended for use with - * Red Hat Linux ifcfg-* files. There is no protection against - * inheritance loops; they will generally cause stack overflows. - * Furthermore, they are only intended for one level of inheritance; - * the value setting algorithm assumes this. - * - * Copyright 1999 Red Hat, Inc. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * + * Copyright (C) 1999 Red Hat, Inc. */ + #ifndef _SHVAR_H #define _SHVAR_H diff --git a/src/settings/plugins/ifcfg-rh/tests/meson.build b/src/settings/plugins/ifcfg-rh/tests/meson.build index f65494bb..21699045 100644 --- a/src/settings/plugins/ifcfg-rh/tests/meson.build +++ b/src/settings/plugins/ifcfg-rh/tests/meson.build @@ -1,11 +1,10 @@ test_unit = 'test-ifcfg-rh' -test_ifcfg_dir = meson.current_source_dir() - exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, link_with: libnms_ifcfg_rh_core, ) diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc index aa00925e..c3cadbb8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc @@ -12,5 +12,6 @@ USERCTL=yes PEERDNS=yes IPV6INIT=no CIPHER_GROUP=CCMP +CIPHER_PAIRWISE=CCMP KEY_MGMT=WPA-PSK diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp index 727d2ceb..5d36675a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp @@ -8,7 +8,12 @@ USERCTL=yes IPV6INIT=no NM_CONTROLLED=yes PEERDNS=no -DHCP_HOSTNAME=foobar +DHCP_FQDN=foo.bar +DHCP_HOSTNAME_FLAGS=6 DNS1=4.2.2.1 DNS2=4.2.2.2 - +IPV6_AUTOCONF=no +IPV6INIT=yes +DHCPV6C=yes +DHCPV6_HOSTNAME_FLAGS=8 +DHCPV6_HOSTNAME=foo.bar diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index 8d6aaac2..5d02c62e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -6,10 +6,10 @@ ADDRESS1=44.55.66.77 NETMASK1=255.255.255.255 GATEWAY1=192.168.1.7 METRIC1=3 -OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 initcwnd lock 13 initrwnd 14" +OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 scope 10 initcwnd lock 13 initrwnd 14" ADDRESS2=44.55.66.78 NETMASK2=255.255.255.255 GATEWAY2=192.168.1.8 METRIC2=3 -OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14" +OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14 scope link" diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 45e90b91..675421d3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2011 Red Hat, Inc. */ @@ -901,6 +887,7 @@ test_read_wired_dhcp (void) NMSettingConnection *s_con; NMSettingWired *s_wired; NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; char *unmanaged = NULL; char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0xee }; const char *mac; @@ -930,11 +917,23 @@ test_read_wired_dhcp (void) s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert_cmpstr (nm_setting_ip_config_get_dhcp_hostname (s_ip4), ==, "foobar"); + g_assert_cmpstr (nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)), ==, "foo.bar"); g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip4)); g_assert_cmpuint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2); g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "4.2.2.1"); g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 1), ==, "4.2.2.2"); + g_assert_cmpuint (nm_setting_ip_config_get_dhcp_hostname_flags (s_ip4), + ==, + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE); + + /* ===== IPv6 SETTING ===== */ + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DHCP); + g_assert_cmpstr (nm_setting_ip_config_get_dhcp_hostname (s_ip6), ==, "foo.bar"); + g_assert_cmpuint (nm_setting_ip_config_get_dhcp_hostname_flags (s_ip6), + ==, + NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS); g_object_unref (connection); } @@ -1348,6 +1347,7 @@ test_read_wired_static_routes (void) nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE); nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE); nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1"); + nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 10); ip4_route = nm_setting_ip_config_get_route (s_ip4, 2); g_assert (ip4_route); @@ -1365,6 +1365,7 @@ test_read_wired_static_routes (void) nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE); nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1"); nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, TRUE); + nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SCOPE, 253); g_object_unref (connection); } @@ -1520,10 +1521,8 @@ test_read_wired_ipv6_manual (void) NMIPAddress *ip6_addr; NMIPRoute *ip6_route; - NMTST_EXPECT_NM_WARN ("*ignoring manual default route*"); connection = _connection_from_file (TEST_IFCFG_DIR"/ifcfg-test-wired-ipv6-manual", NULL, TYPE_ETHERNET, &unmanaged); - g_test_assert_expected_messages (); g_assert (!unmanaged); /* ===== CONNECTION SETTING ===== */ @@ -1581,7 +1580,7 @@ test_read_wired_ipv6_manual (void) g_assert_cmpint (nm_ip_address_get_prefix (ip6_addr), ==, 96); /* Routes */ - g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 3); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 4); /* Route #1 */ ip6_route = nm_setting_ip_config_get_route (s_ip6, 0); g_assert (ip6_route); @@ -1592,12 +1591,19 @@ test_read_wired_ipv6_manual (void) /* Route #2 */ ip6_route = nm_setting_ip_config_get_route (s_ip6, 1); g_assert (ip6_route); + g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "::"); + g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 0); + g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, "dead::beaf"); + g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, -1); + /* Route #3 */ + ip6_route = nm_setting_ip_config_get_route (s_ip6, 2); + g_assert (ip6_route); g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "abbe::cafe"); g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64); g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, NULL); g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, 777); - /* Route #3 */ - ip6_route = nm_setting_ip_config_get_route (s_ip6, 2); + /* Route #4 */ + ip6_route = nm_setting_ip_config_get_route (s_ip6, 3); g_assert (ip6_route); g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "aaaa::cccc"); g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64); @@ -3128,17 +3134,17 @@ test_read_wifi_wpa_psk_adhoc (void) s_wsec = nm_connection_get_setting_wireless_security (connection); g_assert (s_wsec); - g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-none"); + g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk"); g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "I wonder what the king is doing tonight?"); - /* Pairwise cipher is unused in adhoc mode */ - g_assert_cmpint (nm_setting_wireless_security_get_num_pairwise (s_wsec), ==, 0); + g_assert_cmpint (nm_setting_wireless_security_get_num_pairwise (s_wsec), ==, 1); + g_assert_cmpstr (nm_setting_wireless_security_get_pairwise (s_wsec, 0), ==, "ccmp"); g_assert_cmpint (nm_setting_wireless_security_get_num_groups (s_wsec), ==, 1); g_assert_cmpstr (nm_setting_wireless_security_get_group (s_wsec, 0), ==, "ccmp"); g_assert_cmpint (nm_setting_wireless_security_get_num_protos (s_wsec), ==, 1); - g_assert_cmpstr (nm_setting_wireless_security_get_proto (s_wsec, 0), ==, "wpa"); + g_assert_cmpstr (nm_setting_wireless_security_get_proto (s_wsec, 0), ==, "rsn"); /* ===== IPv4 SETTING ===== */ @@ -4464,9 +4470,11 @@ test_write_wired_dhcp (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, "random-client-id-00:22:33", - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, "awesome-hostname", + NM_SETTING_IP4_CONFIG_DHCP_FQDN, "awesome.hostname", + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, (guint) NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED, NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, TRUE, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE, + NM_SETTING_IP_CONFIG_DHCP_IAID, "2864434397", NULL); nmtst_assert_connection_verifies (connection); @@ -4476,8 +4484,10 @@ test_write_wired_dhcp (void) nm_connection_add_setting (connection, NM_SETTING (s_ip6)); g_object_set (s_ip6, - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DHCP, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, "awesome.hostname", + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, (guint) NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, NULL); _writer_new_connection (connection, @@ -6455,12 +6465,13 @@ test_write_wifi_wpa_psk_adhoc (void) nm_connection_add_setting (connection, NM_SETTING (s_wsec)); g_object_set (s_wsec, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NM_SETTING_WIRELESS_SECURITY_PSK, "7d308b11df1b4243b0f78e5f3fc68cdbb9a264ed0edf4c188edf329ff5b467f0", NULL); - nm_setting_wireless_security_add_proto (s_wsec, "wpa"); - nm_setting_wireless_security_add_group (s_wsec, "tkip"); + nm_setting_wireless_security_add_proto (s_wsec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp"); + nm_setting_wireless_security_add_group (s_wsec, "ccmp"); /* IP4 setting */ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); diff --git a/src/settings/plugins/ifupdown/meson.build b/src/settings/plugins/ifupdown/meson.build index 365ae1a9..0cabe771 100644 --- a/src/settings/plugins/ifupdown/meson.build +++ b/src/settings/plugins/ifupdown/meson.build @@ -3,25 +3,18 @@ sources = files( 'nms-ifupdown-parser.c', ) -deps = [ - libudev_dep, - nm_dep, -] - libnms_ifupdown_core = static_library( 'nms-ifupdown-core', sources: sources, - dependencies: deps, -) - -sources = files( - 'nms-ifupdown-plugin.c', + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, ) libnm_settings_plugin_ifupdown = shared_module( 'nm-settings-plugin-ifupdown', - sources: sources, - dependencies: deps, + sources: 'nms-ifupdown-plugin.c', + dependencies: daemon_nm_default_dep, + c_args: daemon_c_flags, link_with: libnms_ifupdown_core, link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, @@ -31,18 +24,6 @@ libnm_settings_plugin_ifupdown = shared_module( core_plugins += libnm_settings_plugin_ifupdown -# FIXME: check_so_symbols replacement -''' -run_target( - 'check-local-symbols-settings-ifupdown', - command: [check_so_symbols, libnm_settings_plugin_ifupdown.full_path()], - depends: libnm_settings_plugin_ifupdown, -) - -check-local-symbols-settings-ifupdown: src/settings/plugins/ifupdown/libnm-settings-plugin-ifupdown.la - $(call check_so_symbols,$(builddir)/src/settings/plugins/ifupdown/.libs/libnm-settings-plugin-ifupdown.so) -''' - if enable_tests subdir('tests') endif diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c index 75f29878..a146ae60 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c @@ -1,22 +1,7 @@ -/* NetworkManager -- Network link manager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Tom Parker <palfrey@tevp.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2004 Tom Parker + * Copyright (C) 2004 Tom Parker */ #include "nm-default.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h index 308228a4..af02c7f6 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h +++ b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h @@ -1,22 +1,7 @@ -/* NetworkManager -- Network link manager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Tom Parker <palfrey@tevp.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2004 Tom Parker + * Copyright (C) 2004 Tom Parker */ #ifndef _INTERFACE_PARSER_H diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/settings/plugins/ifupdown/nms-ifupdown-parser.c index 41b20850..1db9ef15 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -1,22 +1,7 @@ -/* NetworkManager system settings service (ifupdown) - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Alexander Sack <asac@ubuntu.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Canonical Ltd. + * Copyright (C) 2008 Canonical Ltd. */ #include "nm-default.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.h b/src/settings/plugins/ifupdown/nms-ifupdown-parser.h index 7569648f..b8761fc3 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.h +++ b/src/settings/plugins/ifupdown/nms-ifupdown-parser.h @@ -1,22 +1,7 @@ -/* NetworkManager system settings service (ifupdown) - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Alexander Sack <asac@ubuntu.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Canonical Ltd. + * Copyright (C) 2008 Canonical Ltd. */ #ifndef __NMS_IFUPDOWN_PARSER_H__ diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index e663ab8a..d19db0fd 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -1,23 +1,8 @@ -/* NetworkManager system settings service (ifupdown) - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Alexander Sack <asac@ubuntu.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2007,2008 Canonical Ltd. - * (C) Copyright 2009 - 2011 Red Hat, Inc. + * Copyright (C) 2007, 2008 Canonical Ltd. + * Copyright (C) 2009 - 2011 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.h b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.h index 10ea2be4..91e3e43a 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.h +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.h @@ -1,22 +1,7 @@ -/* NetworkManager system settings service (ifupdown) - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Alexander Sack <asac@ubuntu.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Canonical Ltd. + * Copyright (C) 2008 Canonical Ltd. */ #ifndef __NMS_IFUPDOWN_PLUGIN_H__ diff --git a/src/settings/plugins/ifupdown/tests/meson.build b/src/settings/plugins/ifupdown/tests/meson.build index 9b844c75..1ca094b5 100644 --- a/src/settings/plugins/ifupdown/tests/meson.build +++ b/src/settings/plugins/ifupdown/tests/meson.build @@ -3,7 +3,8 @@ test_unit = 'test-ifupdown' exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, link_with: libnms_ifupdown_core, ) diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c index 4adcf085..6a7b5ecc 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -149,6 +135,9 @@ expected_free (Expected *e) g_free (e); } +NM_AUTO_DEFINE_FCN_VOID0 (Expected *, _nm_auto_free_expected, expected_free) +#define nm_auto_free_expected nm_auto(_nm_auto_free_expected) + static void compare_expected_to_ifparser (if_parser *parser, Expected *e) { @@ -226,7 +215,7 @@ init_ifparser_with_file (const char *file) static void test1_ignore_line_before_first_block (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test1"); @@ -238,14 +227,12 @@ test1_ignore_line_before_first_block (void) expected_block_add_key (b, expected_key_new ("inet", "dhcp")); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test2_wrapped_line (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test2"); @@ -254,14 +241,12 @@ test2_wrapped_line (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test3_wrapped_multiline_multiarg (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test3"); @@ -274,14 +259,12 @@ test3_wrapped_multiline_multiarg (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test4_allow_auto_is_auto (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test4"); @@ -290,14 +273,12 @@ test4_allow_auto_is_auto (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test5_allow_auto_multiarg (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test5"); @@ -308,14 +289,12 @@ test5_allow_auto_multiarg (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test6_mixed_whitespace (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test6"); @@ -325,8 +304,6 @@ test6_mixed_whitespace (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void @@ -348,7 +325,7 @@ test8_long_line_wrapped (void) static void test9_wrapped_lines_in_block (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test9"); @@ -362,14 +339,12 @@ test9_wrapped_lines_in_block (void) expected_block_add_key (b, expected_key_new ("gateway", "10.250.2.50")); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test11_complex_wrap (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test11"); @@ -380,14 +355,12 @@ test11_complex_wrap (void) expected_block_add_key (b, expected_key_new ("pre-up", "/sbin/ifconfig eth0 up")); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test12_complex_wrap_split_word (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test12"); @@ -398,14 +371,12 @@ test12_complex_wrap_split_word (void) expected_block_add_key (b, expected_key_new ("up", "ifup ppp0=dsl")); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test13_more_mixed_whitespace (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test13"); @@ -415,14 +386,12 @@ test13_more_mixed_whitespace (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test14_mixed_whitespace_block_start (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test14"); @@ -438,14 +407,12 @@ test14_mixed_whitespace_block_start (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test15_trailing_space (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test15"); @@ -455,23 +422,20 @@ test15_trailing_space (void) expected_add_block (e, b); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test16_missing_newline (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test16"); e = expected_new (); expected_add_block (e, expected_block_new ("mapping", "eth0")); compare_expected_to_ifparser (parser, e); - - expected_free (e); } + static void test17_read_static_ipv4 (void) { @@ -578,7 +542,7 @@ test19_read_static_ipv4_plen (void) static void test20_source_stanza (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test20-source-stanza"); @@ -597,14 +561,12 @@ test20_source_stanza (void) expected_block_add_key (b, expected_key_new ("inet", "dhcp")); compare_expected_to_ifparser (parser, e); - - expected_free (e); } static void test21_source_dir_stanza (void) { - Expected *e; + nm_auto_free_expected Expected *e = NULL; ExpectedBlock *b; nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test21-source-dir-stanza"); @@ -617,10 +579,34 @@ test21_source_dir_stanza (void) expected_block_add_key (b, expected_key_new ("inet", "dhcp")); compare_expected_to_ifparser (parser, e); +} + +static void +test22_duplicate_stanzas (void) +{ + nm_auto_free_expected Expected *e = NULL; + ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test22-duplicate-stanzas"); + + e = expected_new (); - expected_free (e); + b = expected_block_new ("iface", "br10"); + expected_add_block (e, b); + expected_block_add_key (b, expected_key_new ("inet", "manual")); + expected_block_add_key (b, expected_key_new ("bridge-ports", "enp6s0.15")); + expected_block_add_key (b, expected_key_new ("bridge-stp", "off")); + expected_block_add_key (b, expected_key_new ("bridge-maxwait", "0")); + expected_block_add_key (b, expected_key_new ("bridge-fd", "0")); + b = expected_block_new ("iface", "br10"); + expected_add_block (e, b); + expected_block_add_key (b, expected_key_new ("inet", "auto")); + expected_block_add_key (b, expected_key_new ("bridge-ports", "enp6s0.15")); + + compare_expected_to_ifparser (parser, e); } +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -650,6 +636,7 @@ main (int argc, char **argv) g_test_add_func ("/ifupdate/read_static_ipv4_plen", test19_read_static_ipv4_plen); g_test_add_func ("/ifupdate/source_stanza", test20_source_stanza); g_test_add_func ("/ifupdate/source_dir_stanza", test21_source_dir_stanza); + g_test_add_func ("/ifupdate/test22-duplicate-stanzas", test22_duplicate_stanzas); return g_test_run (); } diff --git a/src/settings/plugins/ifupdown/tests/test22-duplicate-stanzas b/src/settings/plugins/ifupdown/tests/test22-duplicate-stanzas new file mode 100644 index 00000000..c13c2e7e --- /dev/null +++ b/src/settings/plugins/ifupdown/tests/test22-duplicate-stanzas @@ -0,0 +1,8 @@ +iface br10 inet manual + bridge_ports enp6s0.15 + bridge_stp off + bridge_maxwait 0 + bridge_fd 0 + +iface br10 inet auto + bridge_ports enp6s0.15 diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c index fbe70ef4..fdb88d2a 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2018 Red Hat, Inc. */ @@ -369,7 +355,7 @@ _load_file (NMSKeyfilePlugin *self, &local); if (!connection) { if (error) - g_propagate_error (error, local); + g_propagate_error (error, g_steal_pointer (&local)); else _LOGW ("load: \"%s\": failed to load connection: %s", full_filename, local->message); return NULL; @@ -1090,7 +1076,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self, gboolean hard_failure = FALSE; NMSKeyfileStorage *storage; gs_unref_object NMSKeyfileStorage *storage_result = NULL; - gboolean nmmeta_success = FALSE; + gboolean nmmeta_errno; gs_free char *nmmeta_filename = NULL; NMSKeyfileStorageType storage_type; const char *loaded_path; @@ -1116,6 +1102,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self, simulate ? "simulate " : "", loaded_path ? "write" : "delete", uuid); + nmmeta_errno = 0; hard_failure = TRUE; goto out; } @@ -1124,29 +1111,30 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self, } if (simulate) { - nmmeta_success = TRUE; + nmmeta_errno = 0; nmmeta_filename = nms_keyfile_nmmeta_filename (dirname, uuid, FALSE); } else { - nmmeta_success = nms_keyfile_nmmeta_write (dirname, - uuid, - loaded_path, - FALSE, - shadowed_storage, - &nmmeta_filename); + nmmeta_errno = nms_keyfile_nmmeta_write (dirname, + uuid, + loaded_path, + FALSE, + shadowed_storage, + &nmmeta_filename); } - _LOGT ("commit: %s nmmeta file \"%s\"%s%s%s%s%s%s %s", + _LOGT ("commit: %s nmmeta file \"%s\"%s%s%s%s%s%s %s%s%s%s", loaded_path ? "writing" : "deleting", nmmeta_filename, NM_PRINT_FMT_QUOTED (loaded_path, " (pointing to \"", loaded_path, "\")", ""), NM_PRINT_FMT_QUOTED (shadowed_storage, " (shadows \"", shadowed_storage, "\")", ""), simulate ? "simulated" - : ( nmmeta_success - ? "succeeded" - : "failed")); + : ( nmmeta_errno < 0 + ? "failed" + : "succeeded"), + NM_PRINT_FMT_QUOTED (nmmeta_errno < 0, " (", nm_strerror_native (nm_errno_native (nmmeta_errno)), ")", "")); - if (!nmmeta_success) + if (nmmeta_errno < 0) goto out; storage = nm_sett_util_storages_lookup_by_filename (&priv->storages, nmmeta_filename); @@ -1177,12 +1165,13 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self, } out: - nm_assert (!nmmeta_success || !hard_failure); - nm_assert (nmmeta_success || !storage_result); + nm_assert (nmmeta_errno <= 0); + nm_assert (nmmeta_errno < 0 || !hard_failure); + nm_assert (nmmeta_errno == 0 || !storage_result); NM_SET_OUT (out_hard_failure, hard_failure); NM_SET_OUT (out_storage, (NMSettingsStorage *) g_steal_pointer (&storage_result)); - return nmmeta_success; + return nmmeta_errno >= 0; } /*****************************************************************************/ diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.h b/src/settings/plugins/keyfile/nms-keyfile-plugin.h index 48440964..e885f16c 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.h +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2011 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c index 8d1f5599..af9e6726 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.c +++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.h b/src/settings/plugins/keyfile/nms-keyfile-reader.h index f20e6d93..307d6ffe 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.h +++ b/src/settings/plugins/keyfile/nms-keyfile-reader.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.c b/src/settings/plugins/keyfile/nms-keyfile-storage.c index d68d60c8..bcc06795 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-storage.c +++ b/src/settings/plugins/keyfile/nms-keyfile-storage.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.h b/src/settings/plugins/keyfile/nms-keyfile-storage.h index 2252b47b..00a034d4 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-storage.h +++ b/src/settings/plugins/keyfile/nms-keyfile-storage.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.c b/src/settings/plugins/keyfile/nms-keyfile-utils.c index ea03e1b6..f03c601a 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/settings/plugins/keyfile/nms-keyfile-utils.c @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #include "nm-default.h" @@ -206,7 +192,7 @@ nms_keyfile_nmmeta_read_from_file (const char *full_filename, return TRUE; } -gboolean +int nms_keyfile_nmmeta_write (const char *dirname, const char *uuid, const char *loaded_path, @@ -216,6 +202,7 @@ nms_keyfile_nmmeta_write (const char *dirname, { gs_free char *full_filename_tmp = NULL; gs_free char *full_filename = NULL; + int errsv; nm_assert (dirname && dirname[0] == '/'); nm_assert ( nm_utils_is_uuid (uuid) @@ -231,13 +218,15 @@ nms_keyfile_nmmeta_write (const char *dirname, (void) unlink (full_filename_tmp); if (!loaded_path) { - gboolean success = TRUE; - full_filename_tmp[strlen (full_filename_tmp) - 1] = '\0'; - if (unlink (full_filename_tmp) != 0) - success = NM_IN_SET (errno, ENOENT); + errsv = 0; + if (unlink (full_filename_tmp) != 0) { + errsv = -NM_ERRNO_NATIVE (errno); + if (errsv == -ENOENT) + errsv = 0; + } NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename_tmp)); - return success; + return errsv; } if (loaded_path_allow_relative) { @@ -266,29 +255,36 @@ nms_keyfile_nmmeta_write (const char *dirname, contents = g_key_file_to_data (kf, &length, NULL); - if (!nm_utils_file_set_contents (full_filename, contents, length, 0600, NULL)) { + if (!nm_utils_file_set_contents (full_filename, + contents, + length, + 0600, + &errsv, + NULL)) { NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename_tmp)); - return FALSE; + return -NM_ERRNO_NATIVE (errsv); } } else { /* we only have the "loaded_path" to store. That is commonly used for the tombstones to * link to /dev/null. A symlink is sufficient to store that ammount of information. * No need to bother with a keyfile. */ if (symlink (loaded_path, full_filename_tmp) != 0) { + errsv = -NM_ERRNO_NATIVE (errno); full_filename_tmp[strlen (full_filename_tmp) - 1] = '\0'; NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename_tmp)); - return FALSE; + return errsv; } if (rename (full_filename_tmp, full_filename) != 0) { + errsv = -NM_ERRNO_NATIVE (errno); (void) unlink (full_filename_tmp); NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename)); - return FALSE; + return errsv; } } NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename)); - return TRUE; + return 0; } /*****************************************************************************/ diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.h b/src/settings/plugins/keyfile/nms-keyfile-utils.h index 723c4436..f943d65c 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.h +++ b/src/settings/plugins/keyfile/nms-keyfile-utils.h @@ -1,20 +1,6 @@ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2010 - 2018 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 - 2018 Red Hat, Inc. */ #ifndef __NMS_KEYFILE_UTILS_H__ @@ -66,12 +52,12 @@ gboolean nms_keyfile_nmmeta_read_from_file (const char *full_filename, char **out_loaded_path, char **out_shadowed_storage); -gboolean nms_keyfile_nmmeta_write (const char *dirname, - const char *uuid, - const char *loaded_path, - gboolean loaded_path_allow_relative, - const char *shadowed_storage, - char **out_full_filename); +int nms_keyfile_nmmeta_write (const char *dirname, + const char *uuid, + const char *loaded_path, + gboolean loaded_path_allow_relative, + const char *shadowed_storage, + char **out_full_filename); /*****************************************************************************/ diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index abd3f1f4..fa95198c 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2015 Red Hat, Inc. */ @@ -130,8 +116,12 @@ cert_writer (NMConnection *connection, * being sure that the entire profile can be written and all circumstances are good to * proceed. That means, while writing we must only collect the blogs in-memory, and write * them all in the end together (or not at all). */ - success = nm_utils_file_set_contents (new_path, (const char *) blob_data, - blob_len, 0600, &local); + success = nm_utils_file_set_contents (new_path, + (const char *) blob_data, + blob_len, + 0600, + NULL, + &local); if (success) { /* Write the path value to the keyfile. * We know, that basename(new_path) starts with a UUID, hence no conflict with "data:;base64," */ @@ -344,7 +334,12 @@ _internal_write_connection (NMConnection *connection, } } - nm_utils_file_set_contents (path, kf_content_buf, kf_content_len, 0600, &local_err); + nm_utils_file_set_contents (path, + kf_content_buf, + kf_content_len, + 0600, + NULL, + &local_err); if (local_err) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "error writing to file '%s': %s", diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/settings/plugins/keyfile/nms-keyfile-writer.h index 99e86025..98ec8a6b 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.h +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.h @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2011 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/tests/meson.build b/src/settings/plugins/keyfile/tests/meson.build index f1e96bdf..7bf9fda0 100644 --- a/src/settings/plugins/keyfile/tests/meson.build +++ b/src/settings/plugins/keyfile/tests/meson.build @@ -3,7 +3,8 @@ test_unit = 'test-keyfile-settings' exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( diff --git a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c index f96111a2..d2da09da 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -1,19 +1,5 @@ -/* NetworkManager system settings service - keyfile plugin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2017 Red Hat, Inc. */ @@ -2543,7 +2529,7 @@ _assert_keyfile_nmmeta (const char *dirname, nm_clear_g_free (&full_filename); - g_assert (nms_keyfile_nmmeta_write (dirname, uuid, loaded_path, allow_relative, NULL, &full_filename)); + g_assert_cmpint (nms_keyfile_nmmeta_write (dirname, uuid, loaded_path, allow_relative, NULL, &full_filename), ==, 0); g_assert_cmpstr (full_filename, ==, exp_full_filename); nm_clear_g_free (&full_filename); diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c index a5a68070..dec4556d 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/supplicant/nm-supplicant-config.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ @@ -598,20 +584,20 @@ nm_supplicant_config_add_bgscan (NMSupplicantConfig *self, * (b) since EAP/802.1x isn't used and thus there are fewer steps to fail * during a roam, we can wait longer before scanning for roam candidates. */ - bgscan = "simple:30:-80:86400"; + bgscan = "simple:30:-70:86400"; - /* If using WPA Enterprise or Dynamic WEP use a shorter bgscan interval on - * the assumption that this is a multi-AP ESS in which we want more reliable - * roaming between APs. Thus trigger scans when the signal is still somewhat - * OK so we have an up-to-date roam candidate list when the signal gets bad. + /* If using WPA Enterprise, Dynamic WEP or we have seen more than one AP use + * a shorter bgscan interval on the assumption that this is a multi-AP ESS + * in which we want more reliable roaming between APs. Thus trigger scans + * when the signal is still somewhat OK so we have an up-to-date roam + * candidate list when the signal gets bad. */ - s_wsec = nm_connection_get_setting_wireless_security (connection); - if (s_wsec) { - if (NM_IN_STRSET (nm_setting_wireless_security_get_key_mgmt (s_wsec), - "ieee8021x", - "wpa-eap")) - bgscan = "simple:30:-65:300"; - } + if ( nm_setting_wireless_get_num_seen_bssids (s_wifi) > 1 + || ( (s_wsec = nm_connection_get_setting_wireless_security (connection)) + && NM_IN_STRSET (nm_setting_wireless_security_get_key_mgmt (s_wsec), + "ieee8021x", + "wpa-eap"))) + bgscan = "simple:30:-65:300"; return nm_supplicant_config_add_option (self, "bgscan", bgscan, -1, FALSE, error); } @@ -897,8 +883,7 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, } /* Only WPA-specific things when using WPA */ - if ( !strcmp (key_mgmt, "wpa-none") - || !strcmp (key_mgmt, "wpa-psk") + if ( !strcmp (key_mgmt, "wpa-psk") || !strcmp (key_mgmt, "wpa-eap") || !strcmp (key_mgmt, "sae")) { if (!ADD_STRING_LIST_VAL (self, setting, wireless_security, proto, protos, "proto", ' ', TRUE, NULL, error)) @@ -909,7 +894,6 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, return FALSE; if ( set_pmf - && !nm_streq (key_mgmt, "wpa-none") && NM_IN_SET (pmf, NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE, NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED)) { diff --git a/src/supplicant/nm-supplicant-config.h b/src/supplicant/nm-supplicant-config.h index c4e7310d..361f9ac6 100644 --- a/src/supplicant/nm-supplicant-config.h +++ b/src/supplicant/nm-supplicant-config.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index be4f65dc..6ef29311 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -1557,7 +1543,7 @@ p2p_props_changed_cb (GDBusProxy *proxy, if (g_variant_lookup (changed_properties, "Group", "&o", &path)) { if (priv->group_proxy && g_strcmp0 (path, g_dbus_proxy_get_object_path (priv->group_proxy)) == 0) { /* We already have the proxy, nothing to do. */ - } else if (path && g_strcmp0 (path, "/") != 0) { + } else if (nm_dbus_path_not_empty (path)) { if (priv->group_proxy != NULL) { _LOGW ("P2P: Unexpected update of the group object path"); priv->group_proxy_acquired = FALSE; diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h index e621f1a3..3580f754 100644 --- a/src/supplicant/nm-supplicant-interface.h +++ b/src/supplicant/nm-supplicant-interface.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2017 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ diff --git a/src/supplicant/nm-supplicant-manager.c b/src/supplicant/nm-supplicant-manager.c index df641c51..49581f6e 100644 --- a/src/supplicant/nm-supplicant-manager.c +++ b/src/supplicant/nm-supplicant-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2010 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ diff --git a/src/supplicant/nm-supplicant-manager.h b/src/supplicant/nm-supplicant-manager.h index a1f23f53..18ca53b6 100644 --- a/src/supplicant/nm-supplicant-manager.h +++ b/src/supplicant/nm-supplicant-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2008 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c index 25cc0bc6..bea17ede 100644 --- a/src/supplicant/nm-supplicant-settings-verify.c +++ b/src/supplicant/nm-supplicant-settings-verify.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2012 Red Hat, Inc. */ @@ -69,7 +55,7 @@ static const char *const proto_allowed[] = { "WPA", "RSN", NULL }; static const char *const key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256", "FT-PSK", "WPA-EAP", "WPA-EAP-SHA256", "FT-EAP", "FT-EAP-SHA384", "FILS-SHA256", "FILS-SHA384", - "IEEE8021X", "WPA-NONE", "SAE", "FT-SAE", + "IEEE8021X", "SAE", "FT-SAE", "NONE", NULL }; static const char *const auth_alg_allowed[] = { "OPEN", "SHARED", "LEAP", NULL }; static const char *const eap_allowed[] = { "LEAP", "MD5", "TLS", "PEAP", "TTLS", "SIM", diff --git a/src/supplicant/nm-supplicant-settings-verify.h b/src/supplicant/nm-supplicant-settings-verify.h index ea2482d3..fe1480cc 100644 --- a/src/supplicant/nm-supplicant-settings-verify.h +++ b/src/supplicant/nm-supplicant-settings-verify.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2008 Red Hat, Inc. */ diff --git a/src/supplicant/nm-supplicant-types.h b/src/supplicant/nm-supplicant-types.h index b28a1efa..2b356354 100644 --- a/src/supplicant/nm-supplicant-types.h +++ b/src/supplicant/nm-supplicant-types.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2006 - 2008 Red Hat, Inc. */ diff --git a/src/supplicant/tests/meson.build b/src/supplicant/tests/meson.build index fbccb313..207d22f8 100644 --- a/src/supplicant/tests/meson.build +++ b/src/supplicant/tests/meson.build @@ -3,7 +3,8 @@ test_unit = 'test-supplicant-config' exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c index ea9bac1e..008735b4 100644 --- a/src/supplicant/tests/test-supplicant-config.c +++ b/src/supplicant/tests/test-supplicant-config.c @@ -1,19 +1,5 @@ -/* NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2011 Red Hat, Inc. */ @@ -236,7 +222,7 @@ test_wifi_wep_key (const char *detail, gs_unref_bytes GBytes *ssid = g_bytes_new (ssid_data, sizeof (ssid_data)); const char *bssid_str = "11:22:33:44:55:66"; gs_unref_bytes GBytes *wep_key_bytes = g_bytes_new (expected, expected_size); - const char *bgscan_data = "simple:30:-80:86400"; + const char *bgscan_data = "simple:30:-70:86400"; gs_unref_bytes GBytes *bgscan = g_bytes_new (bgscan_data, strlen (bgscan_data)); connection = new_basic_connection ("Test Wifi WEP Key", ssid, test_bssid ? bssid_str : NULL); @@ -264,7 +250,7 @@ test_wifi_wep_key (const char *detail, NMTST_EXPECT_NM_INFO ("Config: added 'wep_key0' value *"); NMTST_EXPECT_NM_INFO ("Config: added 'wep_tx_keyidx' value '0'"); if (!test_bssid) - NMTST_EXPECT_NM_INFO ("Config: added 'bgscan' value 'simple:30:-80:86400'*"); + NMTST_EXPECT_NM_INFO ("Config: added 'bgscan' value 'simple:30:-70:86400'*"); config_dict = build_supplicant_config (connection, 1500, 0, TRUE, TRUE); g_test_assert_expected_messages (); diff --git a/src/systemd/meson.build b/src/systemd/meson.build index af1d0c8b..5c4fa3e2 100644 --- a/src/systemd/meson.build +++ b/src/systemd/meson.build @@ -1,45 +1,48 @@ +sources = files( + 'src/libsystemd-network/arp-util.c', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/dhcp-network.c', + 'src/libsystemd-network/dhcp-option.c', + 'src/libsystemd-network/dhcp-packet.c', + 'src/libsystemd-network/dhcp6-network.c', + 'src/libsystemd-network/dhcp6-option.c', + 'src/libsystemd-network/lldp-neighbor.c', + 'src/libsystemd-network/lldp-network.c', + 'src/libsystemd-network/network-internal.c', + 'src/libsystemd-network/sd-dhcp-client.c', + 'src/libsystemd-network/sd-dhcp-lease.c', + 'src/libsystemd-network/sd-dhcp6-client.c', + 'src/libsystemd-network/sd-dhcp6-lease.c', + 'src/libsystemd-network/sd-ipv4acd.c', + 'src/libsystemd-network/sd-ipv4ll.c', + 'src/libsystemd-network/sd-lldp.c', + 'src/libsystemd/sd-event/event-util.c', + 'src/libsystemd/sd-event/sd-event.c', + 'src/libsystemd/sd-id128/id128-util.c', + 'src/libsystemd/sd-id128/sd-id128.c', + 'nm-sd.c', + 'nm-sd-utils-core.c', + 'nm-sd-utils-dhcp.c', + 'sd-adapt-core/nm-sd-adapt-core.c', +) + +incs = include_directories( + 'sd-adapt-core', + 'src/libsystemd-network', + 'src/libsystemd/sd-event', + 'src/systemd', +) + +deps = [ + daemon_nm_default_dep, + libnm_systemd_shared_dep, +] + libnm_systemd_core = static_library( 'nm-systemd-core', - sources: files( - 'sd-adapt-core/nm-sd-adapt-core.c', - 'src/libsystemd-network/arp-util.c', - 'src/libsystemd-network/dhcp-identifier.c', - 'src/libsystemd-network/dhcp-network.c', - 'src/libsystemd-network/dhcp-option.c', - 'src/libsystemd-network/dhcp-packet.c', - 'src/libsystemd-network/dhcp6-network.c', - 'src/libsystemd-network/dhcp6-option.c', - 'src/libsystemd-network/lldp-neighbor.c', - 'src/libsystemd-network/lldp-network.c', - 'src/libsystemd-network/network-internal.c', - 'src/libsystemd-network/sd-dhcp-client.c', - 'src/libsystemd-network/sd-dhcp-lease.c', - 'src/libsystemd-network/sd-dhcp6-client.c', - 'src/libsystemd-network/sd-dhcp6-lease.c', - 'src/libsystemd-network/sd-ipv4acd.c', - 'src/libsystemd-network/sd-ipv4ll.c', - 'src/libsystemd-network/sd-lldp.c', - 'src/libsystemd/sd-event/event-util.c', - 'src/libsystemd/sd-event/sd-event.c', - 'src/libsystemd/sd-id128/id128-util.c', - 'src/libsystemd/sd-id128/sd-id128.c', - 'nm-sd.c', - 'nm-sd-utils-core.c', - 'nm-sd-utils-dhcp.c', - ), - include_directories: [ - src_inc, - include_directories( - 'sd-adapt-core', - 'src/libsystemd-network', - 'src/libsystemd/sd-event', - 'src/systemd', - ) - ], - dependencies: [ - libnm_core_dep, - ], - c_args: [ - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', - ], + sources: sources, + include_directories: incs, + dependencies: deps, + c_args: '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', + link_with: libc_siphash, ) diff --git a/src/systemd/nm-sd-utils-core.c b/src/systemd/nm-sd-utils-core.c index 42560789..4057c70a 100644 --- a/src/systemd/nm-sd-utils-core.c +++ b/src/systemd/nm-sd-utils-core.c @@ -1,18 +1,5 @@ -/* This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/systemd/nm-sd-utils-core.h b/src/systemd/nm-sd-utils-core.h index a7b092b3..3b0bc23b 100644 --- a/src/systemd/nm-sd-utils-core.h +++ b/src/systemd/nm-sd-utils-core.h @@ -1,18 +1,5 @@ -/* This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/systemd/nm-sd-utils-dhcp.c b/src/systemd/nm-sd-utils-dhcp.c index 49a924b6..4cfe054c 100644 --- a/src/systemd/nm-sd-utils-dhcp.c +++ b/src/systemd/nm-sd-utils-dhcp.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/systemd/nm-sd-utils-dhcp.h b/src/systemd/nm-sd-utils-dhcp.h index 496bf374..5228eb25 100644 --- a/src/systemd/nm-sd-utils-dhcp.h +++ b/src/systemd/nm-sd-utils-dhcp.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ diff --git a/src/systemd/nm-sd.c b/src/systemd/nm-sd.c index bcab328f..a277f430 100644 --- a/src/systemd/nm-sd.c +++ b/src/systemd/nm-sd.c @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ @@ -30,7 +18,6 @@ typedef struct SDEventSource { GSource source; GPollFD pollfd; sd_event *event; - guint *default_source_id; } SDEventSource; static gboolean @@ -48,41 +35,49 @@ event_check (GSource *source) static gboolean event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { - return sd_event_dispatch (((SDEventSource *)source)->event) > 0; + return sd_event_dispatch (((SDEventSource *) source)->event) > 0; } static void event_finalize (GSource *source) { - SDEventSource *s; + SDEventSource *s = (SDEventSource *) source; - s = (SDEventSource *) source; sd_event_unref (s->event); - if (s->default_source_id) - *s->default_source_id = 0; } static SDEventSource * -event_create_source (sd_event *event, guint *default_source_id) +event_create_source (sd_event *event) { - static GSourceFuncs event_funcs = { + static const GSourceFuncs event_funcs = { .prepare = event_prepare, .check = event_check, .dispatch = event_dispatch, .finalize = event_finalize, }; SDEventSource *source; + gboolean is_default_event = FALSE; + int r; - g_return_val_if_fail (event, NULL); + if (!event) { + is_default_event = TRUE; + r = sd_event_default (&event); + if (r < 0) + g_return_val_if_reached (NULL); + } - source = (SDEventSource *) g_source_new (&event_funcs, sizeof (SDEventSource)); + source = (SDEventSource *) g_source_new ((GSourceFuncs *) &event_funcs, sizeof (SDEventSource)); - source->event = sd_event_ref (event); - source->pollfd.fd = sd_event_get_fd (event); - source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; - source->default_source_id = default_source_id; + source->event = is_default_event + ? g_steal_pointer (&event) + : sd_event_ref (event); - g_source_add_poll ((GSource *) source, &source->pollfd); + source->pollfd = (GPollFD) { + .fd = sd_event_get_fd (source->event), + .events = G_IO_IN | G_IO_HUP | G_IO_ERR, + }; + + g_source_add_poll (&source->source, &source->pollfd); return source; } @@ -92,35 +87,15 @@ event_attach (sd_event *event, GMainContext *context) { SDEventSource *source; guint id; - int r; - sd_event *e = event; - guint *p_default_source_id = NULL; - if (!e) { - static guint default_source_id = 0; + source = event_create_source (event); - if (default_source_id) { - /* The default event cannot be registered multiple times. */ - g_return_val_if_reached (0); - } + g_return_val_if_fail (source, 0); - r = sd_event_default (&e); - if (r < 0) - g_return_val_if_reached (0); - - p_default_source_id = &default_source_id; - } - - source = event_create_source (e, p_default_source_id); id = g_source_attach ((GSource *) source, context); g_source_unref ((GSource *) source); - if (!event) { - *p_default_source_id = id; - sd_event_unref (e); - } - - g_return_val_if_fail (id, 0); + nm_assert (id != 0); return id; } diff --git a/src/systemd/nm-sd.h b/src/systemd/nm-sd.h index 07fc2ad4..99904243 100644 --- a/src/systemd/nm-sd.h +++ b/src/systemd/nm-sd.h @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c b/src/systemd/sd-adapt-core/nm-sd-adapt-core.c index c461752e..a9f8bd1c 100644 --- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c +++ b/src/systemd/sd-adapt-core/nm-sd-adapt-core.c @@ -1,17 +1,5 @@ -/* 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. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h b/src/systemd/sd-adapt-core/nm-sd-adapt-core.h index bd71dd18..81bc7320 100644 --- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h +++ b/src/systemd/sd-adapt-core/nm-sd-adapt-core.h @@ -1,18 +1,5 @@ -/* This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index e0269b54..6a803d7b 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -15,11 +15,21 @@ #include "dhcp-protocol.h" #include "socket-util.h" +typedef struct sd_dhcp_option { + unsigned n_ref; + + uint8_t option; + void *data; + size_t length; +} sd_dhcp_option; + +extern const struct hash_ops dhcp_option_hash_ops; + int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, const uint8_t *mac_addr, size_t mac_addr_len, uint16_t arp_type, uint16_t port); -int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port); +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type); int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len); int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, @@ -41,7 +51,7 @@ uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len); void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, uint16_t source, be32_t destination_addr, - uint16_t destination, uint16_t len); + uint16_t destination, uint16_t len, int ip_service_type); int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port); diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h index 122042ab..a2d0f8bd 100644 --- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h @@ -58,6 +58,9 @@ struct sd_dhcp_lease { struct in_addr *ntp; size_t ntp_size; + struct in_addr *sip; + size_t sip_size; + struct sd_dhcp_route *static_route; size_t static_route_size, static_route_allocated; diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c index 858fe57c..1f01ece1 100644 --- a/src/systemd/src/libsystemd-network/dhcp-network.c +++ b/src/systemd/src/libsystemd-network/dhcp-network.c @@ -11,7 +11,6 @@ #include <net/if_arp.h> #include <stdio.h> #include <string.h> -#include <sys/socket.h> #include <linux/filter.h> #include <linux/if_infiniband.h> #include <linux/if_packet.h> @@ -148,7 +147,7 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, bcast_addr, ð_mac, arp_type, dhcp_hlen, port); } -int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) { +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) { union sockaddr_union src = { .in.sin_family = AF_INET, .in.sin_port = htobe16(port), @@ -161,7 +160,11 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) { if (s < 0) return -errno; - r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6); + if (ip_service_type >= 0) + r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type); + else + r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6); + if (r < 0) return r; diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c index 50238b0a..49193879 100644 --- a/src/systemd/src/libsystemd-network/dhcp-option.c +++ b/src/systemd/src/libsystemd-network/dhcp-option.c @@ -8,10 +8,10 @@ #include <errno.h> #include <stdint.h> #include <stdio.h> -#include <string.h> #include "alloc-util.h" #include "dhcp-internal.h" +#include "dhcp-server-internal.h" #include "memory-util.h" #include "strv.h" #include "utf8.h" @@ -29,7 +29,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, case SD_DHCP_OPTION_PAD: case SD_DHCP_OPTION_END: - if (size < *offset + 1) + if (*offset + 1 > size) return -ENOBUFS; options[*offset] = code; @@ -37,42 +37,83 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, break; case SD_DHCP_OPTION_USER_CLASS: { - size_t len = 0; + size_t total = 0; char **s; - STRV_FOREACH(s, (char **) optval) - len += strlen(*s) + 1; + STRV_FOREACH(s, (char **) optval) { + size_t len = strlen(*s); + + if (len > 255) + return -ENAMETOOLONG; + + total += 1 + len; + } - if (size < *offset + len + 2) + if (*offset + 2 + total > size) return -ENOBUFS; options[*offset] = code; - options[*offset + 1] = len; + options[*offset + 1] = total; *offset += 2; STRV_FOREACH(s, (char **) optval) { - len = strlen(*s); - - if (len > 255) - return -ENAMETOOLONG; + size_t len = strlen(*s); options[*offset] = len; - memcpy_safe(&options[*offset + 1], *s, len); - *offset += len + 1; + memcpy(&options[*offset + 1], *s, len); + *offset += 1 + len; + } + + break; + } + case SD_DHCP_OPTION_SIP_SERVER: + if (*offset + 3 + optlen > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = optlen + 1; + options[*offset + 2] = 1; + + memcpy_safe(&options[*offset + 3], optval, optlen); + *offset += 3 + optlen; + + break; + case SD_DHCP_OPTION_VENDOR_SPECIFIC: { + OrderedHashmap *s = (OrderedHashmap *) optval; + struct sd_dhcp_option *p; + size_t l = 0; + Iterator i; + + ORDERED_HASHMAP_FOREACH(p, s, i) + l += p->length + 2; + + if (*offset + l + 2 > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = l; + + *offset += 2; + + ORDERED_HASHMAP_FOREACH(p, s, i) { + options[*offset] = p->option; + options[*offset + 1] = p->length; + memcpy(&options[*offset + 2], p->data, p->length); + *offset += 2 + p->length; } break; } default: - if (size < *offset + optlen + 2) + if (*offset + 2 + optlen > size) return -ENOBUFS; options[*offset] = code; options[*offset + 1] = optlen; memcpy_safe(&options[*offset + 2], optval, optlen); - *offset += optlen + 2; + *offset += 2 + optlen; break; } @@ -83,22 +124,25 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, uint8_t code, size_t optlen, const void *optval) { - size_t file_offset = 0, sname_offset =0; - bool file, sname; + const bool use_file = overload & DHCP_OVERLOAD_FILE; + const bool use_sname = overload & DHCP_OVERLOAD_SNAME; int r; assert(message); assert(offset); - file = overload & DHCP_OVERLOAD_FILE; - sname = overload & DHCP_OVERLOAD_SNAME; + /* If *offset is in range [0, size), we are writing to ->options, + * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file, + * if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname)) + * and use_sname, we are writing to ->sname. + */ if (*offset < size) { /* still space in the options array */ r = option_append(message->options, size, offset, code, optlen, optval); if (r >= 0) return 0; - else if (r == -ENOBUFS && (file || sname)) { + else if (r == -ENOBUFS && (use_file || use_sname)) { /* did not fit, but we have more buffers to try close the options array and move the offset to its end */ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); @@ -110,8 +154,8 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, return r; } - if (overload & DHCP_OVERLOAD_FILE) { - file_offset = *offset - size; + if (use_file) { + size_t file_offset = *offset - size; if (file_offset < sizeof(message->file)) { /* still space in the 'file' array */ @@ -119,7 +163,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, if (r >= 0) { *offset = size + file_offset; return 0; - } else if (r == -ENOBUFS && sname) { + } else if (r == -ENOBUFS && use_sname) { /* did not fit, but we have more buffers to try close the file array and move the offset to its end */ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); @@ -132,19 +176,18 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, } } - if (overload & DHCP_OVERLOAD_SNAME) { - sname_offset = *offset - size - (file ? sizeof(message->file) : 0); + if (use_sname) { + size_t sname_offset = *offset - size - use_file*sizeof(message->file); if (sname_offset < sizeof(message->sname)) { /* still space in the 'sname' array */ r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval); if (r >= 0) { - *offset = size + (file ? sizeof(message->file) : 0) + sname_offset; + *offset = size + use_file*sizeof(message->file) + sname_offset; return 0; - } else { + } else /* no space, or other error, give up */ return r; - } } } @@ -274,3 +317,43 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c return message_type; } + +static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) { + if (!i) + return NULL; + + free(i->data); + return mfree(i); +} + +int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) { + assert_return(ret, -EINVAL); + assert_return(length == 0 || data, -EINVAL); + + _cleanup_free_ void *q = memdup(data, length); + if (!q) + return -ENOMEM; + + sd_dhcp_option *p = new(sd_dhcp_option, 1); + if (!p) + return -ENOMEM; + + *p = (sd_dhcp_option) { + .n_ref = 1, + .option = option, + .length = length, + .data = TAKE_PTR(q), + }; + + *ret = TAKE_PTR(p); + return 0; +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + dhcp_option_hash_ops, + void, + trivial_hash_func, + trivial_compare_func, + sd_dhcp_option, + sd_dhcp_option_unref); diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c index 9e565e28..2062be91 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/systemd/src/libsystemd-network/dhcp-packet.c @@ -77,12 +77,15 @@ uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) { void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, uint16_t source_port, be32_t destination_addr, - uint16_t destination_port, uint16_t len) { + uint16_t destination_port, uint16_t len, int ip_service_type) { packet->ip.version = IPVERSION; packet->ip.ihl = DHCP_IP_SIZE / 4; packet->ip.tot_len = htobe16(len); - packet->ip.tos = IPTOS_CLASS_CS6; + if (ip_service_type >= 0) + packet->ip.tos = ip_service_type; + else + packet->ip.tos = IPTOS_CLASS_CS6; packet->ip.protocol = IPPROTO_UDP; packet->ip.saddr = source_addr; diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h index f28ba68d..517e357d 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h @@ -85,7 +85,7 @@ typedef struct DHCP6IA DHCP6IA; int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, size_t optlen, const void *optval); int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia); -int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd); +int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix); int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c index 73c195a7..d43680a5 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-network.c +++ b/src/systemd/src/libsystemd-network/dhcp6-network.c @@ -10,7 +10,6 @@ #include <netinet/ip6.h> #include <stdio.h> #include <string.h> -#include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <linux/if_packet.h> diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index 562a34b5..bb4c4d91 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -7,7 +7,6 @@ #include <errno.h> #include <netinet/in.h> -#include <string.h> #include "sd-dhcp6-client.h" @@ -170,9 +169,10 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { return r; } -int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) { +int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) { DHCP6Option *option = (DHCP6Option *)buf; size_t i = sizeof(*option) + sizeof(pd->ia_pd); + DHCP6PDPrefixOption *prefix_opt; DHCP6Address *prefix; assert_return(buf, -EINVAL); @@ -185,10 +185,7 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) { option->code = htobe16(SD_DHCP6_OPTION_IA_PD); memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd)); - LIST_FOREACH(addresses, prefix, pd->addresses) { - DHCP6PDPrefixOption *prefix_opt; - if (len < i + sizeof(*prefix_opt)) return -ENOBUFS; @@ -196,9 +193,19 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) { prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); - memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, - sizeof(struct iapdprefix)); + memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix)); + i += sizeof(*prefix_opt); + } + + if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) { + if (len < i + sizeof(*prefix_opt)) + return -ENOBUFS; + + prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; + prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); + prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); + memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix)); i += sizeof(*prefix_opt); } diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c index 530af034..238d718b 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.c +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c @@ -10,7 +10,7 @@ #include "lldp-internal.h" #include "lldp-neighbor.h" #include "memory-util.h" -#include "missing.h" +#include "missing_network.h" #include "unaligned.h" static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) { diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c index 5ba9f081..f4764dd1 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/systemd/src/libsystemd-network/lldp-network.c @@ -7,7 +7,7 @@ #include "fd-util.h" #include "lldp-network.h" -#include "missing.h" +#include "missing_network.h" #include "socket-util.h" int lldp_network_bind_raw_socket(int ifindex) { diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 209ce884..7d22e754 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -22,6 +22,7 @@ #include "parse-util.h" #include "siphash24.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "utf8.h" @@ -139,15 +140,38 @@ static int net_condition_test_property(char * const *match_property, sd_device * return true; } +static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = { + [NL80211_IFTYPE_ADHOC] = "ad-hoc", + [NL80211_IFTYPE_STATION] = "station", + [NL80211_IFTYPE_AP] = "ap", + [NL80211_IFTYPE_AP_VLAN] = "ap-vlan", + [NL80211_IFTYPE_WDS] = "wds", + [NL80211_IFTYPE_MONITOR] = "monitor", + [NL80211_IFTYPE_MESH_POINT] = "mesh-point", + [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client", + [NL80211_IFTYPE_P2P_GO] = "p2p-go", + [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device", + [NL80211_IFTYPE_OCB] = "ocb", + [NL80211_IFTYPE_NAN] = "nan", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype); + bool net_match_config(Set *match_mac, char * const *match_paths, char * const *match_drivers, char * const *match_types, char * const *match_names, char * const *match_property, + char * const *match_wifi_iftype, + char * const *match_ssid, + Set *match_bssid, sd_device *device, const struct ether_addr *dev_mac, - const char *dev_name) { + const char *dev_name, + enum nl80211_iftype wifi_iftype, + const char *ssid, + const struct ether_addr *bssid) { const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str; @@ -181,6 +205,15 @@ bool net_match_config(Set *match_mac, if (!net_condition_test_property(match_property, device)) return false; + if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(wifi_iftype))) + return false; + + if (!net_condition_test_strv(match_ssid, ssid)) + return false; + + if (match_bssid && (!bssid || !set_contains(match_bssid, bssid))) + return false; + return true; } @@ -257,7 +290,7 @@ int config_parse_match_strv( for (;;) { _cleanup_free_ char *word = NULL, *k = NULL; - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); if (r == 0) return 0; if (r == -ENOMEM) diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h index 487421fb..2eb0cba5 100644 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ b/src/systemd/src/libsystemd-network/network-internal.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include <linux/nl80211.h> #include <stdbool.h> #include "sd-device.h" @@ -21,9 +22,15 @@ bool net_match_config(Set *match_mac, char * const *match_type, char * const *match_name, char * const *match_property, + char * const *match_wifi_iftype, + char * const *match_ssid, + Set *match_bssid, sd_device *device, const struct ether_addr *dev_mac, - const char *dev_name); + const char *dev_name, + enum nl80211_iftype wifi_iftype, + const char *ssid, + const struct ether_addr *bssid); CONFIG_PARSER_PROTOTYPE(config_parse_net_condition); CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 2f531bc7..0266161d 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -10,7 +10,6 @@ #include <net/if_arp.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/ioctl.h> #include <linux/if_infiniband.h> @@ -92,6 +91,7 @@ struct sd_dhcp_client { usec_t start_time; uint64_t attempt; uint64_t max_attempts; + OrderedHashmap *options; usec_t request_sent; sd_event_source *timeout_t1; sd_event_source *timeout_t2; @@ -100,6 +100,7 @@ struct sd_dhcp_client { void *userdata; sd_dhcp_lease *lease; usec_t start_delay; + int ip_service_type; }; static const uint8_t default_req_opts[] = { @@ -234,6 +235,7 @@ int sd_dhcp_client_set_mac( DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; + int r; assert_return(client, -EINVAL); assert_return(addr, -EINVAL); @@ -261,8 +263,11 @@ int sd_dhcp_client_set_mac( client->mac_addr_len = addr_len; client->arp_type = arp_type; - if (need_restart && client->state != DHCP_STATE_STOPPED) - sd_dhcp_client_start(client); + if (need_restart && client->state != DHCP_STATE_STOPPED) { + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } return 0; } @@ -298,6 +303,7 @@ int sd_dhcp_client_set_client_id( DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; + int r; assert_return(client, -EINVAL); assert_return(data, -EINVAL); @@ -331,8 +337,11 @@ int sd_dhcp_client_set_client_id( memcpy(&client->client_id.raw.data, data, data_len); client->client_id_len = data_len + sizeof (client->client_id.type); - if (need_restart && client->state != DHCP_STATE_STOPPED) - sd_dhcp_client_start(client); + if (need_restart && client->state != DHCP_STATE_STOPPED) { + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } return 0; } @@ -363,7 +372,7 @@ static int dhcp_client_set_iaid_duid_internal( if (duid) { r = dhcp_validate_duid_len(duid_type, duid_len, true); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to validate length of DUID: %m"); } zero(client->client_id); @@ -378,7 +387,7 @@ static int dhcp_client_set_iaid_duid_internal( true, &client->client_id.ns.iaid); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set IAID: %m"); } } @@ -390,32 +399,32 @@ static int dhcp_client_set_iaid_duid_internal( switch (duid_type) { case DUID_TYPE_LLT: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m"); break; case DUID_TYPE_EN: r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m"); break; case DUID_TYPE_LL: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m"); break; case DUID_TYPE_UUID: r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-UUID: %m"); break; default: - return -EINVAL; + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); } client->client_id_len = sizeof(client->client_id.type) + len + @@ -424,7 +433,9 @@ static int dhcp_client_set_iaid_duid_internal( if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : ""); client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - sd_dhcp_client_start(client); + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); } return 0; @@ -534,6 +545,24 @@ int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempt return 0; } +int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) { + int r; + + assert_return(client, -EINVAL); + assert_return(v, -EINVAL); + + r = ordered_hashmap_ensure_allocated(&client->options, &dhcp_option_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(client->options, UINT_TO_PTR(v->option), v); + if (r < 0) + return r; + + sd_dhcp_option_ref(v); + return 0; +} + int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { assert_return(client, -EINVAL); @@ -546,6 +575,14 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { return 0; } +int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { + assert_return(client, -EINVAL); + + client->ip_service_type = type; + + return 0; +} + static int client_notify(sd_dhcp_client *client, int event) { assert(client); @@ -778,7 +815,7 @@ static int dhcp_client_send_raw( size_t len) { dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port, - INADDR_BROADCAST, DHCP_PORT_SERVER, len); + INADDR_BROADCAST, DHCP_PORT_SERVER, len, client->ip_service_type); return dhcp_network_send_raw_socket(client->fd, &client->link, packet, len); @@ -787,6 +824,8 @@ static int dhcp_client_send_raw( static int client_send_discover(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *discover = NULL; size_t optoffset, optlen; + sd_dhcp_option *j; + Iterator i; int r; assert(client); @@ -803,7 +842,9 @@ static int client_send_discover(sd_dhcp_client *client) { address be assigned, and may include the ’IP address lease time’ option to suggest the lease time it would like. */ - if (client->last_addr != INADDR_ANY) { + /* RFC7844 section 3: + SHOULD NOT contain any other option. */ + if (!client->anonymize && client->last_addr != INADDR_ANY) { r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->last_addr); @@ -848,6 +889,13 @@ static int client_send_discover(sd_dhcp_client *client) { return r; } + ORDERED_HASHMAP_FOREACH(j, client->options, i) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + j->option, j->length, j->data); + if (r < 0) + return r; + } + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) @@ -866,41 +914,6 @@ static int client_send_discover(sd_dhcp_client *client) { return 0; } -static int client_send_release(sd_dhcp_client *client) { - _cleanup_free_ DHCPPacket *release = NULL; - size_t optoffset, optlen; - int r; - - assert(client); - assert(!IN_SET(client->state, DHCP_STATE_STOPPED)); - - r = client_message_init(client, &release, DHCP_RELEASE, - &optlen, &optoffset); - if (r < 0) - return r; - - /* Fill up release IP and MAC */ - release->dhcp.ciaddr = client->lease->address; - memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); - - r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - r = dhcp_network_send_udp_socket(client->fd, - client->lease->server_address, - DHCP_PORT_SERVER, - &release->dhcp, - sizeof(DHCPMessage) + optoffset); - if (r < 0) - return r; - - log_dhcp_client(client, "RELEASE"); - - return 0; -} - static int client_send_request(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *request = NULL; size_t optoffset, optlen; @@ -1000,15 +1013,14 @@ static int client_send_request(sd_dhcp_client *client) { if (r < 0) return r; - if (client->state == DHCP_STATE_RENEWING) { + if (client->state == DHCP_STATE_RENEWING) r = dhcp_network_send_udp_socket(client->fd, client->lease->server_address, DHCP_PORT_SERVER, &request->dhcp, sizeof(DHCPMessage) + optoffset); - } else { + else r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset); - } if (r < 0) return r; @@ -1216,7 +1228,7 @@ static int client_initialize_time_events(sd_dhcp_client *client) { assert(client); assert(client->event); - if (client->start_delay) { + if (client->start_delay > 0) { assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); usec += client->start_delay; } @@ -1667,7 +1679,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i goto error; } - r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port); + r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port, client->ip_service_type); if (r < 0) { log_dhcp_client(client, "could not bind UDP socket"); goto error; @@ -1887,6 +1899,17 @@ static int client_receive_message_raw( return client_handle_message(client, &packet->dhcp, len); } +int sd_dhcp_client_send_renew(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + assert_return(client->fd >= 0, -EINVAL); + + client->start_delay = 0; + client->attempt = 1; + client->state = DHCP_STATE_RENEWING; + + return client_initialize_time_events(client); +} + int sd_dhcp_client_start(sd_dhcp_client *client) { int r; @@ -1915,8 +1938,35 @@ int sd_dhcp_client_start(sd_dhcp_client *client) { int sd_dhcp_client_send_release(sd_dhcp_client *client) { assert_return(client, -EINVAL); + assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE); + assert_return(client->lease, -EUNATCH); + + _cleanup_free_ DHCPPacket *release = NULL; + size_t optoffset, optlen; + int r; + + r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset); + if (r < 0) + return r; + + /* Fill up release IP and MAC */ + release->dhcp.ciaddr = client->lease->address; + memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); + + r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; - client_send_release(client); + r = dhcp_network_send_udp_socket(client->fd, + client->lease->server_address, + DHCP_PORT_SERVER, + &release->dhcp, + sizeof(DHCPMessage) + optoffset); + if (r < 0) + return r; + + log_dhcp_client(client, "RELEASE"); return 0; } @@ -1966,7 +2016,8 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { } static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { - assert(client); + if (!client) + return NULL; log_dhcp_client(client, "FREE"); @@ -1985,17 +2036,16 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { free(client->hostname); free(client->vendor_class_identifier); client->user_class = strv_free(client->user_class); + ordered_hashmap_free(client->options); return mfree(client); } DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free); int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { - _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - assert_return(ret, -EINVAL); - client = new(sd_dhcp_client, 1); + _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1); if (!client) return -ENOMEM; @@ -2008,6 +2058,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { .port = DHCP_PORT_CLIENT, .anonymize = !!anonymize, .max_attempts = (uint64_t) -1, + .ip_service_type = -1, }; /* NOTE: this could be moved to a function. */ if (anonymize) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index 7559d066..ac6fe3f4 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -7,9 +7,7 @@ #include <arpa/inet.h> #include <errno.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -122,6 +120,17 @@ int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { return (int) lease->ntp_size; } +int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->sip_size <= 0) + return -ENODATA; + + *addr = lease->sip; + return (int) lease->sip_size; +} + int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { assert_return(lease, -EINVAL); assert_return(domainname, -EINVAL); @@ -271,6 +280,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { free(lease->domainname); free(lease->dns); free(lease->ntp); + free(lease->sip); free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); @@ -404,6 +414,36 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add return 0; } +static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { + assert(option); + assert(ret); + assert(n_ret); + + if (len <= 0) { + *ret = mfree(*ret); + *n_ret = 0; + } else { + size_t n_addresses; + struct in_addr *addresses; + int l = len - 1; + + if (l % 4 != 0) + return -EINVAL; + + n_addresses = l / 4; + + addresses = newdup(struct in_addr, option + 1, n_addresses); + if (!addresses) + return -ENOMEM; + + free(*ret); + *ret = addresses; + *n_ret = n_addresses; + } + + return 0; +} + static int lease_parse_routes( const uint8_t *option, size_t len, struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { @@ -557,6 +597,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); break; + case SD_DHCP_OPTION_SIP_SERVER: + r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size); + if (r < 0) + log_debug_errno(r, "Failed to parse SIP server, ignoring: %m"); + break; + case SD_DHCP_OPTION_STATIC_ROUTE: r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); if (r < 0) @@ -895,6 +941,13 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { fputc('\n', f); } + r = sd_dhcp_lease_get_sip(lease, &addresses); + if (r > 0) { + fputs("SIP=", f); + serialize_in_addrs(f, addresses, r, false, NULL); + fputc('\n', f); + } + r = sd_dhcp_lease_get_domainname(lease, &string); if (r >= 0) fprintf(f, "DOMAINNAME=%s\n", string); @@ -985,6 +1038,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { *broadcast = NULL, *dns = NULL, *ntp = NULL, + *sip = NULL, *mtu = NULL, *routes = NULL, *domains = NULL, @@ -1013,6 +1067,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { "BROADCAST", &broadcast, "DNS", &dns, "NTP", &ntp, + "SIP", &sip, "MTU", &mtu, "DOMAINNAME", &lease->domainname, "HOSTNAME", &lease->hostname, @@ -1117,6 +1172,14 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { lease->ntp_size = r; } + if (sip) { + r = deserialize_in_addrs(&lease->sip, sip); + if (r < 0) + log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip); + else + lease->ntp_size = r; + } + if (mtu) { r = safe_atou16(mtu, &lease->mtu); if (r < 0) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index f67a45bd..e1150f98 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -6,7 +6,6 @@ #include "nm-sd-adapt-core.h" #include <errno.h> -#include <string.h> #include <sys/ioctl.h> #include <linux/if_arp.h> #include <linux/if_infiniband.h> @@ -31,6 +30,9 @@ #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN +#define IRT_DEFAULT (1 * USEC_PER_DAY) +#define IRT_MINIMUM (600 * USEC_PER_SEC) + /* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */ enum { DHCP6_REQUEST_IA_NA = 1, @@ -45,6 +47,7 @@ struct sd_dhcp6_client { sd_event *event; int event_priority; int ifindex; + DHCP6Address hint_pd_prefix; struct in6_addr local_address; uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; @@ -73,6 +76,8 @@ struct sd_dhcp6_client { void *userdata; struct duid duid; size_t duid_len; + usec_t information_request_time_usec; + usec_t information_refresh_time_usec; }; static const uint16_t default_req_opts[] = { @@ -184,6 +189,22 @@ int sd_dhcp6_client_set_mac( return 0; } +int sd_dhcp6_client_set_prefix_delegation_hint( + sd_dhcp6_client *client, + uint8_t prefixlen, + const struct in6_addr *pd_address) { + + assert_return(client, -EINVAL); + assert_return(pd_address, -EINVAL); + + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->hint_pd_prefix.iapdprefix.address = *pd_address; + client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen; + + return 0; +} + static int client_ensure_duid(sd_dhcp6_client *client) { if (client->duid_len != 0) return 0; @@ -213,7 +234,7 @@ static int dhcp6_client_set_duid_internal( if (r < 0) { r = dhcp_validate_duid_len(duid_type, duid_len, false); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m"); log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type); } @@ -225,32 +246,32 @@ static int dhcp6_client_set_duid_internal( switch (duid_type) { case DUID_TYPE_LLT: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LLT: %m"); break; case DUID_TYPE_EN: r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-EN: %m"); break; case DUID_TYPE_LL: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LL: %m"); break; case DUID_TYPE_UUID: r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-UUID: %m"); break; default: - return -EINVAL; + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); } #else /* NM_IGNORED */ g_return_val_if_reached (-EINVAL); @@ -493,7 +514,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { } if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd); + r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix); if (r < 0) return r; @@ -531,7 +552,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { } if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd); + r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) return r; @@ -557,7 +578,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { } if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd); + r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) return r; @@ -826,6 +847,7 @@ static int client_parse_message( uint32_t lt_t1 = ~0, lt_t2 = ~0; bool clientid = false; size_t pos = 0; + usec_t irt = IRT_DEFAULT; int r; assert(client); @@ -1000,6 +1022,13 @@ static int client_parse_message( return r; break; + + case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: + if (optlen != 4) + return -EINVAL; + + irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC; + break; } pos += offsetof(DHCP6Option, data) + optlen; @@ -1031,6 +1060,8 @@ static int client_parse_message( } } + client->information_refresh_time_usec = MAX(irt, IRT_MINIMUM); + return 0; } @@ -1431,8 +1462,15 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { client->fd = r; } - if (client->information_request) + if (client->information_request) { + usec_t t = now(CLOCK_MONOTONIC); + + if (t < usec_add(client->information_request_time_usec, client->information_refresh_time_usec)) + return 0; + + client->information_request_time_usec = t; state = DHCP6_STATE_INFORMATION_REQUEST; + } log_dhcp6_client(client, "Started in %s mode", client->information_request? "Information request": @@ -1521,6 +1559,8 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) { .request = DHCP6_REQUEST_IA_NA, .fd = -1, .req_opts_len = ELEMENTSOF(default_req_opts), + .hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1, + .hint_pd_prefix.iapdprefix.lifetime_valid = (be32_t) -1, .req_opts = TAKE_PTR(req_opts), }; diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index e7561480..3efa8170 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -10,7 +10,6 @@ #include <netinet/if_ether.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "sd-ipv4acd.h" diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index daac8839..2d17b4fe 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -9,7 +9,6 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "sd-id128.h" #include "sd-ipv4acd.h" diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index c3781706..7c4566e3 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -18,7 +18,7 @@ #include "list.h" #include "macro.h" #include "memory-util.h" -#include "missing.h" +#include "missing_syscall.h" #include "prioq.h" #include "process-util.h" #include "set.h" @@ -773,11 +773,13 @@ static void source_disconnect(sd_event_source *s) { event = s->event; - s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID; s->event = NULL; LIST_REMOVE(sources, event->sources, s); event->n_sources--; + /* Note that we don't invalidate the type here, since we still need it in order to close the fd or + * pidfd associated with this event source, which we'll do only on source_free(). */ + if (!s->floating) sd_event_unref(event); } @@ -2556,7 +2558,7 @@ static int process_child(sd_event *e) { * benefit in leaving it queued */ assert(s->child.options & (WSTOPPED|WCONTINUED)); - waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); + (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); } r = source_set_pending(s, true); diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c index eeb29e97..c0d0fe81 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -15,7 +15,7 @@ #include "io-util.h" #include "khash.h" #include "macro.h" -#include "missing.h" +#include "missing_syscall.h" #include "random-util.h" #include "user-util.h" #include "util.h" diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index ab62368e..f97e35b6 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -26,6 +26,7 @@ #include <stdbool.h> #include "sd-dhcp-lease.h" +#include "sd-dhcp-option.h" #include "sd-event.h" #include "_sd-common.h" @@ -87,6 +88,7 @@ enum { SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119, + SD_DHCP_OPTION_SIP_SERVER = 120, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, SD_DHCP_OPTION_PRIVATE_BASE = 224, /* Windows 10 option to send when Anonymize=true */ @@ -173,10 +175,16 @@ int sd_dhcp_client_set_user_class( int sd_dhcp_client_get_lease( sd_dhcp_client *client, sd_dhcp_lease **ret); +int sd_dhcp_client_set_service_type( + sd_dhcp_client *client, + int type); + +int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v); int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client); int sd_dhcp_client_send_release(sd_dhcp_client *client); +int sd_dhcp_client_send_renew(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h index d299c791..b80d607f 100644 --- a/src/systemd/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/src/systemd/sd-dhcp-lease.h @@ -44,6 +44,7 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); diff --git a/src/systemd/src/systemd/sd-dhcp-option.h b/src/systemd/src/systemd/sd-dhcp-option.h new file mode 100644 index 00000000..45dbd279 --- /dev/null +++ b/src/systemd/src/systemd/sd-dhcp-option.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcpoptionhfoo +#define foosddhcpoptionhfoo + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <inttypes.h> +#include <sys/types.h> + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp_option sd_dhcp_option; + +int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret); +sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra); +sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index 43d38f5c..be34d43e 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -66,6 +66,7 @@ enum { SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ + SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 8415, sec. 21.23 */ /* option code 35 is unassigned */ @@ -119,6 +120,10 @@ int sd_dhcp6_client_get_information_request( int sd_dhcp6_client_set_request_option( sd_dhcp6_client *client, uint16_t option); +int sd_dhcp6_client_set_prefix_delegation_hint( + sd_dhcp6_client *client, + uint8_t prefixlen, + const struct in6_addr *pd_address); int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation); int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, diff --git a/src/tests/config/meson.build b/src/tests/config/meson.build index f65f90bb..e3ebfa19 100644 --- a/src/tests/config/meson.build +++ b/src/tests/config/meson.build @@ -1,3 +1,5 @@ +test_config_dir = meson.current_source_dir() + test_unit = 'test-config' sources = files( @@ -5,12 +7,11 @@ sources = files( 'test-config.c', ) -test_config_dir = meson.current_source_dir() - exe = executable( test_unit, sources, - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( diff --git a/src/tests/config/nm-test-device.c b/src/tests/config/nm-test-device.c index dd624b44..6e59a4aa 100644 --- a/src/tests/config/nm-test-device.c +++ b/src/tests/config/nm-test-device.c @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/tests/config/nm-test-device.h b/src/tests/config/nm-test-device.h index 586bbe6d..f10c1589 100644 --- a/src/tests/config/nm-test-device.h +++ b/src/tests/config/nm-test-device.h @@ -1,20 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_TEST_DEVICE_H__ diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index a5ef1431..1c28e976 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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 2013 Red Hat, Inc. - * + * Copyright (C) 2013 Red Hat, Inc. */ #include "nm-default.h" @@ -537,7 +523,7 @@ test_config_confdir (void) g_assert_cmpstr (value, ==, "VAL5"); g_free (value); - nm_config_data_log (nm_config_get_data_orig (config), ">>> TEST: ", " ", NULL); + nm_config_data_log (nm_config_get_data_orig (config), ">>> TEST: ", " ", "/test/file/name", NULL); } static void diff --git a/src/tests/meson.build b/src/tests/meson.build index b2bc13ab..ac877e18 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -14,7 +14,8 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( @@ -27,21 +28,22 @@ endforeach test_unit = 'test-systemd' -cflags = [ +c_flags = [ '-DNETWORKMANAGER_COMPILATION_TEST', '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', ] +links = [ + libnm_systemd_core, + libnm_systemd_shared, +] + exe = executable( test_unit, test_unit + '.c', - include_directories: src_inc, - dependencies: libnm_core_dep, - c_args: cflags, - link_with: [ - libnm_systemd_core, - libnm_systemd_shared, - ], + dependencies: daemon_nm_default_dep, + c_args: c_flags, + link_with: links, ) test( diff --git a/src/tests/test-core-with-expect.c b/src/tests/test-core-with-expect.c index 2d111a41..74e1043b 100644 --- a/src/tests/test-core-with-expect.c +++ b/src/tests/test-core-with-expect.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2014 Red Hat, Inc. - * */ #include "nm-default.h" @@ -58,10 +44,13 @@ test_nm_utils_monotonic_timestamp_as_boottime (void) g_assert_cmpint (now_boottime_2, >=, now_boottime); g_assert_cmpint (now_boottime_2 - now_boottime, <=, NM_UTILS_NS_PER_SECOND / 10); + g_assert_cmpint (now, ==, nm_utils_monotonic_timestamp_from_boottime (now_boottime_2, 1)); + for (timestamp_ns_per_tick = 1; timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND; timestamp_ns_per_tick *= 10) { now_boottime_3 = nm_utils_monotonic_timestamp_as_boottime (now / timestamp_ns_per_tick, timestamp_ns_per_tick); g_assert_cmpint (now_boottime_2 / timestamp_ns_per_tick, ==, now_boottime_3); + g_assert_cmpint (now / timestamp_ns_per_tick, ==, nm_utils_monotonic_timestamp_from_boottime (now_boottime_3, timestamp_ns_per_tick)); } } } diff --git a/src/tests/test-core.c b/src/tests/test-core.c index 3eaad104..f55f3dff 100644 --- a/src/tests/test-core.c +++ b/src/tests/test-core.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2014 Red Hat, Inc. - * */ #include "nm-default.h" @@ -2098,10 +2084,12 @@ test_nm_utils_dhcp_client_id_systemd_node_specific (gconstpointer test_data) gs_unref_bytes GBytes *client_id = NULL; const guint8 *cid; guint32 iaid = d->iaid_ifname; + guint32 tmp; - client_id = nm_utils_dhcp_client_id_systemd_node_specific_full (legacy_unstable_byteorder, - (const guint8 *) d->ifname, - strlen (d->ifname), + tmp = nm_utils_create_dhcp_iaid (legacy_unstable_byteorder, + (const guint8 *) d->ifname, + strlen (d->ifname)); + client_id = nm_utils_dhcp_client_id_systemd_node_specific_full (tmp, (const guint8 *) &d->machine_id, sizeof (d->machine_id)); diff --git a/src/tests/test-dcb.c b/src/tests/test-dcb.c index 55206f1d..82d19cee 100644 --- a/src/tests/test-dcb.c +++ b/src/tests/test-dcb.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2013 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c index 5afd8670..cd7dc8d8 100644 --- a/src/tests/test-ip4-config.c +++ b/src/tests/test-ip4-config.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2013 - 2014 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c index bc212ba7..401d1eee 100644 --- a/src/tests/test-ip6-config.c +++ b/src/tests/test-ip6-config.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2013 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/tests/test-systemd.c b/src/tests/test-systemd.c index 090dd691..faed0e56 100644 --- a/src/tests/test-systemd.c +++ b/src/tests/test-systemd.c @@ -1,18 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2016 Red Hat, Inc. */ diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c index f3eb66ef..0c94e2d0 100644 --- a/src/tests/test-utils.c +++ b/src/tests/test-utils.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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" diff --git a/src/tests/test-wired-defname.c b/src/tests/test-wired-defname.c index 27e0590b..4b557d0c 100644 --- a/src/tests/test-wired-defname.c +++ b/src/tests/test-wired-defname.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * 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) 2010 Red Hat, Inc. - * */ #include "nm-default.h" diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c index 598af04e..6a25ddda 100644 --- a/src/vpn/nm-vpn-connection.c +++ b/src/vpn/nm-vpn-connection.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -111,8 +97,7 @@ typedef struct { NMVpnPluginInfo *plugin_info; char *bus_name; - /* Firewall */ - NMFirewallManagerCallId fw_call; + NMFirewallManagerCallId *fw_call; NMNetns *netns; @@ -1195,7 +1180,7 @@ _cleanup_failed_config (NMVpnConnection *self) static void fw_change_zone_cb (NMFirewallManager *firewall_manager, - NMFirewallManagerCallId call_id, + NMFirewallManagerCallId *call_id, GError *error, gpointer user_data) { diff --git a/src/vpn/nm-vpn-connection.h b/src/vpn/nm-vpn-connection.h index 1527b689..43242a8e 100644 --- a/src/vpn/nm-vpn-connection.h +++ b/src/vpn/nm-vpn-connection.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/vpn/nm-vpn-manager.c b/src/vpn/nm-vpn-manager.c index 36043c93..4c94a260 100644 --- a/src/vpn/nm-vpn-manager.c +++ b/src/vpn/nm-vpn-manager.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2012 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ diff --git a/src/vpn/nm-vpn-manager.h b/src/vpn/nm-vpn-manager.h index bcbd19f1..6a78acd2 100644 --- a/src/vpn/nm-vpn-manager.h +++ b/src/vpn/nm-vpn-manager.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ |