2019-09-10 11:19:01 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2019-09-25 13:13:40 +02:00
|
|
|
/*
|
2014-03-03 15:01:36 +01:00
|
|
|
* Copyright (C) 2008 - 2014 Red Hat, Inc.
|
2008-03-26 13:43:01 +00:00
|
|
|
*/
|
|
|
|
|
|
2015-07-17 14:38:54 +02:00
|
|
|
#include "nm-default.h"
|
2016-02-19 14:57:48 +01:00
|
|
|
|
2008-03-26 13:43:01 +00:00
|
|
|
#include "nm-active-connection.h"
|
2016-06-01 12:31:36 +02:00
|
|
|
|
shared: build helper "libnm-libnm-core-{intern|aux}.la" library for libnm-core
"libnm-core" implements common functionality for "NetworkManager" and
"libnm".
Note that clients like "nmcli" cannot access the internal API provided
by "libnm-core". So, if nmcli wants to do something that is also done by
"libnm-core", , "libnm", or "NetworkManager", the code would have to be
duplicated.
Instead, such code can be in "libnm-libnm-core-{intern|aux}.la".
Note that:
0) "libnm-libnm-core-intern.la" is used by libnm-core itsself.
On the other hand, "libnm-libnm-core-aux.la" is not used by
libnm-core, but provides utilities on top of it.
1) they both extend "libnm-core" with utlities that are not public
API of libnm itself. Maybe part of the code should one day become
public API of libnm. On the other hand, this is code for which
we may not want to commit to a stable interface or which we
don't want to provide as part of the API.
2) "libnm-libnm-core-intern.la" is statically linked by "libnm-core"
and thus directly available to "libnm" and "NetworkManager".
On the other hand, "libnm-libnm-core-aux.la" may be used by "libnm"
and "NetworkManager".
Both libraries may be statically linked by libnm clients (like
nmcli).
3) it must only use glib, libnm-glib-aux.la, and the public API
of libnm-core.
This is important: it must not use "libnm-core/nm-core-internal.h"
nor "libnm-core/nm-utils-private.h" so the static library is usable
by nmcli which couldn't access these.
Note that "shared/nm-meta-setting.c" is an entirely different case,
because it behaves differently depending on whether linking against
"libnm-core" or the client programs. As such, this file must be compiled
twice.
(cherry picked from commit af07ed01c04867e281cc3982a7ab0d244d4f8e2e)
2019-04-15 09:26:53 +02:00
|
|
|
#include "nm-libnm-core-intern/nm-common-macros.h"
|
2014-07-05 16:23:30 -04:00
|
|
|
#include "nm-dbus-interface.h"
|
2016-11-21 00:43:52 +01:00
|
|
|
#include "devices/nm-device.h"
|
|
|
|
|
#include "settings/nm-settings-connection.h"
|
2015-07-14 16:53:24 +02:00
|
|
|
#include "nm-simple-connection.h"
|
2014-08-16 01:33:46 +02:00
|
|
|
#include "nm-auth-utils.h"
|
2018-04-10 08:46:01 +02:00
|
|
|
#include "nm-auth-manager.h"
|
2019-12-19 11:30:38 +01:00
|
|
|
#include "nm-libnm-core-intern/nm-auth-subject.h"
|
2018-10-10 17:10:01 +02:00
|
|
|
#include "nm-keep-alive.h"
|
2012-09-17 10:53:41 -05:00
|
|
|
#include "NetworkManagerUtils.h"
|
2015-07-14 16:53:24 +02:00
|
|
|
#include "nm-core-internal.h"
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
#define AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED ((NMAuthManagerCallId *) GINT_TO_POINTER (1))
|
|
|
|
|
|
2016-09-28 15:58:24 +02:00
|
|
|
typedef struct _NMActiveConnectionPrivate {
|
2018-03-29 14:48:42 +02:00
|
|
|
NMDBusTrackObjPath settings_connection;
|
2015-07-14 16:53:24 +02:00
|
|
|
NMConnection *applied_connection;
|
2012-02-03 14:53:09 -06:00
|
|
|
char *specific_object;
|
2012-08-22 09:38:01 -05:00
|
|
|
NMDevice *device;
|
|
|
|
|
|
2016-02-11 08:36:39 +01:00
|
|
|
guint64 version_id;
|
|
|
|
|
|
core: fix NMActiveConnection to properly add/remove pending action "activation"
When a new activation request is received, NetworkManager creates a new
NMActiveConnection to track that request. The device may already be activated,
in which case NetworkManager stops the old activation and starts the new one,
but both exist in parallel for a short period of time. If the old
NMActiveConnection is activating and already has a pending 'activation'
action, when the new NMActiveConnection adds its own 'activating' action,
they will clash. This is fixed by making each NMActiveConnection's activation
pending action uniquely named.
This fixes a g_warning with the following back trace:
#0 0x000000328224edfd in g_logv () from /lib64/libglib-2.0.so.0
#1 0x000000328224efe2 in g_log () from /lib64/libglib-2.0.so.0
#2 0x000000328224f2e6 in g_warn_message () from /lib64/libglib-2.0.so.0
#3 0x0000000000440aee in nm_device_add_pending_action (device=0x14002e0, action=0x50704a "activation") at devices/nm-device.c:7172
#4 0x000000000047525c in nm_active_connection_set_device (self=0x141b3c0, device=0x14002e0) at nm-active-connection.c:364
#5 0x0000000000475ec1 in set_property (object=0x141b3c0, prop_id=11, value=0x7fff7ff36c20, pspec=0x1405f70) at nm-active-connection.c:647
#6 0x0000003282615d3e in g_object_newv () from /lib64/libgobject-2.0.so.0
#7 0x00000032826162e6 in g_object_new_valist () from /lib64/libgobject-2.0.so.0
#8 0x0000003282616654 in g_object_new () from /lib64/libgobject-2.0.so.0
#9 0x0000000000474193 in nm_act_request_new (connection=0x13bb0e0, specific_object=0x0, subject=0x1447740, device=0x14002e0) at nm-activation-request.c:376
#10 0x000000000048e477 in _new_active_connection (self=0x13e8060, connection=0x13bb0e0, specific_object=0x0, device=0x14002e0, subject=0x1447740, error=0x7fff7ff36f90) at nm-manager.c:2947
#11 0x000000000048ed77 in impl_manager_activate_connection (self=0x13e8060, connection_path=0x134d590 "/org/freedesktop/NetworkManager/Settings/9", device_path=0x134d550 "/org/freedesktop/NetworkManager/Devices/1",
specific_object_path=0x0, context=0x143a9b0) at nm-manager.c:3206
#12 0x00000000004876c8 in dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (closure=0x7fff7ff37220, return_value=0x0, n_param_values=5, param_values=0x1448830, invocation_hint=0x0,
marshal_data=0x48e9dd <impl_manager_activate_connection>) at nm-manager-glue.h:189
#13 0x0000003284a0d6a9 in object_registration_message () from /lib64/libdbus-glib-1.so.2
#14 0x000000348ea1ce66 in _dbus_object_tree_dispatch_and_unlock () from /lib64/libdbus-1.so.3
#15 0x000000348ea0fa31 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#16 0x0000003284a0acc5 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#17 0x0000003282247df6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#18 0x0000003282248148 in g_main_context_iterate.isra.22 () from /lib64/libglib-2.0.so.0
#19 0x000000328224854a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#20 0x000000000042c6c0 in main (argc=1, argv=0x7fff7ff379b8) at main.c:629
Signed-off-by: Thomas Haller <thaller@redhat.com>
2013-12-16 15:02:38 +01:00
|
|
|
char *pending_activation_id;
|
|
|
|
|
|
2017-09-25 19:06:02 +02:00
|
|
|
NMActivationStateFlags state_flags;
|
|
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
NMActiveConnectionState state;
|
2017-03-01 17:26:45 +01:00
|
|
|
bool is_default:1;
|
|
|
|
|
bool is_default6:1;
|
|
|
|
|
bool state_set:1;
|
|
|
|
|
bool vpn:1;
|
|
|
|
|
bool master_ready:1;
|
2012-08-22 09:38:01 -05:00
|
|
|
|
2017-03-07 11:04:36 +01:00
|
|
|
NMActivationType activation_type:3;
|
2018-04-19 13:24:11 +02:00
|
|
|
|
|
|
|
|
/* capture the original reason why the connection was activated.
|
|
|
|
|
* For example with NM_ACTIVATION_REASON_ASSUME, the connection
|
|
|
|
|
* will later change to become fully managed. But the original
|
|
|
|
|
* reason never changes. */
|
|
|
|
|
NMActivationReason activation_reason:4;
|
2017-03-07 11:04:36 +01:00
|
|
|
|
2013-07-29 13:11:47 -05:00
|
|
|
NMAuthSubject *subject;
|
2013-08-27 12:16:57 -05:00
|
|
|
NMActiveConnection *master;
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2016-03-23 14:47:02 +01:00
|
|
|
NMActiveConnection *parent;
|
|
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
struct {
|
|
|
|
|
NMAuthManagerCallId *call_id_network_control;
|
|
|
|
|
NMAuthManagerCallId *call_id_wifi_shared_permission;
|
|
|
|
|
|
|
|
|
|
NMActiveConnectionAuthResultFunc result_func;
|
2018-04-17 14:59:27 +02:00
|
|
|
gpointer user_data;
|
2018-04-10 08:46:01 +02:00
|
|
|
} auth;
|
|
|
|
|
|
2018-10-10 17:10:01 +02:00
|
|
|
NMKeepAlive *keep_alive;
|
2012-02-03 14:53:09 -06:00
|
|
|
} NMActiveConnectionPrivate;
|
|
|
|
|
|
2016-04-13 13:33:04 +02:00
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection,
|
2012-02-03 14:53:09 -06:00
|
|
|
PROP_CONNECTION,
|
2014-03-03 15:01:36 +01:00
|
|
|
PROP_ID,
|
2012-02-03 14:53:09 -06:00
|
|
|
PROP_UUID,
|
2014-03-03 15:01:36 +01:00
|
|
|
PROP_TYPE,
|
2012-02-03 14:53:09 -06:00
|
|
|
PROP_SPECIFIC_OBJECT,
|
|
|
|
|
PROP_DEVICES,
|
|
|
|
|
PROP_STATE,
|
2017-09-25 19:06:02 +02:00
|
|
|
PROP_STATE_FLAGS,
|
2012-02-03 14:53:09 -06:00
|
|
|
PROP_DEFAULT,
|
2013-12-18 08:46:43 -05:00
|
|
|
PROP_IP4_CONFIG,
|
|
|
|
|
PROP_DHCP4_CONFIG,
|
2012-02-03 14:53:09 -06:00
|
|
|
PROP_DEFAULT6,
|
2013-12-18 08:46:43 -05:00
|
|
|
PROP_IP6_CONFIG,
|
|
|
|
|
PROP_DHCP6_CONFIG,
|
2012-02-03 14:53:09 -06:00
|
|
|
PROP_VPN,
|
|
|
|
|
PROP_MASTER,
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
PROP_INT_SETTINGS_CONNECTION,
|
2016-09-07 17:47:26 +02:00
|
|
|
PROP_INT_APPLIED_CONNECTION,
|
2012-08-22 09:38:01 -05:00
|
|
|
PROP_INT_DEVICE,
|
2013-07-29 13:11:47 -05:00
|
|
|
PROP_INT_SUBJECT,
|
2012-08-22 09:38:01 -05:00
|
|
|
PROP_INT_MASTER,
|
2013-09-27 17:13:43 -05:00
|
|
|
PROP_INT_MASTER_READY,
|
2017-03-07 11:04:36 +01:00
|
|
|
PROP_INT_ACTIVATION_TYPE,
|
2018-03-28 17:18:04 +02:00
|
|
|
PROP_INT_ACTIVATION_REASON,
|
2016-04-13 13:33:04 +02:00
|
|
|
);
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2014-10-23 17:04:49 -05:00
|
|
|
enum {
|
|
|
|
|
DEVICE_CHANGED,
|
2015-06-03 09:15:24 +02:00
|
|
|
DEVICE_METERED_CHANGED,
|
2016-03-23 14:47:02 +01:00
|
|
|
PARENT_ACTIVE,
|
2017-03-05 15:30:24 +01:00
|
|
|
STATE_CHANGED,
|
2014-10-23 17:04:49 -05:00
|
|
|
LAST_SIGNAL
|
|
|
|
|
};
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
G_DEFINE_ABSTRACT_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_DBUS_OBJECT)
|
2016-09-28 15:58:24 +02:00
|
|
|
|
|
|
|
|
#define NM_ACTIVE_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMActiveConnection, NM_IS_ACTIVE_CONNECTION)
|
|
|
|
|
|
2017-03-08 15:58:59 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
static const NMDBusInterfaceInfoExtended interface_info_active_connection;
|
|
|
|
|
static const GDBusSignalInfo signal_info_state_changed;
|
|
|
|
|
|
2013-09-27 17:13:43 -05:00
|
|
|
static void check_master_ready (NMActiveConnection *self);
|
2014-01-02 14:59:46 -05:00
|
|
|
static void _device_cleanup (NMActiveConnection *self);
|
2018-04-05 20:15:50 +02:00
|
|
|
static void _settings_connection_flags_changed (NMSettingsConnection *settings_connection,
|
|
|
|
|
NMActiveConnection *self);
|
2017-06-16 14:34:37 +02:00
|
|
|
static void _set_activation_type_managed (NMActiveConnection *self);
|
2013-09-27 17:13:43 -05:00
|
|
|
|
2018-04-18 07:43:03 +02:00
|
|
|
static void auth_complete (NMActiveConnection *self, gboolean result, const char *message);
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2015-08-20 00:07:14 +02:00
|
|
|
#define _NMLOG_DOMAIN LOGD_DEVICE
|
|
|
|
|
#define _NMLOG_PREFIX_NAME "active-connection"
|
|
|
|
|
#define _NMLOG(level, ...) \
|
2015-08-11 13:18:57 +02:00
|
|
|
G_STMT_START { \
|
2015-12-07 20:42:47 +01:00
|
|
|
char _sbuf[64]; \
|
2017-09-26 12:55:34 +02:00
|
|
|
NMActiveConnectionPrivate *_priv = self ? NM_ACTIVE_CONNECTION_GET_PRIVATE (self) : NULL; \
|
2015-08-11 13:18:57 +02:00
|
|
|
\
|
2017-03-02 21:17:22 +01:00
|
|
|
nm_log ((level), _NMLOG_DOMAIN, \
|
2017-09-26 12:55:34 +02:00
|
|
|
(_priv && _priv->device) ? nm_device_get_iface (_priv->device) : NULL, \
|
|
|
|
|
(_priv && _priv->applied_connection) ? nm_connection_get_uuid (_priv->applied_connection) : NULL, \
|
2015-12-07 20:42:47 +01:00
|
|
|
"%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
|
|
|
|
|
_NMLOG_PREFIX_NAME, \
|
|
|
|
|
self ? nm_sprintf_buf (_sbuf, "[%p]", self) : "" \
|
|
|
|
|
_NM_UTILS_MACRO_REST (__VA_ARGS__)); \
|
2015-08-11 13:18:57 +02:00
|
|
|
} G_STMT_END
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-08-11 13:18:57 +02:00
|
|
|
|
2020-02-13 14:55:26 +01:00
|
|
|
static
|
|
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE (_state_to_string, NMActiveConnectionState,
|
2016-02-01 14:09:56 +01:00
|
|
|
NM_UTILS_LOOKUP_DEFAULT (NULL),
|
2016-01-24 14:28:31 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_UNKNOWN, "unknown"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATING, "activating"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATED, "activated"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, "deactivating"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, "deactivated"),
|
2015-12-07 20:42:47 +01:00
|
|
|
);
|
2019-01-10 09:17:28 +01:00
|
|
|
|
|
|
|
|
#define state_to_string_a(state) NM_UTILS_LOOKUP_STR_A (_state_to_string, state)
|
2015-12-07 20:42:47 +01:00
|
|
|
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
/* the maximum required buffer size for _state_flags_to_string(). */
|
|
|
|
|
#define _NM_ACTIVATION_STATE_FLAG_TO_STRING_BUFSIZE (255)
|
|
|
|
|
|
2020-02-13 14:55:26 +01:00
|
|
|
static
|
|
|
|
|
NM_UTILS_FLAGS2STR_DEFINE (_state_flags_to_string, NMActivationStateFlags,
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_NONE, "none"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_IS_MASTER, "is-master"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_IS_SLAVE, "is-slave"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_LAYER2_READY, "layer2-ready"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_IP4_READY, "ip4-ready"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_IP6_READY, "ip6-ready"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES, "master-has-slaves"),
|
|
|
|
|
NM_UTILS_FLAGS2STR (NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, "lifetime-bound-to-profile-visibility"),
|
2017-09-25 19:06:02 +02:00
|
|
|
);
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2013-10-25 19:33:01 -05:00
|
|
|
|
2016-04-13 16:26:23 +02:00
|
|
|
static void
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
_settings_connection_updated (NMSettingsConnection *sett_conn,
|
settings: rework tracking settings connections and settings plugins
Completely rework how settings plugin handle connections and how
NMSettings tracks the list of connections.
Previously, settings plugins would return objects of (a subtype of) type
NMSettingsConnection. The NMSettingsConnection was tightly coupled with
the settings plugin. That has a lot of downsides.
Change that. When changing this basic relation how settings connections
are tracked, everything falls appart. That's why this is a huge change.
Also, since I have to largely rewrite the settings plugins, I also
added support for multiple keyfile directories, handle in-memory
connections only by keyfile plugin and (partly) use copy-on-write NMConnection
instances. I don't want to spend effort rewriting large parts while
preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh,
I don't want to let it handle in-memory connections because that's not right
long-term.
--
If the settings plugins themself create subtypes of NMSettingsConnection
instances, then a lot of knowledge about tracking connections moves
to the plugins.
Just try to follow the code what happend during nm_settings_add_connection().
Note how the logic is spread out:
- nm_settings_add_connection() calls plugin's add_connection()
- add_connection() creates a NMSettingsConnection subtype
- the plugin has to know that it's called during add-connection and
not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal
- NMSettings calls claim_connection() which hocks up the new
NMSettingsConnection instance and configures the instance
(like calling nm_settings_connection_added()).
This summary does not sound like a lot, but try to follow that code. The logic
is all over the place.
Instead, settings plugins should have a very simple API for adding, modifying,
deleting, loading and reloading connections. All the plugin does is to return a
NMSettingsStorage handle. The storage instance is a handle to identify a profile
in storage (e.g. a particular file). The settings plugin is free to subtype
NMSettingsStorage, but it's not necessary.
There are no more events raised, and the settings plugin implements the small
API in a straightforward manner.
NMSettings now drives all of this. Even NMSettingsConnection has now
very little concern about how it's tracked and delegates only to NMSettings.
This should make settings plugins simpler. Currently settings plugins
are so cumbersome to implement, that we avoid having them. It should not be
like that and it should be easy, beneficial and lightweight to create a new
settings plugin.
Note also how the settings plugins no longer care about duplicate UUIDs.
Duplicated UUIDs are a fact of life and NMSettings must handle them. No
need to overly concern settings plugins with that.
--
NMSettingsConnection is exposed directly on D-Bus (being a subtype of
NMDBusObject) but it was also a GObject type provided by the settings
plugin. Hence, it was not possible to migrate a profile from one plugin to
another.
However that would be useful when one profile does not support a
connection type (like ifcfg-rh not supporting VPN). Currently such
migration is not implemented except for migrating them to/from keyfile's
run directory. The problem is that migrating profiles in general is
complicated but in some cases it is important to do.
For example checkpoint rollback should recreate the profile in the right
settings plugin, not just add it to persistent storage. This is not yet
properly implemented.
--
Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved)
profiles, while ifupdown plugin cannot handle them. That meant duplication of code
and a ifupdown profile could not be modified or made unsaved.
This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711).
Also, NMSettings is aware of such profiles and treats them specially.
In particular, NMSettings drives the migration between persistent and non-persistent
storage.
Note that a settings plugins may create truly generated, in-memory profiles.
The settings plugin is free to generate and persist the profiles in any way it
wishes. But the concept of "unsaved" profiles is now something explicitly handled
by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system
too, to the /run directory. This is great for two reasons: first of all, all
profiles from keyfile storage in fact have a backing file -- even the
unsaved ones. It also means you can create "unsaved" profiles in /run
and load them with `nmcli connection load`, meaning there is a file
based API for creating unsaved profiles.
The other advantage is that these profiles now survive restarting
NetworkManager. It's paramount that restarting the daemon is as
non-disruptive as possible. Persisting unsaved files to /run improves
here significantly.
--
In the past, NMSettingsConnection also implemented NMConnection interface.
That was already changed a while ago and instead users call now
nm_settings_connection_get_connection() to delegate to a
NMSimpleConnection. What however still happened was that the NMConnection
instance gets never swapped but instead the instance was modified with
nm_connection_replace_settings_from_connection(), clear-secrets, etc.
Change that and treat the NMConnection instance immutable. Instead of modifying
it, reference/clone a new instance. This changes that previously when somebody
wanted to keep a reference to an NMConnection, then the profile would be cloned.
Now, it is supposed to be safe to reference the instance directly and everybody
must ensure not to modify the instance. nmtst_connection_assert_unchanging()
should help with that.
The point is that the settings plugins may keep references to the
NMConnection instance, and so does the NMSettingsConnection. We want
to avoid cloning the instances as long as they are the same.
Likewise, the device's applied connection can now also be referenced
instead of cloning it. This is not yet done, and possibly there are
further improvements possible.
--
Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545,
bgo #772414).
It was always the case that multiple files could provide the same UUID
(both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in
read-only storage in /usr/lib gets modified, then it gets actually stored in
/etc (or /run, if the profile is unsaved).
--
While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable.
--
https://bugzilla.gnome.org/show_bug.cgi?id=772414
https://bugzilla.gnome.org/show_bug.cgi?id=744711
https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
|
|
|
guint update_reason_u,
|
2016-04-13 16:26:23 +02:00
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = user_data;
|
|
|
|
|
|
|
|
|
|
/* we don't know which properties actually changed. Just to be sure,
|
|
|
|
|
* notify about all possible properties. After all, an update of a
|
|
|
|
|
* connection is a rare event. */
|
|
|
|
|
|
|
|
|
|
_notify (self, PROP_ID);
|
|
|
|
|
|
|
|
|
|
/* it's a bit odd to update the TYPE of an active connection. But the alternative
|
|
|
|
|
* is unexpected too. */
|
|
|
|
|
_notify (self, PROP_TYPE);
|
|
|
|
|
|
|
|
|
|
/* currently, the UUID and the exported CONNECTION path cannot change. Later, we might
|
|
|
|
|
* want to support a re-link operation, which associates an active-connection with a different
|
|
|
|
|
* settings-connection. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
_set_settings_connection (NMActiveConnection *self, NMSettingsConnection *sett_conn)
|
2016-04-13 16:26:23 +02:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
if (priv->settings_connection.obj == sett_conn)
|
2016-04-13 16:26:23 +02:00
|
|
|
return;
|
2018-03-29 14:48:42 +02:00
|
|
|
|
|
|
|
|
if (priv->settings_connection.obj) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_updated, self);
|
2018-04-05 20:15:50 +02:00
|
|
|
g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_flags_changed, self);
|
2016-04-13 16:26:23 +02:00
|
|
|
}
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
if (sett_conn) {
|
|
|
|
|
g_signal_connect (sett_conn, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, (GCallback) _settings_connection_updated, self);
|
2017-03-08 15:58:59 +01:00
|
|
|
if (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL)
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_signal_connect (sett_conn, NM_SETTINGS_CONNECTION_FLAGS_CHANGED, (GCallback) _settings_connection_flags_changed, self);
|
2016-04-13 16:26:23 +02:00
|
|
|
}
|
2018-03-29 14:48:42 +02:00
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
nm_dbus_track_obj_path_set (&priv->settings_connection, sett_conn, TRUE);
|
2016-04-13 16:26:23 +02:00
|
|
|
}
|
|
|
|
|
|
2012-02-26 17:38:41 -06:00
|
|
|
NMActiveConnectionState
|
|
|
|
|
nm_active_connection_get_state (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->state;
|
|
|
|
|
}
|
|
|
|
|
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
static void
|
|
|
|
|
emit_state_changed (NMActiveConnection *self, guint state, guint reason)
|
|
|
|
|
{
|
|
|
|
|
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
|
|
|
|
|
&interface_info_active_connection,
|
|
|
|
|
&signal_info_state_changed,
|
|
|
|
|
"(uu)",
|
|
|
|
|
(guint32) state,
|
|
|
|
|
(guint32) reason);
|
|
|
|
|
g_signal_emit (self, signals[STATE_CHANGED], 0, state, reason);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
void
|
|
|
|
|
nm_active_connection_set_state (NMActiveConnection *self,
|
2017-03-05 15:30:24 +01:00
|
|
|
NMActiveConnectionState new_state,
|
|
|
|
|
NMActiveConnectionStateReason reason)
|
2008-03-26 13:43:01 +00:00
|
|
|
{
|
2012-02-03 14:53:09 -06:00
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2012-08-22 17:34:42 -05:00
|
|
|
NMActiveConnectionState old_state;
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2018-04-17 20:58:20 +02:00
|
|
|
/* DEACTIVATED is a terminal state */
|
|
|
|
|
g_return_if_fail ( priv->state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
|
|
|
|
|
|| new_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
|
|
|
|
|
|
2012-08-22 17:34:42 -05:00
|
|
|
if (priv->state == new_state)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-12-07 20:42:47 +01:00
|
|
|
_LOGD ("set state %s (was %s)",
|
2019-01-10 09:17:28 +01:00
|
|
|
state_to_string_a (new_state),
|
|
|
|
|
state_to_string_a (priv->state));
|
2015-12-07 20:42:47 +01:00
|
|
|
|
2018-11-20 11:28:33 +01:00
|
|
|
if (new_state > NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
|
|
|
|
/* once we are about to deactivate, we don't need the keep-alive instance
|
|
|
|
|
* anymore. Freeze/disarm it. */
|
|
|
|
|
nm_keep_alive_disarm (priv->keep_alive);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 16:06:21 +01:00
|
|
|
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|
|
|
|
|
&& priv->activation_type == NM_ACTIVATION_TYPE_ASSUME) {
|
|
|
|
|
/* assuming connections mean to gracefully take over an externally
|
|
|
|
|
* configured device. Once activation is complete, an assumed
|
|
|
|
|
* activation *is* the same as a full activation. */
|
2017-06-16 14:34:37 +02:00
|
|
|
_set_activation_type_managed (self);
|
2017-03-08 16:06:21 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-22 17:34:42 -05:00
|
|
|
old_state = priv->state;
|
|
|
|
|
priv->state = new_state;
|
2014-10-16 18:00:54 -04:00
|
|
|
priv->state_set = TRUE;
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
emit_state_changed (self, new_state, reason);
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_STATE);
|
2012-08-22 17:34:42 -05:00
|
|
|
|
2013-09-27 17:13:43 -05:00
|
|
|
check_master_ready (self);
|
|
|
|
|
|
2012-08-22 17:34:42 -05:00
|
|
|
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|
|
|
|
|
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
2018-03-29 14:48:42 +02:00
|
|
|
nm_settings_connection_update_timestamp (priv->settings_connection.obj,
|
2019-05-03 14:33:23 +02:00
|
|
|
(guint64) time (NULL));
|
2012-02-03 14:53:09 -06:00
|
|
|
}
|
2013-02-11 11:15:45 -06:00
|
|
|
|
core: ensure 'activation' pending action encompasses full activation process
The NMActiveConnection class tracks the full activation request, and internal
activation requests go through the same process as external ones, including
some authentication. Sometimes that means activation is scheduled, control
returns to the mainloop, and then the activation proceeds from an idle
handler.
Unfortunately, that means that adding a pending "activation" action from
nm-device.c doesn't always work, since there is a short window between when
the activation is started in nm-manager.c (in nm_manager_activate_connection())
and when the device actually changes state. Inside that window, the pending
actions may drop to zero, and startup will be declared complete before the
device actually starts activating.
Instead, ensure that the pending action is added when the internal activation
is actually started (eg, when NMActiveConnection receives the NMDevice object).
2013-12-10 22:11:09 -06:00
|
|
|
if (priv->device) {
|
|
|
|
|
if ( old_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|
core: fix NMActiveConnection to properly add/remove pending action "activation"
When a new activation request is received, NetworkManager creates a new
NMActiveConnection to track that request. The device may already be activated,
in which case NetworkManager stops the old activation and starts the new one,
but both exist in parallel for a short period of time. If the old
NMActiveConnection is activating and already has a pending 'activation'
action, when the new NMActiveConnection adds its own 'activating' action,
they will clash. This is fixed by making each NMActiveConnection's activation
pending action uniquely named.
This fixes a g_warning with the following back trace:
#0 0x000000328224edfd in g_logv () from /lib64/libglib-2.0.so.0
#1 0x000000328224efe2 in g_log () from /lib64/libglib-2.0.so.0
#2 0x000000328224f2e6 in g_warn_message () from /lib64/libglib-2.0.so.0
#3 0x0000000000440aee in nm_device_add_pending_action (device=0x14002e0, action=0x50704a "activation") at devices/nm-device.c:7172
#4 0x000000000047525c in nm_active_connection_set_device (self=0x141b3c0, device=0x14002e0) at nm-active-connection.c:364
#5 0x0000000000475ec1 in set_property (object=0x141b3c0, prop_id=11, value=0x7fff7ff36c20, pspec=0x1405f70) at nm-active-connection.c:647
#6 0x0000003282615d3e in g_object_newv () from /lib64/libgobject-2.0.so.0
#7 0x00000032826162e6 in g_object_new_valist () from /lib64/libgobject-2.0.so.0
#8 0x0000003282616654 in g_object_new () from /lib64/libgobject-2.0.so.0
#9 0x0000000000474193 in nm_act_request_new (connection=0x13bb0e0, specific_object=0x0, subject=0x1447740, device=0x14002e0) at nm-activation-request.c:376
#10 0x000000000048e477 in _new_active_connection (self=0x13e8060, connection=0x13bb0e0, specific_object=0x0, device=0x14002e0, subject=0x1447740, error=0x7fff7ff36f90) at nm-manager.c:2947
#11 0x000000000048ed77 in impl_manager_activate_connection (self=0x13e8060, connection_path=0x134d590 "/org/freedesktop/NetworkManager/Settings/9", device_path=0x134d550 "/org/freedesktop/NetworkManager/Devices/1",
specific_object_path=0x0, context=0x143a9b0) at nm-manager.c:3206
#12 0x00000000004876c8 in dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (closure=0x7fff7ff37220, return_value=0x0, n_param_values=5, param_values=0x1448830, invocation_hint=0x0,
marshal_data=0x48e9dd <impl_manager_activate_connection>) at nm-manager-glue.h:189
#13 0x0000003284a0d6a9 in object_registration_message () from /lib64/libdbus-glib-1.so.2
#14 0x000000348ea1ce66 in _dbus_object_tree_dispatch_and_unlock () from /lib64/libdbus-1.so.3
#15 0x000000348ea0fa31 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#16 0x0000003284a0acc5 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#17 0x0000003282247df6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#18 0x0000003282248148 in g_main_context_iterate.isra.22 () from /lib64/libglib-2.0.so.0
#19 0x000000328224854a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#20 0x000000000042c6c0 in main (argc=1, argv=0x7fff7ff379b8) at main.c:629
Signed-off-by: Thomas Haller <thaller@redhat.com>
2013-12-16 15:02:38 +01:00
|
|
|
&& new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
|
|
|
|
|
priv->pending_activation_id)
|
|
|
|
|
{
|
2014-04-28 11:18:05 +02:00
|
|
|
nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&priv->pending_activation_id);
|
core: fix NMActiveConnection to properly add/remove pending action "activation"
When a new activation request is received, NetworkManager creates a new
NMActiveConnection to track that request. The device may already be activated,
in which case NetworkManager stops the old activation and starts the new one,
but both exist in parallel for a short period of time. If the old
NMActiveConnection is activating and already has a pending 'activation'
action, when the new NMActiveConnection adds its own 'activating' action,
they will clash. This is fixed by making each NMActiveConnection's activation
pending action uniquely named.
This fixes a g_warning with the following back trace:
#0 0x000000328224edfd in g_logv () from /lib64/libglib-2.0.so.0
#1 0x000000328224efe2 in g_log () from /lib64/libglib-2.0.so.0
#2 0x000000328224f2e6 in g_warn_message () from /lib64/libglib-2.0.so.0
#3 0x0000000000440aee in nm_device_add_pending_action (device=0x14002e0, action=0x50704a "activation") at devices/nm-device.c:7172
#4 0x000000000047525c in nm_active_connection_set_device (self=0x141b3c0, device=0x14002e0) at nm-active-connection.c:364
#5 0x0000000000475ec1 in set_property (object=0x141b3c0, prop_id=11, value=0x7fff7ff36c20, pspec=0x1405f70) at nm-active-connection.c:647
#6 0x0000003282615d3e in g_object_newv () from /lib64/libgobject-2.0.so.0
#7 0x00000032826162e6 in g_object_new_valist () from /lib64/libgobject-2.0.so.0
#8 0x0000003282616654 in g_object_new () from /lib64/libgobject-2.0.so.0
#9 0x0000000000474193 in nm_act_request_new (connection=0x13bb0e0, specific_object=0x0, subject=0x1447740, device=0x14002e0) at nm-activation-request.c:376
#10 0x000000000048e477 in _new_active_connection (self=0x13e8060, connection=0x13bb0e0, specific_object=0x0, device=0x14002e0, subject=0x1447740, error=0x7fff7ff36f90) at nm-manager.c:2947
#11 0x000000000048ed77 in impl_manager_activate_connection (self=0x13e8060, connection_path=0x134d590 "/org/freedesktop/NetworkManager/Settings/9", device_path=0x134d550 "/org/freedesktop/NetworkManager/Devices/1",
specific_object_path=0x0, context=0x143a9b0) at nm-manager.c:3206
#12 0x00000000004876c8 in dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (closure=0x7fff7ff37220, return_value=0x0, n_param_values=5, param_values=0x1448830, invocation_hint=0x0,
marshal_data=0x48e9dd <impl_manager_activate_connection>) at nm-manager-glue.h:189
#13 0x0000003284a0d6a9 in object_registration_message () from /lib64/libdbus-glib-1.so.2
#14 0x000000348ea1ce66 in _dbus_object_tree_dispatch_and_unlock () from /lib64/libdbus-1.so.3
#15 0x000000348ea0fa31 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#16 0x0000003284a0acc5 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#17 0x0000003282247df6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#18 0x0000003282248148 in g_main_context_iterate.isra.22 () from /lib64/libglib-2.0.so.0
#19 0x000000328224854a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#20 0x000000000042c6c0 in main (argc=1, argv=0x7fff7ff379b8) at main.c:629
Signed-off-by: Thomas Haller <thaller@redhat.com>
2013-12-16 15:02:38 +01:00
|
|
|
}
|
core: ensure 'activation' pending action encompasses full activation process
The NMActiveConnection class tracks the full activation request, and internal
activation requests go through the same process as external ones, including
some authentication. Sometimes that means activation is scheduled, control
returns to the mainloop, and then the activation proceeds from an idle
handler.
Unfortunately, that means that adding a pending "activation" action from
nm-device.c doesn't always work, since there is a short window between when
the activation is started in nm-manager.c (in nm_manager_activate_connection())
and when the device actually changes state. Inside that window, the pending
actions may drop to zero, and startup will be declared complete before the
device actually starts activating.
Instead, ensure that the pending action is added when the internal activation
is actually started (eg, when NMActiveConnection receives the NMDevice object).
2013-12-10 22:11:09 -06:00
|
|
|
}
|
|
|
|
|
|
2013-12-18 08:46:43 -05:00
|
|
|
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|
|
|
|
|
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_IP4_CONFIG);
|
|
|
|
|
_notify (self, PROP_DHCP4_CONFIG);
|
|
|
|
|
_notify (self, PROP_IP6_CONFIG);
|
|
|
|
|
_notify (self, PROP_DHCP6_CONFIG);
|
2013-12-18 08:46:43 -05:00
|
|
|
}
|
|
|
|
|
|
2013-02-11 11:15:45 -06:00
|
|
|
if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
|
2018-04-18 07:43:03 +02:00
|
|
|
_nm_unused gs_unref_object NMActiveConnection *self_keep_alive = g_object_ref (self);
|
|
|
|
|
|
|
|
|
|
auth_complete (self, FALSE, "Authorization request cancelled");
|
|
|
|
|
|
2013-12-03 16:49:21 +01:00
|
|
|
/* Device is no longer relevant when deactivated. So remove it and
|
|
|
|
|
* emit property change notification so clients re-read the value,
|
|
|
|
|
* which will be NULL due to conditions in get_property().
|
2013-09-27 14:40:18 -05:00
|
|
|
*/
|
2014-01-02 14:59:46 -05:00
|
|
|
_device_cleanup (self);
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_DEVICES);
|
2013-02-11 11:15:45 -06:00
|
|
|
}
|
2012-02-03 14:53:09 -06:00
|
|
|
}
|
|
|
|
|
|
2018-02-05 16:36:24 +01:00
|
|
|
void
|
|
|
|
|
nm_active_connection_set_state_fail (NMActiveConnection *self,
|
|
|
|
|
NMActiveConnectionStateReason reason,
|
|
|
|
|
const char *error_desc)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionState s;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
|
|
|
|
|
|
|
|
|
if (error_desc) {
|
|
|
|
|
_LOGD ("Failed to activate '%s': %s",
|
|
|
|
|
nm_active_connection_get_settings_connection_id (self),
|
|
|
|
|
error_desc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = nm_active_connection_get_state (self);
|
|
|
|
|
if ( s >= NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
|
|
|
|
&& s < NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
|
|
|
|
|
nm_active_connection_set_state (self,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_DEACTIVATING,
|
|
|
|
|
reason);
|
|
|
|
|
s = nm_active_connection_get_state (self);
|
|
|
|
|
}
|
|
|
|
|
if (s < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
|
|
|
|
|
nm_active_connection_set_state (self,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
|
|
|
|
|
reason);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-25 19:06:02 +02:00
|
|
|
NMActivationStateFlags
|
|
|
|
|
nm_active_connection_get_state_flags (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->state_flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_active_connection_set_state_flags_full (NMActiveConnection *self,
|
|
|
|
|
NMActivationStateFlags state_flags,
|
|
|
|
|
NMActivationStateFlags mask)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
NMActivationStateFlags f;
|
|
|
|
|
|
|
|
|
|
f = (priv->state_flags & ~mask) | (state_flags & mask);
|
|
|
|
|
if (f != priv->state_flags) {
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
char buf1[_NM_ACTIVATION_STATE_FLAG_TO_STRING_BUFSIZE];
|
|
|
|
|
char buf2[_NM_ACTIVATION_STATE_FLAG_TO_STRING_BUFSIZE];
|
2017-09-25 19:06:02 +02:00
|
|
|
|
|
|
|
|
_LOGD ("set state-flags %s (was %s)",
|
|
|
|
|
_state_flags_to_string (f, buf1, sizeof (buf1)),
|
|
|
|
|
_state_flags_to_string (priv->state_flags, buf2, sizeof (buf2)));
|
|
|
|
|
priv->state_flags = f;
|
|
|
|
|
_notify (self, PROP_STATE_FLAGS);
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
|
|
|
|
|
nm_keep_alive_set_settings_connection_watch_visible (priv->keep_alive,
|
|
|
|
|
NM_FLAGS_HAS (priv->state_flags,
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY)
|
|
|
|
|
? priv->settings_connection.obj
|
|
|
|
|
: NULL);
|
2017-09-25 19:06:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-21 12:33:13 +02:00
|
|
|
const char *
|
2015-07-14 16:53:24 +02:00
|
|
|
nm_active_connection_get_settings_connection_id (NMActiveConnection *self)
|
2012-09-21 12:33:13 +02:00
|
|
|
{
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NMSettingsConnection *sett_conn;
|
2015-07-14 16:53:24 +02:00
|
|
|
|
2012-09-21 12:33:13 +02:00
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
|
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
sett_conn = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj;
|
|
|
|
|
return sett_conn
|
|
|
|
|
? nm_settings_connection_get_id (sett_conn)
|
2015-07-14 16:53:24 +02:00
|
|
|
: NULL;
|
2012-09-21 12:33:13 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
NMSettingsConnection *
|
|
|
|
|
_nm_active_connection_get_settings_connection (NMActiveConnection *self)
|
2014-03-05 21:11:54 +01:00
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
|
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj;
|
2014-03-05 21:11:54 +01:00
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
NMSettingsConnection *
|
|
|
|
|
nm_active_connection_get_settings_connection (NMActiveConnection *self)
|
2012-02-03 14:53:09 -06:00
|
|
|
{
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NMSettingsConnection *sett_conn;
|
2015-07-14 16:53:24 +02:00
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
sett_conn = _nm_active_connection_get_settings_connection (self);
|
2015-07-14 16:53:24 +02:00
|
|
|
|
|
|
|
|
/* Only call this function on an active-connection that is already
|
|
|
|
|
* fully set-up (i.e. that has a settings-connection). Other uses
|
|
|
|
|
* indicate a bug. */
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_return_val_if_fail (sett_conn, NULL);
|
|
|
|
|
return sett_conn;
|
2012-02-03 14:53:09 -06:00
|
|
|
}
|
2008-03-26 13:43:01 +00:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
NMConnection *
|
|
|
|
|
nm_active_connection_get_applied_connection (NMActiveConnection *self)
|
2014-10-23 13:56:52 -04:00
|
|
|
{
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NMConnection *connection;
|
2015-07-14 16:53:24 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
2014-10-23 13:56:52 -04:00
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
connection = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->applied_connection;
|
2014-10-23 13:56:52 -04:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
/* Only call this function on an active-connection that is already
|
|
|
|
|
* fully set-up (i.e. that has a settings-connection). Other uses
|
|
|
|
|
* indicate a bug. */
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_return_val_if_fail (connection, NULL);
|
|
|
|
|
return connection;
|
2014-10-23 13:56:52 -04:00
|
|
|
}
|
|
|
|
|
|
2017-09-26 13:10:01 +02:00
|
|
|
static void
|
|
|
|
|
_set_applied_connection_take (NMActiveConnection *self,
|
|
|
|
|
NMConnection *applied_connection)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2017-09-26 13:45:25 +02:00
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMActivationStateFlags flags_val = 0;
|
2017-09-26 13:10:01 +02:00
|
|
|
|
|
|
|
|
nm_assert (NM_IS_CONNECTION (applied_connection));
|
|
|
|
|
nm_assert (!priv->applied_connection);
|
|
|
|
|
|
|
|
|
|
/* we take ownership of @applied_connection. Ensure to pass in a reference. */
|
|
|
|
|
priv->applied_connection = applied_connection;
|
|
|
|
|
nm_connection_clear_secrets (priv->applied_connection);
|
2017-09-26 13:45:25 +02:00
|
|
|
|
|
|
|
|
/* we determine whether the connection is a master/slave, based solely
|
|
|
|
|
* on the connection properties itself. */
|
|
|
|
|
s_con = nm_connection_get_setting_connection (priv->applied_connection);
|
|
|
|
|
if (nm_setting_connection_get_master (s_con))
|
|
|
|
|
flags_val |= NM_ACTIVATION_STATE_FLAG_IS_SLAVE;
|
|
|
|
|
|
2018-05-18 10:08:07 +02:00
|
|
|
if (_nm_connection_type_is_master (nm_setting_connection_get_connection_type (s_con)))
|
2017-09-26 13:45:25 +02:00
|
|
|
flags_val |= NM_ACTIVATION_STATE_FLAG_IS_MASTER;
|
|
|
|
|
|
|
|
|
|
nm_active_connection_set_state_flags_full (self,
|
|
|
|
|
flags_val,
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_IS_MASTER
|
|
|
|
|
| NM_ACTIVATION_STATE_FLAG_IS_SLAVE);
|
2017-09-26 13:10:01 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-28 11:43:50 -05:00
|
|
|
void
|
2015-07-14 16:53:24 +02:00
|
|
|
nm_active_connection_set_settings_connection (NMActiveConnection *self,
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NMSettingsConnection *sett_conn)
|
2013-08-28 11:43:50 -05:00
|
|
|
{
|
2015-07-14 16:53:24 +02:00
|
|
|
NMActiveConnectionPrivate *priv;
|
2013-08-28 11:43:50 -05:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (sett_conn));
|
2018-03-29 14:48:42 +02:00
|
|
|
g_return_if_fail (!priv->settings_connection.obj);
|
2015-07-14 16:53:24 +02:00
|
|
|
g_return_if_fail (!priv->applied_connection);
|
|
|
|
|
|
|
|
|
|
/* Can't change connection after the ActiveConnection is exported over D-Bus.
|
|
|
|
|
*
|
|
|
|
|
* Later, we want to change the settings-connection of an activated connection.
|
|
|
|
|
* When doing that, this changes the assumption that the settings-connection
|
|
|
|
|
* never changes (once it's set). That has effects for NMVpnConnection and
|
|
|
|
|
* NMActivationRequest.
|
|
|
|
|
* For example, we'd have to cancel all pending seret requests. */
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
g_return_if_fail (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)));
|
2013-08-28 11:43:50 -05:00
|
|
|
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
_set_settings_connection (self, sett_conn);
|
2017-09-26 13:10:01 +02:00
|
|
|
|
|
|
|
|
_set_applied_connection_take (self,
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
nm_simple_connection_new_clone (nm_settings_connection_get_connection (priv->settings_connection.obj)));
|
2013-08-28 11:43:50 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_active_connection_has_unmodified_applied_connection (NMActiveConnection *self, NMSettingCompareFlags compare_flags)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
g_return_val_if_fail (priv->settings_connection.obj, FALSE);
|
2015-07-14 16:53:24 +02:00
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
return nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
|
2015-07-14 16:53:24 +02:00
|
|
|
priv->applied_connection,
|
|
|
|
|
compare_flags);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-07-14 16:53:24 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_active_connection_clear_secrets (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
|
2015-07-14 16:53:24 +02:00
|
|
|
priv->applied_connection,
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NM_SETTING_COMPARE_FLAG_NONE)) {
|
settings: rework tracking settings connections and settings plugins
Completely rework how settings plugin handle connections and how
NMSettings tracks the list of connections.
Previously, settings plugins would return objects of (a subtype of) type
NMSettingsConnection. The NMSettingsConnection was tightly coupled with
the settings plugin. That has a lot of downsides.
Change that. When changing this basic relation how settings connections
are tracked, everything falls appart. That's why this is a huge change.
Also, since I have to largely rewrite the settings plugins, I also
added support for multiple keyfile directories, handle in-memory
connections only by keyfile plugin and (partly) use copy-on-write NMConnection
instances. I don't want to spend effort rewriting large parts while
preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh,
I don't want to let it handle in-memory connections because that's not right
long-term.
--
If the settings plugins themself create subtypes of NMSettingsConnection
instances, then a lot of knowledge about tracking connections moves
to the plugins.
Just try to follow the code what happend during nm_settings_add_connection().
Note how the logic is spread out:
- nm_settings_add_connection() calls plugin's add_connection()
- add_connection() creates a NMSettingsConnection subtype
- the plugin has to know that it's called during add-connection and
not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal
- NMSettings calls claim_connection() which hocks up the new
NMSettingsConnection instance and configures the instance
(like calling nm_settings_connection_added()).
This summary does not sound like a lot, but try to follow that code. The logic
is all over the place.
Instead, settings plugins should have a very simple API for adding, modifying,
deleting, loading and reloading connections. All the plugin does is to return a
NMSettingsStorage handle. The storage instance is a handle to identify a profile
in storage (e.g. a particular file). The settings plugin is free to subtype
NMSettingsStorage, but it's not necessary.
There are no more events raised, and the settings plugin implements the small
API in a straightforward manner.
NMSettings now drives all of this. Even NMSettingsConnection has now
very little concern about how it's tracked and delegates only to NMSettings.
This should make settings plugins simpler. Currently settings plugins
are so cumbersome to implement, that we avoid having them. It should not be
like that and it should be easy, beneficial and lightweight to create a new
settings plugin.
Note also how the settings plugins no longer care about duplicate UUIDs.
Duplicated UUIDs are a fact of life and NMSettings must handle them. No
need to overly concern settings plugins with that.
--
NMSettingsConnection is exposed directly on D-Bus (being a subtype of
NMDBusObject) but it was also a GObject type provided by the settings
plugin. Hence, it was not possible to migrate a profile from one plugin to
another.
However that would be useful when one profile does not support a
connection type (like ifcfg-rh not supporting VPN). Currently such
migration is not implemented except for migrating them to/from keyfile's
run directory. The problem is that migrating profiles in general is
complicated but in some cases it is important to do.
For example checkpoint rollback should recreate the profile in the right
settings plugin, not just add it to persistent storage. This is not yet
properly implemented.
--
Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved)
profiles, while ifupdown plugin cannot handle them. That meant duplication of code
and a ifupdown profile could not be modified or made unsaved.
This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711).
Also, NMSettings is aware of such profiles and treats them specially.
In particular, NMSettings drives the migration between persistent and non-persistent
storage.
Note that a settings plugins may create truly generated, in-memory profiles.
The settings plugin is free to generate and persist the profiles in any way it
wishes. But the concept of "unsaved" profiles is now something explicitly handled
by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system
too, to the /run directory. This is great for two reasons: first of all, all
profiles from keyfile storage in fact have a backing file -- even the
unsaved ones. It also means you can create "unsaved" profiles in /run
and load them with `nmcli connection load`, meaning there is a file
based API for creating unsaved profiles.
The other advantage is that these profiles now survive restarting
NetworkManager. It's paramount that restarting the daemon is as
non-disruptive as possible. Persisting unsaved files to /run improves
here significantly.
--
In the past, NMSettingsConnection also implemented NMConnection interface.
That was already changed a while ago and instead users call now
nm_settings_connection_get_connection() to delegate to a
NMSimpleConnection. What however still happened was that the NMConnection
instance gets never swapped but instead the instance was modified with
nm_connection_replace_settings_from_connection(), clear-secrets, etc.
Change that and treat the NMConnection instance immutable. Instead of modifying
it, reference/clone a new instance. This changes that previously when somebody
wanted to keep a reference to an NMConnection, then the profile would be cloned.
Now, it is supposed to be safe to reference the instance directly and everybody
must ensure not to modify the instance. nmtst_connection_assert_unchanging()
should help with that.
The point is that the settings plugins may keep references to the
NMConnection instance, and so does the NMSettingsConnection. We want
to avoid cloning the instances as long as they are the same.
Likewise, the device's applied connection can now also be referenced
instead of cloning it. This is not yet done, and possibly there are
further improvements possible.
--
Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545,
bgo #772414).
It was always the case that multiple files could provide the same UUID
(both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in
read-only storage in /usr/lib gets modified, then it gets actually stored in
/etc (or /run, if the profile is unsaved).
--
While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable.
--
https://bugzilla.gnome.org/show_bug.cgi?id=772414
https://bugzilla.gnome.org/show_bug.cgi?id=744711
https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
|
|
|
nm_settings_connection_clear_secrets (priv->settings_connection.obj,
|
|
|
|
|
FALSE,
|
|
|
|
|
FALSE);
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
}
|
2015-07-14 16:53:24 +02:00
|
|
|
nm_connection_clear_secrets (priv->applied_connection);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-07-14 16:53:24 +02:00
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
const char *
|
|
|
|
|
nm_active_connection_get_specific_object (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->specific_object;
|
2008-03-26 13:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-02-03 14:53:09 -06:00
|
|
|
nm_active_connection_set_specific_object (NMActiveConnection *self,
|
|
|
|
|
const char *specific_object)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
2012-09-17 10:28:11 -05:00
|
|
|
/* Nothing that calls this function should be using paths from D-Bus,
|
|
|
|
|
* where NM uses "/" to mean NULL.
|
|
|
|
|
*/
|
2018-04-11 17:16:28 +02:00
|
|
|
nm_assert (!nm_streq0 (specific_object, "/"));
|
2012-09-17 10:28:11 -05:00
|
|
|
|
2018-04-11 17:16:28 +02:00
|
|
|
if (nm_streq0 (priv->specific_object, specific_object))
|
2012-02-03 14:53:09 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_free (priv->specific_object);
|
|
|
|
|
priv->specific_object = g_strdup (specific_object);
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_SPECIFIC_OBJECT);
|
2012-02-03 14:53:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2017-11-23 21:53:04 +01:00
|
|
|
nm_active_connection_set_default (NMActiveConnection *self,
|
|
|
|
|
int addr_family,
|
|
|
|
|
gboolean is_default)
|
2012-02-03 14:53:09 -06:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
2017-11-23 21:53:04 +01:00
|
|
|
nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6));
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2014-06-20 17:56:06 +02:00
|
|
|
is_default = !!is_default;
|
|
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2017-11-23 21:53:04 +01:00
|
|
|
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) {
|
|
|
|
|
if (priv->is_default != is_default) {
|
|
|
|
|
priv->is_default = is_default;
|
|
|
|
|
_notify (self, PROP_DEFAULT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) {
|
|
|
|
|
if (priv->is_default6 != is_default) {
|
|
|
|
|
priv->is_default6 = is_default;
|
|
|
|
|
_notify (self, PROP_DEFAULT6);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-03 14:53:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2017-11-23 21:53:04 +01:00
|
|
|
nm_active_connection_get_default (NMActiveConnection *self, int addr_family)
|
2012-02-03 14:53:09 -06:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
2017-11-23 21:53:04 +01:00
|
|
|
nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6));
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2017-11-23 21:53:04 +01:00
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
switch (addr_family) {
|
|
|
|
|
case AF_INET: return priv->is_default;
|
|
|
|
|
case AF_INET6: return priv->is_default6;
|
|
|
|
|
default: return priv->is_default || priv->is_default6;
|
|
|
|
|
}
|
2012-02-03 14:53:09 -06:00
|
|
|
}
|
|
|
|
|
|
2013-07-29 13:11:47 -05:00
|
|
|
NMAuthSubject *
|
|
|
|
|
nm_active_connection_get_subject (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
|
|
|
|
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-22 09:38:01 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_active_connection_get_user_requested (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2019-12-17 20:36:18 +01:00
|
|
|
return nm_auth_subject_get_subject_type (
|
|
|
|
|
NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject
|
|
|
|
|
) == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
|
2012-08-22 09:38:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMDevice *
|
|
|
|
|
nm_active_connection_get_device (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2012-08-22 09:38:01 -05:00
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->device;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-27 14:40:18 -05:00
|
|
|
static void
|
|
|
|
|
device_state_changed (NMDevice *device,
|
|
|
|
|
NMDeviceState new_state,
|
|
|
|
|
NMDeviceState old_state,
|
|
|
|
|
NMDeviceStateReason reason,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
2014-02-19 13:09:17 -06:00
|
|
|
/* When already deactivated or before activation, device state changes are useless */
|
|
|
|
|
if (priv->state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
|
|
|
|
|
return;
|
2013-09-27 14:40:18 -05:00
|
|
|
if (old_state < NM_DEVICE_STATE_DISCONNECTED)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Let subclasses handle the state change */
|
|
|
|
|
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed)
|
|
|
|
|
NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed (self, device, new_state, old_state);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-02 14:59:46 -05:00
|
|
|
static void
|
|
|
|
|
device_master_changed (GObject *object,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *device = NM_DEVICE (object);
|
|
|
|
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
|
|
|
|
NMActiveConnection *master;
|
|
|
|
|
NMActiveConnectionState master_state;
|
|
|
|
|
|
2014-02-19 13:09:17 -06:00
|
|
|
if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != self)
|
|
|
|
|
return;
|
2014-01-02 14:59:46 -05:00
|
|
|
if (!nm_device_get_master (device))
|
|
|
|
|
return;
|
2014-09-24 16:02:37 +02:00
|
|
|
if (!nm_active_connection_get_master (self))
|
|
|
|
|
return;
|
2014-01-02 14:59:46 -05:00
|
|
|
g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_master_changed), self);
|
|
|
|
|
|
|
|
|
|
master = nm_active_connection_get_master (self);
|
|
|
|
|
master_state = nm_active_connection_get_state (master);
|
|
|
|
|
if (master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
|
|
|
|
|
/* Master failed before attaching the slave */
|
|
|
|
|
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
|
|
|
|
|
NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-03 09:15:24 +02:00
|
|
|
static void
|
|
|
|
|
device_metered_changed (GObject *object,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = (NMActiveConnection *) user_data;
|
|
|
|
|
NMDevice *device = NM_DEVICE (object);
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
|
|
|
|
g_signal_emit (self, signals[DEVICE_METERED_CHANGED], 0, nm_device_get_metered (device));
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-16 17:43:31 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
2014-10-23 17:04:49 -05:00
|
|
|
gs_unref_object NMDevice *old_device = NULL;
|
2013-09-16 17:43:31 -05:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (!device || NM_IS_DEVICE (device), FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2014-10-23 17:04:49 -05:00
|
|
|
if (device == priv->device)
|
|
|
|
|
return TRUE;
|
2013-09-16 17:43:31 -05:00
|
|
|
|
2015-12-07 20:42:47 +01:00
|
|
|
_LOGD ("set device %s%s%s [%p]",
|
|
|
|
|
NM_PRINT_FMT_QUOTED (device && nm_device_get_iface (device),
|
|
|
|
|
"\"",
|
|
|
|
|
nm_device_get_iface (device),
|
|
|
|
|
"\"",
|
|
|
|
|
device ? "(unknown)" : "(null)"),
|
|
|
|
|
device);
|
|
|
|
|
|
2014-10-23 17:04:49 -05:00
|
|
|
old_device = priv->device ? g_object_ref (priv->device) : NULL;
|
|
|
|
|
_device_cleanup (self);
|
2013-09-16 17:43:31 -05:00
|
|
|
|
2014-10-23 17:04:49 -05:00
|
|
|
if (device) {
|
2013-09-16 17:43:31 -05:00
|
|
|
/* Device obviously can't be its own master */
|
|
|
|
|
g_return_val_if_fail (!priv->master || device != nm_active_connection_get_device (priv->master), FALSE);
|
|
|
|
|
|
|
|
|
|
priv->device = g_object_ref (device);
|
|
|
|
|
|
2015-12-07 19:42:59 +01:00
|
|
|
g_signal_connect (device, NM_DEVICE_STATE_CHANGED,
|
2014-01-02 14:59:46 -05:00
|
|
|
G_CALLBACK (device_state_changed), self);
|
2016-08-22 13:45:04 +02:00
|
|
|
g_signal_connect (device, "notify::" NM_DEVICE_MASTER,
|
2014-01-02 14:59:46 -05:00
|
|
|
G_CALLBACK (device_master_changed), self);
|
2015-06-03 09:15:24 +02:00
|
|
|
g_signal_connect (device, "notify::" NM_DEVICE_METERED,
|
|
|
|
|
G_CALLBACK (device_metered_changed), self);
|
core: ensure 'activation' pending action encompasses full activation process
The NMActiveConnection class tracks the full activation request, and internal
activation requests go through the same process as external ones, including
some authentication. Sometimes that means activation is scheduled, control
returns to the mainloop, and then the activation proceeds from an idle
handler.
Unfortunately, that means that adding a pending "activation" action from
nm-device.c doesn't always work, since there is a short window between when
the activation is started in nm-manager.c (in nm_manager_activate_connection())
and when the device actually changes state. Inside that window, the pending
actions may drop to zero, and startup will be declared complete before the
device actually starts activating.
Instead, ensure that the pending action is added when the internal activation
is actually started (eg, when NMActiveConnection receives the NMDevice object).
2013-12-10 22:11:09 -06:00
|
|
|
|
2017-03-08 12:22:01 +01:00
|
|
|
if (priv->activation_type != NM_ACTIVATION_TYPE_EXTERNAL) {
|
2019-10-14 16:31:40 +02:00
|
|
|
priv->pending_activation_id = g_strdup_printf (NM_PENDING_ACTIONPREFIX_ACTIVATION"%"G_GUINT64_FORMAT, priv->version_id);
|
2014-04-28 11:18:05 +02:00
|
|
|
nm_device_add_pending_action (device, priv->pending_activation_id, TRUE);
|
2014-02-12 10:40:24 -05:00
|
|
|
}
|
2014-10-15 21:17:45 -05:00
|
|
|
} else {
|
|
|
|
|
/* The ActiveConnection's device can only be cleared after the
|
|
|
|
|
* connection is activated.
|
|
|
|
|
*/
|
|
|
|
|
g_warn_if_fail (priv->state > NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
|
2014-10-23 17:04:49 -05:00
|
|
|
priv->device = NULL;
|
2014-10-15 21:17:45 -05:00
|
|
|
}
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_INT_DEVICE);
|
2014-10-23 17:04:49 -05:00
|
|
|
|
|
|
|
|
g_signal_emit (self, signals[DEVICE_CHANGED], 0, priv->device, old_device);
|
|
|
|
|
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_DEVICES);
|
2014-10-23 17:04:49 -05:00
|
|
|
|
2013-09-16 17:43:31 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-27 12:16:57 -05:00
|
|
|
NMActiveConnection *
|
2012-08-22 09:38:01 -05:00
|
|
|
nm_active_connection_get_master (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
|
|
|
|
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-27 17:13:43 -05:00
|
|
|
/**
|
|
|
|
|
* nm_active_connection_get_master_ready:
|
|
|
|
|
* @self: the #NMActiveConnection
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the connection has a master connection, and that
|
|
|
|
|
* master connection is ready to accept slaves. Otherwise %FALSE.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_active_connection_get_master_ready (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master_ready;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_master_ready (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2015-12-07 20:42:47 +01:00
|
|
|
gboolean signalling = FALSE;
|
2013-09-27 17:13:43 -05:00
|
|
|
|
|
|
|
|
/* ActiveConnetions don't enter the ACTIVATING state until they have a
|
|
|
|
|
* NMDevice in PREPARE or higher states, so the master active connection's
|
|
|
|
|
* device will be ready to accept slaves when the master is in ACTIVATING
|
|
|
|
|
* or higher states.
|
|
|
|
|
*/
|
2015-12-07 20:42:47 +01:00
|
|
|
if ( !priv->master_ready
|
|
|
|
|
&& priv->master
|
|
|
|
|
&& priv->state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
|
|
|
|
&& NM_IN_SET (nm_active_connection_get_state (priv->master),
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_ACTIVATING,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
|
|
|
|
|
signalling = TRUE;
|
|
|
|
|
}
|
2013-10-25 19:33:01 -05:00
|
|
|
|
2015-12-07 20:42:47 +01:00
|
|
|
_LOGD ("check-master-ready: %s (state %s, %s)",
|
|
|
|
|
signalling
|
|
|
|
|
? "signal"
|
|
|
|
|
: (priv->master_ready ? "already signalled" : "not signalling"),
|
2019-01-10 09:17:28 +01:00
|
|
|
state_to_string_a (priv->state),
|
2015-12-07 20:42:47 +01:00
|
|
|
priv->master
|
|
|
|
|
? nm_sprintf_bufa (128, "master %p is in state %s",
|
|
|
|
|
priv->master,
|
2019-01-10 09:17:28 +01:00
|
|
|
state_to_string_a (nm_active_connection_get_state (priv->master)))
|
2015-12-07 20:42:47 +01:00
|
|
|
: "no master");
|
|
|
|
|
|
|
|
|
|
if (signalling) {
|
2013-09-27 17:13:43 -05:00
|
|
|
priv->master_ready = TRUE;
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_INT_MASTER_READY);
|
2013-09-27 17:13:43 -05:00
|
|
|
|
|
|
|
|
/* Also notify clients to recheck the exported 'master' property to
|
|
|
|
|
* ensure that if the master connection was created without a device
|
|
|
|
|
* that we notify clients when the master device is known.
|
|
|
|
|
*/
|
2016-04-13 13:33:04 +02:00
|
|
|
_notify (self, PROP_MASTER);
|
2013-09-27 17:13:43 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-28 09:08:43 -05:00
|
|
|
static void
|
|
|
|
|
master_state_cb (NMActiveConnection *master,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
|
|
|
|
NMActiveConnectionState master_state = nm_active_connection_get_state (master);
|
2014-09-24 16:58:07 -05:00
|
|
|
NMDevice *master_device = nm_active_connection_get_device (master);
|
2013-08-28 09:08:43 -05:00
|
|
|
|
2013-09-27 17:13:43 -05:00
|
|
|
check_master_ready (self);
|
|
|
|
|
|
2014-09-24 16:58:07 -05:00
|
|
|
if ( master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING
|
|
|
|
|
&& (!master_device || !nm_device_is_real (master_device))) {
|
|
|
|
|
/* Master failed without ever creating or realizing its device */
|
2013-08-28 09:08:43 -05:00
|
|
|
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
|
|
|
|
|
NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-29 16:26:09 -05:00
|
|
|
/**
|
|
|
|
|
* nm_active_connection_set_master:
|
|
|
|
|
* @self: the #NMActiveConnection
|
|
|
|
|
* @master: if the activation depends on another device (ie, bond or bridge
|
2013-08-27 12:16:57 -05:00
|
|
|
* master to which this device will be enslaved) pass the #NMActiveConnection
|
|
|
|
|
* that this activation request is a child of
|
2013-07-29 16:26:09 -05:00
|
|
|
*
|
2013-08-27 12:16:57 -05:00
|
|
|
* Sets the master active connection of @self.
|
2013-07-29 16:26:09 -05:00
|
|
|
*/
|
|
|
|
|
void
|
2013-08-27 12:16:57 -05:00
|
|
|
nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *master)
|
2013-07-29 16:26:09 -05:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
2013-08-27 12:16:57 -05:00
|
|
|
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (master));
|
2013-07-29 16:26:09 -05:00
|
|
|
|
|
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2013-08-27 12:16:57 -05:00
|
|
|
|
2013-07-29 16:26:09 -05:00
|
|
|
/* Master is write-once, and must be set before exporting the object */
|
|
|
|
|
g_return_if_fail (priv->master == NULL);
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
g_return_if_fail (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)));
|
2013-09-16 17:43:31 -05:00
|
|
|
if (priv->device) {
|
|
|
|
|
/* Note, the master ActiveConnection may not yet have a device */
|
|
|
|
|
g_return_if_fail (priv->device != nm_active_connection_get_device (master));
|
|
|
|
|
}
|
2013-07-29 16:26:09 -05:00
|
|
|
|
2015-12-07 20:42:47 +01:00
|
|
|
_LOGD ("set master %p, %s, state %s",
|
|
|
|
|
master,
|
|
|
|
|
nm_active_connection_get_settings_connection_id (master),
|
2019-01-10 09:17:28 +01:00
|
|
|
state_to_string_a (nm_active_connection_get_state (master)));
|
2013-10-25 19:33:01 -05:00
|
|
|
|
2013-07-29 16:26:09 -05:00
|
|
|
priv->master = g_object_ref (master);
|
2013-08-28 09:08:43 -05:00
|
|
|
g_signal_connect (priv->master,
|
|
|
|
|
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
|
|
|
|
(GCallback) master_state_cb,
|
|
|
|
|
self);
|
2013-09-27 17:13:43 -05:00
|
|
|
|
|
|
|
|
check_master_ready (self);
|
2013-07-29 16:26:09 -05:00
|
|
|
}
|
|
|
|
|
|
2017-03-07 11:04:36 +01:00
|
|
|
NMActivationType
|
|
|
|
|
nm_active_connection_get_activation_type (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NM_ACTIVATION_TYPE_MANAGED);
|
|
|
|
|
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->activation_type;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 15:58:59 +01:00
|
|
|
static void
|
|
|
|
|
_set_activation_type (NMActiveConnection *self,
|
|
|
|
|
NMActivationType activation_type)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->activation_type == activation_type)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-06-16 14:34:37 +02:00
|
|
|
priv->activation_type = activation_type;
|
|
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
if (priv->settings_connection.obj) {
|
2017-06-16 14:34:37 +02:00
|
|
|
if (activation_type == NM_ACTIVATION_TYPE_EXTERNAL)
|
2018-04-05 20:15:50 +02:00
|
|
|
g_signal_connect (priv->settings_connection.obj, NM_SETTINGS_CONNECTION_FLAGS_CHANGED, (GCallback) _settings_connection_flags_changed, self);
|
2017-06-16 14:34:37 +02:00
|
|
|
else
|
2018-04-05 20:15:50 +02:00
|
|
|
g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_flags_changed, self);
|
2017-06-16 14:34:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_set_activation_type_managed (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->activation_type == NM_ACTIVATION_TYPE_MANAGED)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-03-08 15:58:59 +01:00
|
|
|
_LOGD ("update activation type from %s to %s",
|
|
|
|
|
nm_activation_type_to_string (priv->activation_type),
|
2017-06-16 14:34:37 +02:00
|
|
|
nm_activation_type_to_string (NM_ACTIVATION_TYPE_MANAGED));
|
|
|
|
|
|
|
|
|
|
_set_activation_type (self, NM_ACTIVATION_TYPE_MANAGED);
|
2017-03-08 15:58:59 +01:00
|
|
|
|
2017-06-16 14:34:37 +02:00
|
|
|
if ( priv->device
|
2017-03-13 15:34:14 +01:00
|
|
|
&& self == NM_ACTIVE_CONNECTION (nm_device_get_act_request (priv->device))
|
|
|
|
|
&& NM_IN_SET (nm_device_sys_iface_state_get (priv->device),
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
|
|
|
|
NM_DEVICE_SYS_IFACE_STATE_ASSUME))
|
|
|
|
|
nm_device_sys_iface_state_set (priv->device, NM_DEVICE_SYS_IFACE_STATE_MANAGED);
|
2013-11-07 01:04:06 -06:00
|
|
|
}
|
|
|
|
|
|
2018-03-28 17:18:04 +02:00
|
|
|
NMActivationReason
|
|
|
|
|
nm_active_connection_get_activation_reason (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NM_ACTIVATION_REASON_UNSET);
|
|
|
|
|
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->activation_reason;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-20 14:51:22 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_active_connection_get_keep_alive:
|
|
|
|
|
* @self: the #NMActiveConnection instance
|
|
|
|
|
*
|
|
|
|
|
* Gives the #NMKeepAlive instance of the active connection. Note that
|
|
|
|
|
* @self is guaranteed not to swap the keep-alive instance, so it is
|
|
|
|
|
* in particular safe to assume that the keep-alive instance is alive
|
|
|
|
|
* as long as @self, and that nm_active_connection_get_keep_alive()
|
|
|
|
|
* will return always the same instance.
|
|
|
|
|
*
|
|
|
|
|
* In particular this means, that it is safe and encouraged, that you
|
|
|
|
|
* register to the notify:alive property changed signal of the returned
|
|
|
|
|
* instance.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the #NMKeepAlive instance.
|
|
|
|
|
*/
|
|
|
|
|
NMKeepAlive *
|
2018-10-10 17:10:01 +02:00
|
|
|
nm_active_connection_get_keep_alive (NMActiveConnection *self)
|
|
|
|
|
{
|
2018-11-20 14:51:22 +01:00
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
2018-10-10 17:10:01 +02:00
|
|
|
|
2018-11-20 14:51:22 +01:00
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->keep_alive;
|
2018-10-10 17:10:01 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2012-08-22 09:38:01 -05:00
|
|
|
|
2017-03-08 15:58:59 +01:00
|
|
|
static void
|
2018-04-05 20:15:50 +02:00
|
|
|
_settings_connection_flags_changed (NMSettingsConnection *settings_connection,
|
|
|
|
|
NMActiveConnection *self)
|
2017-03-08 15:58:59 +01:00
|
|
|
{
|
core: avoid assertion failure in _settings_connection_flags_changed() without device
It seems not unexpected, that we get a flags-changed notification while
having no device. Handle it gracefully and avoid the assertion failure.
#0 _g_log_abort (breakpoint=breakpoint@entry=1) at gmessages.c:583
#1 g_logv (log_domain=0x55f3c86f0262 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7ffcbf88f1c0) at gmessages.c:1391
#2 g_log (log_domain=log_domain@entry=0x55f3c86f0262 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7f21e99adb27 "%s: assertion '%s' failed") at gmessages.c:1432
#3 g_return_if_fail_warning (log_domain=log_domain@entry=0x55f3c86f0262 "NetworkManager", pretty_function=pretty_function@entry=0x55f3c875f290 <__func__.53083> "nm_device_reapply", expression=expression@entry=0x55f3c8752507 "NM_IS_DEVICE (self)") at gmessages.c:2809
#4 nm_device_reapply (self=0x0, connection=connection@entry=0x55f3caab4e60, error=error@entry=0x7ffcbf88f308) at src/devices/nm-device.c:12107
#5 _settings_connection_flags_changed (settings_connection=<optimized out>, self=0x55f3caabca70 [NMActRequest]) at src/nm-active-connection.c:960
#9 <emit signal ??? on instance 0x55f3caaaf530 [NMSettingsConnection]> (instance=instance@entry=0x55f3caaaf530, signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3447
#6 g_closure_invoke (closure=0x55f3caa4c160, return_value=return_value@entry=0x0, n_param_values=1, param_values=param_values@entry=0x7ffcbf88f520, invocation_hint=invocation_hint@entry=0x7ffcbf88f4c0) at gclosure.c:804
#7 signal_emit_unlocked_R (node=node@entry=0x55f3ca9dcf90, detail=detail@entry=0, instance=instance@entry=0x55f3caaaf530, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7ffcbf88f520) at gsignal.c:3635
#8 g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7ffcbf88f6a0) at gsignal.c:3391
#10 nm_settings_connection_set_flags_full (self=self@entry=0x55f3caaaf530 [NMSettingsConnection], mask=<optimized out>, value=<optimized out>) at src/settings/nm-settings-connection.c:2025
#11 _connection_changed_process_all_dirty (update_reason=(NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS), sett_mask=<optimized out>, sett_flags=<optimized out>, connection=0x55f3caab4f80, sett_conn_entry=<optimized out>, self=0x55f3ca99c000 [NMSettings]) at src/settings/nm-settings.c:1099
#12 _connection_changed_process_all_dirty (update_reason=(NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS), override_sett_flags=1, sett_mask=_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK, sett_flags=<optimized out>, allow_add_to_no_auto_default=0, sett_conn_entry=<optimized out>, self=0x55f3ca99c000 [NMSettings]) at src/settings/nm-settings.c:1284
#13 _connection_changed_process_all_dirty (self=self@entry=0x55f3ca99c000 [NMSettings], allow_add_to_no_auto_default=allow_add_to_no_auto_default@entry=0, sett_flags=sett_flags@entry=NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, sett_mask=sett_mask@entry=NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, override_sett_flags=override_sett_flags@entry=1, update_reason=update_reason@entry=(NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS)) at src/settings/nm-settings.c:1304
#14 _plugin_connections_reload (self=self@entry=0x55f3ca99c000 [NMSettings]) at src/settings/nm-settings.c:1417
#15 impl_settings_reload_connections (obj=0x55f3ca99c000 [NMSettings], interface_info=<optimized out>, method_info=<optimized out>, connection=<optimized out>, sender=<optimized out>, invocation=0x7f21d000c100 [GDBusMethodInvocation], parameters=0x55f3ca9e1f20) at src/settings/nm-settings.c:2822
...
https://bugzilla.redhat.com/show_bug.cgi?id=1816067
2020-03-23 11:42:59 +01:00
|
|
|
NMDevice *device;
|
2017-06-16 13:06:26 +02:00
|
|
|
|
2017-03-08 15:58:59 +01:00
|
|
|
nm_assert (NM_IS_ACTIVE_CONNECTION (self));
|
|
|
|
|
nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection));
|
|
|
|
|
nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL);
|
2018-03-29 14:48:42 +02:00
|
|
|
nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj == settings_connection);
|
2017-03-08 15:58:59 +01:00
|
|
|
|
2017-12-05 12:10:16 +01:00
|
|
|
if (NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection),
|
2018-04-05 20:02:45 +02:00
|
|
|
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED))
|
2017-03-08 15:58:59 +01:00
|
|
|
return;
|
|
|
|
|
|
2017-06-16 14:34:37 +02:00
|
|
|
_set_activation_type_managed (self);
|
core: avoid assertion failure in _settings_connection_flags_changed() without device
It seems not unexpected, that we get a flags-changed notification while
having no device. Handle it gracefully and avoid the assertion failure.
#0 _g_log_abort (breakpoint=breakpoint@entry=1) at gmessages.c:583
#1 g_logv (log_domain=0x55f3c86f0262 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7ffcbf88f1c0) at gmessages.c:1391
#2 g_log (log_domain=log_domain@entry=0x55f3c86f0262 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7f21e99adb27 "%s: assertion '%s' failed") at gmessages.c:1432
#3 g_return_if_fail_warning (log_domain=log_domain@entry=0x55f3c86f0262 "NetworkManager", pretty_function=pretty_function@entry=0x55f3c875f290 <__func__.53083> "nm_device_reapply", expression=expression@entry=0x55f3c8752507 "NM_IS_DEVICE (self)") at gmessages.c:2809
#4 nm_device_reapply (self=0x0, connection=connection@entry=0x55f3caab4e60, error=error@entry=0x7ffcbf88f308) at src/devices/nm-device.c:12107
#5 _settings_connection_flags_changed (settings_connection=<optimized out>, self=0x55f3caabca70 [NMActRequest]) at src/nm-active-connection.c:960
#9 <emit signal ??? on instance 0x55f3caaaf530 [NMSettingsConnection]> (instance=instance@entry=0x55f3caaaf530, signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3447
#6 g_closure_invoke (closure=0x55f3caa4c160, return_value=return_value@entry=0x0, n_param_values=1, param_values=param_values@entry=0x7ffcbf88f520, invocation_hint=invocation_hint@entry=0x7ffcbf88f4c0) at gclosure.c:804
#7 signal_emit_unlocked_R (node=node@entry=0x55f3ca9dcf90, detail=detail@entry=0, instance=instance@entry=0x55f3caaaf530, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7ffcbf88f520) at gsignal.c:3635
#8 g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7ffcbf88f6a0) at gsignal.c:3391
#10 nm_settings_connection_set_flags_full (self=self@entry=0x55f3caaaf530 [NMSettingsConnection], mask=<optimized out>, value=<optimized out>) at src/settings/nm-settings-connection.c:2025
#11 _connection_changed_process_all_dirty (update_reason=(NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS), sett_mask=<optimized out>, sett_flags=<optimized out>, connection=0x55f3caab4f80, sett_conn_entry=<optimized out>, self=0x55f3ca99c000 [NMSettings]) at src/settings/nm-settings.c:1099
#12 _connection_changed_process_all_dirty (update_reason=(NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS), override_sett_flags=1, sett_mask=_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK, sett_flags=<optimized out>, allow_add_to_no_auto_default=0, sett_conn_entry=<optimized out>, self=0x55f3ca99c000 [NMSettings]) at src/settings/nm-settings.c:1284
#13 _connection_changed_process_all_dirty (self=self@entry=0x55f3ca99c000 [NMSettings], allow_add_to_no_auto_default=allow_add_to_no_auto_default@entry=0, sett_flags=sett_flags@entry=NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, sett_mask=sett_mask@entry=NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, override_sett_flags=override_sett_flags@entry=1, update_reason=update_reason@entry=(NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS)) at src/settings/nm-settings.c:1304
#14 _plugin_connections_reload (self=self@entry=0x55f3ca99c000 [NMSettings]) at src/settings/nm-settings.c:1417
#15 impl_settings_reload_connections (obj=0x55f3ca99c000 [NMSettings], interface_info=<optimized out>, method_info=<optimized out>, connection=<optimized out>, sender=<optimized out>, invocation=0x7f21d000c100 [GDBusMethodInvocation], parameters=0x55f3ca9e1f20) at src/settings/nm-settings.c:2822
...
https://bugzilla.redhat.com/show_bug.cgi?id=1816067
2020-03-23 11:42:59 +01:00
|
|
|
|
|
|
|
|
device = nm_active_connection_get_device (self);
|
|
|
|
|
if (device) {
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
if (!nm_device_reapply (device,
|
|
|
|
|
nm_settings_connection_get_connection (nm_active_connection_get_settings_connection (self)),
|
|
|
|
|
&error)) {
|
|
|
|
|
_LOGW ("failed to reapply new device settings on previously externally managed device: %s",
|
|
|
|
|
error->message);
|
|
|
|
|
}
|
2017-06-16 13:06:26 +02:00
|
|
|
}
|
2017-03-08 15:58:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-06-29 14:31:19 +02:00
|
|
|
static void unwatch_parent (NMActiveConnection *self, gboolean unref);
|
2016-03-23 14:47:02 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parent_destroyed (gpointer user_data, GObject *parent)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = user_data;
|
|
|
|
|
|
2016-06-29 14:31:19 +02:00
|
|
|
unwatch_parent (self, FALSE);
|
2016-03-23 14:47:02 +01:00
|
|
|
g_signal_emit (self, signals[PARENT_ACTIVE], 0, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parent_state_cb (NMActiveConnection *parent_ac,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = user_data;
|
|
|
|
|
NMActiveConnectionState parent_state = nm_active_connection_get_state (parent_ac);
|
|
|
|
|
|
|
|
|
|
if (parent_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-06-29 14:31:19 +02:00
|
|
|
unwatch_parent (self, TRUE);
|
2020-05-19 09:27:08 +02:00
|
|
|
|
|
|
|
|
if (parent_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
|
|
|
|
|
g_signal_emit (self, signals[PARENT_ACTIVE], 0, parent_ac);
|
2016-03-23 14:47:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2016-06-29 14:31:19 +02:00
|
|
|
unwatch_parent (NMActiveConnection *self, gboolean unref)
|
2016-03-23 14:47:02 +01:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->parent,
|
|
|
|
|
(GCallback) parent_state_cb,
|
|
|
|
|
self);
|
2016-06-29 14:31:19 +02:00
|
|
|
if (unref)
|
|
|
|
|
g_object_weak_unref ((GObject *) priv->parent, parent_destroyed, self);
|
2016-03-23 14:47:02 +01:00
|
|
|
priv->parent = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_active_connection_set_parent:
|
|
|
|
|
* @self: the #NMActiveConnection
|
|
|
|
|
* @parent: The #NMActiveConnection that must be active before the manager
|
|
|
|
|
* can proceed progressing the device to disconnected state for us.
|
|
|
|
|
*
|
|
|
|
|
* Sets the parent connection of @self. A "parent-active" signal will be
|
|
|
|
|
* emitted when the parent connection becomes active.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (priv->parent == NULL);
|
|
|
|
|
priv->parent = parent;
|
|
|
|
|
g_signal_connect (priv->parent,
|
|
|
|
|
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
|
|
|
|
(GCallback) parent_state_cb,
|
|
|
|
|
self);
|
|
|
|
|
g_object_weak_ref ((GObject *) priv->parent, parent_destroyed, self);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-03-23 14:47:02 +01:00
|
|
|
|
2012-09-17 10:53:41 -05:00
|
|
|
static void
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete (NMActiveConnection *self, gboolean result, const char *message)
|
2018-04-10 08:46:01 +02:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2018-04-18 07:43:03 +02:00
|
|
|
NMActiveConnectionAuthResultFunc result_func;
|
|
|
|
|
gpointer user_data;
|
2018-04-10 08:46:01 +02:00
|
|
|
|
|
|
|
|
if (priv->auth.call_id_network_control)
|
|
|
|
|
nm_auth_manager_check_authorization_cancel (priv->auth.call_id_network_control);
|
|
|
|
|
if (priv->auth.call_id_wifi_shared_permission) {
|
|
|
|
|
if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED)
|
|
|
|
|
priv->auth.call_id_wifi_shared_permission = NULL;
|
|
|
|
|
else
|
|
|
|
|
nm_auth_manager_check_authorization_cancel (priv->auth.call_id_wifi_shared_permission);
|
|
|
|
|
}
|
2018-04-18 07:43:03 +02:00
|
|
|
|
|
|
|
|
nm_assert (!priv->auth.call_id_network_control);
|
|
|
|
|
nm_assert (!priv->auth.call_id_wifi_shared_permission);
|
|
|
|
|
if (priv->auth.result_func) {
|
2018-05-21 12:01:46 +02:00
|
|
|
result_func = priv->auth.result_func;
|
|
|
|
|
priv->auth.result_func = NULL;
|
2018-04-18 07:43:03 +02:00
|
|
|
user_data = g_steal_pointer (&priv->auth.user_data);
|
|
|
|
|
|
|
|
|
|
result_func (self,
|
|
|
|
|
result,
|
|
|
|
|
message,
|
|
|
|
|
user_data);
|
|
|
|
|
}
|
2018-04-10 08:46:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete_keep_alive (NMActiveConnection *self, gboolean result, const char *message)
|
2018-04-10 08:46:01 +02:00
|
|
|
{
|
|
|
|
|
_nm_unused gs_unref_object NMActiveConnection *self_keep_alive = g_object_ref (self);
|
|
|
|
|
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete (self, result, message);
|
2018-04-10 08:46:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
auth_done (NMAuthManager *auth_mgr,
|
|
|
|
|
NMAuthManagerCallId *auth_call_id,
|
|
|
|
|
gboolean is_authorized,
|
|
|
|
|
gboolean is_challenge,
|
2012-09-17 10:53:41 -05:00
|
|
|
GError *error,
|
|
|
|
|
gpointer user_data)
|
2018-04-10 08:46:01 +02:00
|
|
|
|
2012-09-17 10:53:41 -05:00
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
NMAuthCallResult result;
|
|
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
nm_assert (auth_call_id);
|
|
|
|
|
nm_assert (priv->auth.result_func);
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
|
|
|
if (auth_call_id == priv->auth.call_id_network_control)
|
|
|
|
|
priv->auth.call_id_network_control = NULL;
|
|
|
|
|
else {
|
|
|
|
|
nm_assert (auth_call_id == priv->auth.call_id_wifi_shared_permission);
|
|
|
|
|
priv->auth.call_id_wifi_shared_permission = NULL;
|
|
|
|
|
}
|
|
|
|
|
return;
|
2012-09-17 10:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
if (auth_call_id == priv->auth.call_id_network_control) {
|
|
|
|
|
priv->auth.call_id_network_control = NULL;
|
2012-09-17 10:53:41 -05:00
|
|
|
if (result != NM_AUTH_CALL_RESULT_YES) {
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete_keep_alive (self, FALSE, "Not authorized to control networking.");
|
2018-04-10 08:46:01 +02:00
|
|
|
return;
|
2012-09-17 10:53:41 -05:00
|
|
|
}
|
2018-04-10 08:46:01 +02:00
|
|
|
} else {
|
|
|
|
|
nm_assert (auth_call_id == priv->auth.call_id_wifi_shared_permission);
|
|
|
|
|
if (result != NM_AUTH_CALL_RESULT_YES) {
|
|
|
|
|
/* we don't fail right away. Instead, we mark that wifi-shared-permissions
|
|
|
|
|
* are missing. We prefer to report the failure about network-control.
|
|
|
|
|
* Below, we will wait longer for call_id_network_control (if it's still
|
|
|
|
|
* pending). */
|
|
|
|
|
priv->auth.call_id_wifi_shared_permission = AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED;
|
|
|
|
|
} else
|
|
|
|
|
priv->auth.call_id_wifi_shared_permission = NULL;
|
2012-09-17 10:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
if (priv->auth.call_id_network_control)
|
|
|
|
|
return;
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
if (priv->auth.call_id_wifi_shared_permission) {
|
|
|
|
|
if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED)
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete_keep_alive (self, FALSE, "Not authorized to share connections via wifi.");
|
2018-04-10 08:46:01 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete_keep_alive (self, TRUE, NULL);
|
2012-09-17 10:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_active_connection_authorize:
|
|
|
|
|
* @self: the #NMActiveConnection
|
2015-07-14 16:53:24 +02:00
|
|
|
* @initial_connection: (allow-none): for add-and-activate, there
|
|
|
|
|
* is no @settings_connection available when creating the active connection.
|
|
|
|
|
* Instead pass an alternative connection.
|
2012-09-17 10:53:41 -05:00
|
|
|
* @result_func: function to be called on success or error
|
2018-04-17 14:59:27 +02:00
|
|
|
* @user_data: pointer passed to @result_func
|
2012-09-17 10:53:41 -05:00
|
|
|
*
|
|
|
|
|
* Checks whether the subject that initiated the active connection (read from
|
|
|
|
|
* the #NMActiveConnection::subject property) is authorized to complete this
|
|
|
|
|
* activation request.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_active_connection_authorize (NMActiveConnection *self,
|
2015-07-14 16:53:24 +02:00
|
|
|
NMConnection *initial_connection,
|
2012-09-17 10:53:41 -05:00
|
|
|
NMActiveConnectionAuthResultFunc result_func,
|
2018-04-17 14:59:27 +02:00
|
|
|
gpointer user_data)
|
2012-09-17 10:53:41 -05:00
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
const char *wifi_permission = NULL;
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NMConnection *connection;
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
g_return_if_fail (result_func);
|
|
|
|
|
g_return_if_fail (!priv->auth.call_id_network_control);
|
|
|
|
|
nm_assert (!priv->auth.call_id_wifi_shared_permission);
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2015-07-14 16:53:24 +02:00
|
|
|
if (initial_connection) {
|
|
|
|
|
g_return_if_fail (NM_IS_CONNECTION (initial_connection));
|
2018-03-29 14:48:42 +02:00
|
|
|
g_return_if_fail (!priv->settings_connection.obj);
|
2015-07-14 16:53:24 +02:00
|
|
|
g_return_if_fail (!priv->applied_connection);
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
connection = initial_connection;
|
2015-07-14 16:53:24 +02:00
|
|
|
} else {
|
2018-03-29 14:48:42 +02:00
|
|
|
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection.obj));
|
2015-07-14 16:53:24 +02:00
|
|
|
g_return_if_fail (NM_IS_CONNECTION (priv->applied_connection));
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
connection = priv->applied_connection;
|
2015-07-14 16:53:24 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
priv->auth.call_id_network_control = nm_auth_manager_check_authorization (nm_auth_manager_get (),
|
|
|
|
|
priv->subject,
|
|
|
|
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
|
|
|
|
TRUE,
|
|
|
|
|
auth_done,
|
|
|
|
|
self);
|
2012-09-17 10:53:41 -05:00
|
|
|
|
|
|
|
|
/* Shared wifi connections require special permissions too */
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
wifi_permission = nm_utils_get_shared_wifi_permission (connection);
|
2012-09-17 10:53:41 -05:00
|
|
|
if (wifi_permission) {
|
2018-04-10 08:46:01 +02:00
|
|
|
priv->auth.call_id_wifi_shared_permission = nm_auth_manager_check_authorization (nm_auth_manager_get (),
|
|
|
|
|
priv->subject,
|
|
|
|
|
wifi_permission,
|
|
|
|
|
TRUE,
|
|
|
|
|
auth_done,
|
|
|
|
|
self);
|
2012-09-17 10:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-10 08:46:01 +02:00
|
|
|
priv->auth.result_func = result_func;
|
2018-04-17 14:59:27 +02:00
|
|
|
priv->auth.user_data = user_data;
|
2012-09-17 10:53:41 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2016-02-11 08:36:39 +01:00
|
|
|
static guint64
|
|
|
|
|
_version_id_new (void)
|
|
|
|
|
{
|
|
|
|
|
static guint64 id = 0;
|
|
|
|
|
|
|
|
|
|
return ++id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint64
|
|
|
|
|
nm_active_connection_version_id_get (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0);
|
|
|
|
|
|
|
|
|
|
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->version_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint64
|
|
|
|
|
nm_active_connection_version_id_bump (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0);
|
|
|
|
|
|
|
|
|
|
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
priv->version_id = _version_id_new ();
|
2017-03-14 11:15:05 +01:00
|
|
|
_LOGT ("new version-id %llu", (unsigned long long) priv->version_id);
|
2016-02-11 08:36:39 +01:00
|
|
|
return priv->version_id;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-02-11 08:36:39 +01:00
|
|
|
|
2012-08-22 09:38:01 -05:00
|
|
|
static void
|
2016-09-28 16:13:44 +02:00
|
|
|
_device_cleanup (NMActiveConnection *self)
|
2013-07-29 13:11:47 -05:00
|
|
|
{
|
2015-12-07 20:42:47 +01:00
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2015-08-11 13:21:54 +02:00
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
if (priv->device) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_state_changed), self);
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_master_changed), self);
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_metered_changed), self);
|
2016-09-07 17:47:26 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
if (priv->pending_activation_id) {
|
|
|
|
|
nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&priv->pending_activation_id);
|
2016-09-28 16:13:44 +02:00
|
|
|
}
|
2015-07-14 16:53:24 +02:00
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
g_clear_object (&priv->device);
|
2013-07-29 13:11:47 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
/*****************************************************************************/
|
2012-02-03 14:53:09 -06:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_property (GObject *object, guint prop_id,
|
2015-12-07 20:42:47 +01:00
|
|
|
GValue *value, GParamSpec *pspec)
|
2012-02-03 14:53:09 -06:00
|
|
|
{
|
2020-02-14 10:50:25 +01:00
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
|
2018-03-29 11:09:11 +02:00
|
|
|
char **strv;
|
2013-08-27 12:16:57 -05:00
|
|
|
NMDevice *master_device = NULL;
|
2012-02-03 14:53:09 -06:00
|
|
|
|
|
|
|
|
switch (prop_id) {
|
2018-03-29 20:36:35 +02:00
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
/* note that while priv->settings_connection.obj might not be set initially,
|
2018-03-29 20:36:35 +02:00
|
|
|
* it will be set before the object is exported on D-Bus. Hence,
|
|
|
|
|
* nobody is calling these property getters before the object is
|
|
|
|
|
* exported, at which point we will have a valid settings-connection.
|
|
|
|
|
*
|
2018-03-29 14:48:42 +02:00
|
|
|
* Therefore, intentionally not check whether priv->settings_connection.obj
|
2018-03-29 20:36:35 +02:00
|
|
|
* is set, to get an assertion failure if somebody tries to access the
|
|
|
|
|
* getters at the wrong time. */
|
2012-02-03 14:53:09 -06:00
|
|
|
case PROP_CONNECTION:
|
2018-03-29 14:48:42 +02:00
|
|
|
g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->settings_connection));
|
2012-02-03 14:53:09 -06:00
|
|
|
break;
|
2014-03-03 15:01:36 +01:00
|
|
|
case PROP_ID:
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_value_set_string (value, nm_settings_connection_get_id (priv->settings_connection.obj));
|
2014-03-03 15:01:36 +01:00
|
|
|
break;
|
2012-02-03 14:53:09 -06:00
|
|
|
case PROP_UUID:
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_value_set_string (value, nm_settings_connection_get_uuid (priv->settings_connection.obj));
|
2012-02-03 14:53:09 -06:00
|
|
|
break;
|
2014-03-03 15:01:36 +01:00
|
|
|
case PROP_TYPE:
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
g_value_set_string (value, nm_settings_connection_get_connection_type (priv->settings_connection.obj));
|
2014-03-03 15:01:36 +01:00
|
|
|
break;
|
2018-03-29 20:36:35 +02:00
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
case PROP_SPECIFIC_OBJECT:
|
2018-04-11 17:11:32 +02:00
|
|
|
g_value_set_string (value, priv->specific_object);
|
2012-02-03 14:53:09 -06:00
|
|
|
break;
|
|
|
|
|
case PROP_DEVICES:
|
2018-03-29 11:09:11 +02:00
|
|
|
strv = g_new0 (char *, 2);
|
2013-09-27 14:40:18 -05:00
|
|
|
if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
|
2018-03-29 11:09:11 +02:00
|
|
|
strv[0] = g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->device)));
|
|
|
|
|
g_value_take_boxed (value, strv);
|
2012-02-03 14:53:09 -06:00
|
|
|
break;
|
|
|
|
|
case PROP_STATE:
|
2014-10-16 18:00:54 -04:00
|
|
|
if (priv->state_set)
|
|
|
|
|
g_value_set_uint (value, priv->state);
|
|
|
|
|
else {
|
|
|
|
|
/* When the AC has just been created, its externally-visible state should
|
|
|
|
|
* be "ACTIVATING", even though internally it is "UNKNOWN".
|
|
|
|
|
*/
|
|
|
|
|
g_value_set_uint (value, NM_ACTIVE_CONNECTION_STATE_ACTIVATING);
|
|
|
|
|
}
|
2012-02-03 14:53:09 -06:00
|
|
|
break;
|
2017-09-25 19:06:02 +02:00
|
|
|
case PROP_STATE_FLAGS:
|
|
|
|
|
g_value_set_uint (value, priv->state_flags);
|
|
|
|
|
break;
|
2012-02-03 14:53:09 -06:00
|
|
|
case PROP_DEFAULT:
|
|
|
|
|
g_value_set_boolean (value, priv->is_default);
|
|
|
|
|
break;
|
2013-12-18 08:46:43 -05:00
|
|
|
case PROP_IP4_CONFIG:
|
|
|
|
|
/* The IP and DHCP config properties may be overridden by a subclass */
|
2018-04-11 17:11:32 +02:00
|
|
|
g_value_set_string (value, NULL);
|
2013-12-18 08:46:43 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DHCP4_CONFIG:
|
2018-04-11 17:11:32 +02:00
|
|
|
g_value_set_string (value, NULL);
|
2013-12-18 08:46:43 -05:00
|
|
|
break;
|
2012-02-03 14:53:09 -06:00
|
|
|
case PROP_DEFAULT6:
|
|
|
|
|
g_value_set_boolean (value, priv->is_default6);
|
|
|
|
|
break;
|
2013-12-18 08:46:43 -05:00
|
|
|
case PROP_IP6_CONFIG:
|
2018-04-11 17:11:32 +02:00
|
|
|
g_value_set_string (value, NULL);
|
2013-12-18 08:46:43 -05:00
|
|
|
break;
|
|
|
|
|
case PROP_DHCP6_CONFIG:
|
2018-04-11 17:11:32 +02:00
|
|
|
g_value_set_string (value, NULL);
|
2013-12-18 08:46:43 -05:00
|
|
|
break;
|
2012-02-03 14:53:09 -06:00
|
|
|
case PROP_VPN:
|
|
|
|
|
g_value_set_boolean (value, priv->vpn);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MASTER:
|
2013-08-27 12:16:57 -05:00
|
|
|
if (priv->master)
|
|
|
|
|
master_device = nm_active_connection_get_device (priv->master);
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
nm_dbus_utils_g_value_set_object_path (value, master_device);
|
2012-02-03 14:53:09 -06:00
|
|
|
break;
|
2013-07-29 13:11:47 -05:00
|
|
|
case PROP_INT_SUBJECT:
|
|
|
|
|
g_value_set_object (value, priv->subject);
|
|
|
|
|
break;
|
2013-09-27 17:13:43 -05:00
|
|
|
case PROP_INT_MASTER_READY:
|
|
|
|
|
g_value_set_boolean (value, priv->master_ready);
|
|
|
|
|
break;
|
2012-02-03 14:53:09 -06:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-03 16:49:21 +01:00
|
|
|
static void
|
2016-09-28 16:13:44 +02:00
|
|
|
set_property (GObject *object, guint prop_id,
|
|
|
|
|
const GValue *value, GParamSpec *pspec)
|
2013-12-03 16:49:21 +01:00
|
|
|
{
|
2016-09-28 16:13:44 +02:00
|
|
|
NMActiveConnection *self = (NMActiveConnection *) object;
|
2014-01-02 14:59:46 -05:00
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2016-09-28 16:13:44 +02:00
|
|
|
const char *tmp;
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
NMSettingsConnection *sett_conn;
|
2016-09-28 16:13:44 +02:00
|
|
|
NMConnection *acon;
|
2017-03-07 11:04:36 +01:00
|
|
|
int i;
|
2014-01-02 14:59:46 -05:00
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_INT_SETTINGS_CONNECTION:
|
|
|
|
|
/* construct-only */
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
sett_conn = g_value_get_object (value);
|
|
|
|
|
if (sett_conn)
|
|
|
|
|
_set_settings_connection (self, sett_conn);
|
2016-09-28 16:13:44 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_INT_APPLIED_CONNECTION:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
acon = g_value_get_object (value);
|
2017-09-26 13:10:01 +02:00
|
|
|
if (acon) {
|
|
|
|
|
/* we don't call _set_applied_connection_take() yet, because the instance
|
|
|
|
|
* is not yet fully initialized. We are currently in the process of setting
|
|
|
|
|
* the constructor properties.
|
|
|
|
|
*
|
|
|
|
|
* For now, just piggyback the connection, but call _set_applied_connection_take()
|
|
|
|
|
* in constructed(). */
|
2016-09-28 16:13:44 +02:00
|
|
|
priv->applied_connection = g_object_ref (acon);
|
2017-09-26 13:10:01 +02:00
|
|
|
}
|
2016-09-28 16:13:44 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_INT_DEVICE:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
nm_active_connection_set_device (self, g_value_get_object (value));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_INT_SUBJECT:
|
2018-02-05 14:55:40 +01:00
|
|
|
/* construct-only */
|
2016-09-28 16:13:44 +02:00
|
|
|
priv->subject = g_value_dup_object (value);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_INT_MASTER:
|
|
|
|
|
nm_active_connection_set_master (self, g_value_get_object (value));
|
|
|
|
|
break;
|
2017-03-07 11:04:36 +01:00
|
|
|
case PROP_INT_ACTIVATION_TYPE:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
i = g_value_get_int (value);
|
2017-03-08 12:22:01 +01:00
|
|
|
if (!NM_IN_SET (i, NM_ACTIVATION_TYPE_MANAGED,
|
|
|
|
|
NM_ACTIVATION_TYPE_ASSUME,
|
|
|
|
|
NM_ACTIVATION_TYPE_EXTERNAL))
|
2017-03-07 11:04:36 +01:00
|
|
|
g_return_if_reached ();
|
2017-06-16 14:34:37 +02:00
|
|
|
_set_activation_type (self, (NMActivationType) i);
|
2017-03-07 11:04:36 +01:00
|
|
|
break;
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
case PROP_STATE_FLAGS:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->state_flags = g_value_get_uint (value);
|
|
|
|
|
nm_assert ((guint) priv->state_flags == g_value_get_uint (value));
|
|
|
|
|
nm_assert (!NM_FLAGS_ANY (priv->state_flags, ~NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY));
|
|
|
|
|
break;
|
2018-03-28 17:18:04 +02:00
|
|
|
case PROP_INT_ACTIVATION_REASON:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
i = g_value_get_int (value);
|
|
|
|
|
priv->activation_reason = i;
|
|
|
|
|
nm_assert (priv->activation_reason == ((NMActivationReason) i));
|
|
|
|
|
break;
|
2016-09-28 16:13:44 +02:00
|
|
|
case PROP_SPECIFIC_OBJECT:
|
2018-02-05 14:55:40 +01:00
|
|
|
/* construct-only */
|
2016-09-28 16:13:44 +02:00
|
|
|
tmp = g_value_get_string (value);
|
2020-01-29 15:55:38 +01:00
|
|
|
tmp = nm_dbus_path_not_empty (tmp);
|
2018-04-11 17:05:00 +02:00
|
|
|
priv->specific_object = g_strdup (tmp);
|
2016-09-28 16:13:44 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_DEFAULT:
|
2017-11-23 21:53:04 +01:00
|
|
|
priv->is_default = g_value_get_boolean (value);
|
2016-09-28 16:13:44 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_DEFAULT6:
|
2017-11-23 21:53:04 +01:00
|
|
|
priv->is_default6 = g_value_get_boolean (value);
|
2016-09-28 16:13:44 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_VPN:
|
2018-02-05 14:55:40 +01:00
|
|
|
/* construct-only */
|
2016-09-28 16:13:44 +02:00
|
|
|
priv->vpn = g_value_get_boolean (value);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MASTER:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
2013-12-03 16:49:21 +01:00
|
|
|
}
|
2016-09-28 16:13:44 +02:00
|
|
|
}
|
2014-01-02 14:59:46 -05:00
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_active_connection_init (NMActiveConnection *self)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnectionPrivate *priv;
|
|
|
|
|
|
|
|
|
|
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate);
|
|
|
|
|
self->_priv = priv;
|
|
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
nm_dbus_track_obj_path_init (&priv->settings_connection,
|
|
|
|
|
G_OBJECT (self),
|
|
|
|
|
obj_properties[PROP_CONNECTION]);
|
|
|
|
|
|
2017-11-23 21:30:09 +01:00
|
|
|
c_list_init (&self->active_connections_lst);
|
|
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
_LOGT ("creating");
|
|
|
|
|
|
2017-03-07 11:04:36 +01:00
|
|
|
priv->activation_type = NM_ACTIVATION_TYPE_MANAGED;
|
2016-09-28 16:13:44 +02:00
|
|
|
priv->version_id = _version_id_new ();
|
2018-10-10 17:10:01 +02:00
|
|
|
|
2018-11-20 14:51:22 +01:00
|
|
|
/* the keep-alive instance must never change. Callers rely on that. */
|
2018-11-20 13:16:54 +01:00
|
|
|
priv->keep_alive = nm_keep_alive_new ();
|
2018-11-20 15:31:59 +01:00
|
|
|
_nm_keep_alive_set_owner (priv->keep_alive, G_OBJECT (self));
|
2016-09-28 16:13:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
constructed (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = (NMActiveConnection *) object;
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
|
|
|
|
|
|
2017-09-26 13:10:01 +02:00
|
|
|
if ( !priv->applied_connection
|
2018-03-29 14:48:42 +02:00
|
|
|
&& priv->settings_connection.obj)
|
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
2018-08-11 11:08:17 +02:00
|
|
|
priv->applied_connection = nm_simple_connection_new_clone (nm_settings_connection_get_connection (priv->settings_connection.obj));
|
2014-01-02 14:59:46 -05:00
|
|
|
|
2017-03-07 11:04:36 +01:00
|
|
|
_LOGD ("constructed (%s, version-id %llu, type %s)",
|
|
|
|
|
G_OBJECT_TYPE_NAME (self),
|
|
|
|
|
(unsigned long long) priv->version_id,
|
|
|
|
|
nm_activation_type_to_string (priv->activation_type));
|
2016-09-28 16:13:44 +02:00
|
|
|
|
2017-09-26 13:10:01 +02:00
|
|
|
if (priv->applied_connection) {
|
|
|
|
|
/* priv->applied_connection was set during the construction of the object.
|
|
|
|
|
* It's not yet fully initialized, so do that now.
|
|
|
|
|
*
|
|
|
|
|
* We delayed that, because we may log in _set_applied_connection_take(), and the
|
|
|
|
|
* first logging line should be "constructed" above). */
|
|
|
|
|
_set_applied_connection_take (self,
|
|
|
|
|
g_steal_pointer (&priv->applied_connection));
|
|
|
|
|
}
|
|
|
|
|
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
if (NM_FLAGS_HAS (priv->state_flags,
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY))
|
|
|
|
|
nm_keep_alive_set_settings_connection_watch_visible (priv->keep_alive, priv->settings_connection.obj);
|
|
|
|
|
|
2016-09-28 16:13:44 +02:00
|
|
|
g_return_if_fail (priv->subject);
|
2018-04-19 13:24:11 +02:00
|
|
|
g_return_if_fail (priv->activation_reason != NM_ACTIVATION_REASON_UNSET);
|
2013-12-03 16:49:21 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-22 09:38:01 -05:00
|
|
|
static void
|
|
|
|
|
dispose (GObject *object)
|
|
|
|
|
{
|
2014-01-02 14:59:46 -05:00
|
|
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
2012-08-22 09:38:01 -05:00
|
|
|
|
2017-11-23 21:30:09 +01:00
|
|
|
nm_assert (!c_list_is_linked (&self->active_connections_lst));
|
|
|
|
|
|
2015-08-11 13:21:54 +02:00
|
|
|
_LOGD ("disposing");
|
|
|
|
|
|
2018-04-18 07:43:03 +02:00
|
|
|
auth_complete (self, FALSE, "Authorization aborted");
|
2012-09-17 10:53:41 -05:00
|
|
|
|
2018-04-11 17:16:28 +02:00
|
|
|
nm_clear_g_free (&priv->specific_object);
|
2012-08-22 09:38:01 -05:00
|
|
|
|
2016-04-13 16:26:23 +02:00
|
|
|
_set_settings_connection (self, NULL);
|
2015-07-14 16:53:24 +02:00
|
|
|
g_clear_object (&priv->applied_connection);
|
2013-09-27 14:40:18 -05:00
|
|
|
|
2014-01-02 14:59:46 -05:00
|
|
|
_device_cleanup (self);
|
2013-08-28 09:08:43 -05:00
|
|
|
|
|
|
|
|
if (priv->master) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func (priv->master,
|
|
|
|
|
(GCallback) master_state_cb,
|
2014-01-02 14:59:46 -05:00
|
|
|
self);
|
2013-08-28 09:08:43 -05:00
|
|
|
}
|
2012-08-22 09:38:01 -05:00
|
|
|
g_clear_object (&priv->master);
|
2016-03-23 14:47:02 +01:00
|
|
|
|
|
|
|
|
if (priv->parent)
|
2016-06-29 14:31:19 +02:00
|
|
|
unwatch_parent (self, TRUE);
|
2016-03-23 14:47:02 +01:00
|
|
|
|
2013-07-29 13:11:47 -05:00
|
|
|
g_clear_object (&priv->subject);
|
2012-08-22 09:38:01 -05:00
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-29 14:48:42 +02:00
|
|
|
static void
|
|
|
|
|
finalize (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
|
|
|
|
|
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
nm_dbus_track_obj_path_set (&priv->settings_connection, NULL, FALSE);
|
2018-11-20 15:31:59 +01:00
|
|
|
|
2019-06-27 12:38:45 +02:00
|
|
|
nm_clear_pointer (&priv->keep_alive, nm_keep_alive_destroy);
|
2018-03-29 14:48:42 +02:00
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
static const GDBusSignalInfo signal_info_state_changed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
|
|
|
|
|
"StateChanged",
|
|
|
|
|
.args = NM_DEFINE_GDBUS_ARG_INFOS (
|
|
|
|
|
NM_DEFINE_GDBUS_ARG_INFO ("state", "u"),
|
|
|
|
|
NM_DEFINE_GDBUS_ARG_INFO ("reason", "u"),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
static const NMDBusInterfaceInfoExtended interface_info_active_connection = {
|
|
|
|
|
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
|
|
|
|
|
NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
|
|
|
|
|
.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS (
|
|
|
|
|
&nm_signal_info_property_changed_legacy,
|
|
|
|
|
&signal_info_state_changed,
|
|
|
|
|
),
|
|
|
|
|
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS (
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Connection", "o", NM_ACTIVE_CONNECTION_CONNECTION),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("SpecificObject", "o", NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Id", "s", NM_ACTIVE_CONNECTION_ID),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Uuid", "s", NM_ACTIVE_CONNECTION_UUID),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Type", "s", NM_ACTIVE_CONNECTION_TYPE),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Devices", "ao", NM_ACTIVE_CONNECTION_DEVICES),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("State", "u", NM_ACTIVE_CONNECTION_STATE),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("StateFlags", "u", NM_ACTIVE_CONNECTION_STATE_FLAGS),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Default", "b", NM_ACTIVE_CONNECTION_DEFAULT),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ip4Config", "o", NM_ACTIVE_CONNECTION_IP4_CONFIG),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Dhcp4Config", "o", NM_ACTIVE_CONNECTION_DHCP4_CONFIG),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Default6", "b", NM_ACTIVE_CONNECTION_DEFAULT6),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Ip6Config", "o", NM_ACTIVE_CONNECTION_IP6_CONFIG),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Dhcp6Config", "o", NM_ACTIVE_CONNECTION_DHCP6_CONFIG),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Vpn", "b", NM_ACTIVE_CONNECTION_VPN),
|
|
|
|
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Master", "o", NM_ACTIVE_CONNECTION_MASTER),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
.legacy_property_changed = TRUE,
|
|
|
|
|
};
|
|
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
static void
|
2013-05-07 12:18:41 -04:00
|
|
|
nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
|
2012-02-03 14:53:09 -06:00
|
|
|
{
|
2013-05-07 12:18:41 -04:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (ac_class);
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (ac_class);
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2013-05-07 12:18:41 -04:00
|
|
|
g_type_class_add_private (ac_class, sizeof (NMActiveConnectionPrivate));
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2018-03-13 10:14:06 +01:00
|
|
|
dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/ActiveConnection");
|
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API
Previously, we used the generated GDBusInterfaceSkeleton types and glued
them via the NMExportedObject base class to our NM types. We also used
GDBusObjectManagerServer.
Don't do that anymore. The resulting code was more complicated despite (or
because?) using generated classes. It was hard to understand, complex, had
ordering-issues, and had a runtime and memory overhead.
This patch refactors this entirely and uses the lower layer API GDBusConnection
directly. It replaces the generated code, GDBusInterfaceSkeleton, and
GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager
and static descriptor instances of type GDBusInterfaceInfo.
This adds a net plus of more then 1300 lines of hand written code. I claim
that this implementation is easier to understand. Note that previously we
also required extensive and complex glue code to bind our objects to the
generated skeleton objects. Instead, now glue our objects directly to
GDBusConnection. The result is more immediate and gets rid of layers of
code in between.
Now that the D-Bus glue us more under our control, we can address issus and
bottlenecks better, instead of adding code to bend the generated skeletons
to our needs.
Note that the current implementation now only supports one D-Bus connection.
That was effectively the case already, although there were places (and still are)
where the code pretends it could also support connections from a private socket.
We dropped private socket support mainly because it was unused, untested and
buggy, but also because GDBusObjectManagerServer could not export the same
objects on multiple connections. Now, it would be rather straight forward to
fix that and re-introduce ObjectManager on each private connection. But this
commit doesn't do that yet, and the new code intentionally supports only one
D-Bus connection.
Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start()
succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to
connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough
for the moment. It could be easily extended later, for example with polling whether the
system bus appears (like was done previously). Also, restart of D-Bus daemon isn't
supported either -- just like before.
Note how NMDBusManager now implements the ObjectManager D-Bus interface
directly.
Also, this fixes race issues in the server, by no longer delaying
PropertiesChanged signals. NMExportedObject would collect changed
properties and send the signal out in idle_emit_properties_changed()
on idle. This messes up the ordering of change events w.r.t. other
signals and events on the bus. Note that not only NMExportedObject
messed up the ordering. Also the generated code would hook into
notify() and process change events in and idle handle, exhibiting the
same ordering issue too.
No longer do that. PropertiesChanged signals will be sent right away
by hooking into dispatch_properties_changed(). This means, changing
a property in quick succession will no longer be combined and is
guaranteed to emit signals for each individual state. Quite possibly
we emit now more PropertiesChanged signals then before.
However, we are now able to group a set of changes by using standard
g_object_freeze_notify()/g_object_thaw_notify(). We probably should
make more use of that.
Also, now that our signals are all handled in the right order, we
might find places where we still emit them in the wrong order. But that
is then due to the order in which our GObjects emit signals, not due
to an ill behavior of the D-Bus glue. Possibly we need to identify
such ordering issues and fix them.
Numbers (for contrib/rpm --without debug on x86_64):
- the patch changes the code size of NetworkManager by
- 2809360 bytes
+ 2537528 bytes (-9.7%)
- Runtime measurements are harder because there is a large variance
during testing. In other words, the numbers are not reproducible.
Currently, the implementation performs no caching of GVariants at all,
but it would be rather simple to add it, if that turns out to be
useful.
Anyway, without strong claim, it seems that the new form tends to
perform slightly better. That would be no surprise.
$ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done)
- real 1m39.355s
+ real 1m37.432s
$ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done)
- real 0m26.843s
+ real 0m25.281s
- Regarding RSS size, just looking at the processes in similar
conditions, doesn't give a large difference. On my system they
consume about 19MB RSS. It seems that the new version has a
slightly smaller RSS size.
- 19356 RSS
+ 18660 RSS
2018-02-26 13:51:52 +01:00
|
|
|
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_active_connection);
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2012-02-03 14:53:09 -06:00
|
|
|
object_class->get_property = get_property;
|
|
|
|
|
object_class->set_property = set_property;
|
2013-07-29 13:11:47 -05:00
|
|
|
object_class->constructed = constructed;
|
2012-02-03 14:53:09 -06:00
|
|
|
object_class->dispose = dispose;
|
2018-03-29 14:48:42 +02:00
|
|
|
object_class->finalize = finalize;
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2016-04-13 13:33:04 +02:00
|
|
|
obj_properties[PROP_CONNECTION] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_ID] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_ID, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_UUID] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_UUID, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_TYPE] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_TYPE, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_SPECIFIC_OBJECT] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_DEVICES] =
|
|
|
|
|
g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES, "", "",
|
|
|
|
|
G_TYPE_STRV,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_STATE] =
|
|
|
|
|
g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE, "", "",
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_DEACTIVATING,
|
|
|
|
|
NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2017-09-25 19:06:02 +02:00
|
|
|
obj_properties[PROP_STATE_FLAGS] =
|
|
|
|
|
g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE_FLAGS, "", "",
|
|
|
|
|
0, G_MAXUINT32, NM_ACTIVATION_STATE_FLAG_NONE,
|
core: improve and fix keeping connection active based on "connection.permissions"
By setting "connection.permissions", a profile is restricted to a
particular user.
That means for example, that another user cannot see, modify, delete,
activate or deactivate the profile. It also means, that the profile
will only autoconnect when the user is logged in (has a session).
Note that root is always able to activate the profile. Likewise, the
user is also allowed to manually activate the own profile, even if no
session currently exists (which can easily happen with `sudo`).
When the user logs out (the session goes away), we want do disconnect
the profile, however there are conflicting goals here:
1) if the profile was activate by root user, then logging out the user
should not disconnect the profile. The patch fixes that by not
binding the activation to the connection, if the activation is done
by the root user.
2) if the profile was activated by the owner when it had no session,
then it should stay alive until the user logs in (once) and logs
out again. This is already handled by the previous commit.
Yes, this point is odd. If you first do
$ sudo -u $OTHER_USER nmcli connection up $PROFILE
the profile activates despite not having a session. If you then
$ ssh guest@localhost nmcli device
you'll still see the profile active. However, the moment the SSH session
ends, a session closes and the profile disconnects. It's unclear, how to
solve that any better. I think, a user who cares about this, should not
activate the profile without having a session in the first place.
There are quite some special cases, in particular with internal
activations. In those cases we need to decide whether to bind the
activation to the profile's visibility.
Also, expose the "bind" setting in the D-Bus API. Note, that in the future
this flag may be modified via D-Bus API. Like we may also add related API
that allows to tweak the lifetime of the activation.
Also, I think we broke handling of connection visiblity with 37e8c53eeed
"core: Introduce helper class to track connection keep alive". This
should be fixed now too, with improved behavior.
Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394
https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
2017-09-25 19:06:02 +02:00
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2016-04-13 13:33:04 +02:00
|
|
|
obj_properties[PROP_DEFAULT] =
|
|
|
|
|
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_IP4_CONFIG] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_IP4_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_DHCP4_CONFIG] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP4_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_DEFAULT6] =
|
|
|
|
|
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_IP6_CONFIG] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_IP6_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_DHCP6_CONFIG] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP6_CONFIG, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_VPN] =
|
|
|
|
|
g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_MASTER] =
|
|
|
|
|
g_param_spec_string (NM_ACTIVE_CONNECTION_MASTER, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2012-02-03 14:53:09 -06:00
|
|
|
|
2012-08-22 09:38:01 -05:00
|
|
|
/* Internal properties */
|
2016-04-13 13:33:04 +02:00
|
|
|
obj_properties[PROP_INT_SETTINGS_CONNECTION] =
|
|
|
|
|
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, "", "",
|
|
|
|
|
NM_TYPE_SETTINGS_CONNECTION,
|
|
|
|
|
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2016-09-07 17:47:26 +02:00
|
|
|
obj_properties[PROP_INT_APPLIED_CONNECTION] =
|
|
|
|
|
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION, "", "",
|
|
|
|
|
NM_TYPE_CONNECTION,
|
|
|
|
|
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2016-04-13 13:33:04 +02:00
|
|
|
obj_properties[PROP_INT_DEVICE] =
|
|
|
|
|
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "", "",
|
|
|
|
|
NM_TYPE_DEVICE,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_INT_SUBJECT] =
|
|
|
|
|
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SUBJECT, "", "",
|
|
|
|
|
NM_TYPE_AUTH_SUBJECT,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_INT_MASTER] =
|
|
|
|
|
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_MASTER, "", "",
|
|
|
|
|
NM_TYPE_ACTIVE_CONNECTION,
|
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
|
|
|
|
obj_properties[PROP_INT_MASTER_READY] =
|
|
|
|
|
g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_MASTER_READY, "", "",
|
|
|
|
|
FALSE, G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2017-03-07 11:04:36 +01:00
|
|
|
obj_properties[PROP_INT_ACTIVATION_TYPE] =
|
|
|
|
|
g_param_spec_int (NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, "", "",
|
|
|
|
|
NM_ACTIVATION_TYPE_MANAGED,
|
2017-03-08 12:22:01 +01:00
|
|
|
NM_ACTIVATION_TYPE_EXTERNAL,
|
2017-03-07 11:04:36 +01:00
|
|
|
NM_ACTIVATION_TYPE_MANAGED,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2018-03-28 17:18:04 +02:00
|
|
|
obj_properties[PROP_INT_ACTIVATION_REASON] =
|
|
|
|
|
g_param_spec_int (NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, "", "",
|
|
|
|
|
NM_ACTIVATION_REASON_UNSET,
|
|
|
|
|
NM_ACTIVATION_REASON_USER_REQUEST,
|
|
|
|
|
NM_ACTIVATION_REASON_UNSET,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
|
2016-04-13 13:33:04 +02:00
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
2013-09-27 17:13:43 -05:00
|
|
|
|
2014-10-23 17:04:49 -05:00
|
|
|
signals[DEVICE_CHANGED] =
|
2016-04-13 13:33:04 +02:00
|
|
|
g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
G_STRUCT_OFFSET (NMActiveConnectionClass, device_changed),
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, NM_TYPE_DEVICE, NM_TYPE_DEVICE);
|
2014-10-23 17:04:49 -05:00
|
|
|
|
2015-06-03 09:15:24 +02:00
|
|
|
signals[DEVICE_METERED_CHANGED] =
|
2016-04-13 13:33:04 +02:00
|
|
|
g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
G_STRUCT_OFFSET (NMActiveConnectionClass, device_metered_changed),
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_UINT);
|
2015-06-03 09:15:24 +02:00
|
|
|
|
2016-03-23 14:47:02 +01:00
|
|
|
signals[PARENT_ACTIVE] =
|
2016-04-13 13:33:04 +02:00
|
|
|
g_signal_new (NM_ACTIVE_CONNECTION_PARENT_ACTIVE,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
G_STRUCT_OFFSET (NMActiveConnectionClass, parent_active),
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION);
|
2016-03-23 14:47:02 +01:00
|
|
|
|
2017-03-05 15:30:24 +01:00
|
|
|
signals[STATE_CHANGED] =
|
|
|
|
|
g_signal_new (NM_ACTIVE_CONNECTION_STATE_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
|
2008-03-26 13:43:01 +00:00
|
|
|
}
|