nm_utils_random_bytes() is supposed to give us good random number from
kernel. It guarantees to always provide some bytes, and it has a
boolean return value that estimates whether the bytes are good
randomness. In practice, most callers ignore that return value, because
what would they do about it anyway?
Of course, we want to primarily use getrandom() (or "/dev/urandom"). But
if we fail to get random bytes from them, we have a fallback path that
tries to generate "random" bytes.
It does so, by initializing a global seed from various sources, and keep
sha256 hashing the buffer in a loop. That's certainly not efficient nor
elegant, but we already are in a fallback path.
Still, we can do slightly better. Instead of just using the global state
and keep updating it (entirely deterministically), every time also mix in
the results from getrandom() and a current timestamp. The idea is that if you
have a virtual machine that gets cloned, we don't want that our global
state keeps giving the same random numbers. In particular, because
getrandom() might handle that case, even if it doesn't have good
entropy.
This doesn't use NM_UNIQ_T() to create a truly unique name.
Instead, it avoids "_arr" as local variable name, which other
macros also use. By choosing a different name, we can nest such
macro calls, without getting a "-Wshadow" warning.
It's similar to nm_ip_addr_cmp(), but it can be used as an argument
to g_qsort_with_data() to sort a list of NMIPAddr (or in_addr_t or
struct in6_addr).
The address family needs to be given as user-data.
The _nm_alignas() exists to choose a suitable alignment. Since it's
on the stack, it has (almost) no overhead to just use the maximum
alignment.
That's why gint64 was chosen before. But that isn't the largest
alignment. We rely on C11 already, and we also always include <stddef.h>.
So use max_align_t instead.
GPtrArray requires an additional heap allocation for the GPtrArray.
Utterly useless in the majority of cases.
Anyway. Allocating (and exponentially grown) a buffer is not too hard,
just slightly more cumbersome. Since nm_utils_strsplit_quoted() is
heavily unit tested and entirely self-contained, let's opt for the
more complicated implementation and avoid the extra allocation.
nm_utils_ip4_netmask_to_prefix() and nm_utils_ip4_prefix_to_netmask()
are public API in libnm.
We thus already have an internal implementation _nm_utils_ip4_prefix_to_netmask(),
for non-libnm users. Internally, we should never use the libnm variant.
For consistency and so that we have the helper available in
libnm-glib-aux, add _nm_utils_ip4_netmask_to_prefix().
Setting `NM_SET_OUT(out_normalized, !is_normalized)` is correct, but looks
odd and required a long code comment.
Try to write the same code differently, I think it is easier to
read and requires less comment to explain.
On m68k, integers are 2-byte aligned. Hence the assertion was wrong.
What we really want to check, is that NMIPAddr has not a smaller
alignment than in_addr_t and similar.
While at it, also assert the alignment for NMEtherAddr.
g_bytes_ref() does not accept NULL. But doing so can be convenient,
add a helper for that.
Note that g_bytes_unref() does accept NULL, so there is no corresponding
helper.
Try to workaround a coverity warning:
30. NetworkManager-1.39.3/src/core/vpn/nm-vpn-connection.c:2000:
overrun-buffer-val: Overrunning array "address.ax.address_ptr" of 1
bytes by passing it to a function which accesses it at byte offset 3.
NM_STR_BUF_INIT() and nm_str_buf_init() were pretty much redundant. Drop one of
them.
Usually our pattern is that we don't have functions that return structs.
But NM_STR_BUF_INIT() returns a struct, because it's convenient to use
with
nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(...);
So use that variant instead.
Allow to initialize NMStrBuf with an externally allocated array.
Usually a stack buffer. If the NMStrBuf grows beyond the size of
that initial buffer, then it would switch using malloc.
The idea is to support the common case where the result is small enough
to fit on the stack.
I always wanted to do such optimization because the main purpose of
NMStrBuf is to put it on the stack and ad-hoc construct a string.
I just figured, it would complicate the implementation and add
a runtime overhead. But turns out, it doesn't really.
The biggest question is how NMStrBuf should behave with a pre-allocated
buffer? Turns out, most choices can be made in a rather obvious way.
The only non-obvious thing is that nm_str_buf_finalize() would malloc()
a buffer, but that too seems consistent and what a user would probably
expect. As such, this doesn't seem to add unexpected semantics to the API.
On glibc, HOST_NAME_MAX is defined as 64. Also, Linux'
sethostname() enforces that limit (__NEW_UTS_LEN). Also,
`man gethostname` comments that HOST_NAME_MAX on Linux is
64.
However, when building against musl, HOST_NAME_MAX is defined as 255.
That seems wrong. We use this limit to validate the hostname, and that
should not depend on the libc or on the compilation.
Hardcode the value to 64.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1197
nm_hostname_is_valid() determines the valid length based on
HOST_NAME_MAX, which is defined differently for glibc and musl.
Fixes: 9ff1f66680 ('glib-aux: add nm_hostname_is_valid() helper from systemd')
We use these functions, currently from our systemd fork. One day we want
to stop importing systemd code, so we need them ourselves.
Copy them, and adjust for NM style.
This seams easier to read. And as we have a unit test that covers all
possible 256 input values, it's easy to refactor and ensure the code
still works.
We effectively already have this function, with the name
nm_utils_named_values_from_strdict(). Which is a decent name,
if you have a strdict. But it seems odd to use for other dictionaries.
Instead, add a variant with a different name. Naming is important,
and just to have the better name, the function is effectively duplicated.
NMUtilsNamedValue is a key-value tuple, usually the key is a string
(hence the name "Named").
But this struct is also useful for keys that are not strings.
Add another "name_ptr" union field to access the key that way.
The alternative would be to add another struct, which serves
a very similar purpose though.
We write lease files for internal DHCP client ("systemd" and "nettools")
in a systemd-specific format. We want to drop systemd code, so we need
to have our own parsing code.
Granted, nettools only writes a single "ADDRESS=" line, so parsing that
would be easy. On the other hand, systemd's parser is not complicated
either (in particular, if we can steal their implementation). Also, it's
a commonly used format in systemd, so having the parser would allow us
to parse similar formats.
Also, we could opt to choose that format, where it makes sense.
Of course, the prefix length cannot be larger than 32 or 128.
But as C does implicit conversions, a buggy prefix length can
lead to a (wrongly) valid prefix length.
Make the type uint32, to prevent that (at least for common cases,
unless you pass a huge 64 bit integer).