libnm exposes simplified variants of hexstr2bin in its public API. I
think that was a mistake, because libnm should provide NetworkManager
specific utils. It should not provide such string functions.
However, nmcli used to need this, so it was added to libnm.
The better approach is to add it to our internally shared static
library, so that all interested components can make use of it.
Will be used later. The point is to set an IP address from
unvalidated/untrusted input (that is, the data length might
not match the address-family).
Will be used later when parsing netlink attributes.
A helper method, only useful for printf debugging -- and thus
unused in the source-tree.
It is relatively cumbersome to lookup the GType that implements
a property. For example, for NMDeviceBond.driver, it should return
NMDevice (which implements the "driver" property).
Subsequent calls to nm_strerror_native() overwrite the previous
buffer. That is potentially dangerious. At least functions in
shared/nm-utils (which are lower-layer utilities) should not do
that and instead use a stack-local buffer. That is because these
functions should not make assumptions about the way they are called.
On the other end, nmcli passing the return-value of nm_strerror_native()
to g_print() is clearly OK because the higher layers are in control of
when the call nm_strerror_native() -- by relying that lower layers don't
interfere.
The native error numbers (from <errno.h>) and our nmerr extention on top
of them are almost the same. But there are peculiarities.
Both errno and nmerr must be positive values. That is because some API
(systemd) like to return negative error codes. So, a positive errno and
its negative counter part indicate the same error. We need normalization
functions that make an error number positive (these are nm_errno() and
nm_errno_native()).
This means, G_MININT needs special treatment, because it cannot be
represented as a positive integer. Also, zero needs special
treatment, because we want to encode an error, and zero already encodes
no-error. Take care of these special cases.
On top of that, nmerr reserves a range within native error numbers for
NetworkManager specific failure codes. So we need to transition from native
numbers to nmerr numbers via nm_errno_from_native().
Take better care of some special cases and clean them up.
Also add NM_ERRNO_NATIVE() macro. While nm_errno_native() coerces a
value in the suitable range, NM_ERRNO_NATIVE() asserts that the number
is already positive (and returns it as-is). It's use is only for
asserting and implicitly documenting the requirements we have on the
number passed to it.
NMIPAddr is a union of IPv4 and IPv6 addresses.
A lot of our internal API handles IPv4 as in_addr_t / guint32 / be32_t
types, as such the union field "addr4" is just a plain number. Possibly
the internal API should be all refactored to prefer "struct in_addr"
instead, but that is yet to be done.
Anyway, at a few places we will need also access to the IPv4 address in form of
a `struct in_addr`. Add an alias for that.
I am not too happy about the resulting naming. It would be nicer to have
struct in_addr addr4;
struct in6_addr addr6;
in_addr_t s_addr4;
but for now, don't do such renaming.
Add a version of nm_utils_strbuf_append_*() that does not care
about NUL terminate strings, but accept any binary data. That makes
it useful for writing a binary buffer.
Since we already cached the result of getpagesize() in a static variable (at
two places), move the code to nm-shared-utils, so it is reusable.
Also, use sysconf() instead of getpagesize(), like suggested by `man
getpagesize`.
Using strncpy() in the macro directly can result in a compiler warning.
We don't want to replace this with memcpy(), because strncpy() aborts
on the first NUL and fills the rest with NUL. Since nm_strndup_a() is a
replacement for g_strndup(), we want to do that here as well.
In file included from ../shared/nm-default.h:294,
from ../libnm-core/nm-utils.c:22:
../libnm-core/nm-utils.c: In function nm_sock_addr_endpoint_new:
../shared/nm-utils/nm-shared-utils.h:281:4: error: strncpy output truncated before terminating nul copying as many bytes from a string as its length [-Werror=stringop-truncation]
strncpy (_s, _str, _len); \
^~~~~~~~~~~~~~~~~~~~~~~~
../libnm-core/nm-utils.c:154:26: note: in expansion of macro nm_strndup_a
host = _parse_endpoint (nm_strndup_a (200, endpoint, l_endpoint - 1, &host_clone),
^~~~~~~~~~~~
../libnm-core/nm-utils.c:152:15: note: length computed here
l_endpoint = strlen (endpoint) + 1;
^~~~~~~~~~~~~~~~~
Add helper wrappers around nm_g_object_set_property() that take a
native value, construct a GValue of the according type, and call
nm_g_object_set_property().
These are simple macros/functions that append a heap-allocated string to
a GPtrArray. It is intended for a GPtrArray which takes ownership of the
strings (meaning, it has a g_free() GDestroyNotify).
The GChecksum API is cumbersome to use.
For example, g_checksum_get_digest() requires a length input/output
argument. At the same time, GChecksum does not allow you to query its
checksum-type nor the desired digest-length. When you have a GChecksum
at hand, you must always know the digest-length you are going to use.
So, the length parameter is only good for asserting.
Add a macro to make that more convenient.
Benefits: it's less lines of code, and we always do all the asserts
that are due.
As we accept addr_family %AF_UNSPEC to detect the address family,
we also need to return it. Just returning the binary address without
the address family makes no sense.
I think g_memdup() is dangerous for integer overflow. There
is no need for accepting this danger, just use our own nm_memdup()
which does not have this flaw.
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"