Commit graph

24906 commits

Author SHA1 Message Date
Thomas Haller
95ea3ccad8 libnm: use nm_utils_ipaddr_is_valid() to implement nm_utils_ipaddr_valid() 2020-01-28 11:17:41 +01:00
Thomas Haller
cdfbbe651b shared: add nm_utils_ipaddr_is_valid()/nm_utils_ipaddr_is_normalized() helpers 2020-01-28 11:17:41 +01:00
Thomas Haller
0f9664f417 shared: use static array indices in function parameter declarations of _nm_utils_inet[46]_ntop()
This should give the compiler more possibilities to warn about wrong
use of the API.

In practice, my current compiler wouldn't flag any issues. However,
some compilers (or compile options) might.
2020-01-28 11:17:41 +01:00
Thomas Haller
cd0863a339 all: use _nm_utils_inet4_ntop() instead of nm_utils_inet4_ntop()
and _nm_utils_inet6_ntop() instead of nm_utils_inet6_ntop().

nm_utils_inet4_ntop()/nm_utils_inet6_ntop() are public API of libnm.
For one, that means they are only available in code that links with
libnm/libnm-core. But such basic helpers should be available everywhere.

Also, they accept NULL as destination buffers. We keep that behavior
for potential libnm users, but internally we never want to use the
static buffers. This patch needs to take care that there are no callers
of _nm_utils_inet[46]_ntop() that pass NULL buffers.

Also, _nm_utils_inet[46]_ntop() are inline functions and the compiler
can get rid of them.

We should consistently use the same variant of the helper. The only
downside is that the "good" name is already taken. The leading
underscore is rather ugly and inconsistent.

Also, with our internal variants we can use "static array indices in
function parameter declarations" next. Thereby the compiler helps
to ensure that the provided buffers are of the right size.
2020-01-28 11:17:41 +01:00
Thomas Haller
c0bd6752b9 shared: move nm_utils_inet* helpers from libnm-core to shared 2020-01-28 11:17:41 +01:00
Thomas Haller
06d6de95d6 platform: use IN6_IS_ADDR_UNSPECIFIED() to check for set IPv6 address in _nl_msg_new_link_set_linkinfo() 2020-01-28 11:17:41 +01:00
Thomas Haller
299fc555b4 libnm/tests: test nm_ip_addr_zero is all-zero and compares to IP addresse as expected 2020-01-28 11:17:41 +01:00
Thomas Haller
e49e509262 libnm: use nm_utils_addr_family_to_size() in "nm-setting-ip-config.c" 2020-01-28 11:17:41 +01:00
Thomas Haller
8590d2ecfb libnm/secret-agent: merge branch 'th/secret-agent-rework'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/383
2020-01-28 11:07:59 +01:00
Thomas Haller
c1ec829099 libnm/secret-agent: rework NMSecretAgentOld
Note that the name "NMSecretAgentOld" comes from when libnm was forked
from libnm-glib. There was a plan to rework the secret agent API and
replace it by a better one. That didn't happen (yet), instead our one
and only agent implementation is still lacking. Don't add a new API, instead
try to improve the existing one, without breaking existing users. Just
get over the fact that the name "NMSecretAgentOld" is ugly.

Also note how nm-applet uses NMSecretAgentOld. It subtypes a class
AppletAgent. The constructor applet_agent_new() is calling the synchronous
g_initable_init() initialization with auto-register enabled. As it was,
g_initable_init() would call nm_secret_agent_old_register(), and if the
"Register" call failed, initialization failed for good. There are even
unit tests that test this behavior. This is bad behavior. It means, when
you start nm-applet without NetworkManager running, it will fail to create
the AppletAgent instance. It would hence be the responsibility of the applet
to recover from this situation (e.g. by retrying after timeout or watching
the D-Bus name owner). Of course, nm-applet doesn't do that and won't recover
from such a failure.
NMSecretAgentOld must try hard not to fail and recover automatically. The
user of the API is not interested in implementing the registration,
unregistration and retry handling. Instead, it should just work best
effort and transparently to the user of the API.

Differences:

- no longer use gdbus-codegen generate bindings. Use GDBusConnection
  directly instead. These generated proxies complicate the code by
  introducing an additional, stateful layer.

- properly handle GMainContext and synchronous initialization by using an
  internal GMainContext.
  With this NMSecretAgentOld can be used in a multi threaded context
  with separate GMainContext. This does not mean that the object
  itself became thread safe, but that the GMainContext gives the means
  to coordinate multi-threaded access.

- there are no more blocking calls except g_initiable_init() which
  iterates an internal GMainContext until initialization completes.

- obtaining the Unix user ID with "GetConnectionUnixUser" to authenticate
  the server is now done asynchronously and only once per name-owner.

- NMSecretAgentOld will now register/export the Agent D-Bus object
  already during initialization and stay registered as long as the
  instance is alive. This is because usually registering a D-Bus
  object would not fail, unless the D-Bus path is already taken.
  Such an error would mean that another agent is registered for the same
  GDBusConnection, that likely would be a bug in the caller. Hence,
  such an issue is truly non-recoverable and should be reported early to
  the user. There is a change in behavior compared to before, where previously
  the D-Bus object would only be registered while the instance is enabled.
  This makes a difference if the user intended to keep the NMSecretAgentOld
  instance around in an unregistered state.
  Note that nm_secret_agent_old_destroy() was added to really unregister
  the D-Bus object. A destroyed instance can no longer be registered.

- the API no longer fully exposes the current registration state. The
  user either enables or disables the agent. Then, in the background
  NMSecretAgentOld will register, and serve requests as they come. It
  will also always automatically re-register and it can de-facto no
  longer fail. That is, there might be a failure to register, or the
  NetworkManager peer might not be authenticated (non-root) or there
  might be some other error, or NetworkManager might not be running.
  But such errors are not exposed to the user. The instance is just not
  able to provide the secrets in those cases, but it may recover if the
  problem can be resolved.

- In particular, it makes no sense that nm_secret_agent_old_register*()
  fails, returns an error, or waits until registration is complete. This
  API is now only to enable/disable the agent. It is idempotent and
  won't fail (there is a catch, see next point).
  In particular, nm_secret_agent_old_unregister*() cannot fail anymore.

- However, with the previous point there is a problem/race. When you create
  a NMSecretAgentOld instance and immediately afterwards activate a
  profile, then you want to be sure that the registration is complete
  first. Otherwise, NetworkManager might fail the activation because
  no secret agent registered yet. A partial solution for this is
  that g_initiable_init()/g_async_initable_init_async() will block
  until registration is complete (or with or without success). That means,
  if NetworkManager is running, initializing the NMSecretAgentOld will
  wait until registration is complete (or failed). However, that does not
  solve the race if NetworkManager was not running when creating the
  instance.
  To solve that race, the user may call nm_secret_agent_old_register_async()
  and wait for the command to finish before starting activating. While
  async registration no longer fails (in the sense of leaving the agent
  permanently disconnected), it will try to ensure that we are
  successfully registered and ready to serve requests. By using this
  API correctly, a race can be avoided and the user can know that the
  instance is now ready to serve request.
2020-01-28 10:54:14 +01:00
Thomas Haller
2c30c1a04f libnm/secret-agent: add dbus-connection and main-context properties to NMSecretAgentOld
The NMSecretAgentOld is build very much around a GDBusConnection, and GDBusConnection
is build around GMainContext. That means, a NMSecretAgentOld instance is
strongly related to these two. That is because NMSecretAgentOld will register
to signals on D-Bus, using GDBusConnection. Hence, that GDBusConnection instance
and the calling GMainContext becomes central to the NMSecretAgentOld instance.
Also, the GMainContext is the way to synchronize access to the
NMSecretAgentOld. Used properly, this allows using the API in multi
threaded context.

Expose these two in the public API. Since NMSecretAgentOld is part of
libnm and supposed to provide a flexible API, this is just useful to
have.

Also, allow to provide a GDBusConnection as construct-only property. This way,
the instance can be used independent of g_bus_get() and the user has full control.

There is no setter for the GMainContext, because it just takes the
g_main_context_get_thread_default() instance at the time of
construction.
2020-01-28 10:54:14 +01:00
Thomas Haller
0382e54d8d libnm: expose nml_cleanup_context_busy_watcher_on_idle() helper for reuse
This can be used by NMSecretAgentOld.
2020-01-28 10:54:14 +01:00
Thomas Haller
587c35b1f4 libnm: factor out nml_init_data_return() for reuse 2020-01-28 10:54:14 +01:00
Thomas Haller
718e524a7f libnm: move InitData to nm-libnm-utils.h for sharing
It can be reused.
2020-01-28 10:54:14 +01:00
Thomas Haller
50bda649b1 libnm: expose nm_context_busy_watcher_integrate_source() as internal API for reuse
This will also be useful for NMSecretAgentOld.

The mechanics how NMClient handles the GMainContext and the
context-busy-watcher apply really to every GObject that uses
GDBusConnection and registers to signals.

At least, as long as the API provides no shutdown/stop method,
because that means shutdown/stop happens when unreferencing the
instance, at which point pending operations get cancelled (but
they cannot complete right away due to the nature of GTask and
g_dbus_connection_call()). If there is a shutdown/stop API, then all
pending operations could keep the instance alive, and the instance
would sticks around (and keeps the GMainContext busy) until shutdown is
completed. Basically, then the instance could be the context-busy-watcher
itself.

But in existing API which does not require the user to explicitly shutdown,
that is not a feasible (backward compatible) addition. But the context-busy-watcher
object is.
2020-01-28 10:54:14 +01:00
Thomas Haller
13d050a3b7 libnm/secret-agent/tests: iterate main context during test cleanup
The test only uses one GMainContext (the g_main_context_get_default()
singleton.

Between tests, ensure that we iterate the main context long enough,
so that no more sources from the previous test are queued. Otherwise,
there is an ugly dependency between tests and the order in which
they run.
2020-01-28 10:54:14 +01:00
Thomas Haller
8dc760d2c2 libnm/secret-agent/tests: test async/sync initialization of NMSecretAgentOld
Use nmtstc_context_object_new() to create the NMSecretAgentOld. This
randomly uses sync or async initialization, and checks whether the
main context gets iterated.
2020-01-28 10:54:14 +01:00
Thomas Haller
18512274ea libnm/secret-agent/tests: cleanup test code 2020-01-28 10:54:14 +01:00
Thomas Haller
15888fc3a8 libnm/tests: cleanup add_device_common() test helper
- use NMClient's GMainContext instead of the default main context.
- add some more assertions.
- use cleanup attribute to free resources.
2020-01-28 10:54:14 +01:00
Thomas Haller
6acdc42e04 libnm/tests: extend nmtstc_client_new() to create other GObject types
nmtstc_client_new() exists to test creating a GInitiable/GAsyncInitiable
in different GMainContext combinations.

This is not only useful for NMClient but will also be useful for
NMSecretAgentOld. Add nmtstc_context_object_new() to allow for that.

Also, allow passing parameters when creating the object.

The resulting nmtstc_context_object_new() is relatively complex. But
this is only testing code, that aims to construct the respective GObject
instance in various manners (randomly using the sync or async initialization).
It is complex, but delivers at testing various code paths of the
underlying code. The API that it provides however is simple.

Also drop _nmtstc_client_new_extra_context() to create the instance with
a different context. For one, this requires that the internal context is
integrated as long as the context-busy-watcher exists. That was not
handled correctly. Also, creating a NMClient instance with a different
context than the current thread default at construct time has
implications to the test later. The tests don't want this variant, and
don't handle them properly. So drop this.
2020-01-28 10:54:14 +01:00
Thomas Haller
f2baa10bb8 shared/tests: add nmtst_main_context_iterate_until() helper
Like nmtst_main_context_iterate_until_assert(), but allows to
run into timeout.
2020-01-28 10:54:14 +01:00
Thomas Haller
90bb46c8ee shared/tests/trivial: rename nmtst_main_context_iterate_until() to nmtst_main_context_iterate_until_assert()
nmtst_main_context_iterate_until*() iterates until the condition is
satisfied. If that doesn't happen within timeout, it fails an assertion.

Rename the function to make that clearer.
2020-01-28 10:54:14 +01:00
Thomas Haller
eceaa39a1e shared/tests: use nmtst_g_source_set_boolean_true() in nmtst_main_context_iterate_until() 2020-01-28 10:54:14 +01:00
Thomas Haller
c4690eeeff shared/tests: add nmtst_main_context_assert_no_dispatch() helper 2020-01-28 10:54:14 +01:00
Thomas Haller
0008c6c801 shared/tests: add nmtst_g_source_set_boolean_true() helper 2020-01-28 10:54:14 +01:00
Thomas Haller
71fb823a43 shared/tests: add nmtst_context_busy_watcher_wait() helper 2020-01-28 10:54:14 +01:00
Thomas Haller
8db5563722 libnm: fix logging message about device's state change signal
The device instance might already be removed from the cache. At that
point, _nm_object_get_client(self) returns %NULL.

Use the correct NMClient instance.
2020-01-28 10:54:14 +01:00
Thomas Haller
2c4f57be19 libnm: log message when NMClient gets disposed
This is useful as a last message to know when the instance is gone
for good.
2020-01-28 10:54:14 +01:00
Thomas Haller
64c53a2afa libnm: add define for disabling NMClient debug logging
For printf debugging (when you recompile the source) it can be useful
to have one switch to disable logging of NMClient.

For example, this is useful with

  $ LIBNM_CLIENT_DEBUG=trace nmcli agent secret
2020-01-28 10:54:14 +01:00
Thomas Haller
6e7e18c86f shared: add nm_g_main_context_is_thread_default() util 2020-01-28 10:54:14 +01:00
Thomas Haller
24b50625bd shared: add NM_UTILS_USEC_PER_SEC macro 2020-01-28 10:54:14 +01:00
Thomas Haller
51ed70228f shared: merge branch 'th/macro-narg-cleanup'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/396
2020-01-28 10:44:35 +01:00
Thomas Haller
86787e0278 core: improve implementation of NM_DEVICE_DEFINE_LINK_TYPES() macro
I think it's technically not correct to rely on the "sentinal" field
being immediately after the previous field, due to alignment. Implement
the macro differently.
2020-01-28 10:42:08 +01:00
Thomas Haller
0cb0ee0482 shared: add _NM_MACRO_COMMA_IF_ARGS() helper macro 2020-01-28 10:42:08 +01:00
Thomas Haller
9b8dcc2665 shared: cleanup NM_NARG() and related macros
- add new helper macros NM_MACRO_CALL(), _NM_MACRO_SELECT_ARG_64(),
  NM_NARG_MAX1(), NM_NARG_MAX2().

- cleanup implementation of NM_NARG() and _NM_UTILS_MACRO_REST() macros
  by reusing helper macros.
2020-01-28 10:42:08 +01:00
Antonio Cardace
abcf8d5245 Merge branch 'ac/fix_startup_complete'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/400
2020-01-28 09:05:13 +01:00
Antonio Cardace
f583aec806 nm-device: add new pending action to keep the device busy when in between states
Add a 'in-state-change' pending action to be sure the device always has a
pending when transitioning between states (this prevents callbacks to mark
startup as complete while running _set_state_full()).

This is needed as during the 'failed'->'disconnected' the pending action 'activation-*'
for the device is removed resulting in an empty pending_actions list which then
triggers 'check_if_startup_complete()' that will find no pending action and mark
startup as complete even if the device could have been activated with another connection.

https://bugzilla.redhat.com/show_bug.cgi?id=1759956
2020-01-27 12:08:53 +01:00
Beniamino Galvani
b9820162f2 dhcp: merge branch 'bg/nettools-dup-options-issue324'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/401
2020-01-25 11:39:26 +01:00
Beniamino Galvani
541db78259 dhcp: don't add server-id option to the parameter request list
The option is mandatory in the replies from server and so we don't
need to ask for it. dhclient doesn't do it either. But especially, it
seems that requesting the option causes some broken server
implementations to send duplicate instances of the option.

So, remove the option from the parameter request list of the internal
nettools and systemd DHCP implementation.
2020-01-25 11:37:44 +01:00
Beniamino Galvani
1cbf9d22a5 n-dhcp4: accept options that are longer than requested
If the server sends a packet with multiple instances of the same
option, they are concatenated during n_dhcp4_incoming_linearize() and
evaluated as a single option as per section 7 of RFC 3396.

However, there are broken server implementations that send
self-contained options in multiple copies. They are reassembled to
form a single instance by the nettools client, which then fails to
parse them because they have a length greater than the expected one.

This problem can be reproduced by starting a server with:

  dnsmasq --bind-interfaces --interface veth1 -d
          --dhcp-range=172.25.1.100,172.25.1.200,1m
	  --dhcp-option=54,172.25.1.1

In this way dnsmasq sends a duplicate option 54 (server-id) when the
client requests it in the 'parameter request list' option, as
dhcp=systemd and dhcp=nettools currently do.

While this is a violation of the RFC by the server, both isc-dhcp and
systemd-networkd client implementations have mechanisms to deal with
this situation. dhclient simply takes the first bytes of the
aggregated option. systemd-networkd doesn't follow RFC 3396 and
doesn't aggregate multiple options; it considers only the last
occurrence of each option.

Change the parsing code to accept options that are longer than
necessary.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/324
2020-01-25 11:31:58 +01:00
Thomas Haller
c6745013fb device: minor cleanup NMDevice's _set_state_full() for unrefing activation request 2020-01-20 14:45:14 +01:00
Thomas Haller
c2f8400e66 libnm: fix another leak when cleaning up NMClient
We now move the deletion of the context-busy-watcher to and idle handler
on the D-Bus GMainContext.

Note that the idle source does not take an additional reference on the
context. Hence, in certain cases it might happen that the context will
be completely unrefed before the idle handler runs. In that case, we
would leak the object.

Avoid that, by taking an additional reference to the GMainContext.

Note that the alternative would be to unref the context-busy-watcher
via the GSource's GDestroyNotify. That is not done, because then the
busy watcher might be unrefed in a different thread. Instead, we want
that to happen for the right context. The only minor downside of this
is that the user now always pays the price and must iterate the context
to fully clean up. But note that the user anyway must be prepared to
iterate the context after NMClient is gone. And that depends on some
unpredictable events that the user cannot control. That means, either
the user handles this correctly already, or the problem anyway exists
(randomly).

Of course all of the discussed "problems" are very specific. In practice, the
users uses the g_main_context_default() instance and anyway will either
keep iterating it or quit the process after the NMClient instance goes
away.
2020-01-16 14:43:29 +01:00
Thomas Haller
b1b69c1c7b libnm: merge branch 'th/client-object-manager-dbus-leak'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/398
2020-01-16 12:47:53 +01:00
Thomas Haller
b572c0542a libnm: keep context-busy-watcher of NMClient alive for one more idle round
The context-busy-watch has two purposes:

1) it allows the user to watch whether the NMClient still has pending
  GSource'es attached to the GMainContext.
2) thereby, it also keeps the inner GMainContext integrated into the
  caller's (in case of synchronous initialization of NMClient).

Especially for 2), we must not get this wrong. Otherwise, we might
un-integrate the inner GMainContext too early and it will be leaked
indefinitely (because the user has no means to access or iterate it).

To be extra careful, extend the lifetime of the context-busy-watcher
for one more idle invocation. Theoretically, this should not be necessary,
but it's not clear whether something else is still pending.

The downside of that extra safety is that it is probably unnecessary in
practice. And in case where it is necessary, it hides an actual
issue, making it harder to notice and fix it.
2020-01-16 12:44:56 +01:00
Thomas Haller
a2fd2ab55d shared: remove nm_dbus_connection_signal_subscribe_object_manager() helper
It seems to complicate things more than helping. Drop it. What we still have
is a wrapper around plain g_dbus_connection_signal_subscribe(). That one is
trivial and helpful. The previous wrapper seems to add more complexity.
2020-01-16 12:42:41 +01:00
Thomas Haller
13c30f987c core/bluetooth: don't use nm_dbus_connection_signal_subscribe_object_manager()
nm_dbus_connection_signal_subscribe_object_manager() wraps the subscription. The problem
is that this requires to pass a destroy notify function for cleaning up. Such a destroy
notify function will result in an idle source when unsubscribing, which keeps the associated
GMainContext alive (until it gets iterated some more). That seems error prone and outright
unsuitable for NMClient.

While the helper may be useful, it cannot be used by NMClient. So, there is only one
user of this function and we don't expect a second one. It seems better to get rid of
this wrapper and implement it directly.
2020-01-16 12:42:41 +01:00
Thomas Haller
e280124757 libnm: avoid leaking GMainContext for sync initialization after context-busy-watcher quits
When passing a destroy notify to g_dbus_connection_signal_subscribe(),
that callback gets invoked as an idle handler of the associated
GMainContext. That caused to have yet another source attached to the
context after the NMClient gets destroyed.

Especially with synchronous initialization of NMClient that is bad,
because we may destroy the context-busy-watcher too early. That results
in removing the integration of the inner GMainContext into the caller's
context, and thus we leak the inner context indefinitely.

Avoid that leak by not passing a cleanup function to
g_dbus_connection_signal_subscribe().

Fixes: ce0e898fb4 ('libnm: refactor caching of D-Bus objects in NMClient')
2020-01-16 12:42:41 +01:00
Thomas Haller
1afabd5ffd shared: add nm_source_func_unref_gobject() helper 2020-01-16 12:42:41 +01:00
Thomas Haller
3925ff4833 ifcfg-rh: merge branch 'th/ifcfg-parse-route-file-cleanup'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/392
2020-01-16 12:41:05 +01:00
Thomas Haller
4fc7c7eec0 ifcfg-rh: avoid creaing route file twice in make_ip4_setting()
Just read the content once. It's wasteful to read the file twice
while parsing.

But what is worse, the file content can change any time we read it.
We make decisions based on what we read, and hence we should only
read the file once in the parsing process to get one consistent result.
2020-01-16 12:40:01 +01:00