LTO without assertion enabled, thinks that certain code paths
result in uninitialized code. Technically, it's not wrong, in practice
those are only in cases where we already failed an assertion.
In function 'nm_ip_addr_is_null',
inlined from 'canonicalize_ip_binary' at src/libnm-core-impl/nm-setting-ip-config.c:67:21,
inlined from 'nm_ip_route_set_next_hop_binary' at src/libnm-core-impl/nm-setting-ip-config.c:1062:23:
./src/libnm-glib-aux/nm-inet-utils.h:80:12: error: 'a' may be used uninitialized [-Werror=maybe-uninitialized]
80 | return IN6_IS_ADDR_UNSPECIFIED(&a.addr6);
| ^
src/libnm-core-impl/nm-setting-ip-config.c: In function 'nm_ip_route_set_next_hop_binary':
./src/libnm-glib-aux/nm-inet-utils.h:73:14: note: 'a' declared here
73 | NMIPAddr a;
| ^
Try to workaround that by letting nm_utils_addr_family_to_size() always
return a non-zero size. This is ugly, because in the assertion case fail
we might now also get an additional memory corruption that could have
been avoided by returning zero. However, it probably doesn't matter, because
in this scenario we are already in a bad situation.
Fixes: b02aeaf2f3 ('glib-aux: fix various nm_ip_addr_*() functions for unaligned addresses')
Most of our nm_ip_addr_*() functions take an opaque pointer, that
can be either in_addr_t, struct in6_addr or NMIPAddr.
They also tend to support that their argument pointer is not aligned.
The reason is not very strong, except that usually it's simple to
support and it allows the caller to use those low-level functions for
pointers of unknown alignment (e.g. from a package on the network).
Fix a few cases for that.
- name things related to `in_addr_t`, `struct in6_addr`, `NMIPAddr` as
`nm_ip4_addr_*()`, `nm_ip6_addr_*()`, `nm_ip_addr_*()`, respectively.
- we have a wrapper `nm_inet_ntop()` for `inet_ntop()`. This name
of our wrapper is chosen to be familiar with the libc underlying
function. With this, also name functions that are about string
representations of addresses `nm_inet_*()`, `nm_inet4_*()`,
`nm_inet6_*()`. For example, `nm_inet_parse_str()`,
`nm_inet_is_normalized()`.
<<<<
R() {
git grep -l "$1" | xargs sed -i "s/\<$1\>/$2/g"
}
R NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX
R NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX
R NM_UTILS_INET_ADDRSTRLEN NM_INET_ADDRSTRLEN
R _nm_utils_inet4_ntop nm_inet4_ntop
R _nm_utils_inet6_ntop nm_inet6_ntop
R _nm_utils_ip4_get_default_prefix nm_ip4_addr_get_default_prefix
R _nm_utils_ip4_get_default_prefix0 nm_ip4_addr_get_default_prefix0
R _nm_utils_ip4_netmask_to_prefix nm_ip4_addr_netmask_to_prefix
R _nm_utils_ip4_prefix_to_netmask nm_ip4_addr_netmask_from_prefix
R nm_utils_inet4_ntop_dup nm_inet4_ntop_dup
R nm_utils_inet6_ntop_dup nm_inet6_ntop_dup
R nm_utils_inet_ntop nm_inet_ntop
R nm_utils_inet_ntop_dup nm_inet_ntop_dup
R nm_utils_ip4_address_clear_host_address nm_ip4_addr_clear_host_address
R nm_utils_ip4_address_is_link_local nm_ip4_addr_is_link_local
R nm_utils_ip4_address_is_loopback nm_ip4_addr_is_loopback
R nm_utils_ip4_address_is_zeronet nm_ip4_addr_is_zeronet
R nm_utils_ip4_address_same_prefix nm_ip4_addr_same_prefix
R nm_utils_ip4_address_same_prefix_cmp nm_ip4_addr_same_prefix_cmp
R nm_utils_ip6_address_clear_host_address nm_ip6_addr_clear_host_address
R nm_utils_ip6_address_same_prefix nm_ip6_addr_same_prefix
R nm_utils_ip6_address_same_prefix_cmp nm_ip6_addr_same_prefix_cmp
R nm_utils_ip6_is_ula nm_ip6_addr_is_ula
R nm_utils_ip_address_same_prefix nm_ip_addr_same_prefix
R nm_utils_ip_address_same_prefix_cmp nm_ip_addr_same_prefix_cmp
R nm_utils_ip_is_site_local nm_ip_addr_is_site_local
R nm_utils_ipaddr_is_normalized nm_inet_is_normalized
R nm_utils_ipaddr_is_valid nm_inet_is_valid
R nm_utils_ipx_address_clear_host_address nm_ip_addr_clear_host_address
R nm_utils_parse_inaddr nm_inet_parse_str
R nm_utils_parse_inaddr_bin nm_inet_parse_bin
R nm_utils_parse_inaddr_bin_full nm_inet_parse_bin_full
R nm_utils_parse_inaddr_prefix nm_inet_parse_with_prefix_str
R nm_utils_parse_inaddr_prefix_bin nm_inet_parse_with_prefix_bin
R test_nm_utils_ip6_address_same_prefix test_nm_ip_addr_same_prefix
./contrib/scripts/nm-code-format.sh -F
Various synchronous methods (D-Bus calls) in libnm's NMClient API were
deprecated. The problem is that NMClient contains a cache of D-Bus
objects, and it gets updated by asynchronous events (D-Bus signals).
Those events get only processed when iterating the GMainContext, but
they are ordered.
When we perform a pseudo blocking D-Bus call with
g_dbus_connection_call_sync(), then GDBus creates a temporary
GMainContext, sends the request and iterates the internal context
blocking for the response. That is, this reply is not synchrounized with
the events that update the NMClient cache.
That is a problem for methods like nm_remote_connection_delete(),
because you call blocking delete, but afterwards the object is still in
the NMClient cache. That's why most blocking methods are deprecated.
While such blocking calls are therefore problematic, they can still be
very convenient to call from a simple script, a test tool or the python
REPL. See "examples/python/gi/nm-wg-set" which calls
nm_remote_connection_get_secrets(), and it would be (unnecessarily)
cumbersome to do the correct thing or using async API.
In particular, nm_remote_connection_get_secrets() doesn't retrieve an object
that is in the NMClient cache in the first place. Sure, the result is
out of order with the cache, but it's not obviously related and in most
cases it wouldn't matter to the user. So undeprecate this function again.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1345
Try work around the issue documented by Emil Velikov in
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1264
When we mirror an 802.1x connection to an IWD config file and there's an
AP in range with matching SSID, that connection should become available
for activation. In IWD terms when an 802.1x network becomes a Known
Network, it can be connected to using the .Connect D-Bus method.
However there's a delay between writing the IWD config file and receiving
the InterfaceAdded event for the Known Network so we don't immediately
find out that the network can now be used. If an NM client creates a
new connection for an 802.1x AP and tries to activate it quickly enough,
NMDeviceIWD will not allow it to because it won't know the network is
known yet. To work around this, we save the SSIDs of 802.1x connections
we recently mirrored to IWD config files, for an arbitrary 2 seconds
period, and we treat them as Known Networks in that period since in
theory activations should succeed.
The alternative proposed in the !1264 is to drop NMDeviceIWD checks that
there's a Known Network for the 802.1x connection being activated since
IWD will eventually perform the same checks and IWD is the ultimate
authority on whether the profile is IWD-connectable.
The IWD backend would originally use .Disconnect() on IWD dbus "Station"
objects to make sure IWD is out of autoconnect or that it isn't
connecting to a network that NM didn't command. Later the default became
to let IWD run autoconnect so now most of the time the backend just
mirrors IWD's state to NMDevice's state.
Now sometimes when NMDevice still seems to have an active connection but
IWD has gone through one or more state changes (which we may see after a
delay due to D-Bus) and is now connected to or connecting to a different
network, NMDevice would first have to go through .deactivate to mirror
the fact the original connection is no longer active, and it'd use
.Disconnect() which could break the new connection, so check for this
situation.
The removed signal did not log the interface name.
That's because _LOG3D() takes the ifindex and looks into the platform
cache to find the interface name. However, if the link is already
removed, it won't find it.
Fix that by explicitly using the right name.
Before:
<debug> [1660070838.2976] platform: signal: link removed: 602: testX6 <DOWN;broadcast,multicast> mtu 1500
Now:
<debug> [1660070838.2976] platform: (testX6) signal: link removed: 602: testX6 <DOWN;broadcast,multicast> mtu 1500
- drop unused "keep_deleted" parameter. It just doesn't make sense.
Even less sense than for rules/routes, where this was taken from.
- fix nmp_global_tracker_sync_mptcp_addrs() to delete addresses
with conflicting flags. We did not correctly delete existing
addresses, that were to be reconfigured with different flags.
Fixes: 5374c403d2 ('platfrom: handle MPTCP addresses with NMPGlobalTracker')
This affects parsing global connection defaults from
"NetworkManager.conf".
Let's use a zero base for strtoll(), which honors the prefixes
"0x" and "0" to use hex and octal numbers, respectively. Otherwise
it uses decimal (base 10).
This causes very little ambiguity, but it makes certain numbers
just work.
Also, we have flags properties, where it makes much more sense
to write them in hex, like `connection.mptcp-flags=0x52`.
When we configure MPTCP addresses, we usually do so per interface
(ifindex). That is, because each interface (via NMDevice and NML3Cfg)
decides how to configure MPTCP, and then we always add MTCP addresses
for this certain ifindex.
With that, we could have a purely interface-specific view and not a
global sync method. However, there are two problems:
The minor problem is that we don't cache the endpoints (because we don't
get notifications). We can only get a dump of all endpoints. It seems
odd to have a mptcp-addr-sync method that is per-ifindex, when it needs
to dump all addresses.
The much more important reason is that the number of endpoints that we
can configure in kernel is very limited. So we need to make a choice
which endpoints to configure, and for that we need to holistic view that
NMPGlobalTracker has.
Since the generic netlink API does (currently) not support notifications
about changes of the MPTCP addresses, we won't get notifications when
they change, and it seems wrong to put such things in the NMPlatform
cache.
We can just get the list of endpoints by polling, so add a function
nm_platform_mptcp_addrs_dump() for that.
Also, add nm_platform_mptcp_addr_update() which can add/remove/update
MPTCP addresses.
We already have two hash functions for MPTCP addresses:
nmp_object_id_hash*() which compares the identity of objects
and nm_platform_mptcp_addr_hash*(), which compares all fields.
There is also a need to hash only the address. Add it. Will be used
next.
The ID of an object does not entail all properties/attributes.
During sync, if we already have an object with the same ID configured,
it may still differ in other aspects.
Handle those cases, by deleting such routes/rules before adding the
desired object.
Since we don't get netlink notifications when the MPTCP endpoints
change, we don't cache them. And since we don't cache them,
there is less need to mark whether they were received from kernel
or created internally.
It's not very clear what the best identity is.
For example, in kernel you cannot add two MPTCP addresses that only differ by
ifindex. Thus (as far as kernel is concerned), the ifindex is not part of the
identity. Still, as we will have an interface centric view, this will be
useful for us.
On the other hand, to kernel is the "id" a second primary key, along
side "addr:port". However, to us it's not useful to consider that as
part of nmp_object_id_equal(), because usually kernel will pick an "id"
for us, and when we track objects that we are about to add, they don't
have an "id" yet.
So, adjust nmp_object_id_equal(). However -- somewhat unusual -- let it
deviate from kernel's understanding of what defines an MPTCP address.