NMStrBuf's API is all about convenience. When you reset the buffer,
is it convenient to immediately append a new string?
It seems not. Make nm_str_buf_reset() simpler by doing only one thing.
This is the same as libnm's nm_utils_hwaddr_aton(), which however
is public API.
We want to use this function also without libnm(-core). Hence add
the helper to "shared/nm-glib-aux".
Add a new key management option to support WPA3 Enteprise wifi
connection.
Only supported with wpa_supplicant for the time being.
Signed-off-by: Antonio Cardace <acardace@redhat.com>
Currently libnm headers include <linux/if_{ether,infiniband,vlan}.h>.
These are public headers, that means we drag in the linux header to all
users of <NetworkManager.h>.
Often the linux headers work badly together with certain headers from libc.
Depending on the libc version, you have to order linux headers in the right
order with respect to libc headers.
We should do better about libnm headers. As a first step, assume that
the linux headers don't get included by libnm, and explicitly include
them where they are needed.
Including <netinet/ether.h> with musl leads to a conflict with <linux/if_ether.h>,
due to redefining ethhdr struct. As we include <linux/if_ether.h> in "nm-utils.h",
that is a problem.
Avoid that, by including other headers.
Run:
./contrib/scripts/nm-code-format.sh -i
./contrib/scripts/nm-code-format.sh -i
Yes, it needs to run twice because the first run doesn't yet produce the
final result.
Signed-off-by: Antonio Cardace <acardace@redhat.com>
nm_utils_hwaddr_len() isn't very useful. It's documented to
only accept two possible input values (ARPHRD_ETHER and ARPHRD_INFINIBAND)
for which the respective return values are well known.
In particular, asserting that the input value is one of the two values
means it becomes harder to extend the function (and make it more useful).
Because, then the user would need to call:
#if NM_VERSION > NM_VERSION_1_XX
len = nm_utils_hwaddr_len (ARPHDR_FOO);
#else
len = 0
#endif
and then it would introduce an unnecessary run time dependency on
NM_VERSION_1_XX.
Instead, just document to return 0 if the value is not supported.
_nm_utils_hwaddr_aton() is only a wrapper around nm_utils_hexstr2bin_full().
But it abstracts the "right" parameters for what we consider a valid MAC
address and what not. As such, this function is useful.
Move it to "shared/" and replace the dupicate macro hwaddr_aton() with
it.
- only call hwaddr_aton() once per function. Also, pass it sizeof(buf)
as buffer size, it seems more correct.
- the only downside is that we now would always first parse up to 20
characters, before comparing the requested length. Previously, a
MAC address that was too long was rejected earlier (and the parsing
aborted earlier). But that is a tiny overhead, also we expect that
in common cases the MAC addresses are in fact of the right size,
then there is no difference.
nm_utils_hexstr2bin_full() is our general hexstr to binary parsing
method. It uses (either mandatory or optional) delimiters. Before,
if delimiters are in use, it would accept individual hexdigits.
E.g. "a:b" would be accepted as "0a:0b:.
Add an argument that prevents accepting such single digits.
The 'clsact' qdisc is similar to 'ingress' but supports both ingress
and egress [1]. It uses the same handle as 'ingress' and has two child
classes :fff2 (ingress) and :fff3 (egress) on which filters can be
attached.
With clsact, for example, it becomes possible to do port mirroring
with a single qdisc:
nmcli connection modify mirror +tc.qdisc "clsact"
nmcli connection modify mirror +tc.tfilter
"parent ffff:fff3 matchall action mirred egress mirror dev dummy1"
nmcli connection modify mirror +tc.tfilter
"parent ffff:fff2 matchall action mirred egress mirror dev dummy1"
instead of two (ingress + i.e. prio). We don't support yet the
symbolic names 'ingress' and 'egress' for :fff2 and :fff3 in the
filter.
See-also: https://bugzilla.redhat.com/show_bug.cgi?id=1436535
[1] https://lwn.net/Articles/671458/
They serve a similar purpose.
Previously, nm-json-aux.h contained the virtual function table for accessing
the dynamically loaded libjansson. But there is no reason why our own
helper functions from nm-json.h cannot be there too.
We anyway load libjansson with dlopen(), and already before it could
happen that libjansson is not available. In that case, we would not
crash, but simply proceed without json validation.
Since libnm-core no longer uses libjansson directly, but only via
"nm-glib-aux/nm-json.h", we can just always compile with that, and use
it at runtime. That means, libjansson is not a build dependency for
libnm anymore, so we don't need a compile time check.
Note that if you build without libjansson, then JANSSON_SONAME is
undefined, and loading it will still fail at runtime. So, even if
we now always build with all our code enabled, it only works if you
actually build with libjansson. Still, it's simpler to drop the
conditional build, as the only benefit is a (minimally) smaller
build.
nm-json.[hc] uses libjansson, but only loads it at runtime with dlopen. There
is no more run compile time dependency. Move it to shared, so that it can be
(theoretically) used by other components.
Also, drop the conditional compilation. Granted, if you don't build with
libjansson enabled, then the JANSSON_SONAME define is unset and the code
will fail to load at runtime (which is fine). However, we can still build
against our JSON wrappers. The code savings of conditional build are minimal
so drop it.
It's error prone to include the header and trying not to use it.
Don't include <jansson.h>. Instead, redefine our nm variants of
everything.
Note that we only redefine stuff that is in public headers (like
"json_t" typedef). libjansson anyway must not change the struct layout
and the like, without breaking all applications. That is because the
non-opaque code from the header anyway is part of the applications that
include it. Later we will add additional unit test that checks that our
redefinition matches to what we had at compile time.
Some symbols in jansson.h are macros, some are regular functions,
and some are inline functions.
Regular functions must not be used directly, only via dlsym().
Macros must be used directly, but it is non-obvious which symbols
are macros. Hence, for each json_* macro add an nm_json_* alias.
Inline functions are a bit odd. If they are inlined and don't use
any non-inlined symbols from libjansson, they could be used directly.
However, it's non obvious whether both of the conditions are met.
Hence, we reimplement them in nm-json.h. The only function of this kind
is json_decref().
The point is to not use any json_* symbols directly -- except structs
and typedefs.
Seemingly, with this change we don't use any jansson symbols directly.
However, that is not true, as macros like nm_json_object_foreach()
still are implemented based on what is included from <jansson.h>.
Hence, we cannot drop patching the included jansson.h header yet and
still need our wrapper functions.
Rework the code how we access libjansson.
libnm wants to use libjansson, but it doesn't directly link to it.
The reason is that (until recently), libjansson has conflicting symbols
with libjson-c and libjson-glib. That means, if libnm would directly
link against libjansson, then if the using application happens to drag
in one of the conflicting libraries, the application would crash. Instead,
we dlopen() the library (with flags RTLD_LOCAL|RTLD_DEEPBIND).
However, as it is currently done, it doesn't fully work, as unit test
failures of libnm show on Debian sid (where libmount links against
libcryptsetup which links against libjson-c). Theoretically, our current
approach should work. At least for libnm; not for the OVS and team
plugins which use libjansson directly in NetworkManager core.
What I dislike about the current approach is that we still include
<jansson.h>, but somehow try not to use any symbols from it (via #define
we remap the json functions). The previous approach is "smaller", but also highly
confusing, and error prone, as there is a subtle bug as the unit test failure
shows (which I don't understand).
Instead, add and load a virtual function table NMJsonVt. Later, we will
go further ad drop all direct uses of <jansson.h> header.
The output of nm_utils_format_variant_attributes() must be accepted by
nm_utils_parse_variant_attributes(), producing the initial attributes.
The latter has a special handling of some attributes, depending on the
input NMVariantAttributeSpec list. For example, if the
NMVariantAttributeSpec is a boolean with the 'no_value' flag, the
parser doesn't look for a value.
Pass the NMVariantAttributeSpec list to the format function so that it
can behave in the same way as the parse one.
- mark global variables as const. This allows the linker to
mark the variable as read only.
- for nm_utils_wifi_[25]ghz_freqs(), don't generate a list based
on bg_table/a_table. Instead, keep static array of frequencies.
Since we have unit tests that check the consistency, this has
little maintenance effort.
- add unit tests
Commit 37e7fa38c2 ("nm-supplicant-interface: enable OWE security
when transition mode is available") adds the OWE security flag in
case a valid OWE transtition mode IE is present on the beacon.
It also removes the OWE security flag in case the Iinformation elements
of a beacon are updated and a OWE transition mode IE can't be found.
When a pure OWE AP updates it's Information Elements (e.g. BSS Load
Element), the OWE security flag is falsely removed.
Introduce a new NM_802_11_AP_SEC_KEY_MGMT_OWE_TM security flag and use
it exclusively for OWE transition mode. Don't use the
M_802_11_AP_SEC_KEY_MGMT_OWE security flag on transition-mode APs.
Signed-off-by: David Bauer <mail@david-bauer.net>
This will be used for nm_setting_option_clear_by_name(), to
filter based on a name. But it is a general purpose typedef
for a predicate, not tied to NMSetting or option.
By passing as length of the MAC addresses -1 for both arguments, one
could get through to compare empty strings, NULL, and addresses longer
than the maximum. Such addresses are not valid, and they should never
compare equal (not even to themselves).
This is a change in behavior of public API, but it never made sense to
claim two addresses are equal, when they are not even valid addresses.
Also, avoid undefined behavior with "NULL, -1, NULL, -1" arguments,
where we would call memcmp() with zero length and NULL arguments.
UBSan flags that too.
When parsing user input if is often convenient to allow stripping whitespace.
Especially with escaped strings, the user could still escape the whitespace,
if the space should be taken literally.
Add support for that to nm_utils_buf_utf8safe_unescape().
Note that this is not the same as calling g_strstrip() before/after
unescape. That is, because nm_utils_buf_utf8safe_unescape() correctly
preserves escaped whitespace. If you call g_strstrip() before/after
the unescape, you don't know whether the whitespace is escaped.