Commit graph

14316 commits

Author SHA1 Message Date
Thomas Haller
06296f7c3c
libnm: belatedly export nm_ip_routing_rule_[gs]et_uid_range() symbols 2021-06-21 10:00:20 +02:00
Thomas Haller
eb8e55c822
version: add 1.34 macros 2021-06-21 10:00:20 +02:00
Beniamino Galvani
637a45e25b policy: prefer IPv4 to determine the hostname
When determining the hostname, it is preferable to evaluate devices in
a predictable order to avoid that the hostname changes between
different boots.

The current order is based first on hostname priority, then on the
presence of a best default route, and then on activation order.

The activation order is not a very strong condition, as it is
basically useless for devices that are autoactivated at boot.

As we already prefer IPv4 over IPv6 within the same connection, also
prefer it when 2 connections have the same priority and the same
default route status, to achieve better predictability.

https://bugzilla.redhat.com/show_bug.cgi?id=1970335
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/895
2021-06-21 08:53:42 +02:00
Thomas Haller
877d2b236f
core: avoid checking sort order for cached settings list
We now have a cached list of NMSettingsConnection instances,
sorted by their autoconnect priority.

However, the sort order nm_settings_connection_cmp_autoconnect_priority()
depends on various properties of the connection:

 - "connection.autoconnect" and "connection.autoconnect-priority"
 - the timestamp
 - "connection.uuid"

These properties almost never change, so it's a waste that every call
to nm_settings_get_connections_sorted_by_autoconnect_priority() needs
to check whether the sort order is still satisfied.

We can do better by tracking when the sort order might have been
destroyed and only check in those (much fewer) cases.

Note that we end up calling nm_settings_get_connections_sorted_by_autoconnect_priority()
a lot, so this makes a difference.
2021-06-18 11:20:30 +02:00
Thomas Haller
252e4a676b
core: cache GVariant for result of GetSettings()
The GetSettings() call is not the only place where we convert a
NMConnection to D-Bus. However it is one of the most prominent ones
with a measurable performance overhead.

The connection seldom changes, so it makes sense to cache it.

Note that GetSettings() is the only caller that specifies an option,
thus it's the only caller that converts a NMConnection to variant
in this particular way. That means, other callers don't benefit from
this caching and we could not cache the variant in the NMConnection
instance itself, because those callers use different parameters.
2021-06-17 17:49:44 +02:00
Thomas Haller
cea52c7cbd
libnm: add nm_connection_serialization_options_equal() helper 2021-06-17 17:48:16 +02:00
Thomas Haller
92daaff7d1
glib-aux: add NM_STRV_EMPTY_CC() helper macro 2021-06-17 17:48:15 +02:00
Thomas Haller
60957a4c8a
libnm: add helper functions for emitting signals in NMConnection
Not very useful, but it seems nicer to read. They anyway can be
inlined. After all, naming and structure is important and the places
where we emit signals are important. By having well-named helper
functions, these places are easier to find and reason about.
2021-06-17 17:48:14 +02:00
Thomas Haller
e7b5650eff
core: add nm_settings_get_connection_sorted_by_autoconnect_priority()
Turns out, we call nm_settings_get_connection_clone() *a lot* with sort order
nm_settings_connection_cmp_autoconnect_priority_p_with_data().

As we cache the (differently sorted) list of connections, also cache
the presorted list. The only complication is that every time we still
need to check whether the list is still sorted, because it would be
more complicated to invalidate the list when an entry changes which
affects the sort order. Still, such a check is usually successful
and requires "only" N-1 comparisons.
2021-06-17 17:48:13 +02:00
Thomas Haller
1f09e13f43
core: add nm_settings_connection_cmp_autoconnect_priority_with_data() helper 2021-06-17 17:48:13 +02:00
Thomas Haller
f51d3862f9
glib-aux: add nm_utils_ptrarray_is_sorted() helper 2021-06-17 17:48:12 +02:00
Thomas Haller
85df025e93
core: avoid undefined behavior comparing plain pointer values in _cmp_last_resort() 2021-06-17 17:48:11 +02:00
Thomas Haller
7a71aedf46
libnm: optimize NM_CONNECTION_GET_PRIVATE() for NMSimpleConnection
NMConnection is a glib interface, implemented only by NMSimpleConnection
and NMRemoteConnection.

Inside the daemon, every NMConnection instance is always a NMSimpleConnection.

Using glib interfaces has an overhead, for example NM_IS_CONNECTION() needs
to search the implemented types for the pointer. And NM_CONNECTION_GET_PRIVATE()
is implemented by attaching user data to the GObject instance. Both have measurable
overhead.

Special case them for NMSimpleConnection.

This optimizes primarily the call to nm_connection_get_setting_connection(),
which easily gets called millions of times. This is easily measurable.
2021-06-17 17:48:11 +02:00
Thomas Haller
f3abf2491a
libnm: add code comment about preserving ABI for libnm GObject structs 2021-06-17 17:48:10 +02:00
Thomas Haller
b0f4bb84bf
libnm: avoid cloning buffer for nm_connection_get_settings() in nm_keyfile_write() 2021-06-17 17:48:10 +02:00
Thomas Haller
5aef93355f
libnm: add _nm_connection_get_settings_arr() helper 2021-06-17 17:48:09 +02:00
Thomas Haller
207b101238
libnm: take reference to settings in nm_connection_for_each_setting_value()
As we iterate over the settings, let's ensure that they stay
alive while we call back to the user data.
2021-06-17 17:48:09 +02:00
Thomas Haller
d829849a7b
libnm: avoid cloning list of settings in nm_connection_to_dbus_full() 2021-06-17 17:48:09 +02:00
Thomas Haller
97eef2bf6d
libnm: implement nm_connection_get_setting*() via NMMetaSettingType
The NM_TYPE_SETTING_* macros are really function calls (to a GType/gsize which is
guarded by an atomic operation for thread safe initialization). Also, finding
the setting_info based on the GType requires additional lookups.

It's no longer necessary. We can directly find the setting using the
well known index.
2021-06-17 17:48:08 +02:00
Thomas Haller
c8c606b323
libnm: avoid cloning list of settings in _nm_connection_verify() 2021-06-17 17:48:08 +02:00
Thomas Haller
91aacbef41
libnm: refactor tracking of NMSetting in NMConnection
A NMConnection tracks a list of NMSetting instances. For
each setting type, it only can track one instance, as is
clear by the API nm_connection_get_setting().

The number of different setting types is known at compile time,
currently it is 52. Also, we have an NMMetaSettingType enum,
which assigns each type a number.

Previously, we were tracking the settings in a GHashTable.
Rework that, to instead use a fixed size array.

Now every NMConnection instance consumes 52 * sizeof(pointer)
for the settings array. Previously, the GHashTable required to malloc
the "struct _GHashTable" (on 64bit that is about the size of 12
pointers) and for N settings it allocated two buffers (for
the key and the values) plus one buffer for the hash values. So,
it may or may not consume a bit more memory now, but also can lookup
settings directly without hashing.

When looking at all settings, we iterate the entire array. Most
entries will be NULL, so it's a question whether this could be done
better. But as the array is of a fixed, small size, naive iteration
is probably still faster and simpler than anything else.

---

Test: compiled with -O2, x86_64:

  $ T=src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh; \
    make -j 8 "$T" && \
    "$T" 1>/dev/null && \
    perf stat -r 200 -B "$T" 1>/dev/null

Before:

 Performance counter stats for 'src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh' (200 runs):

            338.39 msec task-clock:u              #    0.962 CPUs utilized            ( +-  0.68% )
                 0      context-switches:u        #    0.000 K/sec
                 0      cpu-migrations:u          #    0.000 K/sec
             1,121      page-faults:u             #    0.003 M/sec                    ( +-  0.03% )
     1,060,001,815      cycles:u                  #    3.132 GHz                      ( +-  0.50% )
     1,877,905,122      instructions:u            #    1.77  insn per cycle           ( +-  0.01% )
       374,065,113      branches:u                # 1105.429 M/sec                    ( +-  0.01% )
         6,862,991      branch-misses:u           #    1.83% of all branches          ( +-  0.36% )

           0.35185 +- 0.00247 seconds time elapsed  ( +-  0.70% )

After:

 Performance counter stats for 'src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh' (200 runs):

            328.07 msec task-clock:u              #    0.959 CPUs utilized            ( +-  0.39% )
                 0      context-switches:u        #    0.000 K/sec
                 0      cpu-migrations:u          #    0.000 K/sec
             1,130      page-faults:u             #    0.003 M/sec                    ( +-  0.03% )
     1,034,858,368      cycles:u                  #    3.154 GHz                      ( +-  0.33% )
     1,846,714,951      instructions:u            #    1.78  insn per cycle           ( +-  0.00% )
       369,754,267      branches:u                # 1127.052 M/sec                    ( +-  0.01% )
         6,594,396      branch-misses:u           #    1.78% of all branches          ( +-  0.23% )

           0.34193 +- 0.00145 seconds time elapsed  ( +-  0.42% )
2021-06-17 17:48:08 +02:00
Thomas Haller
042cd99049
libnm/tests: test consistency for nm_meta_setting_types_by_priority 2021-06-17 17:48:08 +02:00
Thomas Haller
b7a7cc1b13
libnm: add nm_meta_setting_types_by_priority array for sorting settings
nm_meta_setting_infos is a list of all NMMetaSettingInfo, sorted by name.
Add nm_meta_setting_types_by_priority which provides a mapping with a
different sort order (first by priority). We need that sometimes.
2021-06-17 17:48:08 +02:00
Thomas Haller
1a5a4838f1
libnm: pack NMMetaSettingType enum
We keep the enum around in memory, so let's make it smaller/packed.
2021-06-17 17:48:08 +02:00
Thomas Haller
16b01233fa
libnm: add nm_meta_setting_info helpers 2021-06-17 17:48:07 +02:00
Beniamino Galvani
e3e0afb011 nm-daemon-helper: fix indentation
Ops.

Fixes: 9b802ff7f2 ('nm-daemon-helper: fix build with musl libc')
2021-06-16 18:32:44 +02:00
Beniamino Galvani
9b802ff7f2 nm-daemon-helper: fix build with musl libc
NSS is not available in musl libc:

./src/nm-daemon-helper/nm-daemon-helper.c:9:10: fatal error: nss.h: No such file or directory
    9 | #include <nss.h>
      |          ^~~~~~~
2021-06-16 18:19:35 +02:00
Beniamino Galvani
0cd20f94d0 firewall: fix double free
Fixes: 9ebdb967de ('firewall: implement masquerading for shared mode with nftables')
2021-06-15 19:40:59 +02:00
Thomas Haller
05f2a0b024
libnm: expose nm_ip_address_dup(), nm_ip_route_dup() API in libnm
This fixes commit 21c8a6b20e ('libnm-core, all: merge IPv4 and IPv6
address/route types'), which introduced this API but didn't export it
in the library. In practice this API is thus only usable since 1.32.0.
2021-06-15 19:11:57 +02:00
Thomas Haller
654bb92a69
firewall: use nm_g_main_context_push_thread_default_if_necessary() in _fw_nft_call_communicate_cb()
There is no need to push (and pop) the same main-context.
2021-06-15 18:25:22 +02:00
Thomas Haller
897c6a5744
firewall: fix signalling timeout error reason from _fw_nft_call()
During timeout we cancel the (internal) GCancellable. But the overall
error reason is not cancellation by the user, it's timeout. Fix
the error reason.

Fixes: 9ebdb967de ('firewall: implement masquerading for shared mode with nftables')
2021-06-15 18:15:56 +02:00
Thomas Haller
b8ae2dfa70
core/trivial: add comment about GMainContext to nm_shutdown_wait_obj_register_full() 2021-06-15 18:15:56 +02:00
Thomas Haller
79d9441567
firewall: change default for firewall-backend to "nftables""
It seems that the nftables backend works well. Let's change the default.
This will also be backported to nm-1-32 branch, for 1.32.0 release.

This reverts commit 0609f1f31c.
2021-06-14 11:17:25 +02:00
Thomas Haller
14ec96f262
libnm/tests: avoid coverity warning in test_setting_connection_secondaries_verify()
nm_strvarray_get_strv() returns the input pointer itself, if _secondaries is NULL.
It does so intentionally and correctly to create an artificial empty strv array.

Coverity doesn't like this. Try to workaround the warning:

    Error: ARRAY_VS_SINGLETON (CWE-119): [#def484]
    NetworkManager-1.31.90/src/libnm-core-impl/tests/test-setting.c:4544: address_of: Taking address with "&_secondaries" yields a singleton pointer.
    NetworkManager-1.31.90/src/libnm-core-impl/tests/test-setting.c:4544: identity_transfer: Passing "&_secondaries" as argument 1 to function "nm_strvarray_get_strv", which returns that argument.
    NetworkManager-1.31.90/src/libnm-core-impl/tests/test-setting.c:4544: callee_ptr_arith: Passing "_Generic (nm_strvarray_get_strv(&_secondaries, NULL), char const * const * : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char const ** : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char * const * : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char ** : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), void const * : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), void * : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char const * const * const : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char const ** const : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char * const * const : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), char ** const : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), void const * const : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL), void * const : (char const * const *)nm_strvarray_get_strv(&_secondaries, NULL))" to function "_nm_utils_strv_cmp_n" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
    # 4542|       G_STMT_END
    # 4543|
    # 4544|->         _assert_secondaries(s_con, (const char *const *) arr->pdata);
    # 4545|
    # 4546|           /* reimplement the normalization that we expect to happen and
2021-06-11 22:42:45 +02:00
Thomas Haller
627503ad86
cli: avoid coverity warning in do_connection_down()
Error: USE_AFTER_FREE (CWE-416): [#def729] [important]
    NetworkManager-1.31.90/src/nmcli/connections.c:3288: freed_arg: "connection_cb_info_finish" frees "info".
    NetworkManager-1.31.90/src/nmcli/connections.c:3287: pass_freed_arg: Passing freed pointer "info" as an argument to "g_signal_handlers_disconnect_matched".
    # 3285|
    # 3286|               if (info) {
    # 3287|->                 g_signal_handlers_disconnect_by_func(active, down_active_connection_state_cb, info);
    # 3288|                   connection_cb_info_finish(info, active);
    # 3289|               }
2021-06-11 22:42:45 +02:00
Thomas Haller
7825609f1f
glib-aux/tests: avoid coverity warning in test_nm_g_source_sentinel()
Coverity wrongly think there is a use after free in the test:

    Error: USE_AFTER_FREE (CWE-416): [#def559] [important]
    NetworkManager-1.31.90/src/libnm-glib-aux/tests/test-shared-general.c:1305: alias: Assigning: "s1" = "_s". Now both point to the same storage.
    NetworkManager-1.31.90/src/libnm-glib-aux/tests/test-shared-general.c:1324: freed_arg: "g_source_unref" frees "s1".
    NetworkManager-1.31.90/src/libnm-glib-aux/tests/test-shared-general.c:1330: deref_after_free: Dereferencing freed pointer "s1".
    # 1328|               s2 = nm_g_source_sentinel_get(0);
    # 1329|               g_assert(s2 == s1);
    # 1330|->             g_assert_cmpint(g_atomic_int_get(&s1->ref_count), >=, 1);
    # 1331|           }
    # 1332|       }

Rework the code in the hope to avoid the false warning.
2021-06-11 22:42:44 +02:00
Thomas Haller
c87433ebd2
platform: avoid wrong coverity warning in nmp_utils_sysctl_open_netdir()
The warning is wrong, because we already assert for the string length a few
lines earlier.

  Error: STRING_OVERFLOW (CWE-120): [#def595]
  NetworkManager-1.31.90/src/libnm-platform/nm-platform-utils.c:1896: fixed_size_dest: You might overrun the 16-character fixed-size string "ifname_buf_last_try" by copying "ifname" without checking the length.
  # 1894|           if (nm_streq(ifname, ifname_buf_last_try))
  # 1895|               return -1;
  # 1896|->         strcpy(ifname_buf_last_try, ifname);
  # 1897|
  # 1898|           fd_dir = open(sysdir, O_DIRECTORY | O_CLOEXEC);
2021-06-11 22:42:44 +02:00
Thomas Haller
860b280248
libnm: hide NMSimpleConnection type from public headers 2021-06-11 22:32:24 +02:00
Thomas Haller
e46d484fae
libnm: hide NMSetting types from public headers
When subclassing a GObject type, the class and object structs
must be available and defined in the header.

For libnm, and in particular for NMSetting classes, we don't want
users to subclass NMSetting. It also doesn't work, because libnm
has internal code that is necessary to hook up the NMSetting class.
You cannot define your own type and make it work together with
libnm.

Having the structs in public headers limits what we can do with them.
For example, we could embed the private data directly in the structures
and avoid the additional indirection.

This is an API break, but for something that most likely nobody cares
about. Or better, nobody should care about. API is not what is
accidentally defined in a header, API was the library provides to
meaningfully use. Subclassing these types is not meaningful and was
only accidentally possible so far.

Only hide the structs for now. More cleanup is possible later. We shall
however aim to keep the padding and struct layout to not also break ABI.
2021-06-11 22:32:24 +02:00
Thomas Haller
0d6c35a6d9
core: avoid accessing opaque NMSetting type
Next, NMSetting will be hidden from public headers and become an opaque type.
We cannot do typeof(*setting) anymore.
2021-06-11 22:32:12 +02:00
Beniamino Galvani
c89ac8f0c7 device: remove unused variable
Fixes: 620fbb7894 ('device: use nm_device_resolve_address()')
2021-06-11 21:58:02 +02:00
Beniamino Galvani
620fbb7894 device: use nm_device_resolve_address() 2021-06-11 21:43:12 +02:00
Beniamino Galvani
27eae4043b device: add a nm_device_resolve_address()
The new function resolve an address via DNS, first by using
systemd-resolved (disabling synthesized results) and then by spawning
the daemon helper.

Trying systemd-resolved via D-Bus before spawning the helper is
important to get a correct result. Suppose that resolv.conf points to
the local stub listener at 127.0.0.53; if NM only spawns the helper,
the helper will query the local systemd-resolved which could return a
synthesized result.

Therefore, we first query systemd-resolved with NO_SYNTHESIZE and
then, in case of error, we spawn the helper.
2021-06-11 21:43:12 +02:00
Beniamino Galvani
7285bc56a9 dns: add function to retrieve the systemd-resolved plugin instance
Now that we have nm_dns_systemd_resolved_resolve_address(), we also
need a way to obtain a reference to the plugin.
2021-06-11 21:43:12 +02:00
Beniamino Galvani
648b0848f1 nm-daemon-helper: implement 'resolve-address' operation
Implement a new operation to resolve the hostname from an
address. Note the call to __nss_configure_lookup("hosts", "dns"): this
configures the glibc Name Service Switch (NSS) to only use DNS,
bypassing other modules that might be configured in
/etc/nsswitch.conf. Other modules like 'myhostname' or 'resolve' can
return synthesized names, while we are only interested in real DNS
results.
2021-06-11 21:43:12 +02:00
Beniamino Galvani
6ac21ba916 core: add infrastructure for spawning a helper process 2021-06-11 21:43:12 +02:00
Beniamino Galvani
326dde6d53 core,nm-dispatcher: use nm_utils_get_process_exit_status_desc() 2021-06-11 21:43:11 +02:00
Beniamino Galvani
517852dccd libnm-glib-aux: add nm_utils_get_process_exit_status_desc() 2021-06-11 21:43:11 +02:00
Beniamino Galvani
9e69d921c1 dns/resolved: fix memory leak
'v_name' must be freed. Pass ownership to the result element.

Fixes: e7b76f6757 ('dns/resolved: add API for ResolveAddress call')
2021-06-11 21:43:11 +02:00
Thomas Haller
5ccc5e10b9 shared: add nm_ip_addr_init() helper 2021-06-11 21:43:11 +02:00