Commit graph

108 commits

Author SHA1 Message Date
Tomas Korbar
0b04d9ad83 Add nm_utils_g_ptr_array_add_string_item convenience function 2026-03-23 13:13:13 +01:00
Tomas Korbar
acbd5781e7 dns: Move domain_is_routing and domain_is_valid functions
domain_is_routing and domain_is_valid functions could be used
outside of nm-dns-manager thus move them to core utils.
2026-03-23 13:11:18 +01:00
Beniamino Galvani
112190d09a clat: support layer3 interfaces
When running the CLAT over an interface that doesn't use the Ethernet
header, like an IP tunnel, there are some changes needed. The BPF
program must compute offsets differently. Also, the DAD packet should
not include an Ethernet header.
2026-02-06 17:47:30 +01:00
Beniamino Galvani
5c041cb891 l3cfg: send DAD solicitation for the IPv6 CLAT address
As per draft-ietf-v6ops-claton-14, hosts must perform duplicate
addresses detection (DAD) on the generated CLAT IPv6 address. This is
necessary not only to avoid address collisions but also because some
networks drop traffic from addresses that have not done DAD.

Since doing true DAD adds complexity, adopt the same approach as
Android: start DAD by sending a neighbor solicitation and don't wait
for any reply. This avoids the problem with dropped traffic; it
doesn't help with collisions, but collisions are anyway very unlikely
because the interface identifier is a random 64-bit value.

 5ae193ae36/clatd/main.c (363)
2026-02-06 10:37:59 +01:00
Beniamino Galvani
c4b39914c4 core: limit the result from the helper to 32MiB 2026-01-07 18:20:43 +01:00
Beniamino Galvani
90ea2ddb90 core: introduce nm_utils_ping_host()
Introduce a function that pings a given host. It opens a "ping socket"
(IPPROTO_ICMP), binds it to the given ifindex, connects it to the
remote address, and keep sending ICMP echo-request packets until it
receives a reply or the optional timeout is reached. By using this
kind of socket, the kernel automatically sets the ICMP ID on outgoing
packets and matches incoming packets by the same ID.
2026-01-07 09:48:00 +01:00
Beniamino Galvani
8d8edda3f4 core,libnm-core: introduce property flag for certificate and keys
If we add a new property in the future and it references a certificate
or key stored on disk, we need to also implement the logic to verify
the access to the file for private connections.

Add a new property flag NM_SETTING_PARAM_CERT_KEY_FILE to existing
certificate and key properties, so that it's easier to see that they
need special treatment. Also add some assertions to verify that the
properties with the flag are handled properly.

While at it, move the enumeration of private-files to the settings.
2025-12-12 12:38:50 +01:00
Beniamino Galvani
9703305122 core: add functions to read private files of connections
Add function nm_utils_read_private_files(). It can be used to read a
list of paths as the given user. It spawns the daemon-helper to read
each path and returns asynchronously a hash table containing the files
content.

Also add nm_utils_get_connection_private_files_paths() to return a
list of file paths referenced in a connection. The function currently
returns only 802.1x file paths for certificates and keys.
2025-12-12 12:38:49 +01:00
Beniamino Galvani
4e26403c4a core: support returning binary output from the daemon helper
The full output of the daemon helper is added to a NMStrBuf, without
interpreting it as a string (that is, without stopping at the first
NUL character).

However, when we retrieve the content from the NMStrBuf we assume it's
a string. This is fine for certain commands that expect a string
output, but it's not for other commands as the read-file-as-user one.

Add a new argument to nm_utils_spawn_helper() to specify whether the
output is binary or not. Also have different finish functions
depending on the return type.
2025-12-12 12:38:49 +01:00
Beniamino Galvani
2739850b78 libnm-core, core: add permission helpers
Add utility functions to get the number of users and the first user
from the connection.permissions property of a connection.
2025-12-12 12:38:48 +01:00
Beniamino Galvani
ff0c4346fc core: add rate-limiting helper
It can be used to perform an action like logging a message with
simple rate limiting.
2025-11-12 11:48:59 +01:00
Beniamino Galvani
c312390932 libnm-glib-aux: add temp name argument to nm_utils_file_set_contents()
In some cases it's useful to specify the name of the temporary file to
be used.
2025-10-22 09:56:39 +02:00
Beniamino Galvani
247000deed core: reject new connections if the feature is disabled or removed
If a feature like Wi-Fi, OVS, team, etc. is disabled or no longer
supported, it is better to report an error when the connection is
added via nmcli than accepting the connection and complaining later
about a "missing plugin"; there is no plugin and the connection will
never be able to activate.

Example errors now:
  # nmcli connection add type team
  Error: Failed to add 'team-nm-team' connection: team support is disabled in this build

  # nmcli connection add type gsm
  Error: Failed to add 'gsm' connection: WWAN support is disabled in this build

  # nmcli connection add type wimax nsp 00:99:88:77:66:55
  Error: Failed to add 'wimax' connection: WiMAX is no longer supported

Note that we don't touch libnm-core (the part defining the settings
and properties), as that defines the API of NetworkManager. The API
should not change according to compile flags.
2025-10-21 15:31:58 +02:00
Beniamino Galvani
e56bc740d0 core: fix nm_utils_get_nm_gid()
Fixes: 31dbcb81fe ('core: make nm_utils_get_nm_[ug]id() thread safe')
(cherry picked from commit b58a37acfe)
2025-07-31 15:59:30 +02:00
Beniamino Galvani
12e033368f core: fix Wi-Fi data rate tables
Fixes: f2b0092b5b ('wifi: parse BSS IEs for 80211n and 80211ac data rates')
(cherry picked from commit fa80896ee7)
2025-07-31 15:59:30 +02:00
Jason A. Donenfeld
c627bbea4c nm-random-utils: always generate good random bytes and prioritize getrandom support
The current mess of code seems like a hodgepodge of complex ideas,
partially copied from systemd, but then subtly different, and it's a
mess. Let's simplify this drastically.

First, assume that getrandom() is always available. If the kernel is too
old, we have an unoptimized slowpath for still supporting ancient
kernels, a path that should be removed at some point. If getrandom()
isn't available and the fallback path doesn't work, the system has much
larger problems, so just crash. This should basically never happen.
getrandom() and having randomness available in general is a critical
system API that should be expected to be available on any functioning
system.

Second, assume that the rng is initialized, so that asking for random
numbers should never block. This is virtually always true on modern
kernels. On ancient kernels, it usually becomes true. But, more
importantly, this is not the responsibility of various daemons, even
ones that run at boot. Instead, this is something for the kernel and/or
init to ensure.

Putting these together, we adopt new behavior:

- First, try getrandom(..., ..., 0). The 0 flags field means that this
  call will only return good random bytes, not insecure ones.

- If this fails for some reason that isn't ENOSYS, crash.

- If this fails due to ENOSYS, poll on /dev/random until 1 byte is
  available, suggesting that subsequent reads from the rng will almost
  have good random bytes. If this fails, crash. Then, read from
  /dev/urandom. If this fails, crash.

We don't bother caching when getrandom() returns ENOSYS. We don't apply
any other fancy optimizations to the slow fallback path. We keep that as
barebones and minimal as we can. It works. It's for ancient kernels. It
should be removed soon. It's not worth spending cycles over. Instead,
the goal is to eventually reduce all of this down to a simple boring
call to getrandom(..., ..., 0).

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2127
2025-02-11 10:04:26 +01:00
Beniamino Galvani
bb6881f88c format: run nm-code-format
Reformat with:

  clang-format version 19.1.0 (Fedora 19.1.0-1.fc41)

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2046
2024-10-04 11:07:35 +02:00
Thomas Haller
47283b7c76 deamon-helper: ensure helper_complete() never returns NULL on success
The in_buffer is initialized with a NULL buffer. If we never receive and
data, the buffer might still be NULL.

Maybe it actually can never happen, but it's not clear that this is
always the case. To be sure, ensure we don't return a NULL buffer on
success.
2024-08-09 15:24:11 +02:00
Íñigo Huguet
56179465df Updated code format
The CI will use Fedora 40 for code formatting check. Update the code
formatting so it passes.
2024-04-08 06:35:20 +00:00
Thomas Haller
998206c38e
device: fix generated 'wifi.cloned-mac-address="stable-ssid"' for stable-id
Setting

  wifi.cloned-mac-address="stable-ssid"

should generate the same SSID as

  connection.stable-id="${NETWORK_SSID}"
  wifi.cloned-mac-address="stable"

For that to work correctly, we need to post-process the generated stable
id.

Fixes: d210923c0f ('wifi: add "wifi.cloned-mac-address=stable-ssid"')

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1813
2023-12-13 09:05:15 +01:00
Thomas Haller
d210923c0f
wifi: add "wifi.cloned-mac-address=stable-ssid"
Add a new "stable-ssid" mode that generates the MAC address based on the
Wi-Fi's SSID.

Note that this gives the same MAC address as setting

    connection.stable-id="${NETWORK_SSID}"
    wifi.cloned-mac-address="stable"

The difference is that changing the stable ID of a profile also affects
"ipv6.addr-gen-mode=stable-privacy" and other settings.
2023-11-16 13:07:54 +01:00
Thomas Haller
901a1b096b
core: support "${NETWORK_SSID}" for connection.stable-id
For Wi-Fi profiles, this will encode the SSID in the stable-id.
For other profiles, this encodes the connection UUID (but the SSID and
the UUID will always result in distinct stable IDs).

Also escape the SSID, so that the generated stable-id is always valid
UTF-8.
2023-11-16 13:07:53 +01:00
Thomas Haller
bee14cf47c
all: use NM_MAX() instead of MAX() 2023-11-15 09:32:21 +01:00
Thomas Haller
b4dd83975e
all: use NM_MIN() instead of MIN() 2023-11-15 09:32:20 +01:00
Thomas Haller
6f4a60b6f2
all: ensure same signedness of arguments to MIN()/MAX()
Comparing integers of different signedness gives often unexpected
results. Adjust usages of MIN()/MAX() to ensure that the arguments agree
in signedness.
2023-11-15 09:32:18 +01:00
Thomas Haller
4f62600e21
all: use NM_HASH_SEED_16() macro 2023-11-14 14:15:42 +01:00
Thomas Haller
27ae71b504
core: generate fixed fallback timestamp in _host_id_read_timestamp()
nm_hash_siphash42() uses a randomized seed like nm_hash*(). In this case,
we want to always generate the same fake timestamp, based on the host-id.

In practice, it doesn't really matter, because this is only the fallback
path for something gone horribly wrong already.
2023-11-14 14:15:42 +01:00
Fernando Fernandez Mancera
fe48a4b35c wifi: parse access point announced bandwidth
Parse the access point announced bandwidth in MHz. This is considering
both HT and VHT. Please notice that for VHT 80+80 MHz we are representing it
as 160 MHz.
2023-08-02 00:54:27 +02:00
Thomas Haller
c47d6b17d5
core: replace multiple arguments of nm_match_spec_device() with struct
Struct allow named arguments, which seems easier to maintain instead of
a function with many arguments. Also, adding a new parameter does not
require changes to most of the callers.

The real advantage of this is that we encode all the search parameters
in one argument. And we can add that argument to
_match_section_infos_lookup(), alongside lookup by NMDevice or
NMPlatformLink.
2023-06-14 11:07:34 +02:00
Thomas Haller
cba8eb9784
core: add nm_match_spec_match_type_to_bool() helper to convert enum to boolean
All callers eventually want a boolean instead of a NMMatchSpecMatchType.

I think the NMMatchSpecMatchType enum still has value at the lower
layers, where the enum values are clearer (when reading the code). So
don't drop NMMatchSpecMatchType entirely.

However, let's add nm_match_spec_match_type_to_bool() to convert the
match-type to a boolean to avoid duplicating the code.
2023-06-14 10:49:14 +02:00
Thomas Haller
7deea767d3
core: use NMStrBuf in nm_utils_stable_id_parse() 2023-04-21 12:51:43 +02:00
Thomas Haller
21cf2dc58f
libnm,core: make "default${CONNECTION}" the built-in stable ID
The "connection.stable-id" supports placeholders like "${CONNECTION}" or
"${DEVICE}".

The stable-id can also be specified in global connection defaults in
NetworkManager.conf, by leaving it unset in the profile. Global
connection defaults always follow the pattern, that they correspond to a
per-profile property, and only when the per-profile value indicates a
special default/unset value, the global connection default is consulted.
Finally, if the global connection default is also not configured in
NetworkManager.conf, a built-in default is used (which may not be
constant either, for example ipv6.ip6-privacy's built-in default depends
on a sysctl value).

In any case, every possible configuration that can be achieved should be
configurable both per-profile and via global connection default. That
was not given for the stable-id, because the built-in default generated
an ID in a way that could not be explicitly expressed otherwise.

So you could not:
- explicitly set the per-profile value to the built-in default, to avoid
  that the global-connection-default overwrites it.
- explicitly set the global-connection-default to the built-in default,
  to avoid that a lower priority [connection*] section overwrites the
  stable-id again.

Fix that inconsistency to make it possible to explicitly set the
built-in default.

Change behavior for literally "default${CONNECTION}" and make it behave
as the built-in default. Also document that the built-in default has that
value.

It's unlikely that this breaks an existing configuration, but of course,
if any user configured "connection.stable-id=default${CONNECTION}", then
the behavior changes for them.
2023-04-21 12:49:18 +02:00
Thomas Haller
1378ed7d96
core: drop unnecessary initialization in nm_utils_spawn_helper()
We did not initialize "child_stderr". If that were necessary, we would need
to add it too. However, it is clearly not necessary to initialize those fields.
2023-04-04 08:43:21 +02:00
Thomas Haller
ce414933a7
core: use nm_io_fcntl_setfl_update_nonblock() helper 2023-04-04 08:43:21 +02:00
Thomas Haller
31fd8f60cf
all: use G_SPAWN_CLOEXEC_PIPES with g_spawn_async_with_pipes()
G_SPAWN_CLOEXEC_PIPES is supported since glib 2.40, which we already
depend on.
2023-04-04 08:43:20 +02:00
Thomas Haller
d1f7e439c6
core: fix setting non-blocking stderr in nm_utils_spawn_helper()
Fixes: d65702803c ('core: print stderr from nm-daemon-helper')
2023-04-04 08:43:20 +02:00
Thomas Haller
fd123315e5
core: fix setting non-blocking FD in nm_utils_spawn_helper()
Fixes: 6ac21ba916 ('core: add infrastructure for spawning a helper process')
2023-04-04 08:43:20 +02:00
Thomas Haller
f58a69656a
core: error out in nm_utils_kill_child_{sync,async}() if first waitpid() gives ECHILD
It is wrong trying to send the signal still. Just error out.

Note that ECHILD indicates that the process is either not a child
or was already reaped. In both cases, that is a bug of the caller
who must keep accurate track of the child's process ID.
2023-04-03 10:27:43 +02:00
Thomas Haller
a65e80e8b6
core: pre-allocate exact buffer size for output in nm_utils_spawn_helper()
It's easy enough to know how many bytes are needed. Just allocate the
right size (+1, because NMStrBuf really likes to reserve that extra byte
for the trailing NUL, even if it's not needed in this case).
2023-04-03 10:27:43 +02:00
Thomas Haller
346196792c
core/trivial: add code comment about using GChildWatchSource 2023-04-03 10:27:43 +02:00
Thomas Haller
597e127bcb
core: use nm_g_child_watch_source_new() in nm_utils_spawn_helper() 2023-04-03 10:27:43 +02:00
Thomas Haller
a52d620549
core: assert that nm_utils_spawn_helper() is used with default context 2023-04-03 10:27:43 +02:00
Thomas Haller
3411f42418
core: store main context in variable in nm_utils_spawn_helper()
There is no change in behavior, because the GTask's context
is of course g_main_context_get_thread_default(). Still, not point
in making that unclear.
2023-04-03 10:27:43 +02:00
Thomas Haller
f9c409d34c
core: qualify logging lines related to helper with "nm-daemon-helper"
Seems to be the better name, because that is also the name of the
executable.
2023-04-03 10:27:43 +02:00
Thomas Haller
f74109e4b0
core: rename nmlog defines in "nm-core-utils.c"
Those are related to _NMLOG2() macro. Rename.
2023-04-03 10:27:43 +02:00
Thomas Haller
b5875ec79e
core: use nm_clear_fd() helper in nm_utils_spawn_helper() 2023-04-03 10:27:43 +02:00
Corentin Noël
5d28a0dd89
doc: replace all (allow-none) annotations by (optional) and/or (nullable)
The (allow-none) annotation is deprecated since a long time now, it is better to
use (nullable) and/or (optional) which clarifies what it means with the (out)
annotation.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1551
2023-03-27 11:49:43 +02:00
Beniamino Galvani
d65702803c core: print stderr from nm-daemon-helper
Currently the only way to return an error code from the daemon helper
is via the process exit code, but that is not enough to fully describe
an error from getaddrinfo(); in fact, the function returns a EAI_*
error code and when the value is EAI_SYSTEM, the error code is
returned in errno.

At the moment, any messages printed to stderr by the helper goes to NM
stderr; instead, we want to capture it and pass it through the logging
mechanism of NM, so that it can be filtered according to level and
domain.
2023-02-21 13:46:54 +01:00
Beniamino Galvani
961824d43b core: change buffer allocation size for the daemon helper
Use slightly more efficient sizes.
2023-02-21 13:46:54 +01:00
Thomas Haller
6e96d71731
all: use nm_random_*() instead of g_random_*()
g_random_*() is based on GRand, which is not a CSPRNG. Instead, rely on
kernel to give us good random numbers, which is what nm_random_*() does.

Note that nm_random_*() calls getrandom() (or reads /dev/urandom), which
most likely is slower than GRand. It doesn't matter for our uses though.

It is cumbersome to review all uses of g_rand_*() whether their usage of
a non-cryptographically secure generator is appropriate. Instead, just
always use an appropriate function, thereby avoiding this question. Even
glib documentation refers to reading "/dev/urandom" as alternative. Which
is what nm_random_*() does. These days, it seems unnecessary to not use
the best random generator available, unless it's not fast enough or you
need a stable/seedable stream of random numbers.

In particular in nmcli, we used g_random_int_range() to generate
passwords. That is not appropriate. Sure, it's *only* for the hotspot,
but still.
2023-01-30 10:51:13 +01:00