For internal compilation we want to be able to use deprecated
API without warnings.
Define the version min/max macros to effectively disable deprecation
warnings.
However, don't do it via CFLAGS option in the makefiles, instead hack it
to "nm-default.h". After all, *every* source file that is for internal
compilation needs to include this header as first.
Relax our error checking which will allow us to try harder to
make the best out of whatever NetworkManager sends us.
Also, drop the g_warning(). First, now we really don't expect this
function to fail. And even in that case, raising a g_warning() from
the library is not very friendly to the user of libnm.
We're expecting four callbacks: a client::devices change,
client::active-connections change, client::activate callback,
and a device::active-connection change.
We only hook the second one in the callback to the first one, and
only if client::active-connections is not set already. If it is
(when running slowly in valgrind), we just decrement the counter.
However, as the counter is one less than it should be, it would
underflow and we wait forever* instead.
For the value of forever=20s, given that's the timeout of the
mockup service.
- All internal source files (except "examples", which are not internal)
should include "config.h" first. As also all internal source
files should include "nm-default.h", let "config.h" be included
by "nm-default.h" and include "nm-default.h" as first in every
source file.
We already wanted to include "nm-default.h" before other headers
because it might contains some fixes (like "nm-glib.h" compatibility)
that is required first.
- After including "nm-default.h", we optinally allow for including the
corresponding header file for the source file at hand. The idea
is to ensure that each header file is self contained.
- Don't include "config.h" or "nm-default.h" in any header file
(except "nm-sd-adapt.h"). Public headers anyway must not include
these headers, and internal headers are never included after
"nm-default.h", as of the first previous point.
- Include all internal headers with quotes instead of angle brackets.
In practice it doesn't matter, because in our public headers we must
include other headers with angle brackets. As we use our public
headers also to compile our interal source files, effectively the
result must be the same. Still do it for consistency.
- Except for <config.h> itself. Include it with angle brackets as suggested by
https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers
Add test showing how libnm/libnm-glib handles invalid connections,
i.e. connections that fail nm_connection_verify(). libnm implements
settings a static types (via different NMSetting types). This makes
it unavoidable that eventually a newer server version will
expose connections that fail verification in the client.
For example, master added a new base type NMSettingTun. This setting type
was not backported to legacy libnm-glib, thus such connection will not verify.
Also, we want that newer server versions are backward compatible with older
library versions. Thus also a pre-NMSettingTun libnm version has the same
problem.
The test shows that libnm is agnostic to whether the connection verifies.
That is consistent behavior, but possibly problematic because most
accessors to connections assert against a valid connection. Thus using
the common nm_connection*() functions on an invalid connection can lead
to problems.
Also, due to the static nature of our NMSetting types, some properties
can be silently dropped and thus mangling the connection without the
library user noticing.
libnm-glib prints a g_warning() whenever parsing an invalid connection.
When an invalid connection is added initially, it is exposed to the library
user. When a connection gets later invalidated due to an update, the
connection disappears and it stays missing even if a subsequent update
makes the connection valid again.
libnm-glib's behavior indicates that we might wanted to hide invalid
connections from the user. But it's very broken there.
Up to now, the "include" directory contained (only) header files that were
used project-wide by libs, core, clients, et al.
Since the directory now also contains a non-header file, the "include"
name is misleading. Instead of adding yet another directory that is
project-wide, with non-header-only content, rename the "include"
directory to "shared".
The unit tests for libnm and libnm-glib use a NetworkManager stub
service written in Python (test-networkmanager-service.py). As they
share the same server, it makes sense to also share the same utility
code to drive the stub.
Move the common code to include/.
Note that contrary to "nm-test-utils.h", "nm-test-libnm-utils.h" is not
a header-only file. Instead its implementation is in "nm-test-utils-impl.c".
The reason for that this split is, if we later have yet another non-header-only
test-utility, then all the implementations are in "nm-test-utils-impl.c", requiring
the tests to link only one object file.
For libnm library, "nm-dbus-interface.h" contains defines like the D-Bus
paths of NetworkManager. It is desirable to have this header usable without
having a dependency on "glib.h", for example for a QT application. For that,
commit c0852964a8 removed that dependancy.
For libnm-glib library, the analog to "nm-dbus-interface.h" is
"NetworkManager.h", and the same applies there. Commit
159e827a72 removed that include.
However, that broke build on PackageKit [1] which expected to get the
version macros by including "NetworkManager.h". So at least for libnm-glib,
we need to preserve old behavior so that a user including
"NetworkManager.h" gets the version macros, but not "glib.h".
Extract the version macros to a new header file "nm-version-macros.h".
This header doesn't include "glib.h" and can be included from
"NetworkManager.h". This gives as previous behavior and a glib-free
include.
For libnm we still don't include "nm-version-macros.h" to "nm-dbus-interface.h".
Very few users will actually need the version macros, but not using
libnm.
Users that use libnm, should just include (libnm's) "NetworkManager.h" to
get all headers.
As a special case, a user who doesn't want to use glib/libnm, but still
needs both "nm-dbus-interface.h" and "nm-version-macros.h", can include
them both separately.
[1] https://github.com/hughsie/PackageKit/issues/85
Fixes: 4545a7fe96
Rather than randomly including one or more of <glib.h>,
<glib-object.h>, and <gio/gio.h> everywhere (and forgetting to include
"nm-glib-compat.h" most of the time), rename nm-glib-compat.h to
nm-glib.h, include <gio/gio.h> from there, and then change all .c
files in NM to include "nm-glib.h" rather than including the glib
headers directly.
(Public headers files still have to include the real glib headers,
since nm-glib.h isn't installed...)
Also, remove glib includes from header files that are already
including a base object header file (which must itself already include
the glib headers).
Add a file containing the defines like DBUS_INTERFACE_DBUS from
dbus-shared.h, and use it from the gdbus-using files.
Also, convert a bunch of other places that were previously hardcoding
the string values to use the defines instead, and fix the ifcfg-rh
plugin to properly namespace its own D-Bus-related defines.
Error: INFINITE_LOOP (CWE-835): [#def17]
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:93: loop_top: Top of the loop.
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:94: loop_bottom: Bottom of the loop.
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:93: loop_condition: If "notified" is initially true then it will remain true.
Error: INFINITE_LOOP (CWE-835): [#def18]
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:191: loop_top: Top of the loop.
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:192: loop_bottom: Bottom of the loop.
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:191: loop_condition: If "result & NOTIFY_MASK" is initially true then it will remain true.
NetworkManager-0.9.11.0/libnm/tests/test-nm-client.c:191: loop_condition: If "result & SIGNAL_MASK" is initially true then it will remain true.
config.h should be included from every .c file, and it should be
included before any other include. Fix that.
(As a side effect of how I did this, this also changes us to
consistently use "config.h" rather than <config.h>. To the extent that
it matters [which is not much], quotes are more correct anyway, since
we're talking about a file in our own build tree, not a system
include.)
Causes the info->remaining to be counted incorrectly possibly resulting in
g_main_loop_quit() being called twice:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5a03155 in g_mutex_lock (mutex=0x7ffff7b764b4) at gthread-posix.c:1331
1331 if G_UNLIKELY (g_atomic_int_add (&mutex->i[0], 1) != 0)
Missing separate debuginfos, use: debuginfo-install libgcc-4.9.2-1.fc21.x86_64 libgudev1-216-8.fc21.x86_64 libselinux-2.3-5.fc21.x86_64 libuuid-2.25.2-1.fc21.x86_64 ncurses-libs-5.9-16.20140323.fc21.x86_64 nspr-4.10.7-1.fc21.x86_64 nss-3.17.2-1.fc21.x86_64 nss-softokn-3.17.2-1.fc21.x86_64 nss-softokn-freebl-3.17.2-1.fc21.x86_64 nss-util-3.17.2-1.fc21.x86_64 sqlite-3.8.7-1.fc21.x86_64 systemd-libs-216-8.fc21.x86_64
(gdb) bt
#0 0x00007ffff5a03155 in g_mutex_lock (mutex=0x7ffff7b764b4) at gthread-posix.c:1331
#1 0x00007ffff59bf258 in g_main_loop_quit (loop=0x7fffffffd130) at gmain.c:4000
#5 0x00007ffff5edc3bf in <emit signal notify:active-connection on instance 0x5555557bd180 [NMDeviceVlan]> (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3365
#2 0x00007ffff5ec1d35 in g_closure_invoke (closure=0x5555557b3da0, return_value=return_value@entry=0x0, n_param_values=2, param_values=param_values@entry=0x7fffffffd760, invocation_hint=invocation_hint@entry=0x7fffffffd700) at gclosure.c:768
#3 0x00007ffff5ed3a52 in signal_emit_unlocked_R (node=node@entry=0x555555787040, detail=detail@entry=341, instance=instance@entry=0x5555557bd180, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffd760) at gsignal.c:3553
#4 0x00007ffff5edc191 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffd8f0) at gsignal.c:3309
#6 0x00007ffff5ec6465 in g_object_dispatch_properties_changed (object=0x7ffff7b764b4, n_pspecs=1434087776, pspecs=0x5555557ba880) at gobject.c:1056
#7 0x00007ffff5ec88c1 in g_object_notify (pspec=<optimized out>, object=0x5555557bd180 [NMDeviceVlan])
at gobject.c:1149
#8 0x00007ffff5ec88c1 in g_object_notify (object=0x5555557bd180 [NMDeviceVlan], property_name=property_name@entry=0x7ffff7b772f6 "active-connection") at gobject.c:1197
#9 0x00007ffff7ae57d3 in deferred_notify_cb (data=<optimized out>) at nm-object.c:246
#10 0x00007ffff59beafb in g_main_context_dispatch (context=0x555555784ac0) at gmain.c:3111
#11 0x00007ffff59beafb in g_main_context_dispatch (context=context@entry=0x555555784ac0) at gmain.c:3710
#12 0x00007ffff59bee98 in g_main_context_iterate (context=0x555555784ac0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3781
#13 0x00007ffff59bf1c2 in g_main_loop_run (loop=0x5555557699e0) at gmain.c:3975
#14 0x000055555555811d in test_activate_virtual () at test-nm-client.c:1103
#15 0x00007ffff59e4243 in g_test_run_suite_internal (tc=0x555555769a30) at gtestutils.c:2059
#16 0x00007ffff59e4243 in g_test_run_suite_internal (suite=suite@entry=0x555555766640, path=path@entry=0x7ffff5a6355e "") at gtestutils.c:2120
#17 0x00007ffff59e4412 in g_test_run_suite_internal (suite=suite@entry=0x555555766620, path=<optimized out>,
path@entry=0x7ffff5a6355e "") at gtestutils.c:2131
#18 0x00007ffff59e477b in g_test_run_suite (suite=0x555555766620) at gtestutils.c:2184
#19 0x00007ffff59e47b1 in g_test_run () at gtestutils.c:1488
#20 0x0000555555556c01 in main (argc=1, argv=0x7fffffffe028) at test-nm-client.c:1189
https://bugzilla.gnome.org/show_bug.cgi?id=739861
Because internal objects do some processing/setup in the various
_added class signal handlers, they need to be emitted before
property change notifications. Otherwise it leads to situations
where external objects that listen to NMClient property changes
will be called before internal processing has been completed.
Specifically, NMRemoteSettings uses connection_added() to check
connection visibility and assign the new connection to one of
two internal arrays. If a client got a property notification
for NMClient::connections before NMRemoteSettings can process
the new connection, then nm_client_get_connections() will
return an empty array because NMRemoteSettings hasn't had the
chance to add the new connection to priv->visible yet, which
is done in NMRemoteSettings::connection_added().
Fixes:Beaker:NetworkManager_Test240_nmtui_general_realtime_refresh_edit_screen
Property notifications are queued during object initialization and
reloading, but the added/removed signals were emitted immediately
even before the object was fully initialized.
Additionally, depending on how long asynchronous initialization took,
the notifications could have been emitted before the object was
fully initialized as deferred_notify_cb() wasn't being suppressed
until all the properties were complete.
For synchronous intialization, signals could be emitted at various
times during initialization and not all of the object's properties
may be read. Furthermore property notifications were queued in an
idle handler, which breaks users that may not use a mainloop. All
signals and notifications should be emitted immediately after
initialization is complete for synchronous initialization.
To make things consistent and ensure that all signals and notifications
are emitted only when initialization is complete, queue signals for
deferred emission and only run notifications/signals when all the
object's properties have been read. For synchronous initialization,
emit all notifications and signals immediately after initialization
and not from an idle handler.
It might simply mean that the object disappeared (which is perfectly fine):
(process:7680): libnm-WARNING **: Could not fetch property 'Vpn' of interface 'org.freedesktop.NetworkManager.Connection.Active' on /org/freedesktop/NetworkManager/ActiveConnection/151: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: Method "Get" with signature "ss" on interface "org.freedesktop.DBus.Properties" doesn't exist
https://bugzilla.gnome.org/show_bug.cgi?id=739255
libnm mostly used GPtrArrays in its APIs, except that arrays of
connections were usually GSLists. Fix this and make them GPtrArrays
too (and rename nm_client_list_connections() to
nm_client_get_connections() to match everything else).
They require a tty or X11 displays, thus are not suitable for headless runs
(such as in mock). Furthermore, they die with the tty or X11 session, which
is somehow late -- a lot of them may accumulate. Let's kill them right away.
Consolidate NMClientError and NMObjectError (such that there is now
only one libnm-API-specific error domain). In particular, merge
NM_CONNECTION_ERROR_CONNECTION_REMOVED with
NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE as the new
NM_CONNECTION_ERROR_OBJECT_CREATION_FAILED.
Also make object_creation_failed() be a plain method rather than a
signal, since there's no reason for anyone to be connecting to it on
another object. And remove its GError argument because the subclass
can just create its own more-specific error.
Move the definition of NMSecretAgentError to nm-errors, register it
with D-Bus, and verify in the tests that it maps correctly.
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR is renamed to
NM_SECRET_AGENT_ERROR_FAILED, and NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED
to NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, for consistency with other
error domains. While NMSecretAgentError, unlike most other error
domains, has always been correctly mapped across D-Bus, the renaming
is not an ABI break, because the daemon never checks for either of
those values, so all versions of the daemon will treat
"org.freedesktop.NetworkManager.SecretAgent.InternalError" and
"org.freedesktop.NetworkManager.SecretAgent.Failed" the same (by just
ignoring the error name and keeping only the error message).
Move the definition of NMSettingsError to nm-errors, register it with
D-Bus, and verify in the tests that it maps correctly.
Remove a few unused error codes, simplify a few others, and rename
GENERAL to FAILED and HOSTNAME_INVALID to INVALID_HOSTNAME, for
consistency.
Merge libnm's NMDeviceError and the daemon's NMDeviceError into a
single enum (in nm-errors.h). Register the domain with D-Bus, and add
a test that the client side decodes it correctly.
The daemon's NM_DEVICE_ERROR_CONNECTION_INVALID gets absorbed into
libnm's NM_DEVICE_ERROR_INVALID_CONNECTION, and
NM_DEVICE_ERROR_UNSUPPORTED_DEVICE_TYPE gets dropped, since it was
only returned from one place, which is now using
NM_DEVICE_ERROR_FAILED, since (a) it ought to be a "can't happen", and
(b) the only caller of that function just logs error->message and then
frees the error without ever looking at the code.
Register NMConnectionError with D-Bus on both sides, so that, eg,
connection validation failures in the daemon will translate to the
correct error codes in the client.
Test NMClient's handling of active connections, and in particular test
that we can correctly resolve the circular reference between an
NMDevice and an NMActiveConnection, both synchronously and
asynchronously.