Commit graph

387 commits

Author SHA1 Message Date
Thomas Haller
128099151d shared: fix nm_errno_from_native() for negative input
Fixes: 67130e6706
2019-02-12 09:13:29 +01:00
Thomas Haller
d83d5f1da2 shared: use nm_strerror_native_r() in lower layers
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.
2019-02-12 08:50:28 +01:00
Thomas Haller
9beed4f661 all: replace strerror() calls with nm_strerror_native() 2019-02-12 08:50:28 +01:00
Thomas Haller
a4fb6ddfca all: replace g_strerror() calls with nm_strerror_native() 2019-02-12 08:50:28 +01:00
Thomas Haller
e1ca3bf7ed shared: add nm_strerror_native() to replace strerror() and g_strerror()
We have various options for strerror(), with ups and downsides:

- strerror()

    - returns pointer that is overwritten on next call. It's convenient
      to use, but dangerous.

    - not thread-safe.

    - not guaranteed to be UTF-8.

- strerror_r()

    - takes input buffer and is less convenient to use. At least, we
      are in control of when the buffer gets overwritten.

    - there is a Posix/XSI and a glibc variant, making it sligthly
      inconvenient to used. This could be solved by a wrapper we implement.

    - thread-safe.

    - not guaranteed to be UTF-8.

- g_strerror()

    - convenient and safe to use. Also the buffer is never released for the
      remainder of the program.

    - passing untrusted error numbers to g_strerror() can result in a
      denial of service, as the internal buffer grows until out-of-memory.

    - thread-safe.

    - guaranteed to be UTF-8 (depending on locale).

Add our own wrapper nm_strerror_native(). It is:

    - convenient to use (returning a buffer that does not require
      management).

    - slightly dangerous as the buffer gets overwritten on the next call
      (like strerror()).

    - thread-safe.

    - guaranteed to be UTF-8 (depending on locale).

    - doesn't keep an unlimited cache of strings, unlike g_strerror().

You can't have it all. g_strerror() is leaking all generated error messages.
I think that is unacceptable, because it would mean we need to
keep track where our error numbers come from (and trust libraries we
use to only set a restricted set of known error numbers).
2019-02-12 08:50:28 +01:00
Thomas Haller
4d9918aac2 all: assert that native errno numbers are positive
Use the NM_ERRNO_NATIVE() macro that asserts that these errno numbers are
indeed positive. Using the macro also serves as a documentation of what
the meaning of these numbers is.

That is often not obvious, whether we have an nm_errno(), an nm_errno_native()
(from <errno.h>), or another error number (e.g. WaitForNlResponseResult). This
situation already improved by merging netlink error codes (nle),
NMPlatformError enum and <errno.h> as nm_errno(). But we still must
always be careful about not to mix error codes from different
domains or transform them appropriately (like nm_errno_from_native()).
2019-02-12 08:50:28 +01:00
Thomas Haller
67130e6706 shared: cleanup separation and transition between errno and nmerr numbers
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.
2019-02-12 08:50:28 +01:00
Thomas Haller
89d3c5242b shared: fix nm_errno_from_native() for negative values
We first need to map negative values to their positive form,
and then do the check for the reserved range.

Fixes: 18732c3493
2019-02-12 08:50:28 +01:00
Thomas Haller
047998f80a all: cache errno in local variable before using it 2019-02-12 08:50:28 +01:00
Thomas Haller
a3370af3a8 all: drop unnecessary includes of <errno.h> and <string.h>
"nm-macros-interal.h" already includes <errno.h> and <string.h>.
No need to include it everywhere else too.
2019-02-12 08:50:28 +01:00
Thomas Haller
65884733ec all: minor coding style fixes (space before parentheses) 2019-02-11 15:22:57 +01:00
Thomas Haller
395174f659 shared: avoid "-Wmissing-braces" warning initalizing NMIPAddr
NMIPAddr contains an unnamed union. We have to either explicitly
initialize one field, or omit it.

    ../shared/nm-utils/nm-shared-utils.c:38:36: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
    const NMIPAddr nm_ip_addr_zero = { 0 };
                                       ^
                                       {}
2019-02-08 20:14:50 +01:00
Thomas Haller
06701e9532 macros: don't use __externally_visible__ attribute for clang
clang does not support externally_visible:

    ../libnm/nm-access-point.c:243:1: error: unknown attribute externally_visible ignored [-Werror,-Wunknown-attributes]
    NM_BACKPORT_SYMBOL (libnm_1_0_6, int, nm_access_point_get_last_seen, (NMAccessPoint *ap), (ap));
    ^
    ../shared/nm-utils/nm-macros-internal.h:1299:74: note: expanded from macro NM_BACKPORT_SYMBOL
    #define NM_BACKPORT_SYMBOL(version, return_type, func, args_typed, args) \
                                                                             ^
    ../shared/nm-utils/nm-macros-internal.h:1292:17: note: expanded from macro _NM_BACKPORT_SYMBOL_IMPL
    __attribute__ ((externally_visible)) return_type versioned_func args_typed \
                    ^
2019-02-07 17:31:05 +01:00
Thomas Haller
d80be7825d shared: add nm_clear_g_cancellable_disconnect() 2019-02-05 08:22:01 +01:00
Thomas Haller
fcfd4f4ff2 logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.

However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.

In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.

Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).

So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-02-05 08:18:08 +01:00
Thomas Haller
40b0d7ce1e shared: define NM_THREAD_SAFE_ON_MAIN_THREAD
This will be used by nm-logging to opportunistically avoid locking.
2019-02-05 08:18:07 +01:00
Thomas Haller
61e76e97dc shared: add nm_utils_gettid() and NM_ASSERT_ON_MAIN_THREAD() 2019-02-05 08:18:07 +01:00
Thomas Haller
14957e914a tests: use NM_CONST_MAX() macro where a constant expression is required
Otherwise, "nm-utils/nm-test-utils.h" won't work after we
include systemd headers.
2019-02-04 10:55:25 +01:00
Thomas Haller
b52d3e2ad3 shared: add NM_CONST_MAX() macro
There is:

 1) glib's MAX() macro, which evaluates arguments multiple times,
    but yields a constant expression, if the arguments are constant.

 2) NM's NM_MAX() macro, which evaluates arguments exactly once,
    but never yields a constant expression.

 3) systemd's MAX() which is like NM_MAX().

Now, it's sensible to use

    char buf[MAX (A_CONSTANT, ANOTHER_CONSTANT)];

and this works with glib's variant (1).

However, when we include systemd headers, 1) gets redefined to 3), and
above no longer works. That is because we we don't allow VLA and systemd's
macro gives not a constant expression.

Add NM_CONST_MAX() macro which is like systemd's CONST_MAX(). It can
only operate on constant arguments.
2019-02-04 10:55:25 +01:00
Beniamino Galvani
e6cf4213a7 build: fix building with LTO
Building with link-time optimization requires some tricks explained
in [1].

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48200#c28
2019-02-04 10:55:25 +01:00
Beniamino Galvani
b114b00f0a shared: convert macro argument to lowercase 2019-02-04 10:55:25 +01:00
Rafael Fontenelle
d81e10942f all: fix misspellings
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/64
2019-01-24 17:19:44 +01:00
Thomas Haller
744e11dc0d shared: add "struct in_addr" union member to NMIPAddr struct
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.
2019-01-22 16:30:23 +01:00
Thomas Haller
035c4ad45d shared: suppress -Wstringop-truncation warning in nm_strndup_a()
The compiler is too smart for nm_strndup_a(). The code is correct,
suppress "-Wstringop-truncation" warning.
2019-01-22 16:30:23 +01:00
Thomas Haller
e7e0100062 shared: fix generic selection of integers in nm_strdup_int()
This fixes a test error, which aims to convert "unsigned long int" type,
but the generic type may not have been covered.

Don't select based on the gint32-like typedefs, but on the basic C
integer types.

Fixes: 8c2d58b237

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/108
2019-01-16 15:45:43 +01:00
Thomas Haller
8c2d58b237 shared/tests: add test for nm_strdup_int() macro 2019-01-15 09:52:01 +01:00
Thomas Haller
3263cab596 all: add static assertion for maximumg alloca() allocated buffer
Add a compile time check that the buffer that we allocate on the stack
is reasonably small.
2019-01-15 09:52:01 +01:00
Thomas Haller
617bdbd8c2 all/trivial: rename NM_UTILS_LOOKUP_STR() to have "_A" suffix
NM_UTILS_LOOKUP_STR() uses alloca(). Partly to avoid the overhead of
malloc(), but more important because it's convenient to use. It does
not require to declare a varible to manage the lifetime of the heap
allocation.

It's quite safe, because the stack allocation is of a fixed size of only
a few bytes. Overall, I think the convenience that we get (resulting in
simpler code) outweighs the danger of stack allocation in this case. It's
still worth it.
However, as it uses alloca(), it still must not be used inside a (unbound)
loop and it is obviously a macro.

Rename the macros to have a _A() suffix. This should make the
peculiarities more apparent.
2019-01-15 09:52:01 +01:00
Thomas Haller
694533f529 shared: add nm_utils_strbuf_append_bin() helper
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.
2019-01-14 16:40:39 +01:00
Thomas Haller
2a6e7e917f shared: add nm_g_variant_ref() and nm_g_variant_unref() helpers
Akin to nm_g_object_ref() and nm_g_object_unref().
2019-01-14 11:55:17 +01:00
Thomas Haller
fce3243f12 shared/trivial: rename nm_utils_mem_all_zero() to nm_utils_memeqzero()
in systemd/systemd, systemd/casync, and rustyrussel/ccan (github) this
function is called "memeqzero()". Rename, to use a more popular name.
2019-01-09 16:46:41 +01:00
Thomas Haller
af67b4520f shared: refactor nm_utils_mem_all_zero() to use memcmp() 2019-01-09 16:46:41 +01:00
Thomas Haller
aab3e14883 shared: add nm_utils_getpagesize() and use it in netlink code
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`.
2019-01-09 16:46:41 +01:00
Thomas Haller
6ae04654f7 shared: avoid compiler warning in nm_strndup_a()
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;
                   ^~~~~~~~~~~~~~~~~
2019-01-09 16:46:41 +01:00
Thomas Haller
33bf73f252 shared: add typed nm_g_object_set_property*() helpers
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().
2019-01-07 10:09:10 +01:00
Thomas Haller
04c6c912b0 shared/tests: add nmtst_keyfile_assert_data() test util 2019-01-07 10:09:10 +01:00
Thomas Haller
b93a2cf728 shared/tests: add nmtst_rand_select() test util 2019-01-07 10:09:10 +01:00
Thomas Haller
e3ea8ecd33 shared: add NM_STR_HAS_PREFIX() macro
Commonly, the prefix is a string constant. We don't need to call
g_str_has_prefix() for that, which first requires strlen() on
the prefix. All the information is readily available.

Add a macro for that.
2019-01-07 10:09:10 +01:00
Thomas Haller
1f906d9214 shared/glib: add compat implementation for g_value_unset() to allow unintialized GValue 2019-01-07 10:09:10 +01:00
Thomas Haller
616abe865d shared/trivial: add comment about compat macro _NM_CC_SUPPORT_GENERIC w.r.t. C11
C11 provides _Generic(). Until now we used it when the compiler supports
it (in extended --std=gnu99 mode). In practice, now that we require C11
it should always be present.

We will drop compatibility code in the future. For now, just add a comment
and keep it. The reason is, that "shared/nm-utils/nm-macros-internal.h"
may be used by VPN plugins or applet, which may or may not yet bump to
C11. Keeping it for now, allows for an easier update.
2019-01-02 11:51:42 +01:00
Thomas Haller
ef53b47e7c shared,core: move logging enums to header "shared/nm-utils/nm-logging-fwd.h"
In core ("src/"), we use "nm-logging.h" for all logging. This dispatches
for logging to syslog, glog or systemd-journald.

If we want to log from a shared component under "shared/", we need to
use a common logging function. Add "nm-utils/nm-logging-fwd.h" for
forward declaring the used logging mechaism.

The shared library will still need to link with "src/nm-logging.c"
or an alternative implementation, depending on whether it is used
inside core or not.
2019-01-02 11:51:42 +01:00
Thomas Haller
269c15e873 keyfile: various refactoring and restructure nm_keyfile_read()
- in nm_keyfile_read(), unify _read_setting() and
  _read_setting_vpn_secret() in they way they are called
  (that is, they no longer return any value and don't accept
  any arguments aside @info).

- use cleanup attributes

- use nm_streq() instead of strcmp().

- wrap lines that have multiple statements or conditions.
2019-01-02 11:37:36 +01:00
Thomas Haller
d18f40320d platform: merge NMPlatformError with nm-error
Platform had it's own scheme for reporting errors: NMPlatformError.
Before, NMPlatformError indicated success via zero, negative integer
values are numbers from <errno.h>, and positive integer values are
platform specific codes. This changes now according to nm-error:
success is still zero. Negative values indicate a failure, where the
numeric value is either from <errno.h> or one of our error codes.
The meaning of positive values depends on the functions. Most functions
can only report an error reason (negative) and success (zero). For such
functions, positive values should never be returned (but the caller
should anticipate them).
For some functions, positive values could mean additional information
(but still success). That depends.

This is also what systemd does, except that systemd only returns
(negative) integers from <errno.h>, while we merge our own error codes
into the range of <errno.h>.

The advantage is to get rid of one way how to signal errors. The other
advantage is, that these error codes are compatible with all other
nm-errno values. For example, previously negative values indicated error
codes from <errno.h>, but it did not entail error codes from netlink.
2018-12-27 21:33:59 +01:00
Thomas Haller
18732c3493 shared: declare error numbers as enum and minor cleanup 2018-12-27 21:33:59 +01:00
Thomas Haller
5326100001 trivial: rename nl-errno to nm-errno 2018-12-27 21:33:59 +01:00
Thomas Haller
f9f022b659 shared: move nm_errno() function to nm-errno.h
No other changes (yet).
2018-12-27 21:33:59 +01:00
Thomas Haller
4fe18e5bdf core: move netlink errors to nm-errno.h
No other changes (yet).
2018-12-27 21:33:59 +01:00
Thomas Haller
943dcba531 shared,core: add "nm-errno.h"
This will be our extension on top of <errno.h>.

We want to use (integer) error numbers, that can both
contain native errors from <errno.h> and our own defines,
both merge in one domain. That is, we will reserve a small
range of integers for our own defines (that hopefully won't
clash with errors from <errno.h>).

We can use this at places where GError is too cumbersome to use.

The advantage is, that our error numbers extend <errno.h> and can
be mixed.

This is what "src/platform/nm-netlink.h" already does with nl_errno(). Next,
the netlink errors from there will be merged into "nm-errno.h".

Also, platform has NMPlatformError, which are a distinct set of error
numbers. But these work differently in the sense that negative values
represent codes from <errno.h> and positive numbers are our own platform
specific defines. NMPlatformError will also be merged into "nm-errno.h".

"nm-errno.h" will unify the error handling of platform and netlink,
making it more similar to what we are used to from systemd, and give
room to extend it for our own purpose.
2018-12-27 21:30:22 +01:00
Thomas Haller
9a6a354013 dhcp: fix static-route handling for intenal client and support multiple default routes
Preface: RFC 3442 (The Classless Static Route Option for Dynamic Host
Configuration Protocol (DHCP) version 4) states:

   If the DHCP server returns both a Classless Static Routes option and
   a Router option, the DHCP client MUST ignore the Router option.

   Similarly, if the DHCP server returns both a Classless Static Routes
   option and a Static Routes option, the DHCP client MUST ignore the
   Static Routes option.

Changes:

- sd_dhcp_lease_get_routes() returns the combination of both option 33
(static routes) and 121 (classless static routes). If classless static
routes are provided, the state routes must be ignored.

- we collect the options hash that we expose on D-Bus. For that purpose,
we must not merge both option types as classless static routes. Instead,
we want to expose the values like we received them originally: as two
different options.

- we continue our deviation from RFC 3442, when receiving classless static
routes with option 3 (Router), we only ignore the router if we didn't
already receive a default route via classless static routes.

- in the past, NetworkManager treated the default route specially, and
one device could only have one default route. That limitation was
already (partly) lifted by commit 5c299454b4
(core: rework tracking of gateway/default-route in ip-config). However,
from DHCP we still would only accept one default route. Fix that for
internal client. Installing multiple default routes might make sense, as
kernel apparently can skip unreachable routers (as it notes via ICMP
messages) (rh#1634657).

https://bugzilla.redhat.com/show_bug.cgi?id=1634657
2018-12-19 09:23:08 +01:00
Thomas Haller
1e4c0dd680 shared/tests: add helper functions to convert IP address to string
We have nm_utils_inet*_ntop(), however:

 - that is partly private API libnm-core, and thus only available in
   components that have access to that. Partly it's public API of
   libnm, but still only available in components that use libnm.

 - relying on the static buffers is discouraged for nm_utils_inet*_ntop().
   For testing, that is fine as we are in a more controlled envionment.
   So, add a test variant that explicitly relies on static buffers.
   That way, it's more convenient to use from tests.

 - these functions can assert more and are more convenient to use from
   tests.
2018-12-19 09:23:08 +01:00