Commit graph

363 commits

Author SHA1 Message Date
Thomas Haller
67ee036389
glib-aux/tests: add nmtst_true_once() helper 2022-10-14 17:37:02 +02:00
Thomas Haller
b28c6ca30e
all: avoid "-Wunreachable-code-generic-assoc" warning with _Generic()
Clang 15 ([1], [2]) added

  Added the -Wunreachable-code-generic-assoc diagnostic flag (grouped
  under the -Wunreachable-code flag) which is enabled by default and warns
  the user about _Generic selection associations which are unreachable
  because the type specified is an array type or a qualified type.

This causes compiler warnings with various uses of _Generic():

  ../src/libnm-glib-aux/nm-shared-utils.h:2489:12: error: due to lvalue conversion of the controlling expression, association of type 'const char *const *const' will never be selected becaus
  e it is qualified [-Werror,-Wunreachable-code-generic-assoc]
      return nm_strv_find_first((const char *const *) strv->pdata, strv->len, str);
             ^
  ../src/libnm-glib-aux/nm-shared-utils.h:475:25: note: expanded from macro 'nm_strv_find_first'
      _nm_strv_find_first(NM_CAST_STRV_CC(list), (len), (needle))
                          ^
  ../src/libnm-glib-aux/nm-macros-internal.h:397:22: note: expanded from macro 'NM_CAST_STRV_CC'
                 const char *const*const: (const char *const*) (value), \
                       ^

Clang is correct.

[1] https://releases.llvm.org/15.0.0/tools/clang/docs/ReleaseNotes.html#improvements-to-clang-s-diagnostics
[2] https://reviews.llvm.org/D125259
2022-10-11 17:21:11 +02:00
Thomas Haller
2d8651ba91
glib-aux: extend nm_uuid_generate_from_strings() to honor NULL values
When you call

  nm_uuid_generate_from_strings_strv(uuid_type, type_arg, v1, v2);

you'd probably expect that both values are honored in some way.
However, if v1 happened to be NULL, then previously v2 would be ignored.

Extend nm_uuid_generate_from_strings() to accept also NULL values and
pass on the length. Currently, there are no users of nm_uuid_generate_from_strings(),
so nobody is affected by this change.

Also extend nm_uuid_generate_from_strings_strv() to take a length
argument. It still accepts "-1" to take the input strv as a NULL
terminated array.

If a positive length is provided to nm_uuid_generate_from_strings_strv(),
it hashes the same UUID as the respective NULL terminated array. But of
course only, if there is no NULL inside the array. If there are any
NULLs, a distinct UUID gets generated.
2022-10-11 09:03:17 +02:00
Thomas Haller
b5e7e48bc1
glib-aux: add and use nm_uuid_generate_from_strings_old()
For a long time we have a function like nm_uuid_generate_from_strings().
This was recently reworked and renamed, but it preserved behavior. Preserving
behavior is important for this function, because for the existing users,
we need to keep generating the same UUIDs.

Originally, this function was a variadic function with NULL sentinel.
That means, when you write

  nm_uuid_generate_from_strings(uuid_type, type_arg, v1, v2, v3, NULL);

and v2 happens to be NULL, then v3 is ignored. That is most likely not
what the user intended. Maybe they had a bug and v2 should not be NULL.
But nm_uuid_generate_from_strings() should not require that all
arguments are non-NULL and it should not ignore arguments after the
first NULL.

For example, one user works around this via

    uuid = nm_uuid_generate_from_strings_old("ibft",
                                             s_hwaddr,
                                             s_vlanid ? "V" : "v",
                                             s_vlanid ? s_vlanid : "",
                                             s_ipaddr ? "A" : "DHCP",
                                             s_ipaddr ? s_ipaddr : "");

which is cumbersome and ugly.

That will be fixed next, by adding a function that doesn't suffer
from this problem. But "this problem" is part of the API of the
function, we cannot just change it. Instead, rename it and all
users, so they can keep doing the same.

New users of course should no longer use the "old" function.
2022-10-11 09:03:17 +02:00
Thomas Haller
28fa48aee4
glib-aux: add an inlinable version of nm_array_find_bsearch()
To implement binary search is not very hard. It's almost easy enough to
just open-code it, without using the existing nm_array_find_bsearch() function.
In particular, because nm_array_find_bsearch() won't be inlined,
and thus it is slower than implementing it by hand.

Add nm_array_find_bsearch_inline() as a variant that will be inlined.
This actually is as fast as reimplementing it by hand (I measured),
which takes away any reason to avoid the function.

However, our headers get huge. That may be a problem for complication
time. To counter that a bit, only define the function when the caller
requests it with a NM_WANT_NM_ARRAY_FIND_BSEARCH_INLINE define.
2022-10-11 08:59:48 +02:00
Thomas Haller
1c76fe418b
glib-aux: use nm_assert() in nm_{ptr,}array_find_bsearch()
These checks don't seem very useful, to have them enabled
in production code.

What is actually the real danger of messing up with binary search,
is that the input array is not properly sorted. Asserting for that
would be way more useful, but also likely too expensive to be worth
it.

Checking that the input arguments are not NULL/zero, is not that useful,
because we "usually" won't make such mistakes.

While at it, declare each local variable on a separate line.
2022-10-07 11:49:41 +02:00
Thomas Haller
44d99e366b
glib-aux/trivial: style fix 2022-10-06 16:47:49 +02:00
Thomas Haller
8ab23e5b2d
glib-aux: reorder comparison in nm_ref_string_equal_str()
We usually compare first for pointer equality. It seems to make
more sense this way. Swap.
2022-10-06 13:43:33 +02:00
Thomas Haller
0b6a9e2c88
glib-aux: add nm_ref_string_reset() helper 2022-10-06 13:43:33 +02:00
Thomas Haller
e9a33bbbf8
all: drop nm_uuid_generate_from_strings_v3()
For new uses of nm_uuid_generate_from_strings() we should generate version5
UUIDs and we should use unique namespace UUID arguments.

The namespace UUID was so far replaced by always passing a special prefix
as first string. It seems nicer to use a namespace instead.

Version3 UUIDs should not be used for new applications.

Hence, nm_uuid_generate_from_strings_v3() is no longer a desirable way to
generate UUIDs, so drop the wrapper.
2022-10-03 17:57:53 +02:00
Thomas Haller
871c82fd5f
glib-aux: implement nm_uuid_generate_from_strings_legacy() in terms of nm_uuid_generate_from_strings()
As the unit tests show, the behavior is the same.
2022-10-03 17:57:48 +02:00
Thomas Haller
f849426b84
glib-aux: avoid leaking secrets in memory during nm_uuid_generate_from_strings_strv()
Some snake oil, but this is a low level function and we don't know
whether the caller doesn't try to hash secret information. Just clear
the buffer after use.
2022-10-03 17:57:46 +02:00
Thomas Haller
168bc7f120
glib: add nm_uuid_generate_from_strings() helper
nm_uuid_generate_from_strings() accepts a uuid_type and type_arg
parameter, so that we can use it to generate version 5 UUIDs.

This is a more flexible variant of nm_uuid_generate_from_strings_v3(),
which will be used to replace it. With the right parameters, the new
function behaves the same as nm_uuid_generate_from_strings_v3().
2022-10-03 17:57:45 +02:00
Thomas Haller
2fcea1cf05
glib-aux: rename nm_uuid_generate_from_strings() to nm_uuid_generate_from_strings_v3()
nm_uuid_generate_from_strings() uses variant3 UUIDs based on MD5.
We shouldn't use that in the future.

We will add a replacement, so rename this function so that the "good"
name is free again. Of course, code that uses this function currently
relies on that the behavior doesn't change. We cannot just drop it
entirely, but will replace it by something that gives the same result.

Rename.
2022-10-03 17:57:43 +02:00
Thomas Haller
ee32de41cf
glib-aux: add code comment to NM_UUID_INIT()
`NM_UUID_INIT(00, 09, 01, ...)` would look as if the values are
octal numbers. That is not the case. The macro mangles them,
so that the look like the UUID in string form "000901...".

This is a bit odd. Maybe more confusing than helpful. Or maybe helpful?
2022-10-03 17:57:43 +02:00
Thomas Haller
a5f125f8cb
glib-aux: add NM_UTILS_ERROR_COMMAND_FAILED error code 2022-09-29 14:41:58 +02:00
Thomas Haller
95e6ebec66
glib-aux: add nm_utils_get_process_exit_status_desc_buf() helper 2022-09-29 14:41:58 +02:00
Thomas Haller
520411623d
glib-aux: fix nm_str_buf_finalize() for cloning buffer
NMStrBuf can also contains NUL characters. We thus cannot use g_strndup(),
which uses strncpy() and truncates at the first NUL.

Fixes: 13d25f9d0b ('glib-aux: add support for starting with stack-allocated buffer in NMStrBuf')
2022-09-29 08:21:00 +02:00
Thomas Haller
f786b05479
glib-aux: swap arguments for nm_array_find_bsearch()
Have "len" before "elem_size". That is consistent with g_qsort_with_data()
and bsearch(), and is also what I would expect.

Note that the previous commit just renamed the function. If a user
of the new, changed API gets backported to an older branch, we will
get a compilation error and note that the arguments need to be adjusted.
2022-09-28 13:30:44 +02:00
Thomas Haller
2953ebccba
glib-aux: rename nm_utils_array_find_binary_search() to nm_array_bsearch()
The "nm_utils_" prefix is just too verbose. Drop it.
Also, Posix has a bsearch function. As this function
is similar, rename it.

Note that currently the arguments are provided in differnt
order from bsearch(). That will be partly addressed next.
That is the main reason for the rename. The next commit
will swap the arguments, so do a rename first to get a compilation
error when backporting a patch that uses the changed API.
2022-09-28 13:30:43 +02:00
Thomas Haller
ee0f3f6242
glib-aux: add nm_strv_contains() helper 2022-09-23 15:55:06 +02:00
Thomas Haller
43c3e2b683
glib-aux: add nm_hash_vals() and adjust implementation of nm_hash_update_val(),nm_hash_val()
nm_hash_update_vals() has variadic arguments and accepts (in principle) any
number of arguments. It works by copying the value to a packed struct on
the stack.

nm_hash_update_val() is essentially the same, but accepts only one
argument. Implement nm_hash_update_val() in terms of
nm_hash_update_vals().

Also, add nm_hash_vals(), and adjust nm_hash_val() to be implemented that way.

Maybe we should drop combine the val/vals variants into one, and not
have two variants. We only keep them because both are currently in use.
Also, we have nm_hash_update_valp(), which is useful but can only take one
argument. For naming consistency of nm_hash_update_val(), nm_hash_update_valp()
and nm_hash_update_vals() they are all kept.
2022-09-23 15:18:39 +02:00
Thomas Haller
a8931585be
platform,glib-aux: move and rename nm_platform_ip4_broadcast_address_create() 2022-09-23 11:43:33 +02:00
Thomas Haller
cc36baa5c7
glib-aux: add nm_str_truncate() helper 2022-09-23 11:43:27 +02:00
Thomas Haller
ffd8baa49f
all: use nm_g_array_{index,first,last,index_p}() instead of g_array_index()
These variants provide additional nm_assert() checks, and are thus
preferable.

Note that we cannot just blindly replace &g_array_index() with
&nm_g_array_index(), because the latter would not allow getting a
pointer at index [arr->len]. That might be a valid (though uncommon)
usecase. The correct replacement of &g_array_index() is thus
nm_g_array_index_p().

I checked the code manually and replaced uses of nm_g_array_index_p()
with &nm_g_array_index(), if that was a safe thing to do. The latter
seems preferable, because it is familar to &g_array_index().
2022-09-15 12:39:07 +02:00
Thomas Haller
07b32d5d22
glib-aux: add nm_g_array_index() macro and improve nm_g_array_index_p() macros
Add nm_g_array_index() as a replacement for g_array_index(). The value
of nm_g_array_index(), nm_g_array_index_p(), nm_g_array_first() and
nm_g_array_last() is that they add nm_assert() checks for valid
parameters.

nm_g_array_{first,last}() now returns an lvalue and not a pointer.
As such, they are just shorthands for nm_g_array_index() at index
0 and len-1, respectively.

`nm_g_array_index_p(arr, Type, idx)` is almost the same as
`&nm_g_array_index(arr, Type, idx)`. The only difference (and why the
former variant exists), is that nm_g_array_index_p() allows to get a
pointer one after the end.

This means, this is correct and valid to do:

   // arr->len might be zero
   arr = nm_g_array_index_p(arr, Type, 0);
   for (i = 0; i < arr->len; i++, arr++)
       ...

   ptr = nm_g_array_index_p(arr, Type, 0);
   end = nm_g_array_index_p(arr, Type, arr->len);
   for (; ptr < end; ptr++)
       ...

This would not be valid to do with nm_g_array_{index,first,last}().

Also fix supporting "const GArray *arr" parameter. Of course, the function
casts the constness away. Technically, that matches the fact that arr->data
is also not a const pointer. In practice, we might want to propagate the
constness of the container to the constness of the element lookup. While
doable, that is not implemented.
2022-09-15 12:39:06 +02:00
Thomas Haller
527061ed48
glib-aux/trivial: fix typo in code comment 2022-09-09 16:21:53 +02:00
Wen Liang
75349dc566
glib-aux: add "NM_IPV4LO_NETWORK" defines and similar
Co-authored-by: Thomas Haller <thaller@redhat.com>
2022-09-08 19:42:01 +02:00
Thomas Haller
c413d7c657
glib-aux: add NM_IN6ADDR_INIT() macro and use it 2022-09-08 19:42:01 +02:00
Thomas Haller
f16a6f55fb
glib-aux/trivial: fix typo in comment 2022-08-31 19:20:10 +02:00
Thomas Haller
1326e42823
glib-aux: first try stack allocated temporary buffer in nm_uuid_generate_from_strings()
Try to first use a stack allocated buffer for the temporary string.
Only if the data is too large, NMStrBuf will automatically grow
the buffer on the heap.

In many cases, this buffer will be large enough, and we can avoid the
heap allocation.
2022-08-31 19:20:10 +02:00
Thomas Haller
c5ec4ebd77
glib-aux: fix spurious semicolon after NM_STR_BUF_INIT() macros
It's wrong, and it breaks certain uses.

Fixes: 13d25f9d0b ('glib-aux: add support for starting with stack-allocated buffer in NMStrBuf')
2022-08-31 19:20:10 +02:00
Thomas Haller
6b74f3cc14
cloud-setup,glib-aux: use NULL instead of g_direct_equal() for hash tables 2022-08-31 09:47:48 +02:00
Thomas Haller
eec9efd989
glib-aux: fix nicks for zero flag in nm_utils_enum_to_str()
nm_utils_enum_to_str() can print flags, that is, combinations of
powers of two integers.

It also supports nicks, for certain flags.

When we have a nick for value zero, then that requires special
handling. Otherwise, that zero nick will always show up in the
string representation, although, it should only be used if the
enum value is exactly zero.
2022-08-25 23:07:44 +02:00
Thomas Haller
97a2a566b4
glib-aux/trivial: rename function for consistency 2022-08-25 19:23:41 +02:00
Thomas Haller
0e3ab2782a
glib-aux: simplify nm_inet_parse_str() by using nm_inet_parse_bin() 2022-08-25 19:05:57 +02:00
Thomas Haller
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.
2022-08-25 19:05:55 +02:00
Thomas Haller
232df1c08d
glib-aux/tests: test nm_ip_addr_is_site_local() 2022-08-25 19:05:53 +02:00
Thomas Haller
08eff4c46e
glib-aux: rename IP address related helpers from "nm-inet-utils.h"
- 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
2022-08-25 19:05:51 +02:00
Thomas Haller
d65feb26e5
glib-aux: move inet related helpers to "nm-inet-utils.h" 2022-08-25 19:05:51 +02:00
Thomas Haller
f23e43b18a
glib-aux: add "libnm-glib-aux/nm-inet-utils.h" 2022-08-25 19:05:46 +02:00
Thomas Haller
494b3d82c1
platform/netlink: add nlmsg_parse_error() helper 2022-08-09 08:02:40 +02:00
Thomas Haller
13d334cdbb
glib-aux,platform: add comments to nm_platform_ip_address_get_scope()/nm_utils_ip_is_site_local()
About site-local IPv6 addresses (unique local addresses, ULA).
2022-08-09 08:02:37 +02:00
Thomas Haller
8f67a80537
glib-aux: add nm_utils_ip6_is_ula() helper 2022-08-09 08:02:36 +02:00
Thomas Haller
e0fc8a11d5
glib-aux: add nm_g_hash_table_contains_any() helper 2022-08-09 08:02:36 +02:00
Thomas Haller
d20343c9d0
glib-aux: rework random number utils
Heavily inspired by systemd ([1]).

We now also have nm_random_get_bytes{,_full}() and
nm_random_get_crypto_bytes(), like systemd's random_bytes()
and crypto_random_bytes(), respectively.

Differences:

- instead of systemd's random_bytes(), our nm_random_get_bytes_full()
  also estimates whether the output is of high quality. The caller
  may find that interesting. Due to that, we will first try to call
  getrandom(GRND_NONBLOCK) before getrandom(GRND_INSECURE). That is
  reversed from systemd's random_bytes(), because we want to find
  out whether we can get good random numbers. In most cases, kernel
  should have entropy already, and it makes no difference.

Otherwise, heavily rework the code. It should be easy to understand
and correct.

There is also a major bugfix here. Previously, if getrandom() failed
with ENOSYS and we fell back to /dev/urandom, we would assume that we
have high quality random numbers. That assumption is not warranted.
Now instead poll on /dev/random to find out.

[1] a268e7f402/src/basic/random-util.c (L81)
2022-08-05 19:29:34 +02:00
Thomas Haller
e80fc43f2a
glib-aux: add assertions to nm_utils_fd_wait_for_event() 2022-08-05 16:10:39 +02:00
Thomas Haller
d5b31a05e6
glib-aux: add nm_str_buf_append_printfv()
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1321
2022-08-05 16:07:46 +02:00
Fernando Fernandez Mancera
cd31559ded utils: introduce nm_ether_addr_from_string() helper 2022-08-04 11:18:36 +02:00
Thomas Haller
483d287590
glib-aux: use unsigned long literals in NM_HASH_COMBINE_BOOLS() macro
To avoid the ambiguity for which integer type is used.
2022-08-04 11:05:33 +02:00