We should use the same str2bool parser everywhere: _nm_utils_ascii_str_to_bool().
Incidentally, this function allows more forms of expressing a boolean
value.
$ nmcli connection modify "$CON" ipv4.routes '1.2.3.4/32 1.2.3.1 onlink=1'
Error: failed to modify ipv4.routes: invalid option 'onlink=1': invalid boolean value '1' for attribute 'onlink'.
We also do this for libnm and libnm-core, where it causes visible changes
in behavior. But if somebody would rely on the hashing implementation
for hash tables, it would be seriously flawed.
Next we will use siphash24() instead of the glib version g_direct_hash() or
g_str_hash(). Hence, the "nm-utils/nm-hash-utils.h" header becomes very
fundamental and will be needed basically everywhere.
Instead of requiring the users to include them, let it be included via
"nm-default.h" header.
Currently there are multiple features that require Jansson support,
but WITH_JANSSON=1 is set only when configuring with
--enable-json-validation. Therefore a build with
"--disable-json-validation --enable-ovs" fails.
The availability of Jansson (WITH_JANSSON) should only be used:
- to check if dependent features can be enabled
- to determine compiler and linker flags in the Makefile
- in nm-jansson.h to define compatibility functions if needed
Everything else must be controlled by a configure switch.
https://bugzilla.gnome.org/show_bug.cgi?id=790233
We want to support large number of routes. Reduce the number
of copies, by adding internal accessor functions.
Also, work around a complaint from coverity:
46. NetworkManager-1.9.2/libnm-core/nm-utils.c:1987:
dereference: Dereferencing a null pointer "names".
Since kernel commit a4176a9391868bfa87705bcd2e3b49e9b9dd2996 (net:
reject creation of netdev names with colons), kernel rejects any
colons in the interface name.
Since kernel could get away with tightening up the check, we can
too.
The user anyway can not choose arbitrary interface names, like
"all", "default", "bonding_masters" are all going to fail one
way or another.
teamd adds the "tx_hash" property for "lacp" and "loadbalance" runners
when not present. Do the same so that our original configuration
matches with the one reported by teamd.
https://bugzilla.redhat.com/show_bug.cgi?id=1497333
By using a macro, we don't cast all the types to guint. Instead,
we use their native types directly. Hence, we don't need
nm_hash_update_uint64() nor nm_hash_update_ptr().
Also, for types smaller then guint like char, we save hashing
the all zero bytes.
The privious NM_HASH_* macros directly operated on a guint value
and were thus close to the actual implementation.
Replace them by adding a NMHashState struct and accessors to
update the hash state. This hides the implementation better
and would allow us to carry more state. For example, we could
switch to siphash24() transparently.
For now, we still do a form basically djb2 hashing, albeit with
differing start seed.
Also add nm_hash_str() and nm_str_hash():
- nm_hash_str() is our own string hashing implementation
- nm_str_hash() is our own string implementation, but with a
GHashFunc signature, suitable to pass it to g_hash_table_new().
Also, it has this name in order to remind you of g_str_hash(),
which it is replacing.
"nm-utils/nm-shared-utils.h" shall contain utility function without other
dependencies. It is intended to be used by other projects as-is.
nm_utils_random_bytes() requires getrandom() and a HAVE_GETRANDOM configure
check. That makes it more cumbersome to re-use "nm-shared-utils.h", in
cases where you don't care about nm_utils_random_bytes().
Split nm_utils_random_bytes() out to a separate file.
Same for hash utils, which depend on nm_utils_random_bytes(). Also, hash
utils will eventually be extended to use siphash24.
Introduce a NM_HASH_INIT() function. It makes the places
where we initialize a hash with a certain seed visually clear.
Also, move them from "shared/nm-utils/nm-shared-utils.h" to
"shared/nm-utils/nm-macros-internal.h". We might want to
have NM_HASH_INIT() non-inline (hence, define it in the
source file).
GArray's and GPtrArray's plen argument is unsigned. The index variable
to iterate the list, should not have a smaller range (or different data type).
Also, assert against negative idx argument.
CC libnm-core/libnm_core_libnm_core_la-nm-utils.lo
libnm-core/nm-utils.c:210:6: error: variable 'encodings' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
if (lang) {
^~~~
libnm-core/nm-utils.c:220:7: note: uninitialized use occurs here
if (!encodings) {
^~~~~~~~~
libnm-core/nm-utils.c:210:2: note: remove the 'if' if its condition is always true
if (lang) {
^~~~~~~~~~
libnm-core/nm-utils.c:198:30: note: initialize the variable 'encodings' to silence this warning
const char *const *encodings;
^
= NULL
Fixes: 28a0627481
Using plain numbers make it cumbersome to grep for
setting types by priority.
The only downside is, that with the enum values it
is no longer obvious which value has higher or lower
priority.
Also, introduce NM_SETTING_PRIORITY_INVALID. This is what
_nm_setting_type_get_base_type_priority() returns. For the moment
it still has the same numerical value 0 as before. Later, that
shall be distinct from NM_SETTING_PRIORITY_CONNECTION.
Teamd is not happy about them and would fail anyway. Worse even, if we
json_loads() such a JSON, which is precisely what happens when we inject the
"hwaddr" key, we turn bad JSON into a good one in a lossy matter. Not good.
https://bugzilla.redhat.com/show_bug.cgi?id=1455130
When the two base settings are present, use one of higher priority.
This will pick the "bridge" setting when both "bridge" and "bluetooth" are
present for a Bluetooth NAP connection.
Commit a8730c51c8 moved the enum
utils from libnm-core to shared/nm-utils.
However, three of those functions are part of public API in libnm.
So, when statically linking against "shared/nm-utils/nm-enum-utils.c"
and dynamically linking against libnm.so, those symbols are present
twice and cause a linker failure.
Fix that by moving the public API back to libnm-core.
Fixes: a8730c51c8
libnm contains the public function nm_utils_enum_from_str() et al.
The function is not flexible enough for nmcli's usecase. So, I would
need another public function like nm_utils_enum_from_str_full() that
has an extended API.
That was already required previously for ifcfg-rh writer, but in that
case I could just add it as internal API as libnm-core is linked statically
with NetworkManager.
I don't want to commit to a public API for an utility function. So move
the code instead to the shared directory, so that nmcli may link
statically against it and use the internal API.
nm_utils_enum_to_str() may also output numeric values if there is no
corresponding "nick" for the enum/flag value.
For enums the value is in decimal and for flags the value is hexadecimal
(with a "0x" prefix).
The same was already supported by nm_utils_enum_from_str() when reading
the value. However, previously, reading a flag would only support hex
numbers and reading a enum would only support decimal numbers.
Extend that, to allow passing numbers in any base. For nm_utils_enum_to_str()
also make sure to never output nicks that may be misinterpreted as
numbers.
It is not uncommon that a flags type has also the value 0 mapped,
for example to "unknown" or "none".
In that case, we should not return an empty string, but instead
that zero value.
Also, flags actually have an unsigned type. That isn't a real
problem to cast it to a signed int. But be more careful about
it and use unsigned while handling unsigned values and only
cast to int once.
Various libnm objects (addresses, routes) carry an hash table of
attributes represented as GVariants indexed by name. Add common
routines to convert to and from a string representation.
To parse a string, a knowledge of the supported attributes (and their
types) is needed: we represent it as an opaque type
NMVariantAttributeSpec that callers must query to the library for the
specific object type and pass to the parse function.
- for nm_utils_enum_to_str(), whenever encounter a numeric value
that has no expression as enum/flag, encode the value numerically.
For enums, encode it as decimal. For flags, encode it as hexadecimal
(with 0x prefix).
Also check that an existing value_nick cannot be wrongly interpreted
as a integer, and if they would, encode them instead as integers only.
- Likewise, in nm_utils_enum_from_str() accept numerical values
and for nm_utils_enum_get_values() return enum nicks that look
like numeric values in their numeric form only.
- In nm_utils_enum_from_str(), don't use g_strsplit(), but clone the
string only once and manipulate it inplace.
- Accept '\n' and '\r' as additional delimiters for flags.
- For consistency, also return an err_token for enum types. If the caller
doesn't care about that, he should simply not pass the out-argument.
Unfortunately nm_utils_enum_to_str() doesn't allow to specify the
separator between enum values. Since the function is public API and
can't be modified now, add a new internal function which accepts the
separator as argument.
The -Wimplicit-fallthrough=3 warning is quite flexible of accepting
a fall-through warning.
Some comments were missing or not detected correctly.
Thereby, also change all other comments to follow the exact
same pattern.
The function is used, among others, in the get_property() of many
objects to return a boxed strv from a list. The default value for a
boxed strv property is NULL, but _nm_utils_slist_to_strv() returns a
pointer to an array with zero elements when the list is empty.
Change the function to return NULL if the input list is empty.