From 700cd20d4dad91f38497b74df76b0e2d1177a4fd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 19 Jan 2023 20:26:31 +0100 Subject: release: bump version to 1.43.0 (development) --- configure.ac | 4 ++-- meson.build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index bb9be0b33a..69e6c67272 100644 --- a/configure.ac +++ b/configure.ac @@ -7,8 +7,8 @@ dnl - add corresponding NM_VERSION_x_y_z macros in dnl "shared/nm-version-macros.h.in" dnl - update number in meson.build m4_define([nm_major_version], [1]) -m4_define([nm_minor_version], [41]) -m4_define([nm_micro_version], [90]) +m4_define([nm_minor_version], [43]) +m4_define([nm_micro_version], [0]) m4_define([nm_version], [nm_major_version.nm_minor_version.nm_micro_version]) diff --git a/meson.build b/meson.build index b5e8701ac6..d864ce8fd3 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ project( # - add corresponding NM_VERSION_x_y_z macros in # "src/libnm-core-public/nm-version-macros.h.in" # - update number in configure.ac - version: '1.41.90', + version: '1.43.0', license: 'GPL2+', default_options: [ 'buildtype=debugoptimized', -- cgit v1.2.1 From 93424dc2c26d432db4b4c7fa75298c7aa557789d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Jan 2023 13:22:07 +0100 Subject: glib-aux/trivial: fix code comment about nmtst_is_debug() Fixes: c1b57a2c7294 ('glib-aux/tests: enable TRACE logging level when debugging nmtst tests') --- src/libnm-glib-aux/nm-test-utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h index 50280d92b4..b35eeb4b09 100644 --- a/src/libnm-glib-aux/nm-test-utils.h +++ b/src/libnm-glib-aux/nm-test-utils.h @@ -39,7 +39,7 @@ * depending on the test. See nmtst_is_debug(). * Known differences: * - a test might leave the logging level unspecified. In this case, running in - * debug mode, will turn on DEBUG logging, otherwise WARN logging only. + * debug mode, will turn on TRACE logging, otherwise WARN logging only. * - if G_MESSAGES_DEBUG is unset, nm-test will set G_MESSAGES_DEBUG=all * for tests that don't do assert-logging. * Debug mode is determined as follows (highest priority first): -- cgit v1.2.1 From 9ee42c0979d3889655a4394129c41133f7651b49 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 20 Jan 2023 08:12:51 +0100 Subject: meson: increase "default_test_timeout" to 3 minutes Obviously, it would be nice if our unit tests are fast. However, with valgrind and a busy machine, some of the tests can take a relatively long time. In particular those, that are marked as "slow" (if you want to skip them during development, do so via "NMTST_DEBUG=quick" environment, or "CFLAGS=-DNMTST_TEST_QUICK=TRUE", see "nm-test-utils.h"). Anyway. Our tests almost never hit the timeout, and if they do, the most likely reason is that something was just slower then expected, and the timeout is a bogus error. Timeouts only act as last fail safe. It more important to avoid a false (premature) timeout failure, than to minimize the wait time when the test really hangs. Because a real hang is a bug anyway, that we will discover and need to fix. Increase the default test timeout for meson tests to 3 minutes. Also, "test-route-linux" is known to take a long time. Increase that timeout even further. --- meson.build | 2 +- src/core/platform/tests/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index d864ce8fd3..e6f0327d87 100644 --- a/meson.build +++ b/meson.build @@ -96,7 +96,7 @@ set_defines = [ ['VERSION', nm_version], ] -default_test_timeout = 90 +default_test_timeout = 180 foreach define: set_defines config_h.set_quoted(define[0], define[1]) diff --git a/src/core/platform/tests/meson.build b/src/core/platform/tests/meson.build index 8824ed2f67..252c6840f9 100644 --- a/src/core/platform/tests/meson.build +++ b/src/core/platform/tests/meson.build @@ -13,7 +13,7 @@ test_units = [ ['test-nmp-object', 'test-nmp-object.c', test_c_flags, default_test_timeout], ['test-platform-general', 'test-platform-general.c', test_c_flags, default_test_timeout], ['test-route-fake', 'test-route.c', test_fake_c_flags, default_test_timeout], - ['test-route-linux', 'test-route.c', test_linux_c_flags, default_test_timeout], + ['test-route-linux', 'test-route.c', test_linux_c_flags, 900], ['test-tc-linux', 'test-tc.c', test_linux_c_flags, default_test_timeout], ] -- cgit v1.2.1 From 4f719da32d77af1e8a39df22800cce84ae0aadd7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 19 Jan 2023 16:08:08 +0100 Subject: libnm: valide IPv4 ECMP routes in NMIPRoute as unicast routes Kernel does not allow ECMP routes for route types other than unicast. Reject that in NetworkManager settings too. Fixes: 3cd02b6ed6e7 ('libnm,platform: fix range for "weight" property of next hops for routes') https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1507 --- src/libnm-core-impl/nm-setting-ip-config.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index bea0ee7f11..3a31848e84 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -1303,8 +1303,9 @@ nm_ip_route_get_variant_attribute_spec(void) } typedef struct { - int type; - int scope; + int type; + int scope; + gint16 weight; } IPRouteAttrParseData; static gboolean @@ -1440,6 +1441,8 @@ _ip_route_attribute_validate(const char *name, _("route weight cannot be larger than 256")); return FALSE; } + if (parse_data) + parse_data->weight = (guint16) u32; break; case '\0': break; @@ -1490,8 +1493,9 @@ _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) guint attrs_len; guint i; IPRouteAttrParseData parse_data = { - .type = RTN_UNICAST, - .scope = -1, + .type = RTN_UNICAST, + .scope = -1, + .weight = 0, }; g_return_val_if_fail(route, FALSE); @@ -1540,6 +1544,17 @@ _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) break; } + if (parse_data.weight > 0) { + if (parse_data.type != RTN_UNICAST) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a %s route cannot have a ECMP multi-hop \"weight\""), + nm_net_aux_rtnl_rtntype_n2a(parse_data.type)); + return FALSE; + } + } + return TRUE; } -- cgit v1.2.1 From 11832e2ba3906d63f9c31b414f1cdcf96833f980 Mon Sep 17 00:00:00 2001 From: Alexander Lochmann Date: Wed, 14 Dec 2022 14:23:29 +0100 Subject: ndisc: Accept routes from on-link prefixes form ra It is possible that an ra leads to two routes having the same prefix as well as the same prefix length. One of them, however, refers to the on-link prefix, and the other one to a route from the route information field. (Moreover, they might have different route preferences.) Hence, if both routes differ in the on-link property, both are added, and the route from the route information option receives a metric penalty. Fixed #1163. --- src/core/ndisc/nm-lndp-ndisc.c | 2 ++ src/core/ndisc/nm-ndisc.c | 53 ++++++++++++++++++++++++++++++++++++++---- src/core/ndisc/nm-ndisc.h | 2 ++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/core/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c index 39a7e2a8d5..63dde5a5b8 100644 --- a/src/core/ndisc/nm-lndp-ndisc.c +++ b/src/core/ndisc/nm-lndp-ndisc.c @@ -211,6 +211,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) const NMNDiscRoute route = { .network = r_network, .plen = r_plen, + .on_link = TRUE, .expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_prefix_valid_time(msg, offset)), @@ -249,6 +250,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) .network = network, .gateway = gateway_addr, .plen = plen, + .on_link = FALSE, .expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_route_lifetime(msg, offset)), .preference = _route_preference_coerce(ndp_msg_opt_route_preference(msg, offset)), diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index a2d06e49be..39a4df4824 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -161,8 +161,9 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx, .table_any = TRUE, .table_coerced = 0, .metric_any = TRUE, - .metric = 0, - .rt_pref = ndisc_route->preference, + /* Non-on_link routes get a small penalty */ + .metric = ndisc_route->duplicate && !ndisc_route->on_link ? 5 : 0, + .rt_pref = ndisc_route->preference, }; nm_assert((NMIcmpv6RouterPref) r.rt_pref == ndisc_route->preference); @@ -349,12 +350,47 @@ _ASSERT_data_gateways(const NMNDiscDataInternal *data) } /*****************************************************************************/ +static bool +is_duplicate_route(const NMNDiscRoute *r0, const NMNDiscRoute *r1) +{ + return IN6_ARE_ADDR_EQUAL(&r0->network, &r1->network) && r0->plen == r1->plen; +} + +static void +_data_complete_prepare_routes(GArray *routes) +{ + guint i, j; + + for (i = 0; i < routes->len; i++) { + NMNDiscRoute *r0 = &nm_g_array_index(routes, NMNDiscRoute, i); + + r0->duplicate = FALSE; + } + for (i = 0; i < routes->len; i++) { + NMNDiscRoute *r0 = &nm_g_array_index(routes, NMNDiscRoute, i); + + for (j = i + 1; j < routes->len; j++) { + NMNDiscRoute *r1 = &nm_g_array_index(routes, NMNDiscRoute, j); + + if (!is_duplicate_route(r0, r1)) + continue; + + r0->duplicate = TRUE; + r1->duplicate = TRUE; + + /* Maybe after index j, there is yet another duplicate. But we + * will find that later, when i becomes j. */ + break; + } + } +} static const NMNDiscData * _data_complete(NMNDiscDataInternal *data) { _ASSERT_data_gateways(data); + _data_complete_prepare_routes(data->routes); #define _SET(data, field) \ G_STMT_START \ { \ @@ -658,8 +694,17 @@ nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec for (i = 0; i < rdata->routes->len;) { NMNDiscRoute *item = &nm_g_array_index(rdata->routes, NMNDiscRoute, i); - if (IN6_ARE_ADDR_EQUAL(&item->network, &new_item->network) - && item->plen == new_item->plen) { + /* + * It is possible that two entries in rdata->routes have + * the same prefix as well as the same prefix length. + * One of them, however, refers to the on-link prefix, + * and the other one to a route from the route information field. + * Moreover, they might have different route preferences. + * Hence, if both routes differ in the on-link flag, + * comparison is aborted, and both routes are added. + */ + if (IN6_ARE_ADDR_EQUAL(&item->network, &new_item->network) && item->plen == new_item->plen + && item->on_link == new_item->on_link) { if (new_item->expiry_msec <= now_msec) { g_array_remove_index(rdata->routes, i); return TRUE; diff --git a/src/core/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h index 980f7a5414..8f1a12a267 100644 --- a/src/core/ndisc/nm-ndisc.h +++ b/src/core/ndisc/nm-ndisc.h @@ -115,6 +115,8 @@ typedef struct _NMNDiscRoute { gint64 expiry_msec; NMIcmpv6RouterPref preference; guint8 plen; + bool on_link : 1; + bool duplicate : 1; } NMNDiscRoute; typedef struct { -- cgit v1.2.1 From a9cb294b7334e99454401b3dc41b9523c5bad31d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 23 Jan 2023 16:12:28 +0100 Subject: contrib/fedora: explicitly set "pppd" path in configure script We have "BuildRequires: ppp-devel". While in Fedora 37 that has a dependency on "ppp" package, that is not the case on Centos7. I didn't test others, but the point is it's not always there. "/usr/sbin/pppd" is provided by "ppp" package, and we might not have it installed via the build requirements. But we only need it to detect the path, which is not necessary on RHEL/Fedora. Just set the path explicitly with the respective configure option. --- contrib/fedora/rpm/NetworkManager.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index c6561f68f4..1670bc26dc 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -714,7 +714,8 @@ Preferably use nmcli instead. -Difcfg_rh=true \ -Difupdown=false \ %if %{with ppp} - -Dpppd_plugin_dir=%{_libdir}/pppd/%{ppp_version} \ + -Dpppd_plugin_dir="%{_libdir}/pppd/%{ppp_version}" \ + -Dpppd="%{_sbindir}/pppd" \ -Dppp=true \ %endif %if %{with firewalld_zone} @@ -855,8 +856,9 @@ autoreconf --install --force --enable-ifcfg-rh=yes \ --enable-ifupdown=no \ %if %{with ppp} - --with-pppd-plugin-dir=%{_libdir}/pppd/%{ppp_version} \ --enable-ppp=yes \ + --with-pppd="%{_sbindir}/pppd" \ + --with-pppd-plugin-dir="%{_libdir}/pppd/%{ppp_version}" \ %endif %if %{with firewalld_zone} --enable-firewalld-zone=yes \ -- cgit v1.2.1 From ea16997c4abf08333ebb33f4372b87e32b61acad Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 23 Jan 2023 17:53:37 +0100 Subject: contrib/fedora: disable "qt" build of examples for spec file Otherwise, we require a C++ compiler, but our build requirements don't install g++. So build will fail. --- contrib/fedora/rpm/NetworkManager.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 1670bc26dc..97e602b518 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -680,6 +680,7 @@ Preferably use nmcli instead. %else -Ddocs=false \ %endif + -Dqt=false \ %if %{with team} -Dteamdctl=true \ %else -- cgit v1.2.1 From 128c000f0c1237c48a731e5b28cb23b54f114907 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 23 Jan 2023 21:28:51 +0100 Subject: contrib/fedora: install "python36-gobject" when building with meson on centos7 With the meson build configuration, there is obviously python3 installed and in the path. The build script will pick that up as preferred python. However, we will also need working pygobject to build the documentation. But we only have that for python2 installed. Fix that, by installing "python36-gobject". --- contrib/fedora/rpm/NetworkManager.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 97e602b518..c5b8fbf4b9 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -297,6 +297,10 @@ BuildRequires: python2 BuildRequires: pygobject3-base BuildRequires: dbus-python BuildRequires: pexpect +%if 0%{?rhel} >= 7 && %{with meson} +BuildRequires: python36-dbus +BuildRequires: python36-gobject +%endif %endif BuildRequires: libselinux-devel BuildRequires: polkit-devel -- cgit v1.2.1 From 74f66ee27678ae6cd97e414b65e35d63a831058c Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Mon, 23 Jan 2023 22:09:14 +0100 Subject: gitlab-ci: fix CentOS Linux 9 containers during ".gitlab-ci/fedora-install.sh" https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1511 --- .gitlab-ci.yml | 4 ++-- .gitlab-ci/fedora-install.sh | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dc80aae51a..f3bd3561e3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,10 +53,10 @@ variables: # # This is done by running `ci-fairy generate-template` and possibly bumping # ".default_tag". - FEDORA_TAG: '2023-01-18.0-1423f8164e71' + FEDORA_TAG: '2023-01-18.0-296fbfd97862' UBUNTU_TAG: '2023-01-18.0-08fb4e6eb861' DEBIAN_TAG: '2023-01-18.0-08fb4e6eb861' - CENTOS_TAG: '2023-01-18.0-1423f8164e71' + CENTOS_TAG: '2023-01-18.0-296fbfd97862' ALPINE_TAG: '2023-01-18.0-14c807942fa4' FEDORA_EXEC: 'bash .gitlab-ci/fedora-install.sh' diff --git a/.gitlab-ci/fedora-install.sh b/.gitlab-ci/fedora-install.sh index 6a4b91bfe6..575c65b743 100755 --- a/.gitlab-ci/fedora-install.sh +++ b/.gitlab-ci/fedora-install.sh @@ -23,19 +23,21 @@ fi localedef -c -i pl_PL -f UTF-8 pl_PL.UTF-8 locale -a yum install -y python36-dbus python36-gobject-base - else - if [ $IS_CENTOS_8 = 1 ]; then - # CentOS Linux 8 is now EOF and plain `dnf upgrade` does not work. We need - # to patch the mirror list. - sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* - sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* - fi + elif [ $IS_CENTOS_8 = 1 ]; then + # CentOS Linux 8 is now EOF and plain `dnf upgrade` does not work. We need + # to patch the mirror list. + sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* + sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm dnf install -y 'dnf-command(config-manager)' dnf config-manager --set-enabled powertools || \ dnf config-manager --set-enabled PowerTools curl https://copr.fedorainfracloud.org/coprs/nmstate/nm-build-deps/repo/epel-8/nmstate-nm-build-deps-epel-8.repo > /etc/yum.repos.d/nmstate-nm-build-deps-epel-8.repo + else + dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + dnf install -y 'dnf-command(config-manager)' + curl https://copr.fedorainfracloud.org/coprs/nmstate/nm-build-deps/repo/epel-9/nmstate-nm-build-deps-epel-9.repo > /etc/yum.repos.d/nmstate-nm-build-deps-epel-9.repo fi fi -- cgit v1.2.1 From 0566e9dc63fbd7cffd9d1c738b67a7a3d0b9e870 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 24 Jan 2023 08:46:08 +0100 Subject: contrib: support disabling "LTO" in "nm-copr-build.sh" The "nm-copr-build.sh" script is run by our copr to generate the SRPM of NetworkManager (via `curl ... | bash`). Building with LTO takes a long time, for testing it can be nice to disable that. Add an environment variable for that. It can be used when manually building an RPM in copr. --- contrib/scripts/nm-copr-build.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/contrib/scripts/nm-copr-build.sh b/contrib/scripts/nm-copr-build.sh index 89269fae83..ed3fad8ef4 100755 --- a/contrib/scripts/nm-copr-build.sh +++ b/contrib/scripts/nm-copr-build.sh @@ -2,7 +2,10 @@ # environment variables: # - GIT_REF: the ref that should be build. Can be "main" or a git sha. -# - DEBUG: set to 1 to build "--with debug". +# - DEBUG: set to 1 to build "--with debug". Otherwise the default is a release +# build. +# - LTO: set to 1/0 to build "--with/--without lto", otherwise the default depends +# on the distribution. # - NM_GIT_BUNDLE: set to a HTTP url where to fetch the nm-git-bundle-*.noarch.rpm # from. Set to empty to skip it. By default, it fetches the bundle from copr. @@ -14,6 +17,14 @@ else DEBUG="--without debug" fi +if [ "$LTO" = 0 ]; then + LTO='--without -lto' +elif [ "$LTO" = 1 ]; then + LTO='--with -lto' +else + LTO= +fi + if [[ -z "$GIT_REF" ]]; then echo "\$GIT_REF is not set!" exit 1 @@ -59,7 +70,7 @@ GIT_SHA="$(git show-ref --verify --hash "$GIT_REF" 2>/dev/null || git checkout -b tmp "$GIT_SHA" -./contrib/fedora/rpm/build_clean.sh -g -S -w test $DEBUG -s copr +./contrib/fedora/rpm/build_clean.sh -g -S -w test $DEBUG $LTO -s copr popd mv ./NetworkManager/contrib/fedora/rpm/latest/{SOURCES,SPECS}/* . -- cgit v1.2.1 From 096b9955d67d3c915c1a9599446aaff7fae60b99 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 24 Jan 2023 10:29:35 +0100 Subject: contrib/fedora: make "lto" in the spec file configurable When we build a copr image, we run the "nm-copr-build.sh" script. That script, should honor "LTO=0|1|" to explicitly enable/disable LTO. Since the copr script only builds a SRPM, which then gets build we need that the default LTO flag in the SRPM is templated. Fixes: 0566e9dc63fb ('contrib: support disabling "LTO" in "nm-copr-build.sh"') --- contrib/fedora/rpm/NetworkManager.spec | 9 +++++++++ contrib/fedora/rpm/build.sh | 5 +++++ contrib/fedora/rpm/build_clean.sh | 15 +++++++++++++++ contrib/scripts/nm-copr-build.sh | 4 ++-- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index c5b8fbf4b9..2f7a2d36ec 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -19,6 +19,7 @@ %global snapshot __SNAPSHOT__ %global git_sha __COMMIT__ %global bcond_default_debug __BCOND_DEFAULT_DEBUG__ +%global bcond_default_lto __BCOND_DEFAULT_LTO__ %global bcond_default_test __BCOND_DEFAULT_TEST__ %global obsoletes_device_plugins 1:0.9.9.95-1 @@ -69,11 +70,19 @@ %else %bcond_with test %endif +%if %{bcond_default_lto} == '' %if 0%{?fedora} >= 33 || 0%{?rhel} >= 9 %bcond_without lto %else %bcond_with lto %endif +%else +%if %{bcond_default_lto} +%bcond_without lto +%else +%bcond_with lto +%endif +%endif %bcond_with sanitizer %if 0%{?fedora} %bcond_without connectivity_fedora diff --git a/contrib/fedora/rpm/build.sh b/contrib/fedora/rpm/build.sh index e5a3d84468..777f9c4a53 100755 --- a/contrib/fedora/rpm/build.sh +++ b/contrib/fedora/rpm/build.sh @@ -25,6 +25,7 @@ # SIGN_SOURCE= # DO_RELEASE= # BCOND_DEFAULT_DEBUG= +# BCOND_DEFAULT_LTO= # BCOND_DEFAULT_TEST= die() { @@ -119,6 +120,7 @@ COMMIT_FULL="${COMMIT_FULL:-$(git rev-parse --verify HEAD || die "Error reading COMMIT="${COMMIT:-$(printf '%s' "$COMMIT_FULL" | sed 's/^\(.\{10\}\).*/\1/' || die "Error reading HEAD revision")}" BCOND_DEFAULT_DEBUG="${BCOND_DEFAULT_DEBUG:-0}" BCOND_DEFAULT_TEST="${BCOND_DEFAULT_TEST:-0}" +BCOND_DEFAULT_LTO="${BCOND_DEFAULT_LTO}" USERNAME="${USERNAME:-"$(git config user.name) <$(git config user.email)>"}" SPECFILE="$(abs_path "$SPECFILE" "$SCRIPTDIR/NetworkManager.spec")" || die "invalid \$SPECFILE argument" SOURCE_FROM_GIT="$(coerce_bool "$SOURCE_FROM_GIT" "")" @@ -174,12 +176,14 @@ LOG "SOURCE_README_IFCFG_FILES=$SOURCE_README_IFCFG_FILES" LOG "BUILDTYPE=$BUILDTYPE" LOG "NM_RPMBUILD_ARGS=$NM_RPMBUILD_ARGS" LOG "BCOND_DEFAULT_DEBUG=$BCOND_DEFAULT_DEBUG" +LOG "BCOND_DEFAULT_LTO=$BCOND_DEFAULT_LTO" LOG "BCOND_DEFAULT_TEST=$BCOND_DEFAULT_TEST" LOG "" LOG "UUID=$UUID" LOG "BASEDIR=$TEMP" in_set "$BCOND_DEFAULT_DEBUG" 0 1 || die "Invalid value for \$BCOND_DEFAULT_DEBUG: \"$BCOND_DEFAULT_DEBUG\"" +in_set "$BCOND_DEFAULT_LTO" '' 0 1 || die "Invalid value for \$BCOND_DEFAULT_LTO: \"$BCOND_DEFAULT_LTO\"" in_set "$BCOND_DEFAULT_TEST" 0 1 || die "Invalid value for \$BCOND_DEFAULT_TEST: \"$BCOND_DEFAULT_TEST\"" ln -snf "$TEMPBASE" ./latest0 @@ -209,6 +213,7 @@ sed -e "s/__VERSION__/$VERSION/g" \ -e "s/__SNAPSHOT__/$SNAPSHOT/g" \ -e "s/__SOURCE1__/$(basename "$SOURCE")/g" \ -e "s/__BCOND_DEFAULT_DEBUG__/$BCOND_DEFAULT_DEBUG/g" \ + -e "s/__BCOND_DEFAULT_LTO__/$BCOND_DEFAULT_LTO/g" \ -e "s/__BCOND_DEFAULT_TEST__/$BCOND_DEFAULT_TEST/g" \ "$SPECFILE" | sed -e "/^__CHANGELOG__$/ \ diff --git a/contrib/fedora/rpm/build_clean.sh b/contrib/fedora/rpm/build_clean.sh index 7c221d69a5..6ba202674e 100755 --- a/contrib/fedora/rpm/build_clean.sh +++ b/contrib/fedora/rpm/build_clean.sh @@ -26,6 +26,7 @@ usage() { echo " -s|--snapshot TEXT: use TEXT as the snapshot version for the new package (overwrites \$NM_BUILD_SNAPSHOT environment)" echo " -r|--release: built a release tarball (this option must be alone)" echo " --default-for-debug \$OPTION: set the default for "debug" option in the generated spec file" + echo " --default-for-lto \$OPTION: set the default for "lto" option in the generated spec file" echo " --default-for-test \$OPTION: set the default for "test" option in the generated spec file" } @@ -56,6 +57,7 @@ SOURCE_FROM_GIT=0 SNAPSHOT="$NM_BUILD_SNAPSHOT" DO_RELEASE=0 unset BCOND_DEFAULT_DEBUG +unset BCOND_DEFAULT_LTO unset BCOND_DEFAULT_TEST ADD_WITH_TEST=1 @@ -110,6 +112,9 @@ while [[ $# -gt 0 ]]; do debug) [[ -z ${BCOND_DEFAULT_DEBUG+.} ]] && BCOND_DEFAULT_DEBUG=1 ;; + lto) + [[ -z ${BCOND_DEFAULT_LTO+.} ]] && BCOND_DEFAULT_LTO=1 + ;; test) ADD_WITH_TEST=0 [[ -z ${BCOND_DEFAULT_TEST+.} ]] && BCOND_DEFAULT_TEST=1 @@ -124,6 +129,9 @@ while [[ $# -gt 0 ]]; do debug) [[ -z ${BCOND_DEFAULT_DEBUG+.} ]] && BCOND_DEFAULT_DEBUG=0 ;; + lto) + [[ -z ${BCOND_DEFAULT_LTO+.} ]] && BCOND_DEFAULT_LTO=0 + ;; test) ADD_WITH_TEST=0 [[ -z ${BCOND_DEFAULT_TEST+.} ]] && BCOND_DEFAULT_TEST=0 @@ -145,6 +153,12 @@ while [[ $# -gt 0 ]]; do BCOND_DEFAULT_DEBUG="$1" shift ;; + --default-for-lto) + [[ $# -gt 0 ]] || die "Missing argument to $A" + in_set "$1" "" 0 1 || die "invalid argument $A \"$1\"" + BCOND_DEFAULT_LTO="$1" + shift + ;; --default-for-test) [[ $# -gt 0 ]] || die "Missing argument to $A" in_set "$1" "" 0 1 || die "invalid argument $A \"$1\"" @@ -226,6 +240,7 @@ export NM_RPMBUILD_ARGS="${WITH_LIST[@]}" export SNAPSHOT export DO_RELEASE export BCOND_DEFAULT_DEBUG="$BCOND_DEFAULT_DEBUG" +export BCOND_DEFAULT_LTO="$BCOND_DEFAULT_LTO" export BCOND_DEFAULT_TEST="$BCOND_DEFAULT_TEST" "$SCRIPTDIR"/build.sh diff --git a/contrib/scripts/nm-copr-build.sh b/contrib/scripts/nm-copr-build.sh index ed3fad8ef4..d16465b838 100755 --- a/contrib/scripts/nm-copr-build.sh +++ b/contrib/scripts/nm-copr-build.sh @@ -18,9 +18,9 @@ else fi if [ "$LTO" = 0 ]; then - LTO='--without -lto' + LTO='--without lto' elif [ "$LTO" = 1 ]; then - LTO='--with -lto' + LTO='--with lto' else LTO= fi -- cgit v1.2.1 From 7a62845424c443e705cee647ad0f6d316230c66a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 24 Jan 2023 11:24:06 +0100 Subject: contrib/rpm: fix condition in "NetworkManager.spec" Fixes: 096b9955d67d ('contrib/fedora: make "lto" in the spec file configurable') --- contrib/fedora/rpm/NetworkManager.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 2f7a2d36ec..df84255997 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -70,7 +70,7 @@ %else %bcond_with test %endif -%if %{bcond_default_lto} == '' +%if "%{bcond_default_lto}" == "" %if 0%{?fedora} >= 33 || 0%{?rhel} >= 9 %bcond_without lto %else -- cgit v1.2.1 From 13dfdaf3a090f01930c7fa2cf7a8cb3a071de947 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 24 Jan 2023 11:46:28 +0100 Subject: contrib/rpm: fix condition in "NetworkManager.spec" (2) Fixes: 096b9955d67d ('contrib/fedora: make "lto" in the spec file configurable') Fixes: 7a62845424c4 ('contrib/rpm: fix condition in "NetworkManager.spec"') --- contrib/fedora/rpm/NetworkManager.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index df84255997..832b2019ce 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -70,7 +70,7 @@ %else %bcond_with test %endif -%if "%{bcond_default_lto}" == "" +%if "%{?bcond_default_lto}" == "" %if 0%{?fedora} >= 33 || 0%{?rhel} >= 9 %bcond_without lto %else -- cgit v1.2.1 From 36ad5cbb3bb4b60dd0e701d2eba4a4fbee87a6f5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 24 Jan 2023 12:29:04 +0100 Subject: contrib/rpm: fix condition in "NetworkManager.spec" (3) Fixes: 096b9955d67d ('contrib/fedora: make "lto" in the spec file configurable') Fixes: 7a62845424c4 ('contrib/rpm: fix condition in "NetworkManager.spec"') --- contrib/fedora/rpm/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fedora/rpm/build.sh b/contrib/fedora/rpm/build.sh index 777f9c4a53..590929660a 100755 --- a/contrib/fedora/rpm/build.sh +++ b/contrib/fedora/rpm/build.sh @@ -213,7 +213,7 @@ sed -e "s/__VERSION__/$VERSION/g" \ -e "s/__SNAPSHOT__/$SNAPSHOT/g" \ -e "s/__SOURCE1__/$(basename "$SOURCE")/g" \ -e "s/__BCOND_DEFAULT_DEBUG__/$BCOND_DEFAULT_DEBUG/g" \ - -e "s/__BCOND_DEFAULT_LTO__/$BCOND_DEFAULT_LTO/g" \ + -e "s/__BCOND_DEFAULT_LTO__/${BCOND_DEFAULT_LTO:-"%{nil}"}/g" \ -e "s/__BCOND_DEFAULT_TEST__/$BCOND_DEFAULT_TEST/g" \ "$SPECFILE" | sed -e "/^__CHANGELOG__$/ \ -- cgit v1.2.1 From fce8e572d0e9c6f5e26dea93a524abf2268d24ca Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 24 Jan 2023 14:58:47 +0100 Subject: contrib/copr: better detect git-ref in "nm-copr-build.sh" --- contrib/scripts/nm-copr-build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/scripts/nm-copr-build.sh b/contrib/scripts/nm-copr-build.sh index d16465b838..28ce4fced5 100755 --- a/contrib/scripts/nm-copr-build.sh +++ b/contrib/scripts/nm-copr-build.sh @@ -66,6 +66,7 @@ git remote remove nm-git-bundle || true GIT_SHA="$(git show-ref --verify --hash "$GIT_REF" 2>/dev/null || git show-ref --verify --hash "refs/remotes/origin/$GIT_REF" 2>/dev/null || + git rev-parse --verify "refs/remotes/origin/$GIT_REF" 2>/dev/null || git rev-parse --verify "$GIT_REF^{commit}" 2>/dev/null)" git checkout -b tmp "$GIT_SHA" -- cgit v1.2.1 From 621b41ebfa009ff11a41fe47f77fd162a98072a1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Jan 2023 09:03:49 +0100 Subject: platform: detect EINVAL as failure to set the MTU Some drivers will reject an invalid MTU size with EINVAL. Quote from [1]: While investigating, I did notice that do_change_link in nm-linux-platform.c really ought to count -EINVAL as an MTU out-of-range error and not just -ERANGE. Even if the hardware supports a large MTU, if the transmit FIFO is set too small, stmmac_change_mtu [2] will return -EINVAL. For example, on my device, the maxmtu is 9000 but in practice I can't set an MTU larger than 4096 unless I first run ethtool --set-channels eno1 tx 3. [1] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1198#note_1738311 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c?h=v6.1#n5577 --- src/libnm-platform/nm-linux-platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 762b1645e1..41d7163ae6 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -8217,7 +8217,8 @@ retry: } else if (NM_IN_SET(seq_result, -ESRCH, -ENOENT)) { log_detail = ", firmware not found"; result = -NME_PL_NO_FIRMWARE; - } else if (NM_IN_SET(seq_result, -ERANGE) && change_link_type == CHANGE_LINK_TYPE_SET_MTU) { + } else if (NM_IN_SET(seq_result, -ERANGE, -EINVAL) + && change_link_type == CHANGE_LINK_TYPE_SET_MTU) { log_detail = ", setting MTU to requested size is not possible"; result = -NME_PL_CANT_SET_MTU; } else if (NM_IN_SET(seq_result, -ENFILE) && change_link_type == CHANGE_LINK_TYPE_SET_ADDRESS -- cgit v1.2.1 From 66c9a5e8490fc75431a914b2e68dc03dd81c85d0 Mon Sep 17 00:00:00 2001 From: Yuri Chornoivan Date: Fri, 20 Jan 2023 16:03:00 +0200 Subject: po: update Ukrainian translation https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1508 --- po/uk.po | 1667 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 849 insertions(+), 818 deletions(-) diff --git a/po/uk.po b/po/uk.po index bca4ba5896..8f9cc7d734 100644 --- a/po/uk.po +++ b/po/uk.po @@ -1,7 +1,7 @@ # Copyright (C) 2011 Free Software Foundation, Inc. # This file is distributed under the same license as the NetworkManager package. # -# Yuri Chornoivan , 2011-2021, 2022. +# Yuri Chornoivan , 2011-2021, 2022, 2023. # Lubomir Rintel , 2016. #zanata. # Lubomir Rintel , 2017. #zanata. # Thomas Haller , 2017. #zanata. @@ -10,9 +10,9 @@ msgstr "" "Project-Id-Version: NetworkManager\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/NetworkManager/NetworkMa" "nager/issues\n" -"POT-Creation-Date: 2022-12-21 15:26+0000\n" -"PO-Revision-Date: 2022-12-28 15:23+0200\n" -"Last-Translator: Fracture dept \n" +"POT-Creation-Date: 2023-01-17 15:26+0000\n" +"PO-Revision-Date: 2023-01-20 15:40+0200\n" +"Last-Translator: Yuri Chornoivan \n" "Language-Team: Ukrainian \n" "Language: uk\n" "MIME-Version: 1.0\n" @@ -201,7 +201,7 @@ msgid "%s %u" msgstr "%s %u" #: src/core/devices/adsl/nm-device-adsl.c:115 -#: src/libnmc-setting/nm-meta-setting-desc.c:8385 +#: src/libnmc-setting/nm-meta-setting-desc.c:8400 msgid "ADSL connection" msgstr "З'єднання ADSL" @@ -286,7 +286,7 @@ msgid "Wired connection %d" msgstr "Дротове з'єднання %d" #: src/core/devices/nm-device-ethernet.c:1638 -#: src/libnmc-setting/nm-meta-setting-desc.c:8424 +#: src/libnmc-setting/nm-meta-setting-desc.c:8440 msgid "Veth connection" msgstr "З'єднання veth" @@ -299,7 +299,7 @@ msgid "Wired connection" msgstr "Дротове з'єднання" #: src/core/devices/nm-device-infiniband.c:157 -#: src/libnmc-setting/nm-meta-setting-desc.c:8399 +#: src/libnmc-setting/nm-meta-setting-desc.c:8414 msgid "InfiniBand connection" msgstr "З'єднання InfiniBand" @@ -308,7 +308,6 @@ msgid "IP tunnel connection" msgstr "З'єднання IP-тунель" #: src/core/devices/nm-device-loopback.c:67 -#| msgid "ADSL connection" msgid "Loopback connection" msgstr "Петльове з'єднання" @@ -321,17 +320,17 @@ msgid "TUN connection" msgstr "З'єднання TUN" #: src/core/devices/nm-device-vlan.c:377 -#: src/libnmc-setting/nm-meta-setting-desc.c:8425 +#: src/libnmc-setting/nm-meta-setting-desc.c:8441 msgid "VLAN connection" msgstr "З'єднання VLAN" #: src/core/devices/nm-device-vrf.c:182 -#: src/libnmc-setting/nm-meta-setting-desc.c:8427 +#: src/libnmc-setting/nm-meta-setting-desc.c:8443 msgid "VRF connection" msgstr "З'єднання VRF" #: src/core/devices/nm-device-vxlan.c:382 -#: src/libnmc-setting/nm-meta-setting-desc.c:8428 +#: src/libnmc-setting/nm-meta-setting-desc.c:8444 msgid "VXLAN connection" msgstr "З'єднання VXLAN" @@ -343,7 +342,7 @@ msgstr "З'єднання WPAN" msgid "Team connection" msgstr "Командне з'єднання" -#: src/core/devices/wifi/nm-device-olpc-mesh.c:112 src/nmcli/devices.c:1397 +#: src/core/devices/wifi/nm-device-olpc-mesh.c:112 src/nmcli/devices.c:1394 msgid "Mesh" msgstr "Сітка" @@ -601,7 +600,7 @@ msgstr "Не вдалося створити фонову службу: %s [по #: src/core/nm-config.c:544 src/libnm-core-impl/nm-setting-ovs-bridge.c:187 #: src/libnmc-setting/nm-meta-setting-desc.c:2200 -#: src/libnmc-setting/nm-meta-setting-desc.c:4344 +#: src/libnmc-setting/nm-meta-setting-desc.c:4343 #, c-format msgid "'%s' is not valid" msgstr "«%s» не є коректним" @@ -671,29 +670,29 @@ msgstr "Параметри NetworkManager" msgid "Show NetworkManager options" msgstr "Показати параметри NetworkManager" -#: src/core/nm-manager.c:6193 src/libnmc-setting/nm-meta-setting-desc.c:8426 +#: src/core/nm-manager.c:6193 src/libnmc-setting/nm-meta-setting-desc.c:8442 msgid "VPN connection" msgstr "З'єднання VPN" -#: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:5598 +#: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:5609 #: src/libnm-client-impl/nm-device.c:1780 #: src/libnm-core-impl/nm-connection.c:3190 src/nmtui/nm-editor-utils.c:196 msgid "Bond" msgstr "Прив'язка" -#: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:5669 +#: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:5680 #: src/libnm-client-impl/nm-device.c:1782 #: src/libnm-core-impl/nm-connection.c:3192 src/nmtui/nm-editor-utils.c:214 msgid "Team" msgstr "Команда" -#: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:6006 +#: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:6017 #: src/libnm-client-impl/nm-device.c:1784 #: src/libnm-core-impl/nm-connection.c:3194 src/nmtui/nm-editor-utils.c:205 msgid "Bridge" msgstr "Місток" -#: src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c:8970 +#: src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c:8982 #: src/libnm-core-impl/nm-team-utils.c:2391 msgid "invalid json" msgstr "некоректний код JSON" @@ -838,7 +837,6 @@ msgid "The connection was not an IP tunnel connection." msgstr "З'єднання не є тунельованим IP-з'єднанням." #: src/libnm-client-impl/nm-device-loopback.c:41 -#| msgid "The connection was not a wpan connection." msgid "The connection was not a loopback connection." msgstr "З'єднання не належить до петльового типу." @@ -1152,6 +1150,48 @@ msgstr "значення властивості не може бути довш msgid "property cannot contain any nul bytes" msgstr "значення властивості не може містити нульових байтів" +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:659 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:82 +#: src/libnm-core-impl/nm-setting-user.c:93 +msgid "missing key" +msgstr "не вказано ключ" + +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:667 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:90 +#: src/libnm-core-impl/nm-setting-user.c:101 +msgid "key is too long" +msgstr "ключ є надто довгим" + +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:674 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:97 +#: src/libnm-core-impl/nm-setting-user.c:108 +msgid "key must be UTF8" +msgstr "ключ має зберігатися у кодуванні UTF8" + +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:683 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:106 +#: src/libnm-core-impl/nm-setting-user.c:155 +msgid "key contains invalid characters" +msgstr "ключ містить некоректний символ" + +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:711 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:195 +#: src/libnm-core-impl/nm-setting-user.c:182 +msgid "value is missing" +msgstr "не вказано значення" + +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:720 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:204 +#: src/libnm-core-impl/nm-setting-user.c:191 +msgid "value is too large" +msgstr "значення є надто великим" + +#: src/libnm-core-aux-intern/nm-libnm-core-utils.c:728 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:212 +#: src/libnm-core-impl/nm-setting-user.c:199 +msgid "value is not valid UTF8" +msgstr "значення не записано у коректному кодуванні UTF8" + #: src/libnm-core-impl/nm-connection.c:431 msgid "wrong type; should be a list of strings." msgstr "помилковий тип; має бути список рядків." @@ -1218,7 +1258,7 @@ msgstr "неочікуваний UUID %s замість %s" #: src/libnm-core-impl/nm-setting-connection.c:1149 #: src/libnm-core-impl/nm-setting-connection.c:1187 #: src/libnm-core-impl/nm-setting-connection.c:1516 -#: src/libnm-core-impl/nm-setting-ip-config.c:5435 +#: src/libnm-core-impl/nm-setting-ip-config.c:5467 #: src/libnm-core-impl/nm-setting-ip-tunnel.c:407 #: src/libnm-core-impl/nm-setting-olpc-mesh.c:99 #: src/libnm-core-impl/nm-setting-ovs-patch.c:75 @@ -1248,235 +1288,236 @@ msgstr "Значення не може бути оброблено як спис msgid "value is not an integer in range [%lld, %lld]" msgstr "значення не є цілим числом у діапазоні [%lld, %lld]" -#: src/libnm-core-impl/nm-keyfile.c:331 +#: src/libnm-core-impl/nm-keyfile.c:333 msgid "ignoring missing number" msgstr "ігноруємо пропущене число" -#: src/libnm-core-impl/nm-keyfile.c:343 +#: src/libnm-core-impl/nm-keyfile.c:345 #, c-format msgid "ignoring invalid number '%s'" msgstr "ігноруємо некоректне число «%s»" -#: src/libnm-core-impl/nm-keyfile.c:372 +#: src/libnm-core-impl/nm-keyfile.c:374 #, c-format msgid "ignoring invalid %s address: %s" msgstr "ігноруємо некоректну адресу %s: %s" -#: src/libnm-core-impl/nm-keyfile.c:418 +#: src/libnm-core-impl/nm-keyfile.c:420 #, c-format msgid "ignoring invalid gateway '%s' for %s route" msgstr "ігноруємо некоректний шлюз «%s» для маршруту %s" -#: src/libnm-core-impl/nm-keyfile.c:440 +#: src/libnm-core-impl/nm-keyfile.c:442 #, c-format msgid "ignoring invalid %s route: %s" msgstr "ігноруємо некоректний маршрут %s: %s" -#: src/libnm-core-impl/nm-keyfile.c:618 +#: src/libnm-core-impl/nm-keyfile.c:620 #, c-format msgid "unexpected character '%c' for address %s: '%s' (position %td)" msgstr "неочікуваний символ «%c» для адреси %s: «%s» (позиція %td)" -#: src/libnm-core-impl/nm-keyfile.c:634 +#: src/libnm-core-impl/nm-keyfile.c:636 #, c-format msgid "unexpected character '%c' for %s: '%s' (position %td)" msgstr "неочікуваний символ «%c» для %s: «%s» (позиція %td)" -#: src/libnm-core-impl/nm-keyfile.c:650 +#: src/libnm-core-impl/nm-keyfile.c:652 #, c-format msgid "unexpected character '%c' in prefix length for %s: '%s' (position %td)" msgstr "" "неочікуваний символ «%c» у префіксі довжини для %s: «%s» (позиція %td)" -#: src/libnm-core-impl/nm-keyfile.c:667 +#: src/libnm-core-impl/nm-keyfile.c:669 #, c-format msgid "garbage at the end of value %s: '%s'" msgstr "зайві дані наприкінці значення %s: «%s»" -#: src/libnm-core-impl/nm-keyfile.c:677 +#: src/libnm-core-impl/nm-keyfile.c:679 #, c-format msgid "deprecated semicolon at the end of value %s: '%s'" msgstr "застаріла крапка з комою наприкінці значення %s: «%s»" -#: src/libnm-core-impl/nm-keyfile.c:696 +#: src/libnm-core-impl/nm-keyfile.c:698 #, c-format msgid "invalid prefix length for %s '%s', defaulting to %d" msgstr "некоректний префікс довжини для %s «%s», повертаємося до типового, %d" -#: src/libnm-core-impl/nm-keyfile.c:708 +#: src/libnm-core-impl/nm-keyfile.c:710 #, c-format msgid "missing prefix length for %s '%s', defaulting to %d" msgstr "пропущено префікс довжини для %s «%s», повертаємося до типового, %d" -#: src/libnm-core-impl/nm-keyfile.c:1051 -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:322 +#: src/libnm-core-impl/nm-keyfile.c:1053 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:370 +#: src/libnm-core-impl/nm-setting-ovs-other-config.c:208 #: src/libnm-core-impl/nm-setting-user.c:368 #, c-format msgid "invalid value for \"%s\": %s" msgstr "некоректне значення для «%s»: %s" -#: src/libnm-core-impl/nm-keyfile.c:1128 +#: src/libnm-core-impl/nm-keyfile.c:1140 #, c-format msgid "ignoring invalid DNS server IPv%c address '%s'" msgstr "ігноруємо некоректну адресу IPv%c сервера DNS «%s»" -#: src/libnm-core-impl/nm-keyfile.c:1165 +#: src/libnm-core-impl/nm-keyfile.c:1177 #: src/libnmc-setting/nm-meta-setting-desc.c:1663 #, c-format msgid "invalid option '%s', use one of [%s]" msgstr "" "некоректний параметр «%s», скористайтеся одним із таких параметрів [%s]" -#: src/libnm-core-impl/nm-keyfile.c:1240 +#: src/libnm-core-impl/nm-keyfile.c:1252 msgid "ignoring invalid MAC address" msgstr "ігноруємо некоректну MAC-адресу" -#: src/libnm-core-impl/nm-keyfile.c:1316 +#: src/libnm-core-impl/nm-keyfile.c:1328 #, c-format msgid "ignoring invalid bond option %s%s%s = %s%s%s: %s" msgstr "ігноруємо некоректний параметр bond %s%s%s = %s%s%s: %s" -#: src/libnm-core-impl/nm-keyfile.c:1506 +#: src/libnm-core-impl/nm-keyfile.c:1518 msgid "ignoring invalid SSID" msgstr "ігноруємо некоректний SSID" -#: src/libnm-core-impl/nm-keyfile.c:1524 +#: src/libnm-core-impl/nm-keyfile.c:1536 msgid "ignoring invalid raw password" msgstr "ігноруємо некоректний необроблений пароль" -#: src/libnm-core-impl/nm-keyfile.c:1669 +#: src/libnm-core-impl/nm-keyfile.c:1681 msgid "invalid key/cert value" msgstr "некоректне значення ключа/сертифіката" -#: src/libnm-core-impl/nm-keyfile.c:1684 +#: src/libnm-core-impl/nm-keyfile.c:1696 #, c-format msgid "invalid key/cert value path \"%s\"" msgstr "некоректний шлях до ключа/сертифіката, «%s»" -#: src/libnm-core-impl/nm-keyfile.c:1709 src/libnm-core-impl/nm-keyfile.c:1806 +#: src/libnm-core-impl/nm-keyfile.c:1721 src/libnm-core-impl/nm-keyfile.c:1818 #, c-format msgid "certificate or key file '%s' does not exist" msgstr "файла сертифіката або ключа «%s» не існує" -#: src/libnm-core-impl/nm-keyfile.c:1722 +#: src/libnm-core-impl/nm-keyfile.c:1734 #, c-format msgid "invalid PKCS#11 URI \"%s\"" msgstr "некоректна адреса PKCS#11 «%s»" -#: src/libnm-core-impl/nm-keyfile.c:1768 +#: src/libnm-core-impl/nm-keyfile.c:1780 msgid "invalid key/cert value data:;base64, is not base64" msgstr "некоректні дані значення ключа/сертифіката data:;base64, не є base64" -#: src/libnm-core-impl/nm-keyfile.c:1781 +#: src/libnm-core-impl/nm-keyfile.c:1793 msgid "invalid key/cert value data:;base64,file://" msgstr "некоректне значення ключа/сертифіката data:;base64,file://" -#: src/libnm-core-impl/nm-keyfile.c:1822 +#: src/libnm-core-impl/nm-keyfile.c:1834 msgid "invalid key/cert value is not a valid blob" msgstr "" "некоректне значення ключа/сертифіката, не є коректним значення «%s» не є " "коректним великим бінарним об'єктом" -#: src/libnm-core-impl/nm-keyfile.c:1924 +#: src/libnm-core-impl/nm-keyfile.c:1936 #, c-format msgid "invalid parity value '%s'" msgstr "некоректне значення парності, «%s»" -#: src/libnm-core-impl/nm-keyfile.c:1946 src/libnm-core-impl/nm-keyfile.c:3511 +#: src/libnm-core-impl/nm-keyfile.c:1958 src/libnm-core-impl/nm-keyfile.c:3540 #, c-format msgid "invalid setting: %s" msgstr "некоректний параметр: %s" -#: src/libnm-core-impl/nm-keyfile.c:1966 +#: src/libnm-core-impl/nm-keyfile.c:1978 #, c-format msgid "ignoring invalid team configuration: %s" msgstr "ігноруємо некоректне налаштування команди: %s" -#: src/libnm-core-impl/nm-keyfile.c:2087 +#: src/libnm-core-impl/nm-keyfile.c:2099 #, c-format msgid "invalid qdisc: %s" msgstr "некоректний qdisc: %s" -#: src/libnm-core-impl/nm-keyfile.c:2137 +#: src/libnm-core-impl/nm-keyfile.c:2149 #, c-format msgid "invalid tfilter: %s" msgstr "некоректний tfilter: %s" -#: src/libnm-core-impl/nm-keyfile.c:3336 +#: src/libnm-core-impl/nm-keyfile.c:3365 #, c-format msgid "error loading setting value: %s" msgstr "помилка під час завантаження значення параметра: %s" -#: src/libnm-core-impl/nm-keyfile.c:3367 src/libnm-core-impl/nm-keyfile.c:3379 -#: src/libnm-core-impl/nm-keyfile.c:3398 src/libnm-core-impl/nm-keyfile.c:3410 -#: src/libnm-core-impl/nm-keyfile.c:3422 src/libnm-core-impl/nm-keyfile.c:3484 -#: src/libnm-core-impl/nm-keyfile.c:3496 +#: src/libnm-core-impl/nm-keyfile.c:3396 src/libnm-core-impl/nm-keyfile.c:3408 +#: src/libnm-core-impl/nm-keyfile.c:3427 src/libnm-core-impl/nm-keyfile.c:3439 +#: src/libnm-core-impl/nm-keyfile.c:3451 src/libnm-core-impl/nm-keyfile.c:3513 +#: src/libnm-core-impl/nm-keyfile.c:3525 msgid "value cannot be interpreted as integer" msgstr "значення не може бути оброблено як ціле число" -#: src/libnm-core-impl/nm-keyfile.c:3452 +#: src/libnm-core-impl/nm-keyfile.c:3481 #, c-format msgid "ignoring invalid byte element '%u' (not between 0 and 255 inclusive)" msgstr "" "ігноруємо некоректний байтовий елемент «%u» (не у діапазоні від 0 до 255, " "включно)" -#: src/libnm-core-impl/nm-keyfile.c:3536 +#: src/libnm-core-impl/nm-keyfile.c:3565 #, c-format msgid "invalid setting name '%s'" msgstr "некоректна назва параметра, «%s»" -#: src/libnm-core-impl/nm-keyfile.c:3583 +#: src/libnm-core-impl/nm-keyfile.c:3612 #, c-format msgid "invalid key '%s.%s'" msgstr "некоректний ключ «%s.%s»" -#: src/libnm-core-impl/nm-keyfile.c:3599 +#: src/libnm-core-impl/nm-keyfile.c:3628 #, c-format msgid "key '%s.%s' is not boolean" msgstr "ключ «%s.%s» не є булевим значенням" -#: src/libnm-core-impl/nm-keyfile.c:3616 +#: src/libnm-core-impl/nm-keyfile.c:3645 #, c-format msgid "key '%s.%s' is not a uint32" msgstr "ключ «%s.%s» не є значенням uint32" -#: src/libnm-core-impl/nm-keyfile.c:3673 +#: src/libnm-core-impl/nm-keyfile.c:3702 #, c-format msgid "invalid peer public key in section '%s'" msgstr "некоректний відкритий ключ вузла у розділі «%s»" -#: src/libnm-core-impl/nm-keyfile.c:3688 +#: src/libnm-core-impl/nm-keyfile.c:3717 #, c-format msgid "key '%s.%s' is not a valid 256 bit key in base64 encoding" msgstr "ключ «%s.%s» не є коректним 256-бітовим ключем у кодуванні base64" -#: src/libnm-core-impl/nm-keyfile.c:3711 +#: src/libnm-core-impl/nm-keyfile.c:3740 #, c-format msgid "key '%s.%s' is not a valid secret flag" msgstr "ключ «%s.%s» не є коректним прапорцем реєстраційних даних" -#: src/libnm-core-impl/nm-keyfile.c:3734 +#: src/libnm-core-impl/nm-keyfile.c:3763 #, c-format msgid "key '%s.%s' is not a integer in range 0 to 2^32" msgstr "ключ «%s.%s» не є цілими числом у діапазоні від 0 до 2^32" -#: src/libnm-core-impl/nm-keyfile.c:3750 +#: src/libnm-core-impl/nm-keyfile.c:3779 #, c-format msgid "key '%s.%s' is not a valid endpoint" msgstr "ключ «%s.%s» не є коректною кінцевою точкою" -#: src/libnm-core-impl/nm-keyfile.c:3776 +#: src/libnm-core-impl/nm-keyfile.c:3805 #, c-format msgid "key '%s.%s' has invalid allowed-ips" msgstr "для ключа «%s.%s» вказано некоректне значення allowed-ips" -#: src/libnm-core-impl/nm-keyfile.c:3791 +#: src/libnm-core-impl/nm-keyfile.c:3820 #, c-format msgid "peer '%s' is invalid: %s" msgstr "вузол «%s» є некоректним: %s" -#: src/libnm-core-impl/nm-keyfile.c:4319 +#: src/libnm-core-impl/nm-keyfile.c:4348 #, c-format msgid "unsupported option \"%s.%s\" of variant type %s" msgstr "непідтримуваний параметр «%s.%s» типу варіанта %s" @@ -1566,7 +1607,7 @@ msgstr "" #: src/libnm-core-impl/nm-setting-gsm.c:353 #: src/libnm-core-impl/nm-setting-gsm.c:396 #: src/libnm-core-impl/nm-setting-gsm.c:405 -#: src/libnm-core-impl/nm-setting-ip-config.c:5444 +#: src/libnm-core-impl/nm-setting-ip-config.c:5476 #: src/libnm-core-impl/nm-setting-ip4-config.c:286 #: src/libnm-core-impl/nm-setting-ip4-config.c:298 #: src/libnm-core-impl/nm-setting-pppoe.c:151 @@ -1644,8 +1685,8 @@ msgstr "некоректні прапорці розпізнавання: «%d» msgid "" "invalid auth flags: both enable and disable are set for the same TLS version" msgstr "" -"некоректні прапорці розпізнавання: одночасно встановлено enable і disable" -" для тієї самої версії TLS" +"некоректні прапорці розпізнавання: одночасно встановлено enable і disable " +"для тієї самої версії TLS" #: src/libnm-core-impl/nm-setting-bluetooth.c:169 #, c-format @@ -2070,282 +2111,286 @@ msgstr "Некоректний префікс адреси IPv6, «%u»" msgid "Invalid routing metric '%s'" msgstr "Некоректна метрика маршрутизації, «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:1330 +#: src/libnm-core-impl/nm-setting-ip-config.c:1335 #: src/libnm-core-impl/nm-setting-sriov.c:400 msgid "unknown attribute" msgstr "невідомий атрибут" -#: src/libnm-core-impl/nm-setting-ip-config.c:1340 +#: src/libnm-core-impl/nm-setting-ip-config.c:1345 #: src/libnm-core-impl/nm-setting-sriov.c:410 #, c-format msgid "invalid attribute type '%s'" msgstr "некоректний тип атрибута «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:1349 +#: src/libnm-core-impl/nm-setting-ip-config.c:1354 msgid "attribute is not valid for a IPv4 route" msgstr "атрибут не є коректним для маршрутизації IPv4" -#: src/libnm-core-impl/nm-setting-ip-config.c:1350 +#: src/libnm-core-impl/nm-setting-ip-config.c:1355 msgid "attribute is not valid for a IPv6 route" msgstr "атрибут не є коректним для маршрутизації IPv6" -#: src/libnm-core-impl/nm-setting-ip-config.c:1361 -#: src/libnm-core-impl/nm-setting-ip-config.c:1393 +#: src/libnm-core-impl/nm-setting-ip-config.c:1366 +#: src/libnm-core-impl/nm-setting-ip-config.c:1398 #, c-format msgid "'%s' is not a valid IPv4 address" msgstr "«%s» не є коректною адресою IPv4" -#: src/libnm-core-impl/nm-setting-ip-config.c:1362 -#: src/libnm-core-impl/nm-setting-ip-config.c:1394 +#: src/libnm-core-impl/nm-setting-ip-config.c:1367 +#: src/libnm-core-impl/nm-setting-ip-config.c:1399 #, c-format msgid "'%s' is not a valid IPv6 address" msgstr "«%s» не є коректною адресою IPv6" -#: src/libnm-core-impl/nm-setting-ip-config.c:1384 +#: src/libnm-core-impl/nm-setting-ip-config.c:1389 #, c-format msgid "invalid prefix %s" msgstr "некоректний префікс %s" -#: src/libnm-core-impl/nm-setting-ip-config.c:1416 +#: src/libnm-core-impl/nm-setting-ip-config.c:1421 #, c-format msgid "%s is not a valid route type" msgstr "%s не є коректним типом маршруту" -#: src/libnm-core-impl/nm-setting-ip-config.c:1509 +#: src/libnm-core-impl/nm-setting-ip-config.c:1440 +#| msgid "property cannot be longer than 255 bytes" +msgid "route weight cannot be larger than 256" +msgstr "вага маршруту не може бути більшою за 256" + +#: src/libnm-core-impl/nm-setting-ip-config.c:1524 msgid "route scope is invalid for local route" msgstr "область маршрутів є некоректною для локального маршруту" -#: src/libnm-core-impl/nm-setting-ip-config.c:1521 +#: src/libnm-core-impl/nm-setting-ip-config.c:1536 #, c-format msgid "a %s route cannot have a next-hop" msgstr "маршрут %s не може мати наступного переходу" -#: src/libnm-core-impl/nm-setting-ip-config.c:2710 +#: src/libnm-core-impl/nm-setting-ip-config.c:2725 msgid "missing priority" msgstr "пропущено пріоритетність" -#: src/libnm-core-impl/nm-setting-ip-config.c:2723 +#: src/libnm-core-impl/nm-setting-ip-config.c:2738 msgid "missing table" msgstr "не вказано таблиці" -#: src/libnm-core-impl/nm-setting-ip-config.c:2733 +#: src/libnm-core-impl/nm-setting-ip-config.c:2748 msgid "invalid action type" msgstr "некоректний тип дії" -#: src/libnm-core-impl/nm-setting-ip-config.c:2742 +#: src/libnm-core-impl/nm-setting-ip-config.c:2757 msgid "has from/src but the prefix-length is zero" msgstr "" "містить from/src, але значення довжини префікса (prefix-length) є нульовим" -#: src/libnm-core-impl/nm-setting-ip-config.c:2750 +#: src/libnm-core-impl/nm-setting-ip-config.c:2765 msgid "missing from/src for a non zero prefix-length" msgstr "пропущено from/src для ненульового значення довжини префікса" -#: src/libnm-core-impl/nm-setting-ip-config.c:2757 +#: src/libnm-core-impl/nm-setting-ip-config.c:2772 msgid "invalid from/src" msgstr "некоректне значення from/src" -#: src/libnm-core-impl/nm-setting-ip-config.c:2764 +#: src/libnm-core-impl/nm-setting-ip-config.c:2779 msgid "invalid prefix length for from/src" msgstr "некоректна довжина префікса для from/src" -#: src/libnm-core-impl/nm-setting-ip-config.c:2773 +#: src/libnm-core-impl/nm-setting-ip-config.c:2788 msgid "has to/dst but the prefix-length is zero" msgstr "" "містить to/dst, але значення довжини префікса (prefix-length) є нульовим" -#: src/libnm-core-impl/nm-setting-ip-config.c:2781 +#: src/libnm-core-impl/nm-setting-ip-config.c:2796 msgid "missing to/dst for a non zero prefix-length" msgstr "пропущено to/dst для ненульового значення довжини префікса" -#: src/libnm-core-impl/nm-setting-ip-config.c:2788 +#: src/libnm-core-impl/nm-setting-ip-config.c:2803 msgid "invalid to/dst" msgstr "некоректне значення to/dst" -#: src/libnm-core-impl/nm-setting-ip-config.c:2795 +#: src/libnm-core-impl/nm-setting-ip-config.c:2810 msgid "invalid prefix length for to/dst" msgstr "некоректна довжина префікса для to/dst" -#: src/libnm-core-impl/nm-setting-ip-config.c:2805 +#: src/libnm-core-impl/nm-setting-ip-config.c:2820 msgid "invalid iifname" msgstr "некоректна назва інтерфейсу" -#: src/libnm-core-impl/nm-setting-ip-config.c:2815 +#: src/libnm-core-impl/nm-setting-ip-config.c:2830 msgid "invalid oifname" msgstr "некоректна назва інтерфейсу (oifname)" -#: src/libnm-core-impl/nm-setting-ip-config.c:2823 +#: src/libnm-core-impl/nm-setting-ip-config.c:2838 msgid "invalid source port range" msgstr "некоректний діапазон номерів порту джерела" -#: src/libnm-core-impl/nm-setting-ip-config.c:2831 +#: src/libnm-core-impl/nm-setting-ip-config.c:2846 msgid "invalid destination port range" msgstr "некоректний діапазон номерів порту призначення" -#: src/libnm-core-impl/nm-setting-ip-config.c:2841 +#: src/libnm-core-impl/nm-setting-ip-config.c:2856 msgid "suppress_prefixlength out of range" msgstr "suppress_prefixlength поза припустимим діапазоном" -#: src/libnm-core-impl/nm-setting-ip-config.c:2849 +#: src/libnm-core-impl/nm-setting-ip-config.c:2864 msgid "suppress_prefixlength is only allowed with the to-table action" msgstr "" "suppress_prefixlength можна використовувати лише разом із дією to-table" -#: src/libnm-core-impl/nm-setting-ip-config.c:2992 +#: src/libnm-core-impl/nm-setting-ip-config.c:3007 #, c-format msgid "invalid key \"%s\"" msgstr "некоректний ключ «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3004 +#: src/libnm-core-impl/nm-setting-ip-config.c:3019 #, c-format msgid "duplicate key %s" msgstr "дублікат ключа %s" -#: src/libnm-core-impl/nm-setting-ip-config.c:3020 +#: src/libnm-core-impl/nm-setting-ip-config.c:3035 #, c-format msgid "invalid variant type '%s' for \"%s\"" msgstr "некоректний тип варіанта «%s» для «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3031 +#: src/libnm-core-impl/nm-setting-ip-config.c:3046 msgid "missing \"family\"" msgstr "пропущено \"family\"" -#: src/libnm-core-impl/nm-setting-ip-config.c:3039 +#: src/libnm-core-impl/nm-setting-ip-config.c:3054 msgid "invalid \"family\"" msgstr "некоректне значення \"family\"" -#: src/libnm-core-impl/nm-setting-ip-config.c:3096 +#: src/libnm-core-impl/nm-setting-ip-config.c:3111 msgid "\"uid-range-start\" is greater than \"uid-range-end\"" msgstr "\"uid-range-start\" є більшим за \"uid-range-end\"" -#: src/libnm-core-impl/nm-setting-ip-config.c:3290 +#: src/libnm-core-impl/nm-setting-ip-config.c:3305 msgid "Unsupported to-string-flags argument" msgstr "Непідтримуваний аргумент to-string-flags" -#: src/libnm-core-impl/nm-setting-ip-config.c:3298 +#: src/libnm-core-impl/nm-setting-ip-config.c:3313 msgid "Unsupported extra-argument" msgstr "Непідтримуваний додатковий аргумент" -#: src/libnm-core-impl/nm-setting-ip-config.c:3600 +#: src/libnm-core-impl/nm-setting-ip-config.c:3615 #, c-format msgid "unsupported key \"%s\"" msgstr "непідтримуваний ключ «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3607 +#: src/libnm-core-impl/nm-setting-ip-config.c:3622 #, c-format msgid "duplicate key \"%s\"" msgstr "дублікат ключа «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3614 +#: src/libnm-core-impl/nm-setting-ip-config.c:3629 #, c-format msgid "invalid value for \"%s\"" msgstr "некоректне значення «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3626 +#: src/libnm-core-impl/nm-setting-ip-config.c:3641 msgid "empty text does not describe a rule" msgstr "порожній текст не описує правило" -#: src/libnm-core-impl/nm-setting-ip-config.c:3634 +#: src/libnm-core-impl/nm-setting-ip-config.c:3649 #, c-format msgid "missing argument for \"%s\"" msgstr "пропущено аргумент «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3648 +#: src/libnm-core-impl/nm-setting-ip-config.c:3663 msgid "invalid \"from\" part" msgstr "некоректна частина «from»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3664 +#: src/libnm-core-impl/nm-setting-ip-config.c:3679 msgid "invalid \"to\" part" msgstr "некоректна частина «to»" -#: src/libnm-core-impl/nm-setting-ip-config.c:3675 +#: src/libnm-core-impl/nm-setting-ip-config.c:3690 msgid "cannot detect address family for rule" msgstr "не вдалося визначити сімейство адрес для правила" -#: src/libnm-core-impl/nm-setting-ip-config.c:3742 -#: src/libnm-core-impl/nm-setting-ip-config.c:3832 +#: src/libnm-core-impl/nm-setting-ip-config.c:3757 +#: src/libnm-core-impl/nm-setting-ip-config.c:3847 #, c-format msgid "rule is invalid: %s" msgstr "правило є некоректним: %s" -#: src/libnm-core-impl/nm-setting-ip-config.c:3813 +#: src/libnm-core-impl/nm-setting-ip-config.c:3828 msgid "invalid address family" msgstr "некоректне сімейство адрес" -#: src/libnm-core-impl/nm-setting-ip-config.c:5092 +#: src/libnm-core-impl/nm-setting-ip-config.c:5108 #, c-format msgid "rule #%u is invalid: %s" msgstr "правило %u є некоректним: %s" -#: src/libnm-core-impl/nm-setting-ip-config.c:5465 +#: src/libnm-core-impl/nm-setting-ip-config.c:5497 #, c-format -#| msgid "%d. DNS server address is invalid" msgid "%u. DNS server address is invalid" msgstr "%u. Адреса сервера DNS є некоректною." -#: src/libnm-core-impl/nm-setting-ip-config.c:5485 +#: src/libnm-core-impl/nm-setting-ip-config.c:5517 #, c-format msgid "%d. IP address is invalid" msgstr "%d. IP-адреса є некоректною." -#: src/libnm-core-impl/nm-setting-ip-config.c:5500 +#: src/libnm-core-impl/nm-setting-ip-config.c:5532 #, c-format msgid "%d. IP address has 'label' property with invalid type" msgstr "%d. IP-адреса має властивість «label» некоректного типу" -#: src/libnm-core-impl/nm-setting-ip-config.c:5512 +#: src/libnm-core-impl/nm-setting-ip-config.c:5544 #, c-format msgid "%d. IP address has invalid label '%s'" msgstr "%d. IP-адреса має некоректну мітку, «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:5530 +#: src/libnm-core-impl/nm-setting-ip-config.c:5562 msgid "gateway cannot be set if there are no addresses configured" msgstr "шлюз не може бути встановлено, якщо не налаштовано адрес" -#: src/libnm-core-impl/nm-setting-ip-config.c:5542 +#: src/libnm-core-impl/nm-setting-ip-config.c:5574 msgid "gateway is invalid" msgstr "шлюз є некоректним" -#: src/libnm-core-impl/nm-setting-ip-config.c:5560 +#: src/libnm-core-impl/nm-setting-ip-config.c:5592 #, c-format msgid "%d. route is invalid" msgstr "%d. Некоректний маршрут" -#: src/libnm-core-impl/nm-setting-ip-config.c:5573 +#: src/libnm-core-impl/nm-setting-ip-config.c:5605 #, c-format msgid "invalid attribute: %s" msgstr "некоректний атрибут: %s" -#: src/libnm-core-impl/nm-setting-ip-config.c:5593 +#: src/libnm-core-impl/nm-setting-ip-config.c:5625 #, c-format msgid "%u. rule has wrong address-family" msgstr "%u. у правилі вказано помилкове сімейство адрес" -#: src/libnm-core-impl/nm-setting-ip-config.c:5605 +#: src/libnm-core-impl/nm-setting-ip-config.c:5637 #, c-format msgid "%u. rule is invalid: %s" msgstr "%u. правило є некоректним: %s" -#: src/libnm-core-impl/nm-setting-ip-config.c:5621 +#: src/libnm-core-impl/nm-setting-ip-config.c:5653 #, c-format msgid "'%s' is not a valid IAID" msgstr "«%s» не є коректним IAID" -#: src/libnm-core-impl/nm-setting-ip-config.c:5635 +#: src/libnm-core-impl/nm-setting-ip-config.c:5667 #, c-format msgid "the property cannot be set when '%s' is disabled" msgstr "властивість не можна встановлювати, якщо вимкнено «%s»" -#: src/libnm-core-impl/nm-setting-ip-config.c:5661 +#: src/libnm-core-impl/nm-setting-ip-config.c:5693 msgid "the property is currently supported only for DHCPv4" msgstr "у поточній версії підтримку властивості передбачено лише для DHCPv4" -#: src/libnm-core-impl/nm-setting-ip-config.c:5678 +#: src/libnm-core-impl/nm-setting-ip-config.c:5710 #, c-format msgid "'%s' is not a valid IP or subnet" msgstr "«%s» є некоректною IP-адресою або підмережею" -#: src/libnm-core-impl/nm-setting-ip-config.c:5694 +#: src/libnm-core-impl/nm-setting-ip-config.c:5726 #, c-format msgid "a gateway is incompatible with '%s'" msgstr "шлюз є несумісним з «%s»" @@ -2362,7 +2407,6 @@ msgid "'%s' is not a valid IPv%c address" msgstr "«%s» не є коректною адресою у форматі IPv%c" #: src/libnm-core-impl/nm-setting-ip-tunnel.c:440 -#| msgid "tunnel keys can only be specified for GRE tunnels" msgid "tunnel keys can only be specified for GRE and VTI tunnels" msgstr "ключі тунелювання можна задавати лише для тунелів GRE та VTI" @@ -2384,7 +2428,6 @@ msgid "some flags are invalid for the select mode: %s" msgstr "деякі з прапорців для режиму вибору є некоректними: %s" #: src/libnm-core-impl/nm-setting-ip-tunnel.c:513 -#| msgid "can be enabled only on Ethernet connections" msgid "can be set only on VTI tunnels" msgstr "можна встановити лише для тунелів VTI" @@ -2464,7 +2507,6 @@ msgstr "" #: src/libnm-core-impl/nm-setting-loopback.c:86 #, c-format -#| msgid "method \"%s\" is not supported for WireGuard" msgid "ipv4 method \"%s\" is not supported for loopback" msgstr "підтримки методу ipv4 «%s» для петльового інтерфейсу не передбачено" @@ -2474,7 +2516,6 @@ msgstr "ipv4.link-local не можна вмикати для петльовог #: src/libnm-core-impl/nm-setting-loopback.c:117 #, c-format -#| msgid "method \"%s\" is not supported for WireGuard" msgid "ipv6 method \"%s\" is not supported for loopback" msgstr "підтримки методу ipv6 «%s» для петльового інтерфейсу не передбачено" @@ -2492,7 +2533,6 @@ msgid "the key must be %d characters" msgstr "ключ має складатися з %d символів" #: src/libnm-core-impl/nm-setting-macsec.c:271 -#| msgid "IV must be an even number of bytes in length." msgid "the key must have an even number of characters between 2 and 64" msgstr "у ключі має бути парна кількість символів, від 2 до 64" @@ -2552,65 +2592,35 @@ msgstr "З'єднання з параметром «%s» не повинне м msgid "'%s' is not allowed in fail_mode" msgstr "«%s» не можна використовувати у режимі fail_mode" -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:90 -#: src/libnm-core-impl/nm-setting-user.c:93 -msgid "missing key" -msgstr "не вказано ключ" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:98 -#: src/libnm-core-impl/nm-setting-user.c:101 -msgid "key is too long" -msgstr "ключ є надто довгим" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:105 -#: src/libnm-core-impl/nm-setting-user.c:108 -msgid "key must be UTF8" -msgstr "ключ має зберігатися у кодуванні UTF8" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:114 -#: src/libnm-core-impl/nm-setting-user.c:155 -msgid "key contains invalid characters" -msgstr "ключ містить некоректний символ" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:123 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:115 msgid "key cannot start with \"NM.\"" msgstr "запис ключа не починається з «NM.»" -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:153 -#: src/libnm-core-impl/nm-setting-user.c:182 -msgid "value is missing" -msgstr "не вказано значення" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:162 -#: src/libnm-core-impl/nm-setting-user.c:191 -msgid "value is too large" -msgstr "значення є надто великим" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:170 -#: src/libnm-core-impl/nm-setting-user.c:199 -msgid "value is not valid UTF8" -msgstr "значення не записано у коректному кодуванні UTF8" +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:166 +#, c-format +#| msgid "" +#| "OVS external IDs can only be added to a profile of type OVS bridge/port/" +#| "interface or to OVS system interface" +msgid "" +"OVS %s can only be added to a profile of type OVS bridge/port/interface or " +"to OVS system interface" +msgstr "" +"%s OVS можна додавати лише до профілів типу місток, " +"порт або інтерфейс OVS або до загальносистемного інтерфейсу OVS" -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:315 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:363 +#: src/libnm-core-impl/nm-setting-ovs-other-config.c:201 #: src/libnm-core-impl/nm-setting-user.c:361 #, c-format msgid "invalid key \"%s\": %s" msgstr "некоректний ключ «%s»: %s" -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:339 -#: src/libnm-core-impl/nm-setting-user.c:385 +#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:387 +#: src/libnm-core-impl/nm-setting-ovs-other-config.c:225 #, c-format -msgid "maximum number of user data entries reached (%u instead of %u)" -msgstr "" -"досягнуто максимальної кількості записів даних користувача (%u замість %u)" - -#: src/libnm-core-impl/nm-setting-ovs-external-ids.c:382 -msgid "" -"OVS external IDs can only be added to a profile of type OVS bridge/port/" -"interface or to OVS system interface" -msgstr "" -"Зовнішні ідентифікатори OVS можна додавати лише до профілів типу місток, " -"порт або інтерфейс OVS або до загальносистемного інтерфейсу OVS" +#| msgid "maximum number of user data entries reached (%u instead of %u)" +msgid "maximum number of entries reached (%u instead of %u)" +msgstr "досягнуто максимальної кількості записів (%u замість %u)" #: src/libnm-core-impl/nm-setting-ovs-interface.c:110 #, c-format @@ -2679,19 +2689,16 @@ msgid "A connection with a '%s' setting must have a master." msgstr "З'єднання з параметром «%s» повинне мати основне." #: src/libnm-core-impl/nm-setting-ovs-port.c:347 -#| msgid "page must be between %d and %d" msgid "VLANs must be between 0 and 4095" msgstr "VLAN має належати діапазону від 0 до 4095" #: src/libnm-core-impl/nm-setting-ovs-port.c:356 #, c-format -#| msgid "duplicate bridge VLAN vid %u" msgid "duplicate VLAN %u" msgstr "дублювання VLAN %u" #: src/libnm-core-impl/nm-setting-ovs-port.c:384 #, c-format -#| msgid "VFs %d and %d are not sorted by ascending index" msgid "VLANs %u and %u are not sorted in ascending order" msgstr "VLAN %u та %u не упорядковано за зростанням" @@ -2867,6 +2874,12 @@ msgstr "у записі ключа не може міститися «..»" msgid "maximum number of user data entries reached" msgstr "досягнуто максимальної кількості записів даних користувача" +#: src/libnm-core-impl/nm-setting-user.c:385 +#, c-format +msgid "maximum number of user data entries reached (%u instead of %u)" +msgstr "" +"досягнуто максимальної кількості записів даних користувача (%u замість %u)" + #: src/libnm-core-impl/nm-setting-veth.c:90 #, c-format msgid "'%s' is not a valid interface name" @@ -4051,7 +4064,7 @@ msgstr "деактивація (ззовні)" #: src/libnmc-setting/nm-meta-setting-desc.c:881 #: src/libnmc-setting/nm-meta-setting-desc.c:2883 src/nmcli/connections.c:5534 #: src/nmcli/connections.c:7508 src/nmcli/connections.c:7509 -#: src/nmcli/devices.c:590 src/nmcli/devices.c:596 src/nmcli/devices.c:1408 +#: src/nmcli/devices.c:590 src/nmcli/devices.c:596 src/nmcli/devices.c:1405 #: src/nmcli/general.c:92 src/nmcli/utils.h:313 msgid "yes" msgstr "так" @@ -4060,7 +4073,7 @@ msgstr "так" #: src/libnmc-setting/nm-meta-setting-desc.c:881 #: src/libnmc-setting/nm-meta-setting-desc.c:2886 src/nmcli/connections.c:5533 #: src/nmcli/connections.c:7508 src/nmcli/connections.c:7509 -#: src/nmcli/devices.c:590 src/nmcli/devices.c:596 src/nmcli/devices.c:1408 +#: src/nmcli/devices.c:590 src/nmcli/devices.c:596 src/nmcli/devices.c:1405 #: src/nmcli/general.c:93 src/nmcli/utils.h:313 msgid "no" msgstr "ні" @@ -4460,7 +4473,7 @@ msgstr "Попередньо поширений ключ для %s" #: src/libnmc-base/nm-secret-agent-simple.c:270 #: src/libnmc-base/nm-secret-agent-simple.c:357 -#: src/libnmc-setting/nm-meta-setting-desc.c:5132 +#: src/libnmc-setting/nm-meta-setting-desc.c:5135 #: src/nmtui/nmt-8021x-fields.c:182 src/nmtui/nmt-8021x-fields.c:353 #: src/nmtui/nmt-8021x-fields.c:457 src/nmtui/nmt-page-dsl.c:51 #: src/nmtui/nmt-page-wifi.c:345 @@ -4476,7 +4489,7 @@ msgstr "Користувач" #: src/libnmc-base/nm-secret-agent-simple.c:979 #: src/libnmc-base/nm-vpn-helpers.c:143 src/libnmc-base/nm-vpn-helpers.c:147 #: src/libnmc-base/nm-vpn-helpers.c:153 src/libnmc-base/nm-vpn-helpers.c:158 -#: src/nmcli/devices.c:4717 src/nmtui/nmt-8021x-fields.c:195 +#: src/nmcli/devices.c:4714 src/nmtui/nmt-8021x-fields.c:195 #: src/nmtui/nmt-8021x-fields.c:373 src/nmtui/nmt-8021x-fields.c:477 #: src/nmtui/nmt-page-dsl.c:64 src/nmtui/nmt-page-wifi.c:287 #: src/nmtui/nmt-page-wifi.c:319 src/nmtui/nmt-page-wifi.c:358 @@ -4579,7 +4592,7 @@ msgid "MACsec PSK authentication" msgstr "Розпізнавання у MACsec за PSK" #: src/libnmc-base/nm-secret-agent-simple.c:931 -#: src/libnmc-setting/nm-meta-setting-desc.c:6664 +#: src/libnmc-setting/nm-meta-setting-desc.c:6673 msgid "MKA CAK" msgstr "MKA CAK" @@ -4729,7 +4742,7 @@ msgstr "%s (%s)" #: src/libnmc-setting/nm-meta-setting-desc.c:1413 #: src/libnmc-setting/nm-meta-setting-desc.c:1421 -#: src/libnmc-setting/nm-meta-setting-desc.c:4472 +#: src/libnmc-setting/nm-meta-setting-desc.c:4475 msgid "'%s' is out of range [%" msgstr "«%s» поза діапазоном [%" @@ -4985,7 +4998,6 @@ msgstr "" "<тип>'" #: src/libnmc-setting/nm-meta-setting-desc.c:3869 -#| msgid "The valid syntax is: '[-] [pvid] [untagged]'" msgid "The valid syntax is: '' or '-" msgstr "" "Коректна синтаксична конструкція: «<значення>» або «<початок>-<кінець>»" @@ -5025,7 +5037,7 @@ msgstr "«%s» не є коректним каналом" msgid "'%ld' is not a valid channel" msgstr "«%ld» не є коректним каналом" -#: src/libnmc-setting/nm-meta-setting-desc.c:4355 +#: src/libnmc-setting/nm-meta-setting-desc.c:4356 #, c-format msgid "" "'%s' not compatible with %s '%s', please change the key or set the right %s " @@ -5034,73 +5046,74 @@ msgstr "" "«%s» є несумісним з %s «%s», будь ласка, спочатку змініть ключ або " "встановіть правильне значення %s." -#: src/libnmc-setting/nm-meta-setting-desc.c:4370 +#: src/libnmc-setting/nm-meta-setting-desc.c:4372 #, c-format -msgid "WEP key is guessed to be of '%s'" -msgstr "Припускаємо, що ключем WEP є «%s»" +#| msgid "WEP key is guessed to be of '%s'" +msgid "WEP key is guessed to be of %s" +msgstr "Припускаємо, що ключем WEP є %s" -#: src/libnmc-setting/nm-meta-setting-desc.c:4376 +#: src/libnmc-setting/nm-meta-setting-desc.c:4379 #, c-format msgid "WEP key index set to '%d'" msgstr "індекс ключа WEP встановлено у значення «%d»" -#: src/libnmc-setting/nm-meta-setting-desc.c:4415 +#: src/libnmc-setting/nm-meta-setting-desc.c:4418 #, c-format msgid "" "'%s' is not compatible with '%s' type, please change or delete the key." msgstr "«%s» несумісний з типом «%s». Будь ласка, змініть або вилучіть ключ." -#: src/libnmc-setting/nm-meta-setting-desc.c:4450 src/nmcli/utils.h:319 +#: src/libnmc-setting/nm-meta-setting-desc.c:4453 src/nmcli/utils.h:319 msgid "on" msgstr "увімкн." -#: src/libnmc-setting/nm-meta-setting-desc.c:4450 src/nmcli/utils.h:319 +#: src/libnmc-setting/nm-meta-setting-desc.c:4453 src/nmcli/utils.h:319 msgid "off" msgstr "вимкн." -#: src/libnmc-setting/nm-meta-setting-desc.c:4491 +#: src/libnmc-setting/nm-meta-setting-desc.c:4494 #, c-format msgid "'%s' is not valid; use 'on', 'off', or 'ignore'" msgstr "" "«%s» не є коректним значенням; можна використовувати лише значення «on», " "«off» або «ignore»" -#: src/libnmc-setting/nm-meta-setting-desc.c:4560 +#: src/libnmc-setting/nm-meta-setting-desc.c:4563 msgid "Bonding primary interface" msgstr "Основний інтерфейс прив'язування" #. this is a virtual property, only needed during "ask" mode. -#: src/libnmc-setting/nm-meta-setting-desc.c:4568 +#: src/libnmc-setting/nm-meta-setting-desc.c:4571 msgid "Bonding monitoring mode" msgstr "Режим спостереження за зв'язком" -#: src/libnmc-setting/nm-meta-setting-desc.c:4577 +#: src/libnmc-setting/nm-meta-setting-desc.c:4580 msgid "Bonding miimon" msgstr "Частота спостереження MII прив'язування" -#: src/libnmc-setting/nm-meta-setting-desc.c:4586 +#: src/libnmc-setting/nm-meta-setting-desc.c:4589 msgid "Bonding downdelay" msgstr "downdelay прив'язування" -#: src/libnmc-setting/nm-meta-setting-desc.c:4595 +#: src/libnmc-setting/nm-meta-setting-desc.c:4598 msgid "Bonding updelay" msgstr "updelay прив'язування" -#: src/libnmc-setting/nm-meta-setting-desc.c:4604 +#: src/libnmc-setting/nm-meta-setting-desc.c:4607 msgid "Bonding arp-interval" msgstr "arp-interval прив'язування" -#: src/libnmc-setting/nm-meta-setting-desc.c:4613 +#: src/libnmc-setting/nm-meta-setting-desc.c:4616 msgid "Bonding arp-ip-target" msgstr "arp-ip-target прив'язування" -#: src/libnmc-setting/nm-meta-setting-desc.c:4622 +#: src/libnmc-setting/nm-meta-setting-desc.c:4625 msgid "LACP rate (slow/fast)" msgstr "Швидкість LACP (slow або fast)" #. macro that returns @func as const (guint32(*)(NMSetting*)) type, but checks #. * that the actual type is (guint32(*)(type *)). -#: src/libnmc-setting/nm-meta-setting-desc.c:4796 +#: src/libnmc-setting/nm-meta-setting-desc.c:4799 msgid "" "nmcli can accepts both direct JSON configuration data and a file name " "containing the configuration. In the latter case the file is read and the " @@ -5119,7 +5132,7 @@ msgstr "" "\"roundrobin\"}, \"ports\": {\"eth1\": {}, \"eth2\": {}} }\n" " set team.config /etc/my-team.conf\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:4804 +#: src/libnmc-setting/nm-meta-setting-desc.c:4807 msgid "" "Enter a list of link watchers formatted as dictionaries where the keys are " "teamd properties. Dictionary pairs are in the form: key=value and pairs are " @@ -5168,11 +5181,11 @@ msgstr "" " name=arp_ping source-host=172.16.1.1 target-host=172.16.1.254, " "name=ethtool delay-up=3\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:4853 +#: src/libnmc-setting/nm-meta-setting-desc.c:4856 msgid "IEEE 802.15.4 (WPAN) parent device or connection UUID" msgstr "Батьківський пристрій або UUID з'єднання IEEE 802.15.4 (WPAN)" -#: src/libnmc-setting/nm-meta-setting-desc.c:4889 +#: src/libnmc-setting/nm-meta-setting-desc.c:4892 msgid "" "Enter file path to CA certificate (optionally prefixed with file://).\n" " [file://]\n" @@ -5185,7 +5198,7 @@ msgstr "" "форматі простого масиву даних.\n" "Приклад: /home/cimrman/cacert.crt\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:4931 +#: src/libnmc-setting/nm-meta-setting-desc.c:4934 msgid "" "Enter file path to client certificate (optionally prefixed with file://).\n" " [file://]\n" @@ -5199,7 +5212,7 @@ msgstr "" "форматі простого масиву даних.\n" "Приклад: /home/cimrman/jara.crt\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:4988 +#: src/libnmc-setting/nm-meta-setting-desc.c:4991 msgid "" "Enter file path to CA certificate for inner authentication (optionally " "prefixed\n" @@ -5215,7 +5228,7 @@ msgstr "" "форматі простого масиву даних.\n" "Приклад: /home/cimrman/ca-zweite-phase.crt\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5031 +#: src/libnmc-setting/nm-meta-setting-desc.c:5034 msgid "" "Enter file path to client certificate for inner authentication (optionally " "prefixed\n" @@ -5231,7 +5244,7 @@ msgstr "" "форматі простого масиву даних.\n" "Приклад: /home/cimrman/jara-zweite-phase.crt\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5058 +#: src/libnmc-setting/nm-meta-setting-desc.c:5061 msgid "" "Enter bytes as a list of hexadecimal values.\n" "Two formats are accepted:\n" @@ -5253,8 +5266,8 @@ msgstr "" "Приклади: ab0455a6ea3a74C2\n" " ab 4 55 0xa6 ea 3a 74 C2\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5075 -#: src/libnmc-setting/nm-meta-setting-desc.c:5093 +#: src/libnmc-setting/nm-meta-setting-desc.c:5078 +#: src/libnmc-setting/nm-meta-setting-desc.c:5096 msgid "" "Enter path to a private key and the key password (if not set yet):\n" " [file://] []\n" @@ -5268,87 +5281,87 @@ msgstr "" "форматі простого масиву даних.\n" "Приклад: /home/cimrman/jara-priv-key Dardanely\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5138 -#: src/libnmc-setting/nm-meta-setting-desc.c:5434 -#: src/libnmc-setting/nm-meta-setting-desc.c:5924 -#: src/libnmc-setting/nm-meta-setting-desc.c:7013 +#: src/libnmc-setting/nm-meta-setting-desc.c:5141 +#: src/libnmc-setting/nm-meta-setting-desc.c:5437 +#: src/libnmc-setting/nm-meta-setting-desc.c:5927 +#: src/libnmc-setting/nm-meta-setting-desc.c:7028 msgid "Password [none]" msgstr "Пароль [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:5184 +#: src/libnmc-setting/nm-meta-setting-desc.c:5187 msgid "Bluetooth device address" msgstr "Адреса пристрою Bluetooth" -#: src/libnmc-setting/nm-meta-setting-desc.c:5232 +#: src/libnmc-setting/nm-meta-setting-desc.c:5235 #: src/nmtui/nmt-page-bond-port.c:51 msgid "Queue ID" msgstr "Ідентифікатор черги" -#: src/libnmc-setting/nm-meta-setting-desc.c:5244 -#: src/libnmc-setting/nm-meta-setting-desc.c:5998 -#: src/libnmc-setting/nm-meta-setting-desc.c:7739 -#: src/libnmc-setting/nm-meta-setting-desc.c:7777 -#: src/libnmc-setting/nm-meta-setting-desc.c:7962 -#: src/libnmc-setting/nm-meta-setting-desc.c:8195 +#: src/libnmc-setting/nm-meta-setting-desc.c:5247 +#: src/libnmc-setting/nm-meta-setting-desc.c:6001 +#: src/libnmc-setting/nm-meta-setting-desc.c:7754 +#: src/libnmc-setting/nm-meta-setting-desc.c:7792 +#: src/libnmc-setting/nm-meta-setting-desc.c:7977 +#: src/libnmc-setting/nm-meta-setting-desc.c:8210 msgid "MAC [none]" msgstr "MAC [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:5250 +#: src/libnmc-setting/nm-meta-setting-desc.c:5253 msgid "Enable STP" msgstr "Увімкнути STP" -#: src/libnmc-setting/nm-meta-setting-desc.c:5256 +#: src/libnmc-setting/nm-meta-setting-desc.c:5259 msgid "STP priority" msgstr "Пріоритет STP" -#: src/libnmc-setting/nm-meta-setting-desc.c:5262 +#: src/libnmc-setting/nm-meta-setting-desc.c:5265 #: src/nmtui/nmt-page-bridge.c:120 msgid "Forward delay" msgstr "Затримка переспрямування" -#: src/libnmc-setting/nm-meta-setting-desc.c:5268 +#: src/libnmc-setting/nm-meta-setting-desc.c:5271 #: src/nmtui/nmt-page-bridge.c:134 msgid "Hello time" msgstr "Час на вітання" -#: src/libnmc-setting/nm-meta-setting-desc.c:5274 +#: src/libnmc-setting/nm-meta-setting-desc.c:5277 #: src/nmtui/nmt-page-bridge.c:148 msgid "Max age" msgstr "Макс. вік" -#: src/libnmc-setting/nm-meta-setting-desc.c:5280 +#: src/libnmc-setting/nm-meta-setting-desc.c:5283 msgid "MAC address ageing time" msgstr "Час застарівання MAC-адреси" -#: src/libnmc-setting/nm-meta-setting-desc.c:5290 +#: src/libnmc-setting/nm-meta-setting-desc.c:5293 #: src/nmtui/nmt-page-bridge.c:156 msgid "Group forward mask" msgstr "Маска групового переспрямовування" -#: src/libnmc-setting/nm-meta-setting-desc.c:5332 +#: src/libnmc-setting/nm-meta-setting-desc.c:5335 #: src/nmtui/nmt-page-bridge.c:79 msgid "Enable IGMP snooping" msgstr "Увімкнути підглядання IGMP" -#: src/libnmc-setting/nm-meta-setting-desc.c:5390 +#: src/libnmc-setting/nm-meta-setting-desc.c:5393 msgid "Bridge port priority" msgstr "Пріоритетний порт містка" -#: src/libnmc-setting/nm-meta-setting-desc.c:5396 +#: src/libnmc-setting/nm-meta-setting-desc.c:5399 msgid "Bridge port STP path cost" msgstr "Вартість маршруту STP порту містка" -#: src/libnmc-setting/nm-meta-setting-desc.c:5402 +#: src/libnmc-setting/nm-meta-setting-desc.c:5405 msgid "Hairpin" msgstr "Початкова зона" -#: src/libnmc-setting/nm-meta-setting-desc.c:5428 -#: src/libnmc-setting/nm-meta-setting-desc.c:5918 -#: src/libnmc-setting/nm-meta-setting-desc.c:7586 +#: src/libnmc-setting/nm-meta-setting-desc.c:5431 +#: src/libnmc-setting/nm-meta-setting-desc.c:5921 +#: src/libnmc-setting/nm-meta-setting-desc.c:7601 msgid "Username [none]" msgstr "Користувач [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:5533 +#: src/libnmc-setting/nm-meta-setting-desc.c:5536 msgid "" "Enter a list of user permissions. This is a list of user names formatted " "as:\n" @@ -5363,7 +5376,7 @@ msgstr "" "\n" "Приклад: alice bob charlie\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5586 +#: src/libnmc-setting/nm-meta-setting-desc.c:5589 msgid "" "Enter secondary connections that should be activated when this connection " "is\n" @@ -5384,7 +5397,7 @@ msgstr "" "\n" "Приклад: private-openvpn, fe6ba5d8-c2fc-4aae-b2e3-97efddd8d9a7\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5609 +#: src/libnmc-setting/nm-meta-setting-desc.c:5612 msgid "" "Enter a value which indicates whether the connection is subject to a data\n" "quota, usage costs or other limitations. Accepted options are:\n" @@ -5400,29 +5413,29 @@ msgstr "" "«unknown» — дозволити NetworkManager вибирати значення за допомогою " "евристики\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:5934 +#: src/libnmc-setting/nm-meta-setting-desc.c:5937 msgid "APN" msgstr "APN" -#: src/libnmc-setting/nm-meta-setting-desc.c:6007 -#: src/libnmc-setting/nm-meta-setting-desc.c:6621 -#: src/libnmc-setting/nm-meta-setting-desc.c:7808 -#: src/libnmc-setting/nm-meta-setting-desc.c:8002 +#: src/libnmc-setting/nm-meta-setting-desc.c:6010 +#: src/libnmc-setting/nm-meta-setting-desc.c:6630 +#: src/libnmc-setting/nm-meta-setting-desc.c:7823 +#: src/libnmc-setting/nm-meta-setting-desc.c:8017 #: src/nmtui/nmt-page-ethernet.c:124 src/nmtui/nmt-page-infiniband.c:81 #: src/nmtui/nmt-page-ip-tunnel.c:178 src/nmtui/nmt-page-vlan.c:100 #: src/nmtui/nmt-page-wifi.c:395 src/nmtui/nmt-page-wireguard.c:85 msgid "MTU" msgstr "MTU" -#: src/libnmc-setting/nm-meta-setting-desc.c:6026 +#: src/libnmc-setting/nm-meta-setting-desc.c:6029 msgid "P_KEY [none]" msgstr "P_KEY [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6035 +#: src/libnmc-setting/nm-meta-setting-desc.c:6038 msgid "Parent interface [none]" msgstr "Батьківський інтерфейс [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6062 +#: src/libnmc-setting/nm-meta-setting-desc.c:6065 msgid "" "Enter a list of IPv4 addresses of DNS servers.\n" "\n" @@ -5432,11 +5445,11 @@ msgstr "" "\n" "Приклад: 8.8.8.8, 8.8.4.4\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6109 +#: src/libnmc-setting/nm-meta-setting-desc.c:6112 msgid "IPv4 address (IP[/plen]) [none]" msgstr "Адреса IPv4 (IP[/plen]) [немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6111 +#: src/libnmc-setting/nm-meta-setting-desc.c:6114 msgid "" "Enter a list of IPv4 addresses formatted as:\n" " ip[/prefix], ip[/prefix],...\n" @@ -5450,11 +5463,11 @@ msgstr "" "\n" "Приклад: 192.168.1.5/24, 10.0.0.11/24\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6130 +#: src/libnmc-setting/nm-meta-setting-desc.c:6133 msgid "IPv4 gateway [none]" msgstr "Шлюз IPv4 [немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6138 +#: src/libnmc-setting/nm-meta-setting-desc.c:6141 msgid "" "Enter a list of IPv4 routes formatted as:\n" " ip[/prefix] [next-hop] [metric],...\n" @@ -5477,7 +5490,7 @@ msgstr "" "Приклади: 192.168.2.0/24 192.168.2.1 3, 10.1.0.0/16 10.0.0.254\n" " 10.1.2.0/24\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6178 +#: src/libnmc-setting/nm-meta-setting-desc.c:6181 msgid "" "Enter a list of IPv4 routing rules formatted as:\n" " priority [prio] [from [src]] [to [dst]], ,...\n" @@ -5487,7 +5500,7 @@ msgstr "" " priority [пріоритетність] [from [джерело]] [to [призначення]], ,...\n" "\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6308 +#: src/libnmc-setting/nm-meta-setting-desc.c:6314 msgid "" "Enter a list of IPv6 addresses of DNS servers. If the IPv6 configuration " "method is 'auto' these DNS servers are appended to those (if any) returned " @@ -5508,11 +5521,11 @@ msgstr "" "\n" "Приклад: 2607:f0d0:1002:51::4, 2607:f0d0:1002:51::1\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6361 +#: src/libnmc-setting/nm-meta-setting-desc.c:6367 msgid "IPv6 address (IP[/plen]) [none]" msgstr "Адреса IPv6 (IP[/plen]) [немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6363 +#: src/libnmc-setting/nm-meta-setting-desc.c:6369 msgid "" "Enter a list of IPv6 addresses formatted as:\n" " ip[/prefix], ip[/prefix],...\n" @@ -5526,11 +5539,11 @@ msgstr "" "\n" "Приклад: 2607:f0d0:1002:51::4/64, 1050:0:0:0:5:600:300c:326b\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6382 +#: src/libnmc-setting/nm-meta-setting-desc.c:6388 msgid "IPv6 gateway [none]" msgstr "Шлюз IPv6 [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6390 +#: src/libnmc-setting/nm-meta-setting-desc.c:6396 msgid "" "Enter a list of IPv6 routes formatted as:\n" " ip[/prefix] [next-hop] [metric],...\n" @@ -5555,7 +5568,7 @@ msgstr "" "db8:beef::3 2\n" " abbe::/64 55\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6430 +#: src/libnmc-setting/nm-meta-setting-desc.c:6436 msgid "" "Enter a list of IPv6 routing rules formatted as:\n" " priority [prio] [from [src]] [to [dst]], ,...\n" @@ -5565,170 +5578,170 @@ msgstr "" " priority [пріоритетність] [from [джерело]] [to [призначення]], ,...\n" "\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:6558 -#: src/libnmc-setting/nm-meta-setting-desc.c:7639 +#: src/libnmc-setting/nm-meta-setting-desc.c:6567 +#: src/libnmc-setting/nm-meta-setting-desc.c:7654 msgid "Parent device [none]" msgstr "Батьківський пристрій [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6564 +#: src/libnmc-setting/nm-meta-setting-desc.c:6573 msgid "Local endpoint [none]" msgstr "Локальна кінцева точка [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6571 -#: src/libnmc-setting/nm-meta-setting-desc.c:7658 +#: src/libnmc-setting/nm-meta-setting-desc.c:6580 +#: src/libnmc-setting/nm-meta-setting-desc.c:7673 msgid "Remote" msgstr "Віддалений" -#: src/libnmc-setting/nm-meta-setting-desc.c:6637 +#: src/libnmc-setting/nm-meta-setting-desc.c:6646 msgid "MACsec parent device or connection UUID" msgstr "Батьківський пристрій MACsec або UUID з'єднання" -#: src/libnmc-setting/nm-meta-setting-desc.c:6658 +#: src/libnmc-setting/nm-meta-setting-desc.c:6667 msgid "Enable encryption" msgstr "Увімкнути шифрування" -#: src/libnmc-setting/nm-meta-setting-desc.c:6674 +#: src/libnmc-setting/nm-meta-setting-desc.c:6683 msgid "MKA_CKN" msgstr "MKA_CKN" -#: src/libnmc-setting/nm-meta-setting-desc.c:6680 +#: src/libnmc-setting/nm-meta-setting-desc.c:6689 #: src/nmtui/nmt-page-macsec.c:170 msgid "SCI port" msgstr "Порт SCI" -#: src/libnmc-setting/nm-meta-setting-desc.c:6706 +#: src/libnmc-setting/nm-meta-setting-desc.c:6715 msgid "MACVLAN parent device or connection UUID" msgstr "Батьківський пристрій MACVLAN або UUID з'єднання" -#: src/libnmc-setting/nm-meta-setting-desc.c:6727 +#: src/libnmc-setting/nm-meta-setting-desc.c:6736 msgid "Tap" msgstr "Tap" -#: src/libnmc-setting/nm-meta-setting-desc.c:6794 -#: src/libnmc-setting/nm-meta-setting-desc.c:7916 src/nmtui/nmt-page-wifi.c:216 +#: src/libnmc-setting/nm-meta-setting-desc.c:6803 +#: src/libnmc-setting/nm-meta-setting-desc.c:7931 src/nmtui/nmt-page-wifi.c:216 msgid "SSID" msgstr "SSID" -#: src/libnmc-setting/nm-meta-setting-desc.c:6803 +#: src/libnmc-setting/nm-meta-setting-desc.c:6812 msgid "OLPC Mesh channel" msgstr "Канал OLPC Mesh" -#: src/libnmc-setting/nm-meta-setting-desc.c:6812 +#: src/libnmc-setting/nm-meta-setting-desc.c:6821 msgid "DHCP anycast MAC address [none]" msgstr "MAC-адреса довільного надсилання (anycast) DHCP [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:6994 +#: src/libnmc-setting/nm-meta-setting-desc.c:7009 msgid "PPPoE parent device" msgstr "Батьківський пристрій PPPoE" -#: src/libnmc-setting/nm-meta-setting-desc.c:7000 +#: src/libnmc-setting/nm-meta-setting-desc.c:7015 msgid "Service [none]" msgstr "Служба [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7007 +#: src/libnmc-setting/nm-meta-setting-desc.c:7022 msgid "PPPoE username" msgstr "Користувач PPPoE" -#: src/libnmc-setting/nm-meta-setting-desc.c:7043 +#: src/libnmc-setting/nm-meta-setting-desc.c:7058 msgid "Browser only" msgstr "Лише навігатор" -#: src/libnmc-setting/nm-meta-setting-desc.c:7049 +#: src/libnmc-setting/nm-meta-setting-desc.c:7064 msgid "PAC URL" msgstr "Адреса PAC" -#: src/libnmc-setting/nm-meta-setting-desc.c:7055 +#: src/libnmc-setting/nm-meta-setting-desc.c:7070 msgid "PAC script" msgstr "Скрипт PAC" -#: src/libnmc-setting/nm-meta-setting-desc.c:7179 -#: src/libnmc-setting/nm-meta-setting-desc.c:7367 +#: src/libnmc-setting/nm-meta-setting-desc.c:7194 +#: src/libnmc-setting/nm-meta-setting-desc.c:7382 msgid "Team JSON configuration [none]" msgstr "Налаштування JSON команди [немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7470 +#: src/libnmc-setting/nm-meta-setting-desc.c:7485 msgid "User ID [none]" msgstr "Ідентифікатор користувача [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7476 +#: src/libnmc-setting/nm-meta-setting-desc.c:7491 msgid "Group ID [none]" msgstr "Ідентифікатор групи [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7482 +#: src/libnmc-setting/nm-meta-setting-desc.c:7497 msgid "Enable PI" msgstr "Увімкнути PI" -#: src/libnmc-setting/nm-meta-setting-desc.c:7488 +#: src/libnmc-setting/nm-meta-setting-desc.c:7503 msgid "Enable VNET header" msgstr "Увімкнути заголовок VNET" -#: src/libnmc-setting/nm-meta-setting-desc.c:7494 +#: src/libnmc-setting/nm-meta-setting-desc.c:7509 msgid "Enable multi queue" msgstr "Увімкнути декілька черг" -#: src/libnmc-setting/nm-meta-setting-desc.c:7507 +#: src/libnmc-setting/nm-meta-setting-desc.c:7522 msgid "veth peer" msgstr "вузол veth" -#: src/libnmc-setting/nm-meta-setting-desc.c:7520 +#: src/libnmc-setting/nm-meta-setting-desc.c:7535 msgid "VLAN parent device or connection UUID" msgstr "Батьківський пристрій VLAN або UUID з'єднання" -#: src/libnmc-setting/nm-meta-setting-desc.c:7527 +#: src/libnmc-setting/nm-meta-setting-desc.c:7542 msgid "VLAN ID (<0-4094>)" msgstr "Ід. VLAN (<0-4094>)" -#: src/libnmc-setting/nm-meta-setting-desc.c:7533 +#: src/libnmc-setting/nm-meta-setting-desc.c:7548 msgid "VLAN flags (<0-7>) [none]" msgstr "Прапорці VLAN (<0-7>) [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7548 +#: src/libnmc-setting/nm-meta-setting-desc.c:7563 msgid "Ingress priority maps [none]" msgstr "Відображення пріоритетності вхідного доступу [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7558 +#: src/libnmc-setting/nm-meta-setting-desc.c:7573 msgid "Egress priority maps [none]" msgstr "Відображення пріоритетності вихідного доступу [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7626 +#: src/libnmc-setting/nm-meta-setting-desc.c:7641 msgid "Table" msgstr "Таблиця" -#: src/libnmc-setting/nm-meta-setting-desc.c:7646 +#: src/libnmc-setting/nm-meta-setting-desc.c:7661 msgid "VXLAN ID" msgstr "Ід. VXLAN" -#: src/libnmc-setting/nm-meta-setting-desc.c:7652 +#: src/libnmc-setting/nm-meta-setting-desc.c:7667 msgid "Local address [none]" msgstr "Локальна адреса [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7664 +#: src/libnmc-setting/nm-meta-setting-desc.c:7679 msgid "Minimum source port" msgstr "Мінімальний порт джерела" -#: src/libnmc-setting/nm-meta-setting-desc.c:7670 +#: src/libnmc-setting/nm-meta-setting-desc.c:7685 msgid "Maximum source port" msgstr "Максимальний порт джерела" -#: src/libnmc-setting/nm-meta-setting-desc.c:7676 +#: src/libnmc-setting/nm-meta-setting-desc.c:7691 msgid "Destination port" msgstr "Порт призначення" -#: src/libnmc-setting/nm-meta-setting-desc.c:7716 +#: src/libnmc-setting/nm-meta-setting-desc.c:7731 #: src/nmtui/nmt-wireguard-peer-editor.c:78 msgid "Peer" msgstr "Вузол" -#: src/libnmc-setting/nm-meta-setting-desc.c:7746 +#: src/libnmc-setting/nm-meta-setting-desc.c:7761 msgid "WiMAX NSP name" msgstr "Назва NSP WiMAX" -#: src/libnmc-setting/nm-meta-setting-desc.c:7783 -#: src/libnmc-setting/nm-meta-setting-desc.c:7967 +#: src/libnmc-setting/nm-meta-setting-desc.c:7798 +#: src/libnmc-setting/nm-meta-setting-desc.c:7982 msgid "Cloned MAC [none]" msgstr "Клонований MAC [типово немає]" -#: src/libnmc-setting/nm-meta-setting-desc.c:7816 +#: src/libnmc-setting/nm-meta-setting-desc.c:7831 msgid "" "Enter a list of subchannels (comma or space separated).\n" "\n" @@ -5738,7 +5751,7 @@ msgstr "" "\n" "Приклад: 0.0.0e20 0.0.0e21 0.0.0e22\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:8144 +#: src/libnmc-setting/nm-meta-setting-desc.c:8159 msgid "" "Enter the type of WEP keys. The accepted values are: 0 or unknown, 1 or key, " "and 2 or passphrase.\n" @@ -5746,209 +5759,212 @@ msgstr "" "Вкажіть тип ключів WEP. Можливі значення: 0 або unknown (невідомо), 1 або " "key (ключ) та 2 або passphrase (пароль).\n" -#: src/libnmc-setting/nm-meta-setting-desc.c:8203 +#: src/libnmc-setting/nm-meta-setting-desc.c:8218 msgid "Short address (<0x0000-0xffff>)" msgstr "Коротка адреса (<0x0000-0xffff>)" -#: src/libnmc-setting/nm-meta-setting-desc.c:8219 +#: src/libnmc-setting/nm-meta-setting-desc.c:8234 msgid "PAN Identifier (<0x0000-0xffff>)" msgstr "Ідентифікатор PAN (<0x0000-0xffff>)" -#: src/libnmc-setting/nm-meta-setting-desc.c:8234 +#: src/libnmc-setting/nm-meta-setting-desc.c:8249 msgid "Page ()" msgstr "Сторінка ()" -#: src/libnmc-setting/nm-meta-setting-desc.c:8248 +#: src/libnmc-setting/nm-meta-setting-desc.c:8263 msgid "Channel ()" msgstr "Канал ()" #. *************************************************************************** -#: src/libnmc-setting/nm-meta-setting-desc.c:8383 +#: src/libnmc-setting/nm-meta-setting-desc.c:8398 msgid "6LOWPAN settings" msgstr "Параметри 6LOWPAN" -#: src/libnmc-setting/nm-meta-setting-desc.c:8384 +#: src/libnmc-setting/nm-meta-setting-desc.c:8399 msgid "802-1x settings" msgstr "Параметри 802-1x" -#: src/libnmc-setting/nm-meta-setting-desc.c:8386 +#: src/libnmc-setting/nm-meta-setting-desc.c:8401 msgid "bluetooth connection" msgstr "з'єднання bluetooth" -#: src/libnmc-setting/nm-meta-setting-desc.c:8387 +#: src/libnmc-setting/nm-meta-setting-desc.c:8402 msgid "Bond device" msgstr "Пристрій Bond" -#: src/libnmc-setting/nm-meta-setting-desc.c:8388 +#: src/libnmc-setting/nm-meta-setting-desc.c:8403 msgid "Bond port" msgstr "Пори прив'язки" -#: src/libnmc-setting/nm-meta-setting-desc.c:8389 +#: src/libnmc-setting/nm-meta-setting-desc.c:8404 msgid "Bridge device" msgstr "Пристрій містка" -#: src/libnmc-setting/nm-meta-setting-desc.c:8390 +#: src/libnmc-setting/nm-meta-setting-desc.c:8405 msgid "Bridge port" msgstr "Порт містка" -#: src/libnmc-setting/nm-meta-setting-desc.c:8391 +#: src/libnmc-setting/nm-meta-setting-desc.c:8406 msgid "CDMA mobile broadband connection" msgstr "мобільне широкосмугове з'єднання CDMA" -#: src/libnmc-setting/nm-meta-setting-desc.c:8392 +#: src/libnmc-setting/nm-meta-setting-desc.c:8407 msgid "General settings" msgstr "Загальні параметри" -#: src/libnmc-setting/nm-meta-setting-desc.c:8393 +#: src/libnmc-setting/nm-meta-setting-desc.c:8408 msgid "DCB settings" msgstr "Параметри DCB" -#: src/libnmc-setting/nm-meta-setting-desc.c:8394 +#: src/libnmc-setting/nm-meta-setting-desc.c:8409 msgid "Dummy settings" msgstr "Фіктивні параметри" -#: src/libnmc-setting/nm-meta-setting-desc.c:8395 +#: src/libnmc-setting/nm-meta-setting-desc.c:8410 msgid "Ethtool settings" msgstr "Параметри Ethtool" -#: src/libnmc-setting/nm-meta-setting-desc.c:8396 +#: src/libnmc-setting/nm-meta-setting-desc.c:8411 msgid "Generic settings" msgstr "Загальні параметри" -#: src/libnmc-setting/nm-meta-setting-desc.c:8397 +#: src/libnmc-setting/nm-meta-setting-desc.c:8412 msgid "GSM mobile broadband connection" msgstr "мобільне широкосмугове з'єднання GSM" -#: src/libnmc-setting/nm-meta-setting-desc.c:8398 +#: src/libnmc-setting/nm-meta-setting-desc.c:8413 msgid "Hostname settings" msgstr "Параметри назви вузла" -#: src/libnmc-setting/nm-meta-setting-desc.c:8400 +#: src/libnmc-setting/nm-meta-setting-desc.c:8415 msgid "IPv4 protocol" msgstr "Протокол IPv4" -#: src/libnmc-setting/nm-meta-setting-desc.c:8401 +#: src/libnmc-setting/nm-meta-setting-desc.c:8416 msgid "IPv6 protocol" msgstr "Протокол IPv6" -#: src/libnmc-setting/nm-meta-setting-desc.c:8402 +#: src/libnmc-setting/nm-meta-setting-desc.c:8417 msgid "IP-tunnel settings" msgstr "Параметри IP-тунелювання" -#: src/libnmc-setting/nm-meta-setting-desc.c:8403 -#| msgid "Ethtool settings" +#: src/libnmc-setting/nm-meta-setting-desc.c:8418 msgid "Loopback settings" msgstr "Параметри петлі" -#: src/libnmc-setting/nm-meta-setting-desc.c:8404 +#: src/libnmc-setting/nm-meta-setting-desc.c:8419 msgid "MACsec connection" msgstr "З'єднання MACsec" -#: src/libnmc-setting/nm-meta-setting-desc.c:8405 +#: src/libnmc-setting/nm-meta-setting-desc.c:8420 msgid "macvlan connection" msgstr "З'єднання MACVLAN" -#: src/libnmc-setting/nm-meta-setting-desc.c:8406 +#: src/libnmc-setting/nm-meta-setting-desc.c:8421 msgid "Match" msgstr "Відповідність" -#: src/libnmc-setting/nm-meta-setting-desc.c:8407 +#: src/libnmc-setting/nm-meta-setting-desc.c:8422 msgid "OLPC Mesh connection" msgstr "З'єднання OLPC Mesh" -#: src/libnmc-setting/nm-meta-setting-desc.c:8408 +#: src/libnmc-setting/nm-meta-setting-desc.c:8423 msgid "Open vSwitch bridge settings" msgstr "Параметри містка Open vSwitch" -#: src/libnmc-setting/nm-meta-setting-desc.c:8409 +#: src/libnmc-setting/nm-meta-setting-desc.c:8424 msgid "Open vSwitch DPDK interface settings" msgstr "Параметри інтерфейсу Open vSwitch DPDK" -#: src/libnmc-setting/nm-meta-setting-desc.c:8410 +#: src/libnmc-setting/nm-meta-setting-desc.c:8425 +msgid "OVS Other Config" +msgstr "Інші налаштування OVS" + +#: src/libnmc-setting/nm-meta-setting-desc.c:8426 msgid "OVS External IDs" msgstr "Зовнішні ідентифікатори OVS" -#: src/libnmc-setting/nm-meta-setting-desc.c:8411 +#: src/libnmc-setting/nm-meta-setting-desc.c:8427 msgid "Open vSwitch interface settings" msgstr "Параметри інтерфейсу Open vSwitch" -#: src/libnmc-setting/nm-meta-setting-desc.c:8412 +#: src/libnmc-setting/nm-meta-setting-desc.c:8428 msgid "Open vSwitch patch interface settings" msgstr "Параметри інтерфейсу латок Open vSwitch" -#: src/libnmc-setting/nm-meta-setting-desc.c:8413 +#: src/libnmc-setting/nm-meta-setting-desc.c:8429 msgid "Open vSwitch port settings" msgstr "Параметри портів Open vSwitch" -#: src/libnmc-setting/nm-meta-setting-desc.c:8414 +#: src/libnmc-setting/nm-meta-setting-desc.c:8430 msgid "PPP settings" msgstr "Параметри PPP" -#: src/libnmc-setting/nm-meta-setting-desc.c:8415 +#: src/libnmc-setting/nm-meta-setting-desc.c:8431 msgid "PPPoE" msgstr "PPPoE" -#: src/libnmc-setting/nm-meta-setting-desc.c:8416 +#: src/libnmc-setting/nm-meta-setting-desc.c:8432 msgid "Proxy" msgstr "Проксі" -#: src/libnmc-setting/nm-meta-setting-desc.c:8417 +#: src/libnmc-setting/nm-meta-setting-desc.c:8433 msgid "Serial settings" msgstr "Параметри послідовного з'єднання" -#: src/libnmc-setting/nm-meta-setting-desc.c:8418 +#: src/libnmc-setting/nm-meta-setting-desc.c:8434 msgid "SR-IOV settings" msgstr "Параметри SR-IOV" -#: src/libnmc-setting/nm-meta-setting-desc.c:8419 +#: src/libnmc-setting/nm-meta-setting-desc.c:8435 msgid "Traffic controls" msgstr "Засоби керування обміном даними" -#: src/libnmc-setting/nm-meta-setting-desc.c:8420 +#: src/libnmc-setting/nm-meta-setting-desc.c:8436 msgid "Team device" msgstr "Пристрій Team" -#: src/libnmc-setting/nm-meta-setting-desc.c:8421 +#: src/libnmc-setting/nm-meta-setting-desc.c:8437 msgid "Team port" msgstr "Порт Team" -#: src/libnmc-setting/nm-meta-setting-desc.c:8422 +#: src/libnmc-setting/nm-meta-setting-desc.c:8438 msgid "Tun device" msgstr "Пристрій TUN" -#: src/libnmc-setting/nm-meta-setting-desc.c:8423 +#: src/libnmc-setting/nm-meta-setting-desc.c:8439 msgid "User settings" msgstr "Параметри користувача" -#: src/libnmc-setting/nm-meta-setting-desc.c:8429 +#: src/libnmc-setting/nm-meta-setting-desc.c:8445 msgid "Wi-Fi P2P connection" msgstr "З'єднання P2P Wi-Fi" -#: src/libnmc-setting/nm-meta-setting-desc.c:8430 +#: src/libnmc-setting/nm-meta-setting-desc.c:8446 msgid "WiMAX connection" msgstr "З'єднання WiMAX" -#: src/libnmc-setting/nm-meta-setting-desc.c:8431 +#: src/libnmc-setting/nm-meta-setting-desc.c:8447 msgid "Wired Ethernet" msgstr "Дротовий Ethernet" -#: src/libnmc-setting/nm-meta-setting-desc.c:8432 +#: src/libnmc-setting/nm-meta-setting-desc.c:8448 msgid "WireGuard VPN settings" msgstr "Параметри VPN WireGuard" -#: src/libnmc-setting/nm-meta-setting-desc.c:8433 +#: src/libnmc-setting/nm-meta-setting-desc.c:8449 msgid "Wi-Fi connection" msgstr "З'єднання Wi-Fi" -#: src/libnmc-setting/nm-meta-setting-desc.c:8434 +#: src/libnmc-setting/nm-meta-setting-desc.c:8450 msgid "Wi-Fi security settings" msgstr "Параметри захисту Wi-Fi" -#: src/libnmc-setting/nm-meta-setting-desc.c:8435 +#: src/libnmc-setting/nm-meta-setting-desc.c:8451 msgid "WPAN settings" msgstr "Параметри WPAN" -#: src/libnmc-setting/nm-meta-setting-desc.c:8847 +#: src/libnmc-setting/nm-meta-setting-desc.c:8864 msgid "name" msgstr "назва" @@ -6438,13 +6454,6 @@ msgstr "" "параметрів (тобто «vpn» або «bridge» тощо)." #: src/libnmc-setting/settings-docs.h.in:27 -#| msgid "" -#| "The connection.uuid is the real identifier of a profile. It cannot change " -#| "and it must be unique. It is therefore often best to refer to a profile " -#| "by UUID, for example with `nmcli connection up uuid $UUID`. The UUID " -#| "cannot be changed, except in offline mode. In that case, the special " -#| "values \"new\", \"generate\" and \"\" are allowed to generate a new " -#| "random UUID." msgid "" "The connection.uuid is the real identifier of a profile. It cannot change " "and it must be unique. It is therefore often best to refer to a profile by " @@ -6723,7 +6732,7 @@ msgstr "" #: src/libnmc-setting/settings-docs.h.in:81 #: src/libnmc-setting/settings-docs.h.in:123 #: src/libnmc-setting/settings-docs.h.in:148 -#: src/libnmc-setting/settings-docs.h.in:286 +#: src/libnmc-setting/settings-docs.h.in:290 msgid "Flags indicating how to handle the \"password\" property." msgstr "Прапорці, які позначають, як обробляти властивість «password»." @@ -7838,7 +7847,20 @@ msgstr "" "основною." #: src/libnmc-setting/settings-docs.h.in:160 -#: src/libnmc-setting/settings-docs.h.in:188 +#: src/libnmc-setting/settings-docs.h.in:189 +msgid "" +"VPN connections will default to add the route automatically unless this " +"setting is set to FALSE. For other connection types, adding such an " +"automatic route is currently not supported and setting this to TRUE has no " +"effect." +msgstr "" +"Типово, для з'єднань VPN маршрут додаватиметься автоматично, якщо для цього" +" параметра не встановлено значення FALSE. Для інших типів з'єднань підтримки" +" додавання такого автоматичного маршруту у поточній версії не передбачено і" +" встановлення для цього параметра значення TRUE ні на що не вплине." + +#: src/libnmc-setting/settings-docs.h.in:161 +#: src/libnmc-setting/settings-docs.h.in:190 msgid "" "Timeout in milliseconds used to check for the presence of duplicate IP " "addresses on the network. If an address conflict is detected, the " @@ -7855,7 +7877,7 @@ msgstr "" "перевищує нуль, вважатиметься часом очікування у мілісекундах. Цю " "властивість у поточній версії реалізовано лише для IPv4." -#: src/libnmc-setting/settings-docs.h.in:161 +#: src/libnmc-setting/settings-docs.h.in:162 msgid "" "A string sent to the DHCP server to identify the local machine which the " "DHCP server may use to customize the DHCP lease and options. When the " @@ -7905,7 +7927,7 @@ msgstr "" "використано загальне типове налаштоване значення. Якщо і це значення не " "налаштовано, типове значення залежатиме від додатка DHCP." -#: src/libnmc-setting/settings-docs.h.in:162 +#: src/libnmc-setting/settings-docs.h.in:163 msgid "" "If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will " "be sent to the DHCP server when acquiring a lease. This property and \"dhcp-" @@ -7915,8 +7937,8 @@ msgstr "" "адреси до сервера DHCP буде надіслано вказану FDQN. Цю властивість не можна " "використовувати разом із властивістю «dhcp-hostname»." -#: src/libnmc-setting/settings-docs.h.in:163 -#: src/libnmc-setting/settings-docs.h.in:190 +#: src/libnmc-setting/settings-docs.h.in:164 +#: src/libnmc-setting/settings-docs.h.in:192 msgid "" "If the \"dhcp-send-hostname\" property is TRUE, then the specified name will " "be sent to the DHCP server when acquiring a lease. This property and \"dhcp-" @@ -7926,8 +7948,8 @@ msgstr "" "адреси до сервера DHCP буде надіслано вказану назву. Цю властивість не можна " "використовувати разом із властивістю «dhcp-fqdn»." -#: src/libnmc-setting/settings-docs.h.in:164 -#: src/libnmc-setting/settings-docs.h.in:191 +#: src/libnmc-setting/settings-docs.h.in:165 +#: src/libnmc-setting/settings-docs.h.in:193 msgid "" "Flags for the DHCP hostname and FQDN. Currently, this property only includes " "flags to control the FQDN flags set in the DHCP FQDN option. Supported FQDN " @@ -7964,8 +7986,8 @@ msgstr "" "NM_DHCP_HOSTNAME_FLAG_NONE (0x0), у запитах DHCP надсилатимуться стандартні " "прапорці FQDN, описані вище." -#: src/libnmc-setting/settings-docs.h.in:165 -#: src/libnmc-setting/settings-docs.h.in:192 +#: src/libnmc-setting/settings-docs.h.in:166 +#: src/libnmc-setting/settings-docs.h.in:194 msgid "" "A string containing the \"Identity Association Identifier\" (IAID) used by " "the DHCP client. The property is a 32-bit decimal value or a special value " @@ -7994,8 +8016,8 @@ msgstr "" "буде проігноровано у dhclient, який завжди визначає IAID на основі MAC-" "адреси." -#: src/libnmc-setting/settings-docs.h.in:166 -#: src/libnmc-setting/settings-docs.h.in:193 +#: src/libnmc-setting/settings-docs.h.in:167 +#: src/libnmc-setting/settings-docs.h.in:195 msgid "" "Array of servers from which DHCP offers must be rejected. This property is " "useful to avoid getting a lease from misconfigured or rogue servers. For " @@ -8010,8 +8032,8 @@ msgstr "" "\"192.168.122.0/24\"). У поточній версії цю властивість не реалізовано для " "DHCPv6." -#: src/libnmc-setting/settings-docs.h.in:167 -#: src/libnmc-setting/settings-docs.h.in:194 +#: src/libnmc-setting/settings-docs.h.in:168 +#: src/libnmc-setting/settings-docs.h.in:196 msgid "" "If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some " "DHCP servers use this hostname to update DNS databases, essentially " @@ -8026,8 +8048,8 @@ msgstr "" "властивості вказано значення TRUE, буде надіслано поточну стану назву вузла " "комп'ютера." -#: src/libnmc-setting/settings-docs.h.in:168 -#: src/libnmc-setting/settings-docs.h.in:195 +#: src/libnmc-setting/settings-docs.h.in:169 +#: src/libnmc-setting/settings-docs.h.in:197 msgid "" "A timeout for a DHCP transaction in seconds. If zero (the default), a " "globally configured default is used. If still unspecified, a device specific " @@ -8041,13 +8063,7 @@ msgstr "" "секунд). Встановіть значення 2147483647 (MAXINT32), якщо час очікування має " "бути необмеженим." -#: src/libnmc-setting/settings-docs.h.in:169 -#| msgid "" -#| "The Vendor Class Identifier DHCP option (60). Special characters in the " -#| "data string may be escaped using C-style escapes, nevertheless this " -#| "property cannot contain nul bytes. If the per-profile value is " -#| "unspecified (the default), a global connection default gets consulted. If " -#| "still unspecified, the DHCP option is not sent to the server. Since 1.28" +#: src/libnmc-setting/settings-docs.h.in:170 msgid "" "The Vendor Class Identifier DHCP option (60). Special characters in the data " "string may be escaped using C-style escapes, nevertheless this property " @@ -8063,19 +8079,19 @@ msgstr "" "визначити значення властивості, цей параметр DHCP не буде надіслано на " "сервер." -#: src/libnmc-setting/settings-docs.h.in:170 -#: src/libnmc-setting/settings-docs.h.in:196 +#: src/libnmc-setting/settings-docs.h.in:171 +#: src/libnmc-setting/settings-docs.h.in:198 msgid "" "Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server " "name can be specified by appending \"#example.com\" to the IP address of the " "DNS server. This currently only has effect when using systemd-resolved." msgstr "" -"Масив IP-адрес серверів DNS. Для DoT (DNS over TLS) може бути вказано назву" -" сервера SNI дописуванням «#example.com» до IP-адреси сервера DNS. У" -" поточній версії це працює лише при використанні systemd-resolved." +"Масив IP-адрес серверів DNS. Для DoT (DNS over TLS) може бути вказано назву " +"сервера SNI дописуванням «#example.com» до IP-адреси сервера DNS. У поточній " +"версії це працює лише при використанні systemd-resolved." -#: src/libnmc-setting/settings-docs.h.in:171 -#: src/libnmc-setting/settings-docs.h.in:197 +#: src/libnmc-setting/settings-docs.h.in:172 +#: src/libnmc-setting/settings-docs.h.in:199 msgid "" "Array of DNS options as described in man 5 resolv.conf. NULL means that the " "options are unset and left at the default. In this case NetworkManager will " @@ -8102,8 +8118,8 @@ msgstr "" "кешуванням (dnsmasq або systemd-resolved у NetworkManager.conf), «edns0» і " "«trust-ad» буде додано автоматично." -#: src/libnmc-setting/settings-docs.h.in:172 -#: src/libnmc-setting/settings-docs.h.in:198 +#: src/libnmc-setting/settings-docs.h.in:173 +#: src/libnmc-setting/settings-docs.h.in:200 msgid "" "DNS servers priority. The relative priority for DNS servers specified by " "this setting. A lower numerical value is better (higher priority). Negative " @@ -8184,8 +8200,8 @@ msgstr "" "небажаних витоків DNS належним налаштовування пріоритетностей DNS та доменів " "пошуку, так, щоб було налаштовано лише сервери назв бажаного інтерфейсу." -#: src/libnmc-setting/settings-docs.h.in:173 -#: src/libnmc-setting/settings-docs.h.in:199 +#: src/libnmc-setting/settings-docs.h.in:174 +#: src/libnmc-setting/settings-docs.h.in:201 msgid "" "List of DNS search domains. Domains starting with a tilde ('~') are " "considered 'routing' domains and are used only to decide the interface over " @@ -8214,8 +8230,8 @@ msgstr "" "auto-dns». Зауважте, що якщо не налаштовано пошуки DNS, резервне значення " "буде похідним від домену з DHCP (варіант 15)." -#: src/libnmc-setting/settings-docs.h.in:174 -#: src/libnmc-setting/settings-docs.h.in:200 +#: src/libnmc-setting/settings-docs.h.in:175 +#: src/libnmc-setting/settings-docs.h.in:202 msgid "" "The gateway associated with this configuration. This is only meaningful if " "\"addresses\" is also set. Setting the gateway causes NetworkManager to " @@ -8236,8 +8252,8 @@ msgstr "" "тому, зазвичай, її не слід встановлювати у цьому випадку. Див. «ip4-auto-" "default-route»." -#: src/libnmc-setting/settings-docs.h.in:175 -#: src/libnmc-setting/settings-docs.h.in:201 +#: src/libnmc-setting/settings-docs.h.in:176 +#: src/libnmc-setting/settings-docs.h.in:203 msgid "" "When \"method\" is set to \"auto\" and this property to TRUE, automatically " "configured name servers and search domains are ignored and only name servers " @@ -8250,8 +8266,8 @@ msgstr "" "пошуку, вказані за допомогою властивостей «dns» і «dns-search», якщо буде " "вказано якісь записи серверів і доменів для цих властивостей." -#: src/libnmc-setting/settings-docs.h.in:176 -#: src/libnmc-setting/settings-docs.h.in:202 +#: src/libnmc-setting/settings-docs.h.in:177 +#: src/libnmc-setting/settings-docs.h.in:204 msgid "" "When \"method\" is set to \"auto\" and this property to TRUE, automatically " "configured routes are ignored and only routes specified in the \"routes\" " @@ -8262,16 +8278,7 @@ msgstr "" "використовуватимуться лише маршрути, вказані за допомогою властивості " "«routes», якщо такі існують." -#: src/libnmc-setting/settings-docs.h.in:177 -#| msgid "" -#| "Enable and disable the IPv4 link-local configuration independently of the " -#| "ipv4.method configuration. This allows a link-local address (169.254.x." -#| "y/16) to be obtained in addition to other addresses, such as those " -#| "manually configured or obtained from a DHCP server. When set to \"auto\", " -#| "the value is dependent on \"ipv4.method\". When set to \"default\", it " -#| "honors the global connection default, before falling back to \"auto\". " -#| "Note that if \"ipv4.method\" is \"disabled\", then link local addressing " -#| "is always disabled too. The default is \"default\". Since 1.40" +#: src/libnmc-setting/settings-docs.h.in:178 msgid "" "Enable and disable the IPv4 link-local configuration independently of the " "ipv4.method configuration. This allows a link-local address (169.254.x.y/16) " @@ -8291,8 +8298,8 @@ msgstr "" "«auto». Зауважте, що якщо значенням «ipv4.method» є «disabled», також буде " "вимкнено адресування link-local. Типовим значенням є «default»." -#: src/libnmc-setting/settings-docs.h.in:178 -#: src/libnmc-setting/settings-docs.h.in:204 +#: src/libnmc-setting/settings-docs.h.in:179 +#: src/libnmc-setting/settings-docs.h.in:206 msgid "" "If TRUE, allow overall network configuration to proceed even if the " "configuration specified by this property times out. Note that at least one " @@ -8309,8 +8316,8 @@ msgstr "" "NMSettingIP4Config уможливлює успішне налаштовування усієї мережі, якщо не " "вдається налаштувати IPv4, але IPv6 налаштовано успішно." -#: src/libnmc-setting/settings-docs.h.in:179 -#: src/libnmc-setting/settings-docs.h.in:205 +#: src/libnmc-setting/settings-docs.h.in:180 +#: src/libnmc-setting/settings-docs.h.in:207 msgid "" "IP configuration method. NMSettingIP4Config and NMSettingIP6Config both " "support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the " @@ -8339,8 +8346,8 @@ msgstr "" "налаштовано на інтерфейсі, який надає спільний доступ до інтернету для " "підмережі, а не на з'єднанні, яке надається у спільний доступ." -#: src/libnmc-setting/settings-docs.h.in:180 -#: src/libnmc-setting/settings-docs.h.in:207 +#: src/libnmc-setting/settings-docs.h.in:181 +#: src/libnmc-setting/settings-docs.h.in:209 msgid "" "If TRUE, this connection will never be the default connection for this IP " "type, meaning it will never be assigned the default route by NetworkManager." @@ -8349,8 +8356,8 @@ msgstr "" "IP, що означає, що його ніколи не буде пов'язано із типовим маршрутом у " "NetworkManager." -#: src/libnmc-setting/settings-docs.h.in:181 -#: src/libnmc-setting/settings-docs.h.in:209 +#: src/libnmc-setting/settings-docs.h.in:182 +#: src/libnmc-setting/settings-docs.h.in:211 msgid "" "The minimum time interval in milliseconds for which dynamic IP configuration " "should be tried before the connection succeeds. This property is useful for " @@ -8379,8 +8386,8 @@ msgstr "" "означає типове значення (або пріоритетне значення налаштування ipvx.required-" "timeout, або нуль)." -#: src/libnmc-setting/settings-docs.h.in:182 -#: src/libnmc-setting/settings-docs.h.in:210 +#: src/libnmc-setting/settings-docs.h.in:183 +#: src/libnmc-setting/settings-docs.h.in:212 msgid "" "The default metric for routes that don't explicitly specify a metric. The " "default value -1 means that the metric is chosen automatically based on the " @@ -8400,8 +8407,8 @@ msgstr "" "насправді означає, що встановлено значення 1024. Для IPv4 нуль є звичайним " "значенням для метрики." -#: src/libnmc-setting/settings-docs.h.in:183 -#: src/libnmc-setting/settings-docs.h.in:211 +#: src/libnmc-setting/settings-docs.h.in:184 +#: src/libnmc-setting/settings-docs.h.in:213 msgid "" "Enable policy routing (source routing) and set the routing table used when " "adding routes. This affects all routes, including device-routes, IPv4LL, " @@ -8433,7 +8440,7 @@ msgstr "" "таблиці. Так зроблено, щоб зберегти зворотну сумісність для користувачів, " "які змінюють таблиці маршрутизації з-поза меж NetworkManager." -#: src/libnmc-setting/settings-docs.h.in:184 +#: src/libnmc-setting/settings-docs.h.in:185 msgid "" "A list of IPv4 destination addresses, prefix length, optional IPv4 next hop " "addresses, optional route metric, optional attribute. The valid syntax is: " @@ -8446,13 +8453,13 @@ msgstr "" "[атрибут=значення]...[,ip[/префікс]...]\". Приклад: \"192.0.2.0/24 10.1.1.1 " "77, 198.51.100.0/24\"." -#: src/libnmc-setting/settings-docs.h.in:185 -#: src/libnmc-setting/settings-docs.h.in:213 +#: src/libnmc-setting/settings-docs.h.in:186 +#: src/libnmc-setting/settings-docs.h.in:215 msgid "A comma separated list of routing rules for policy routing." msgstr "" "Список відокремлених комами правил маршрутизації для розподілу правил." -#: src/libnmc-setting/settings-docs.h.in:186 +#: src/libnmc-setting/settings-docs.h.in:187 msgid "" "Configure method for creating the address for use with RFC4862 IPv6 " "Stateless Address Autoconfiguration. The permitted values are: " @@ -8508,7 +8515,7 @@ msgstr "" "налаштовуються властивістю «ip6-privacy», і не впливає на тимчасові адреси, " "які налаштовано за допомогою відповідної властивості." -#: src/libnmc-setting/settings-docs.h.in:187 +#: src/libnmc-setting/settings-docs.h.in:188 msgid "" "A list of IPv6 addresses and their prefix length. Multiple addresses can be " "separated by comma. For example \"2001:db8:85a3::8a2e:370:7334/64, 2001:" @@ -8522,7 +8529,7 @@ msgstr "" "тобто перша адреса буде основною. Це може вплинути на вибір початкової " "адреси при використанні IPv6 (RFC 6724, розділ 5)." -#: src/libnmc-setting/settings-docs.h.in:189 +#: src/libnmc-setting/settings-docs.h.in:191 msgid "" "A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp " "client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried " @@ -8579,7 +8586,7 @@ msgstr "" "використано загальне значення для «ipv6.dhcp-duid». Якщо загальне значення " "не вказано, буде використано типове значення «lease»." -#: src/libnmc-setting/settings-docs.h.in:203 +#: src/libnmc-setting/settings-docs.h.in:205 msgid "" "Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If " "enabled, it makes the kernel generate a temporary IPv6 address in addition " @@ -8610,7 +8617,7 @@ msgstr "" "увімкнено за допомогою параметра «stable-privacy» властивості «addr-gen-" "mode», як інший спосіб уникнути стеження за вузлом за допомогою адрес IPv6." -#: src/libnmc-setting/settings-docs.h.in:206 +#: src/libnmc-setting/settings-docs.h.in:208 msgid "" "Maximum transmission unit size, in bytes. If zero (the default), the MTU is " "set automatically from router advertisements or is left equal to the link-" @@ -8623,7 +8630,7 @@ msgstr "" "перевищує значення MTU шару зв'язку або є більшим за нуль, але меншим за " "мінімальний MTU IPv6, 1280, це значення враховано не буде." -#: src/libnmc-setting/settings-docs.h.in:208 +#: src/libnmc-setting/settings-docs.h.in:210 msgid "" "A timeout for waiting Router Advertisements in seconds. If zero (the " "default), a globally configured default is used. If still unspecified, the " @@ -8636,11 +8643,11 @@ msgstr "" "залежатиме від параметрів sysctl пристрою. Встановіть значення 2147483647 " "(MAXINT32), якщо час очікування має бути необмеженим." -#: src/libnmc-setting/settings-docs.h.in:212 +#: src/libnmc-setting/settings-docs.h.in:214 msgid "Array of IP routes." msgstr "Масив IP-маршрутів." -#: src/libnmc-setting/settings-docs.h.in:214 +#: src/libnmc-setting/settings-docs.h.in:216 msgid "" "Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 " "tokenized interface identifiers. Useful with eui64 addr-gen-mode." @@ -8649,7 +8656,7 @@ msgstr "" "chown-6man-tokenised-ipv6-identifiers-02. Корисне у поєднанні зі значення " "addr-gen-mode eui64." -#: src/libnmc-setting/settings-docs.h.in:215 +#: src/libnmc-setting/settings-docs.h.in:217 msgid "" "How many additional levels of encapsulation are permitted to be prepended to " "packets. This property applies only to IPv6 tunnels." @@ -8657,7 +8664,7 @@ msgstr "" "Кількість додаткових рівнів вкладеності, які дозволено дописувати до " "пакетів. Цю властивість стосується лише тунелів IPv6." -#: src/libnmc-setting/settings-docs.h.in:216 +#: src/libnmc-setting/settings-docs.h.in:218 msgid "" "Tunnel flags. Currently, the following values are supported: " "NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT (0x1), " @@ -8675,25 +8682,22 @@ msgstr "" "(0x10), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). Ці значення є " "коректними лише для тунелів IPv6." -#: src/libnmc-setting/settings-docs.h.in:217 +#: src/libnmc-setting/settings-docs.h.in:219 msgid "" "The flow label to assign to tunnel packets. This property applies only to " "IPv6 tunnels." msgstr "" "Мітка потоку для пакетів тунелю. Ця властивість стосується лише тунелів IPv6." -#: src/libnmc-setting/settings-docs.h.in:218 -#| msgid "" -#| "The flow label to assign to tunnel packets. This property applies only to " -#| "IPv6 tunnels." +#: src/libnmc-setting/settings-docs.h.in:220 msgid "" "The fwmark value to assign to tunnel packets. This property can be set to a " "non zero value only on VTI and VTI6 tunnels." msgstr "" -"Значення fwmark для прив'язки до пакетів тунелю. Для цієї властивості можна" -" встановлювати ненульове значення лише для тунелів VTI та VTI6." +"Значення fwmark для прив'язки до пакетів тунелю. Для цієї властивості можна " +"встановлювати ненульове значення лише для тунелів VTI та VTI6." -#: src/libnmc-setting/settings-docs.h.in:219 +#: src/libnmc-setting/settings-docs.h.in:221 msgid "" "The key used for tunnel input packets; the property is valid only for " "certain tunnel modes (GRE, IP6GRE). If empty, no key is used." @@ -8702,7 +8706,7 @@ msgstr "" "лише для певних режимів роботи тунелю (GRE, IP6GRE). Якщо порожній, ключ не " "використовується." -#: src/libnmc-setting/settings-docs.h.in:220 +#: src/libnmc-setting/settings-docs.h.in:222 msgid "" "The local endpoint of the tunnel; the value can be empty, otherwise it must " "contain an IPv4 or IPv6 address." @@ -8710,7 +8714,7 @@ msgstr "" "Локальна кінцева точка тунелю; значення може бути порожнім або має містити " "адресу IPv4 або IPv6." -#: src/libnmc-setting/settings-docs.h.in:221 +#: src/libnmc-setting/settings-docs.h.in:223 msgid "" "The tunneling mode, for example NM_IP_TUNNEL_MODE_IPIP (1) or " "NM_IP_TUNNEL_MODE_GRE (2)." @@ -8718,7 +8722,7 @@ msgstr "" "Режим тунелювання, наприклад NM_IP_TUNNEL_MODE_IPIP (1) або " "NM_IP_TUNNEL_MODE_GRE (2)." -#: src/libnmc-setting/settings-docs.h.in:222 +#: src/libnmc-setting/settings-docs.h.in:224 msgid "" "If non-zero, only transmit packets of the specified size or smaller, " "breaking larger packets up into multiple fragments." @@ -8726,7 +8730,7 @@ msgstr "" "Якщо має ненульове значення, передавати пакети лише вказаного або меншого " "розміру, розбиваючи великі пакети на декілька фрагментів." -#: src/libnmc-setting/settings-docs.h.in:223 +#: src/libnmc-setting/settings-docs.h.in:225 msgid "" "The key used for tunnel output packets; the property is valid only for " "certain tunnel modes (GRE, IP6GRE). If empty, no key is used." @@ -8735,7 +8739,7 @@ msgstr "" "чинною лише для певних режимів роботи тунелю (GRE, IP6GRE). Якщо порожній, " "ключ не використовується." -#: src/libnmc-setting/settings-docs.h.in:224 +#: src/libnmc-setting/settings-docs.h.in:226 msgid "" "If given, specifies the parent interface name or parent connection UUID the " "new device will be bound to so that tunneled packets will only be routed via " @@ -8745,18 +8749,18 @@ msgstr "" "з'єднання, до якого буде прив'язано новий пристрій так, що тунельовані " "пакети маршрутизуватимуться лише крізь цей інтерфейс." -#: src/libnmc-setting/settings-docs.h.in:225 +#: src/libnmc-setting/settings-docs.h.in:227 msgid "Whether to enable Path MTU Discovery on this tunnel." msgstr "Визначає, чи слід вмикати Path MTU Discovery для цього тунелю." -#: src/libnmc-setting/settings-docs.h.in:226 +#: src/libnmc-setting/settings-docs.h.in:228 msgid "" "The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 " "address." msgstr "" "Віддалена кінцева точка тунелю; значення має містити адресу IPv4 або IPv6." -#: src/libnmc-setting/settings-docs.h.in:227 +#: src/libnmc-setting/settings-docs.h.in:229 msgid "" "The type of service (IPv4) or traffic class (IPv6) field to be set on " "tunneled packets." @@ -8764,7 +8768,7 @@ msgstr "" "Поле типу служби (IPv4) або класу передавання даних (IPv6), яке слід " "встановити для тунельованих пакетів." -#: src/libnmc-setting/settings-docs.h.in:228 +#: src/libnmc-setting/settings-docs.h.in:230 msgid "" "The TTL to assign to tunneled packets. 0 is a special value meaning that " "packets inherit the TTL value." @@ -8772,14 +8776,11 @@ msgstr "" "Значення TTL, яке слід призначити для тунельованих пакетів. 0 — спеціальне " "значення, яке означає, що пакети успадковують значення TTL." -#: src/libnmc-setting/settings-docs.h.in:229 +#: src/libnmc-setting/settings-docs.h.in:231 msgid "Whether the transmitted traffic must be encrypted." msgstr "Визначає, чи слід шифрувати дані, які передаються." -#: src/libnmc-setting/settings-docs.h.in:230 -#| msgid "" -#| "The pre-shared CAK (Connectivity Association Key) for MACsec Key " -#| "Agreement." +#: src/libnmc-setting/settings-docs.h.in:232 msgid "" "The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement. " "Must be a string of 32 hexadecimal characters." @@ -8787,24 +8788,21 @@ msgstr "" "Попереднього поширений CAK (ключ прив'язки з'єднань) для узгодження ключів " "MACsec. Має бути рядком з 32 шістнадцяткових цифр." -#: src/libnmc-setting/settings-docs.h.in:231 +#: src/libnmc-setting/settings-docs.h.in:233 msgid "Flags indicating how to handle the \"mka-cak\" property." msgstr "Прапорці, які позначають, як обробляти властивість «mka-cak»." -#: src/libnmc-setting/settings-docs.h.in:232 -#| msgid "" -#| "The pre-shared CKN (Connectivity-association Key Name) for MACsec Key " -#| "Agreement." +#: src/libnmc-setting/settings-docs.h.in:234 msgid "" "The pre-shared CKN (Connectivity-association Key Name) for MACsec Key " "Agreement. Must be a string of hexadecimal characters with a even length " "between 2 and 64." msgstr "" "Попереднього поширена CKN (назва ключа ключ прив'язки з'єднань) для " -"узгодження ключів MACsec. Має бути рядком з шістнадцяткових цифр парної" -" довжини від 2 до 64 символів." +"узгодження ключів MACsec. Має бути рядком з шістнадцяткових цифр парної " +"довжини від 2 до 64 символів." -#: src/libnmc-setting/settings-docs.h.in:233 +#: src/libnmc-setting/settings-docs.h.in:235 msgid "" "Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key " "Agreement) is obtained." @@ -8812,7 +8810,7 @@ msgstr "" "Визначає спосіб отримання CAK (ключа прив'язки з'єднань) для MKA (узгодження " "ключів MACsec)." -#: src/libnmc-setting/settings-docs.h.in:234 +#: src/libnmc-setting/settings-docs.h.in:236 msgid "" "If given, specifies the parent interface name or parent connection UUID from " "which this MACSEC interface should be created. If this property is not " @@ -8824,7 +8822,7 @@ msgstr "" "значення для цієї властивості не вказано, запис з'єднання має містити " "параметр «802-3-ethernet» із властивістю «mac-address»." -#: src/libnmc-setting/settings-docs.h.in:235 +#: src/libnmc-setting/settings-docs.h.in:237 msgid "" "The port component of the SCI (Secure Channel Identifier), between 1 and " "65534." @@ -8832,18 +8830,18 @@ msgstr "" "Компонент порту SCI (ідентифікатора безпечного каналу), значення від 1 до " "65534." -#: src/libnmc-setting/settings-docs.h.in:236 +#: src/libnmc-setting/settings-docs.h.in:238 msgid "" "Specifies whether the SCI (Secure Channel Identifier) is included in every " "packet." msgstr "" "Вказує, чи включено SCI (Secure Channel Identifier) до кожного пакета." -#: src/libnmc-setting/settings-docs.h.in:237 +#: src/libnmc-setting/settings-docs.h.in:239 msgid "Specifies the validation mode for incoming frames." msgstr "Визначає режим перевірки для вхідних кадрів." -#: src/libnmc-setting/settings-docs.h.in:238 +#: src/libnmc-setting/settings-docs.h.in:240 msgid "" "The macvlan mode, which specifies the communication mechanism between " "multiple macvlans on the same lower device." @@ -8851,7 +8849,7 @@ msgstr "" "Режим macvlan, який визначає механізм обміну даними між декількома macvlan " "на одному пристрої нижнього рівня." -#: src/libnmc-setting/settings-docs.h.in:239 +#: src/libnmc-setting/settings-docs.h.in:241 msgid "" "If given, specifies the parent interface name or parent connection UUID from " "which this MAC-VLAN interface should be created. If this property is not " @@ -8863,15 +8861,15 @@ msgstr "" "значення для цієї властивості не вказано, запис з'єднання має містити " "параметр «802-3-ethernet» із властивістю «mac-address»." -#: src/libnmc-setting/settings-docs.h.in:240 +#: src/libnmc-setting/settings-docs.h.in:242 msgid "Whether the interface should be put in promiscuous mode." msgstr "Визначає, чи слід переводити інтерфейс у нерозбірливий режим." -#: src/libnmc-setting/settings-docs.h.in:241 +#: src/libnmc-setting/settings-docs.h.in:243 msgid "Whether the interface should be a MACVTAP." msgstr "Визначає, чи має бути інтерфейс інтерфейсом MACVTAP." -#: src/libnmc-setting/settings-docs.h.in:242 +#: src/libnmc-setting/settings-docs.h.in:244 msgid "" "A list of driver names to match. Each element is a shell wildcard pattern. " "See NMSettingMatch:interface-name for how special characters '|', '&', '!' " @@ -8884,7 +8882,7 @@ msgstr "" "символами — «|», «&», «!» та «\\» — для визначення необов'язкових і " "обов'язкових відповідностей та інвертування взірців." -#: src/libnmc-setting/settings-docs.h.in:243 +#: src/libnmc-setting/settings-docs.h.in:245 msgid "" "A list of interface names to match. Each element is a shell wildcard " "pattern. An element can be prefixed with a pipe symbol (|) or an ampersand " @@ -8916,7 +8914,7 @@ msgstr "" "початку взірця. Наприклад, «&\\!a» є обов'язковою умовою для встановлення " "відповідності рядку «!a»." -#: src/libnmc-setting/settings-docs.h.in:244 +#: src/libnmc-setting/settings-docs.h.in:246 msgid "" "A list of kernel command line arguments to match. This may be used to check " "whether a specific kernel command line option is set (or unset, if prefixed " @@ -8941,7 +8939,7 @@ msgstr "" "«&», «!» та «\\» — для визначення необов'язкових і обов'язкових " "відповідностей та інвертування взірців." -#: src/libnmc-setting/settings-docs.h.in:245 +#: src/libnmc-setting/settings-docs.h.in:247 msgid "" "A list of paths to match against the ID_PATH udev property of devices. " "ID_PATH represents the topological persistent path of a device. It typically " @@ -8969,11 +8967,11 @@ msgstr "" "«\\» — для визначення необов'язкових і обов'язкових відповідностей та " "інвертування взірців." -#: src/libnmc-setting/settings-docs.h.in:246 +#: src/libnmc-setting/settings-docs.h.in:248 msgid "Channel on which the mesh network to join is located." msgstr "Канал, на якому розташовано мережу mesh, до якої слід долучитися." -#: src/libnmc-setting/settings-docs.h.in:247 +#: src/libnmc-setting/settings-docs.h.in:249 msgid "" "Anycast DHCP MAC address used when requesting an IP address via DHCP. The " "specific anycast address used determines which DHCP server class answers the " @@ -8985,39 +8983,39 @@ msgstr "" "відповідатиме на запит. У поточній версії реалізовано лише у додатку DHCP до " "dhclient." -#: src/libnmc-setting/settings-docs.h.in:248 +#: src/libnmc-setting/settings-docs.h.in:250 msgid "SSID of the mesh network to join." msgstr "SSID мережі mesh, до якої слід долучитися." -#: src/libnmc-setting/settings-docs.h.in:249 +#: src/libnmc-setting/settings-docs.h.in:251 msgid "The data path type. One of \"system\", \"netdev\" or empty." msgstr "" "Тип шляху до даних. Одне з таких значень: «system», «netdev» або порожнє " "значення." -#: src/libnmc-setting/settings-docs.h.in:250 +#: src/libnmc-setting/settings-docs.h.in:252 msgid "The bridge failure mode. One of \"secure\", \"standalone\" or empty." msgstr "" "Режим відмови містка. Одне з таких значень: «secure», «standalone» або " "порожнє значення." -#: src/libnmc-setting/settings-docs.h.in:251 +#: src/libnmc-setting/settings-docs.h.in:253 msgid "Enable or disable multicast snooping." msgstr "Увімкнути або вимкнути переставляння універсальної трансляції." -#: src/libnmc-setting/settings-docs.h.in:252 +#: src/libnmc-setting/settings-docs.h.in:254 msgid "Enable or disable RSTP." msgstr "Увімкнути або вимкнути RSTP." -#: src/libnmc-setting/settings-docs.h.in:253 +#: src/libnmc-setting/settings-docs.h.in:255 msgid "Enable or disable STP." msgstr "Увімкнути або вимкнути STP." -#: src/libnmc-setting/settings-docs.h.in:254 +#: src/libnmc-setting/settings-docs.h.in:256 msgid "Open vSwitch DPDK device arguments." msgstr "Параметри пристрою Open vSwitch DPDK." -#: src/libnmc-setting/settings-docs.h.in:255 +#: src/libnmc-setting/settings-docs.h.in:257 msgid "" "Open vSwitch DPDK number of rx queues. Defaults to zero which means to leave " "the parameter in OVS unspecified and effectively configures one queue." @@ -9026,7 +9024,41 @@ msgstr "" "значення, що означає «лишити цей параметр в OVS невизначеним і, власне, " "налаштувати одну чергу»." -#: src/libnmc-setting/settings-docs.h.in:256 +#: src/libnmc-setting/settings-docs.h.in:258 +#| msgid "" +#| "Open vSwitch DPDK number of rx queues. Defaults to zero which means to " +#| "leave the parameter in OVS unspecified and effectively configures one " +#| "queue." +msgid "" +"The rx queue size (number of rx descriptors) for DPDK ports. Must be zero or " +"a power of 2 between 1 and 4096, and supported by the hardware. Defaults to " +"zero which means to leave the parameter in OVS unspecified and effectively " +"configures 2048 descriptors." +msgstr "" +"Розмір черги приймання (кількість rx-дескрипторів) для портів DPDK. Має бути" +" нульовим або степенем 2 від 1 до 4096 і підтримуваним обладнанням. Типовим" +" є нульове " +"значення, що означає «лишити цей параметр в OVS невизначеним і, власне, " +"налаштувати 2048 дескрипторів»." + +#: src/libnmc-setting/settings-docs.h.in:259 +#| msgid "" +#| "Open vSwitch DPDK number of rx queues. Defaults to zero which means to " +#| "leave the parameter in OVS unspecified and effectively configures one " +#| "queue." +msgid "" +"The tx queue size (number of tx descriptors) for DPDK ports. Must be zero or " +"a power of 2 between 1 and 4096, and supported by the hardware. Defaults to " +"zero which means to leave the parameter in OVS unspecified and effectively " +"configures 2048 descriptors." +msgstr "" +"Розмір черги передавання (кількість tx-дескрипторів) для портів DPDK. Має" +" бути нульовим або степенем 2 від 1 до 4096 і підтримуваним обладнанням." +" Типовим є нульове " +"значення, що означає «лишити цей параметр в OVS невизначеним і, власне, " +"налаштувати 2048 дескрипторів»." + +#: src/libnmc-setting/settings-docs.h.in:260 msgid "" "Open vSwitch openflow port number. Defaults to zero which means that port " "number will not be specified and it will be chosen randomly by ovs. OpenFlow " @@ -9041,7 +9073,7 @@ msgstr "" "Комутатори OpenFlow встановлюють з'єднання між собою за допомогою власних " "портів OpenFlow." -#: src/libnmc-setting/settings-docs.h.in:257 +#: src/libnmc-setting/settings-docs.h.in:261 msgid "" "The interface type. Either \"internal\", \"system\", \"patch\", \"dpdk\", or " "empty." @@ -9049,7 +9081,7 @@ msgstr "" "Тип інтерфейсу. Рядок «internal», «system», «patch», «dpdk» або порожній " "рядок." -#: src/libnmc-setting/settings-docs.h.in:258 +#: src/libnmc-setting/settings-docs.h.in:262 msgid "" "Specifies the name of the interface for the other side of the patch. The " "patch on the other side must also set this interface as peer." @@ -9058,44 +9090,40 @@ msgstr "" "з'єднання на іншому боці також має встановлювати цей інтерфейс як " "однорівневий вузол." -#: src/libnmc-setting/settings-docs.h.in:259 +#: src/libnmc-setting/settings-docs.h.in:263 msgid "The time port must be inactive in order to be considered down." msgstr "Щоб вважатися вимкненим, порт часу має бути неактивним." -#: src/libnmc-setting/settings-docs.h.in:260 +#: src/libnmc-setting/settings-docs.h.in:264 msgid "" "Bonding mode. One of \"active-backup\", \"balance-slb\", or \"balance-tcp\"." msgstr "" "Режим прив'язування. Одне з таких значень: «active-backup», «balance-slb» " "або «balance-tcp»." -#: src/libnmc-setting/settings-docs.h.in:261 +#: src/libnmc-setting/settings-docs.h.in:265 msgid "The time port must be active before it starts forwarding traffic." msgstr "Щоб почати переспрямовувати дані, слід активувати порт часу." -#: src/libnmc-setting/settings-docs.h.in:262 +#: src/libnmc-setting/settings-docs.h.in:266 msgid "LACP mode. One of \"active\", \"off\", or \"passive\"." msgstr "Режим LACP. Одне з таких значень: «active», «off» або «passive»." -#: src/libnmc-setting/settings-docs.h.in:263 +#: src/libnmc-setting/settings-docs.h.in:267 msgid "The VLAN tag in the range 0-4095." msgstr "Теґ VLAN у діапазоні від 0 до 4095." -#: src/libnmc-setting/settings-docs.h.in:264 +#: src/libnmc-setting/settings-docs.h.in:268 msgid "" "A list of VLAN ranges that this port trunks. The property is valid only for " "ports with mode \"trunk\", \"native-tagged\", or \"native-untagged port\". " "If it is empty, the port trunks all VLANs." msgstr "" -"Список діапазонів VLAN, які цей порт вважає «trunk». Властивість є чинною" -" лише для портів із режимом «trunk», «native-tagged» або «native-untagged" -" port». Якщо значення властивості є порожнім, порт вважатиме «trunk» усі" -" VLAN." +"Список діапазонів VLAN, які цей порт вважає «trunk». Властивість є чинною " +"лише для портів із режимом «trunk», «native-tagged» або «native-untagged " +"port». Якщо значення властивості є порожнім, порт вважатиме «trunk» усі VLAN." -#: src/libnmc-setting/settings-docs.h.in:265 -#| msgid "" -#| "The VLAN mode. One of \"access\", \"native-tagged\", \"native-untagged\", " -#| "\"trunk\" or unset." +#: src/libnmc-setting/settings-docs.h.in:269 msgid "" "The VLAN mode. One of \"access\", \"native-tagged\", \"native-untagged\", " "\"trunk\", \"dot1q-tunnel\" or unset." @@ -9103,7 +9131,7 @@ msgstr "" "Режим VLAN. Одне з таких значень: «access», «native-tagged», «native-" "untagged», «trunk», «dot1q-tunnel» або порожнє значення." -#: src/libnmc-setting/settings-docs.h.in:266 +#: src/libnmc-setting/settings-docs.h.in:270 msgid "" "If non-zero, instruct pppd to set the serial port to the specified " "baudrate. This value should normally be left as 0 to automatically choose " @@ -9113,7 +9141,7 @@ msgstr "" "вказану швидкість передавання даних у бодах. Зазвичай, для цієї властивості " "слід залишити нульове значення, щоб швидкість було вибрано автоматично." -#: src/libnmc-setting/settings-docs.h.in:267 +#: src/libnmc-setting/settings-docs.h.in:271 msgid "" "If TRUE, specify that pppd should set the serial port to use hardware flow " "control with RTS and CTS signals. This value should normally be set to " @@ -9123,7 +9151,7 @@ msgstr "" "керування потоком апаратних даних за допомогою сигналів RTS і CTS. За " "звичних умов, для цієї властивості має бути встановлено значення FALSE." -#: src/libnmc-setting/settings-docs.h.in:268 +#: src/libnmc-setting/settings-docs.h.in:272 msgid "" "If non-zero, instruct pppd to presume the connection to the peer has failed " "if the specified number of LCP echo-requests go unanswered by the peer. The " @@ -9135,7 +9163,7 @@ msgstr "" "кількість луна-запитів LCP. Якщо використовується ця властивість, для " "властивості «lcp-echo-interval» слід встановити ненульове значення." -#: src/libnmc-setting/settings-docs.h.in:269 +#: src/libnmc-setting/settings-docs.h.in:273 msgid "" "If non-zero, instruct pppd to send an LCP echo-request frame to the peer " "every n seconds (where n is the specified value). Note that some PPP peers " @@ -9147,7 +9175,7 @@ msgstr "" "відповідатимуть на луна-запити, а деякі — ні. Визначити, чи відповідатиме " "певний вузол, у автоматичному режимі неможливо." -#: src/libnmc-setting/settings-docs.h.in:270 +#: src/libnmc-setting/settings-docs.h.in:274 msgid "" "If TRUE, stateful MPPE is used. See pppd documentation for more information " "on stateful MPPE." @@ -9155,7 +9183,7 @@ msgstr "" "Якщо TRUE, використовуватиметься режим MPPE зі станами (stateful). " "Докладніший опис режиму MPPE зі станами наведено у документації із pppd." -#: src/libnmc-setting/settings-docs.h.in:271 +#: src/libnmc-setting/settings-docs.h.in:275 msgid "" "If non-zero, instruct pppd to request that the peer send packets no larger " "than the specified size. If non-zero, the MRU should be between 128 and " @@ -9165,20 +9193,20 @@ msgstr "" "щодо того, щоб він надсилав пакети, не більші за вказаний розмір. Якщо має " "ненульове значення, MRU має бути від 128 до 16384." -#: src/libnmc-setting/settings-docs.h.in:272 +#: src/libnmc-setting/settings-docs.h.in:276 msgid "" "If non-zero, instruct pppd to send packets no larger than the specified size." msgstr "" "Якщо має ненульове значення, наказує pppd надсилати пакети, не більші за " "вказаний розмір." -#: src/libnmc-setting/settings-docs.h.in:273 +#: src/libnmc-setting/settings-docs.h.in:277 msgid "If TRUE, Van Jacobsen TCP header compression will not be requested." msgstr "" "Якщо має значення TRUE, запит щодо стискання заголовків TCP ван Якобсена не " "надсилатиметься." -#: src/libnmc-setting/settings-docs.h.in:274 +#: src/libnmc-setting/settings-docs.h.in:278 msgid "" "If TRUE, do not require the other side (usually the PPP server) to " "authenticate itself to the client. If FALSE, require authentication from " @@ -9189,35 +9217,35 @@ msgstr "" "FALSE, вимагати проходження розпізнавання з боку віддаленого вузла. У " "більшості випадків слід використовувати значення TRUE." -#: src/libnmc-setting/settings-docs.h.in:275 +#: src/libnmc-setting/settings-docs.h.in:279 msgid "If TRUE, BSD compression will not be requested." msgstr "Якщо TRUE, стискання BSD не вимагатиметься." -#: src/libnmc-setting/settings-docs.h.in:276 +#: src/libnmc-setting/settings-docs.h.in:280 msgid "If TRUE, \"deflate\" compression will not be requested." msgstr "Якщо TRUE, стискання «deflate» не вимагатиметься." -#: src/libnmc-setting/settings-docs.h.in:277 +#: src/libnmc-setting/settings-docs.h.in:281 msgid "If TRUE, the CHAP authentication method will not be used." msgstr "Якщо TRUE, спосіб розпізнавання CHAP не використовуватиметься." -#: src/libnmc-setting/settings-docs.h.in:278 +#: src/libnmc-setting/settings-docs.h.in:282 msgid "If TRUE, the EAP authentication method will not be used." msgstr "Якщо TRUE, спосіб розпізнавання EAP не використовуватиметься." -#: src/libnmc-setting/settings-docs.h.in:279 +#: src/libnmc-setting/settings-docs.h.in:283 msgid "If TRUE, the MSCHAP authentication method will not be used." msgstr "Якщо TRUE, спосіб розпізнавання MSCHAP не використовуватиметься." -#: src/libnmc-setting/settings-docs.h.in:280 +#: src/libnmc-setting/settings-docs.h.in:284 msgid "If TRUE, the MSCHAPv2 authentication method will not be used." msgstr "Якщо TRUE, спосіб розпізнавання MSCHAPv2 не використовуватиметься." -#: src/libnmc-setting/settings-docs.h.in:281 +#: src/libnmc-setting/settings-docs.h.in:285 msgid "If TRUE, the PAP authentication method will not be used." msgstr "Якщо TRUE, спосіб розпізнавання PAP не використовуватиметься." -#: src/libnmc-setting/settings-docs.h.in:282 +#: src/libnmc-setting/settings-docs.h.in:286 msgid "" "If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for the " "PPP session. If either 64-bit or 128-bit MPPE is not available the session " @@ -9228,7 +9256,7 @@ msgstr "" "128-бітове MPPE виявиться недоступним, сеанс не буде створено. Зауважте, що " "MPPE не використовується для мобільних широкосмугових з'єднань." -#: src/libnmc-setting/settings-docs.h.in:283 +#: src/libnmc-setting/settings-docs.h.in:287 msgid "" "If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be required " "for the PPP session, and the \"require-mppe\" property must also be set to " @@ -9239,7 +9267,7 @@ msgstr "" "для властивості «require-mppe» також має бути встановлено TRUE. Якщо 128-" "бітове MPPE виявиться недоступним, сеанс не буде створено." -#: src/libnmc-setting/settings-docs.h.in:284 +#: src/libnmc-setting/settings-docs.h.in:288 msgid "" "If given, specifies the parent interface name on which this PPPoE connection " "should be created. If this property is not specified, the connection is " @@ -9251,11 +9279,11 @@ msgstr "" "з'єднання буде активовано на інтерфейсі, який вказано за допомогою параметра " "«interface-name» NMSettingConnection." -#: src/libnmc-setting/settings-docs.h.in:285 +#: src/libnmc-setting/settings-docs.h.in:289 msgid "Password used to authenticate with the PPPoE service." msgstr "Пароль, який використовуватиметься для розпізнавання на службі PPPoE." -#: src/libnmc-setting/settings-docs.h.in:287 +#: src/libnmc-setting/settings-docs.h.in:291 msgid "" "If specified, instruct PPPoE to only initiate sessions with access " "concentrators that provide the specified service. For most providers, this " @@ -9268,25 +9296,25 @@ msgstr "" "якщо ви маєте справу із концентраторами із декількома способами доступу або " "відомо, що вказана служба є необхідною." -#: src/libnmc-setting/settings-docs.h.in:288 +#: src/libnmc-setting/settings-docs.h.in:292 msgid "Username used to authenticate with the PPPoE service." msgstr "" "Ім'я користувача, яке використовуватиметься для розпізнавання на службі " "PPPoE." -#: src/libnmc-setting/settings-docs.h.in:289 +#: src/libnmc-setting/settings-docs.h.in:293 msgid "Whether the proxy configuration is for browser only." msgstr "" "Визначає, чи використовуються налаштування проксі лише для програм для " "перегляду інтернету." -#: src/libnmc-setting/settings-docs.h.in:290 +#: src/libnmc-setting/settings-docs.h.in:294 msgid "" "Method for proxy configuration, Default is NM_SETTING_PROXY_METHOD_NONE (0)" msgstr "" "Спосіб налаштовування проксі. Типовим є NM_SETTING_PROXY_METHOD_NONE (0)" -#: src/libnmc-setting/settings-docs.h.in:291 +#: src/libnmc-setting/settings-docs.h.in:295 msgid "" "The PAC script. In the profile this must be an UTF-8 encoded javascript code " "that defines a FindProxyForURL() function. When setting the property in " @@ -9300,11 +9328,11 @@ msgstr "" "файла і встановить скрипт. Для явного розмежування двох можливих випадків " "передбачено підтримку префіксів «file://» і «js://»." -#: src/libnmc-setting/settings-docs.h.in:292 +#: src/libnmc-setting/settings-docs.h.in:296 msgid "PAC URL for obtaining PAC file." msgstr "Адреса PAC для отримання файла PAC." -#: src/libnmc-setting/settings-docs.h.in:293 +#: src/libnmc-setting/settings-docs.h.in:297 msgid "" "Speed to use for communication over the serial port. Note that this value " "usually has no effect for mobile broadband modems as they generally ignore " @@ -9315,20 +9343,20 @@ msgstr "" "загалом, для них параметри швидкості ігноруються — просто використовується " "найвища доступна швидкість." -#: src/libnmc-setting/settings-docs.h.in:294 +#: src/libnmc-setting/settings-docs.h.in:298 msgid "Byte-width of the serial communication. The 8 in \"8n1\" for example." msgstr "Байтова ширина послідовного обміну даними. Наприклад, 8 у «8n1»." -#: src/libnmc-setting/settings-docs.h.in:295 +#: src/libnmc-setting/settings-docs.h.in:299 msgid "Parity setting of the serial port." msgstr "Параметр парності послідовного порту." -#: src/libnmc-setting/settings-docs.h.in:296 +#: src/libnmc-setting/settings-docs.h.in:300 msgid "Time to delay between each byte sent to the modem, in microseconds." msgstr "" "Затримка у часі між надсиланнями одного байта на модем, у мікросекундах." -#: src/libnmc-setting/settings-docs.h.in:297 +#: src/libnmc-setting/settings-docs.h.in:301 msgid "" "Number of stop bits for communication on the serial port. Either 1 or 2. " "The 1 in \"8n1\" for example." @@ -9336,7 +9364,7 @@ msgstr "" "Кількість бітів зупинки для обміну даними на послідовному порту. Може мати " "значення 1 або 2. Наприклад, 1 у «8n1»." -#: src/libnmc-setting/settings-docs.h.in:298 +#: src/libnmc-setting/settings-docs.h.in:302 msgid "" "Whether to autoprobe virtual functions by a compatible driver. If set to " "NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver " @@ -9356,7 +9384,7 @@ msgstr "" "використовуватимуться загальні типові параметри. Якщо загальні типові " "параметри не вказано, припускатиметься варіант NM_TERNARY_TRUE (1)." -#: src/libnmc-setting/settings-docs.h.in:299 +#: src/libnmc-setting/settings-docs.h.in:303 msgid "" "The total number of virtual functions to create. Note that when the sriov " "setting is present NetworkManager enforces the number of virtual functions " @@ -9371,7 +9399,7 @@ msgstr "" "внесенню будь-яких змін до параметрів SR-IOV, не додавайте параметр sriov до " "параметрів з'єднання." -#: src/libnmc-setting/settings-docs.h.in:300 +#: src/libnmc-setting/settings-docs.h.in:304 msgid "" "Array of virtual function descriptors. Each VF descriptor is a dictionary " "mapping attribute names to GVariant values. The 'index' entry is mandatory " @@ -9397,7 +9425,7 @@ msgstr "" "форму: «ІДЕНТИФІКАТОР[.ПРІОРИТЕТНІСТЬ[.ПРОТОКОЛ]]». Значенням ПРОТОКОЛ може " "бути або «q» для 802.1Q (типовий варіант) або «ad» для 802.1ad." -#: src/libnmc-setting/settings-docs.h.in:301 +#: src/libnmc-setting/settings-docs.h.in:305 msgid "" "Array of TC queueing disciplines. When the \"tc\" setting is present, qdiscs " "from this property are applied upon activation. If the property is empty, " @@ -9413,7 +9441,7 @@ msgstr "" "параметра «net.core.default_qdisc». Якщо параметр «tc» не вказано, " "NetworkManager не втручатиметься у наявні планування черги інтерфейсу." -#: src/libnmc-setting/settings-docs.h.in:302 +#: src/libnmc-setting/settings-docs.h.in:306 msgid "" "Array of TC traffic filters. When the \"tc\" setting is present, filters " "from this property are applied upon activation. If the property is empty, " @@ -9425,7 +9453,7 @@ msgstr "" "порожнім, NetworkManager вилучає усі фільтри. Якщо параметр «tc» не " "встановлено, NetworkManager не втручатиметься у поточні фільтри інтерфейсу." -#: src/libnmc-setting/settings-docs.h.in:303 +#: src/libnmc-setting/settings-docs.h.in:307 msgid "" "The JSON configuration for the team network interface. The property should " "contain raw JSON configuration data suitable for teamd, because the value is " @@ -9438,8 +9466,8 @@ msgstr "" "використовуватимуться типові налаштування. Щоб дізнатися більше про " "форматування даних, ознайомитеся із підручником (man) з teamd.conf." -#: src/libnmc-setting/settings-docs.h.in:304 -#: src/libnmc-setting/settings-docs.h.in:322 +#: src/libnmc-setting/settings-docs.h.in:308 +#: src/libnmc-setting/settings-docs.h.in:326 msgid "" "Link watchers configuration for the connection: each link watcher is defined " "by a dictionary, whose keys depend upon the selected link watcher. Available " @@ -9460,23 +9488,23 @@ msgstr "" "«validate-inactive», «send-always». Докладніше про це на сторінці підручника " "(man) щодо teamd.conf." -#: src/libnmc-setting/settings-docs.h.in:305 +#: src/libnmc-setting/settings-docs.h.in:309 msgid "Corresponds to the teamd mcast_rejoin.count." msgstr "Відповідає mcast_rejoin.count у teamd." -#: src/libnmc-setting/settings-docs.h.in:306 +#: src/libnmc-setting/settings-docs.h.in:310 msgid "Corresponds to the teamd mcast_rejoin.interval." msgstr "Відповідає mcast_rejoin.interval у teamd." -#: src/libnmc-setting/settings-docs.h.in:307 +#: src/libnmc-setting/settings-docs.h.in:311 msgid "Corresponds to the teamd notify_peers.count." msgstr "Відповідає notify_peers.count у teamd." -#: src/libnmc-setting/settings-docs.h.in:308 +#: src/libnmc-setting/settings-docs.h.in:312 msgid "Corresponds to the teamd notify_peers.interval." msgstr "Відповідає notify_peers.interval у teamd." -#: src/libnmc-setting/settings-docs.h.in:309 +#: src/libnmc-setting/settings-docs.h.in:313 msgid "" "Corresponds to the teamd runner.name. Permitted values are: \"roundrobin\", " "\"broadcast\", \"activebackup\", \"loadbalance\", \"lacp\", \"random\"." @@ -9484,43 +9512,43 @@ msgstr "" "Відповідає runner.name у teamd. Можливі такі значення: «roundrobin», " "«broadcast», «activebackup», «loadbalance», «lacp», «random»." -#: src/libnmc-setting/settings-docs.h.in:310 +#: src/libnmc-setting/settings-docs.h.in:314 msgid "Corresponds to the teamd runner.active." msgstr "Відповідає runner.active у teamd." -#: src/libnmc-setting/settings-docs.h.in:311 +#: src/libnmc-setting/settings-docs.h.in:315 msgid "Corresponds to the teamd runner.agg_select_policy." msgstr "Відповідає runner.agg_select_policy у teamd." -#: src/libnmc-setting/settings-docs.h.in:312 +#: src/libnmc-setting/settings-docs.h.in:316 msgid "Corresponds to the teamd runner.fast_rate." msgstr "Відповідає runner.fast_rate у teamd." -#: src/libnmc-setting/settings-docs.h.in:313 +#: src/libnmc-setting/settings-docs.h.in:317 msgid "Corresponds to the teamd runner.hwaddr_policy." msgstr "Відповідає runner.hwaddr_policy у teamd." -#: src/libnmc-setting/settings-docs.h.in:314 +#: src/libnmc-setting/settings-docs.h.in:318 msgid "Corresponds to the teamd runner.min_ports." msgstr "Відповідає runner.min_ports у teamd." -#: src/libnmc-setting/settings-docs.h.in:315 +#: src/libnmc-setting/settings-docs.h.in:319 msgid "Corresponds to the teamd runner.sys_prio." msgstr "Відповідає runner.sys_prio у teamd." -#: src/libnmc-setting/settings-docs.h.in:316 +#: src/libnmc-setting/settings-docs.h.in:320 msgid "Corresponds to the teamd runner.tx_balancer.name." msgstr "Відповідає runner.tx_balancer.name у teamd." -#: src/libnmc-setting/settings-docs.h.in:317 +#: src/libnmc-setting/settings-docs.h.in:321 msgid "Corresponds to the teamd runner.tx_balancer.interval." msgstr "Відповідає runner.tx_balancer.interval у teamd." -#: src/libnmc-setting/settings-docs.h.in:318 +#: src/libnmc-setting/settings-docs.h.in:322 msgid "Corresponds to the teamd runner.tx_hash." msgstr "Відповідає runner.tx_hash у teamd." -#: src/libnmc-setting/settings-docs.h.in:319 +#: src/libnmc-setting/settings-docs.h.in:323 msgid "" "The JSON configuration for the team port. The property should contain raw " "JSON configuration data suitable for teamd, because the value is passed " @@ -9533,19 +9561,19 @@ msgstr "" "використовуватимуться типові налаштування. Щоб дізнатися більше про " "форматування даних, ознайомитеся із підручником (man) з teamd.conf." -#: src/libnmc-setting/settings-docs.h.in:320 +#: src/libnmc-setting/settings-docs.h.in:324 msgid "Corresponds to the teamd ports.PORTIFNAME.lacp_key." msgstr "Відповідає ports.PORTIFNAME.lacp_key у teamd." -#: src/libnmc-setting/settings-docs.h.in:321 +#: src/libnmc-setting/settings-docs.h.in:325 msgid "Corresponds to the teamd ports.PORTIFNAME.lacp_prio." msgstr "Відповідає ports.PORTIFNAME.lacp_prio у teamd." -#: src/libnmc-setting/settings-docs.h.in:323 +#: src/libnmc-setting/settings-docs.h.in:327 msgid "Corresponds to the teamd ports.PORTIFNAME.prio." msgstr "Відповідає ports.PORTIFNAME.prio у teamd." -#: src/libnmc-setting/settings-docs.h.in:324 +#: src/libnmc-setting/settings-docs.h.in:328 msgid "" "Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means the " "parameter is skipped from the json config." @@ -9553,11 +9581,11 @@ msgstr "" "Відповідає ports.PORTIFNAME.queue_id у teamd. Значення -1 означає, що " "параметр пропускається у налаштуваннях json." -#: src/libnmc-setting/settings-docs.h.in:325 +#: src/libnmc-setting/settings-docs.h.in:329 msgid "Corresponds to the teamd ports.PORTIFNAME.sticky." msgstr "Відповідає ports.PORTIFNAME.sticky у teamd." -#: src/libnmc-setting/settings-docs.h.in:326 +#: src/libnmc-setting/settings-docs.h.in:330 msgid "" "The group ID which will own the device. If set to NULL everyone will be able " "to use the device." @@ -9565,7 +9593,7 @@ msgstr "" "Ідентифікатор групи-власника пристрою. Якщо встановлено значення NULL, " "пристроєм зможе користуватися будь-хто." -#: src/libnmc-setting/settings-docs.h.in:327 +#: src/libnmc-setting/settings-docs.h.in:331 msgid "" "The operating mode of the virtual device. Allowed values are " "NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and " @@ -9575,7 +9603,7 @@ msgstr "" "NM_SETTING_TUN_MODE_TUN (1) для створення пристрою шару 3 і " "NM_SETTING_TUN_MODE_TAP (2) для створення пристрою Ethernet-подібного шару 2." -#: src/libnmc-setting/settings-docs.h.in:328 +#: src/libnmc-setting/settings-docs.h.in:332 msgid "" "If the property is set to TRUE, the interface will support multiple file " "descriptors (queues) to parallelize packet sending or receiving. Otherwise, " @@ -9586,7 +9614,7 @@ msgstr "" "надсилання або отримування пакетів. Якщо ж встановлено значення FALSE, " "інтерфейсом підтримуватиметься лише одна черга." -#: src/libnmc-setting/settings-docs.h.in:329 +#: src/libnmc-setting/settings-docs.h.in:333 msgid "" "The user ID which will own the device. If set to NULL everyone will be able " "to use the device." @@ -9594,7 +9622,7 @@ msgstr "" "Ідентифікатор користувача-власника пристрою. Якщо встановлено значення NULL, " "пристроєм зможе користуватися будь-хто." -#: src/libnmc-setting/settings-docs.h.in:330 +#: src/libnmc-setting/settings-docs.h.in:334 msgid "" "If TRUE the interface will prepend a 4 byte header describing the physical " "interface to the packets." @@ -9602,7 +9630,7 @@ msgstr "" "Якщо TRUE, інтерфейс дописуватиме на початку пакетів заголовок у 4 байти із " "описом фізичного інтерфейсу." -#: src/libnmc-setting/settings-docs.h.in:331 +#: src/libnmc-setting/settings-docs.h.in:335 msgid "" "If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network " "header." @@ -9610,7 +9638,7 @@ msgstr "" "Якщо IFF_VNET_HDR має значення TRUE, тунельовані пакети включатимуть " "заголовок мережі virtio." -#: src/libnmc-setting/settings-docs.h.in:332 +#: src/libnmc-setting/settings-docs.h.in:336 msgid "" "A dictionary of key/value pairs with user data. This data is ignored by " "NetworkManager and can be used at the users discretion. The keys only " @@ -9623,7 +9651,7 @@ msgstr "" "формату ASCII, але значення можуть бути довільними рядками UTF8, довжина " "яких не перевищує певного значення." -#: src/libnmc-setting/settings-docs.h.in:333 +#: src/libnmc-setting/settings-docs.h.in:337 msgid "" "For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p " "priorities. The mapping is given in the format \"from:to\" where both \"from" @@ -9633,7 +9661,7 @@ msgstr "" "802.1p. Прив'язка визначається у форматі «з:до», де обидва значення, «з» і " "«до» є цілими додатними числами, наприклад «7:3»." -#: src/libnmc-setting/settings-docs.h.in:334 +#: src/libnmc-setting/settings-docs.h.in:338 msgid "" "One or more flags which control the behavior and features of the VLAN " "interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of " @@ -9655,7 +9683,7 @@ msgstr "" "зберегти зворотну сумісність, типовим значенням у програмному інтерфейсі D-" "Bus лишається 0, а нестача властивості у D-Bus також розглядається як 0." -#: src/libnmc-setting/settings-docs.h.in:335 +#: src/libnmc-setting/settings-docs.h.in:339 msgid "" "The VLAN identifier that the interface created by this connection should be " "assigned. The valid range is from 0 to 4094, without the reserved id 4095." @@ -9664,7 +9692,7 @@ msgstr "" "з'єднанням. Коректним діапазоном є діапазон від 0 до 4094, без " "зарезервованого ідентифікатора 4095." -#: src/libnmc-setting/settings-docs.h.in:336 +#: src/libnmc-setting/settings-docs.h.in:340 msgid "" "For incoming packets, a list of mappings from 802.1p priorities to Linux SKB " "priorities. The mapping is given in the format \"from:to\" where both \"from" @@ -9674,7 +9702,7 @@ msgstr "" "Linux. Прив'язка визначається у форматі «з:до», де обидва значення, «з» і " "«до» є цілими додатними числами, наприклад «7:3»." -#: src/libnmc-setting/settings-docs.h.in:337 +#: src/libnmc-setting/settings-docs.h.in:341 msgid "" "If given, specifies the parent interface name or parent connection UUID from " "which this VLAN interface should be created. If this property is not " @@ -9686,19 +9714,16 @@ msgstr "" "значення для цієї властивості не вказано, запис з'єднання має містити " "параметр «802-3-ethernet» із властивістю «mac-address»." -#: src/libnmc-setting/settings-docs.h.in:338 -#| msgid "" -#| "If specified, the protocol used for VLAN filtering. Supported values are: " -#| "'802.1Q', '802.1ad'. If not specified the default value is '802.1Q'." +#: src/libnmc-setting/settings-docs.h.in:342 msgid "" "Specifies the VLAN protocol to use for encapsulation. Supported values are: " "'802.1Q', '802.1ad'. If not specified the default value is '802.1Q'." msgstr "" -"Вказує протокол VLAN, яким слід скористатися для інкапсуляції. Підтримувані" -" значення: «802.1Q», «802.1ad». Якщо не вказано, типовим " -"значенням буде «802.1Q»." +"Вказує протокол VLAN, яким слід скористатися для інкапсуляції. Підтримувані " +"значення: «802.1Q», «802.1ad». Якщо не вказано, типовим значенням буде " +"«802.1Q»." -#: src/libnmc-setting/settings-docs.h.in:339 +#: src/libnmc-setting/settings-docs.h.in:343 msgid "" "Dictionary of key/value pairs of VPN plugin specific data. Both keys and " "values must be strings." @@ -9706,7 +9731,7 @@ msgstr "" "Словник із пар ключ-значення для специфічних даних додатка VPN. Величинами " "ключа і значення можуть бути лише текстові рядки." -#: src/libnmc-setting/settings-docs.h.in:340 +#: src/libnmc-setting/settings-docs.h.in:344 msgid "" "If the VPN service supports persistence, and this property is TRUE, the VPN " "will attempt to stay connected across link changes and outages, until " @@ -9717,7 +9742,7 @@ msgstr "" "час зміни параметрів зв'язку або неможливості обміну даними, аж доки " "з'єднання не буде розірвано явним чином." -#: src/libnmc-setting/settings-docs.h.in:341 +#: src/libnmc-setting/settings-docs.h.in:345 msgid "" "Dictionary of key/value pairs of VPN plugin specific secrets like passwords " "or private keys. Both keys and values must be strings." @@ -9726,7 +9751,7 @@ msgstr "" "VPN, зокрема паролів або закритих ключів. Величинами ключа і значення можуть " "бути лише текстові рядки." -#: src/libnmc-setting/settings-docs.h.in:342 +#: src/libnmc-setting/settings-docs.h.in:346 msgid "" "D-Bus service name of the VPN plugin that this setting uses to connect to " "its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin." @@ -9735,7 +9760,7 @@ msgstr "" "додатка з його мережею. Приклад: org.freedesktop.NetworkManager.vpnc для " "додатка vpnc." -#: src/libnmc-setting/settings-docs.h.in:343 +#: src/libnmc-setting/settings-docs.h.in:347 msgid "" "Timeout for the VPN service to establish the connection. Some services may " "take quite a long time to connect. Value of 0 means a default timeout, which " @@ -9748,7 +9773,7 @@ msgstr "" "допомогою параметра vpn.timeout у файлі налаштувань). Значення, які " "перевищують нуль, визначають час очікування у секундах." -#: src/libnmc-setting/settings-docs.h.in:344 +#: src/libnmc-setting/settings-docs.h.in:348 msgid "" "If the VPN connection requires a user name for authentication, that name " "should be provided here. If the connection is available to more than one " @@ -9764,15 +9789,15 @@ msgstr "" "порожнє, NetworkManager автоматично використає ім'я користувача, який " "надіслав запит щодо встановлення з'єднання VPN." -#: src/libnmc-setting/settings-docs.h.in:345 +#: src/libnmc-setting/settings-docs.h.in:349 msgid "The routing table for this VRF." msgstr "Таблиця маршрутизації для цього VRF." -#: src/libnmc-setting/settings-docs.h.in:346 +#: src/libnmc-setting/settings-docs.h.in:350 msgid "Specifies the lifetime in seconds of FDB entries learnt by the kernel." msgstr "Визначає час життя у секундах записів FDB, вивчених ядром." -#: src/libnmc-setting/settings-docs.h.in:347 +#: src/libnmc-setting/settings-docs.h.in:351 msgid "" "Specifies the UDP destination port to communicate to the remote VXLAN tunnel " "endpoint." @@ -9780,22 +9805,22 @@ msgstr "" "Визначає порт призначення UDP для обміну даними із віддаленою кінцевою " "точкою тунелю VXLAN." -#: src/libnmc-setting/settings-docs.h.in:348 +#: src/libnmc-setting/settings-docs.h.in:352 msgid "" "Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use." msgstr "" "Визначає ідентифікатор мережі VXLAN (або ідентифікатор сегмента VXLAN), яким " "слід скористатися." -#: src/libnmc-setting/settings-docs.h.in:349 +#: src/libnmc-setting/settings-docs.h.in:353 msgid "Specifies whether netlink LL ADDR miss notifications are generated." msgstr "Визначає, чи будуть створюватися сповіщення netlink LL ADDR miss." -#: src/libnmc-setting/settings-docs.h.in:350 +#: src/libnmc-setting/settings-docs.h.in:354 msgid "Specifies whether netlink IP ADDR miss notifications are generated." msgstr "Визначає, чи будуть створюватися сповіщення netlink IP ADDR miss." -#: src/libnmc-setting/settings-docs.h.in:351 +#: src/libnmc-setting/settings-docs.h.in:355 msgid "" "Specifies whether unknown source link layer addresses and IP addresses are " "entered into the VXLAN device forwarding database." @@ -9803,7 +9828,7 @@ msgstr "" "Вказує, чи вводяться невідомі адреси шару посилань та IP-адреси до бази " "даних переспрямовування пристроїв VXLAN." -#: src/libnmc-setting/settings-docs.h.in:352 +#: src/libnmc-setting/settings-docs.h.in:356 msgid "" "Specifies the maximum number of FDB entries. A value of zero means that the " "kernel will store unlimited entries." @@ -9811,24 +9836,24 @@ msgstr "" "Вказує максимальну кількість записів FDB. Нульове значення означає, що ядро " "зберігатиме необмежену кількість записів." -#: src/libnmc-setting/settings-docs.h.in:353 +#: src/libnmc-setting/settings-docs.h.in:357 msgid "If given, specifies the source IP address to use in outgoing packets." msgstr "" "Якщо задано, визначає початкову IP-адресу, якою слід скористатися для " "вихідних пакетів." -#: src/libnmc-setting/settings-docs.h.in:354 +#: src/libnmc-setting/settings-docs.h.in:358 msgid "" "If given, specifies the parent interface name or parent connection UUID." msgstr "" "Якщо задано, визначає назву батьківського інтерфейсу або UUID батьківського " "з'єднання." -#: src/libnmc-setting/settings-docs.h.in:355 +#: src/libnmc-setting/settings-docs.h.in:359 msgid "Specifies whether ARP proxy is turned on." msgstr "Визначає, чи увімкнено ARP-проксі." -#: src/libnmc-setting/settings-docs.h.in:356 +#: src/libnmc-setting/settings-docs.h.in:360 msgid "" "Specifies the unicast destination IP address to use in outgoing packets when " "the destination link layer address is not known in the VXLAN device " @@ -9839,11 +9864,11 @@ msgstr "" "переспрямовування пристроїв VXLAN, або IP-адреса універсальної трансляції, з " "якою слід встановити зв'язок." -#: src/libnmc-setting/settings-docs.h.in:357 +#: src/libnmc-setting/settings-docs.h.in:361 msgid "Specifies whether route short circuit is turned on." msgstr "Визначає, чи увімкнено коротке замикання маршруту." -#: src/libnmc-setting/settings-docs.h.in:358 +#: src/libnmc-setting/settings-docs.h.in:362 msgid "" "Specifies the maximum UDP source port to communicate to the remote VXLAN " "tunnel endpoint." @@ -9851,7 +9876,7 @@ msgstr "" "Визначає максимальний початковий порт UDP для обміну даними із віддаленою " "кінцевою точкою тунелю VXLAN." -#: src/libnmc-setting/settings-docs.h.in:359 +#: src/libnmc-setting/settings-docs.h.in:363 msgid "" "Specifies the minimum UDP source port to communicate to the remote VXLAN " "tunnel endpoint." @@ -9859,16 +9884,16 @@ msgstr "" "Визначає мінімальний початковий порт UDP для обміну даними із віддаленою " "кінцевою точкою тунелю VXLAN." -#: src/libnmc-setting/settings-docs.h.in:360 +#: src/libnmc-setting/settings-docs.h.in:364 msgid "Specifies the TOS value to use in outgoing packets." msgstr "Визначає значення TOS, яке слід використовувати для вихідних пакетів." -#: src/libnmc-setting/settings-docs.h.in:361 +#: src/libnmc-setting/settings-docs.h.in:365 msgid "Specifies the time-to-live value to use in outgoing packets." msgstr "" "Визначає значення часу життя, яке слід використовувати для вихідних пакетів." -#: src/libnmc-setting/settings-docs.h.in:362 +#: src/libnmc-setting/settings-docs.h.in:366 msgid "" "The P2P device that should be connected to. Currently, this is the only way " "to create or join a group." @@ -9876,7 +9901,7 @@ msgstr "" "Пристрій P2P, з яким слід встановити з'єднання. У поточній версії це єдиний " "спосіб створення групи або долучення до неї." -#: src/libnmc-setting/settings-docs.h.in:363 +#: src/libnmc-setting/settings-docs.h.in:367 msgid "" "The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display " "requires a protocol specific information element to be set in certain Wi-Fi " @@ -9890,7 +9915,7 @@ msgstr "" "Вказати ці елементи з метою встановлення з'єднання можна тут. Цей параметр є " "корисним лише для реалізації клієнта дисплея Wi-Fi." -#: src/libnmc-setting/settings-docs.h.in:364 +#: src/libnmc-setting/settings-docs.h.in:368 msgid "" "Flags indicating which mode of WPS is to be used. There's little point in " "changing the default setting as NetworkManager will automatically determine " @@ -9900,7 +9925,7 @@ msgstr "" "типове значення не варто, оскільки NetworkManager автоматично визначає " "найкращий режим." -#: src/libnmc-setting/settings-docs.h.in:365 +#: src/libnmc-setting/settings-docs.h.in:369 msgid "" "If specified, this connection will only apply to the WiMAX device whose MAC " "address matches. This property does not change the MAC address of the device " @@ -9910,7 +9935,7 @@ msgstr "" "відповідною адресою MAC. Ця властивість не змінює MAC-адреси пристрою (таку " "зміну називають підміною MAC)." -#: src/libnmc-setting/settings-docs.h.in:366 +#: src/libnmc-setting/settings-docs.h.in:370 msgid "" "Network Service Provider (NSP) name of the WiMAX network this connection " "should use." @@ -9918,7 +9943,7 @@ msgstr "" "Назва надавача мережевих послуг (NSP) для мережі WiMAX, яку має " "використовувати це з'єднання." -#: src/libnmc-setting/settings-docs.h.in:367 +#: src/libnmc-setting/settings-docs.h.in:371 msgid "" "When TRUE, setup the interface to accept packets for all MAC addresses. This " "is enabling the kernel interface flag IFF_PROMISC. When FALSE, the interface " @@ -9930,7 +9955,7 @@ msgstr "" "має значення FALSE, інтерфейс прийматиме лише пакети із MAC-адресою " "призначення інтерфейсу або трансляції." -#: src/libnmc-setting/settings-docs.h.in:368 +#: src/libnmc-setting/settings-docs.h.in:372 msgid "" "When TRUE, enforce auto-negotiation of speed and duplex mode. If \"speed\" " "and \"duplex\" properties are both specified, only that single mode will be " @@ -9949,7 +9974,7 @@ msgstr "" "FALSE, має бути вручну встановлено значення властивостей «speed» і «duplex», " "інакше налаштування зв'язку буде пропущено." -#: src/libnmc-setting/settings-docs.h.in:369 +#: src/libnmc-setting/settings-docs.h.in:373 msgid "" "If specified, request that the device use this MAC address instead. This is " "known as MAC cloning or spoofing. Beside explicitly specifying a MAC " @@ -9981,7 +10006,7 @@ msgstr "" "використовуватися інше типове значення). У D-Bus це поле позначається як " "«assigned-mac-address», а у застарілих версіях, як «cloned-mac-address»." -#: src/libnmc-setting/settings-docs.h.in:370 +#: src/libnmc-setting/settings-docs.h.in:374 msgid "" "When a value is set, either \"half\" or \"full\", configures the device to " "use the specified duplex mode. If \"auto-negotiate\" is \"yes\" the " @@ -10008,8 +10033,8 @@ msgstr "" "Перш ніж вказувати двобічний режим, переконайтеся, що у пристрої передбачено " "його підтримку." -#: src/libnmc-setting/settings-docs.h.in:371 -#: src/libnmc-setting/settings-docs.h.in:395 +#: src/libnmc-setting/settings-docs.h.in:375 +#: src/libnmc-setting/settings-docs.h.in:399 msgid "" "With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all " "bits of the MAC address are scrambled and a locally-administered, unicast " @@ -10062,7 +10087,7 @@ msgstr "" "буде створено повністю перемішану MAC-адресу із випадковим локальним або " "глобальним адмініструванням." -#: src/libnmc-setting/settings-docs.h.in:372 +#: src/libnmc-setting/settings-docs.h.in:376 msgid "" "If specified, this connection will only apply to the Ethernet device whose " "permanent MAC address matches. This property does not change the MAC address " @@ -10072,7 +10097,7 @@ msgstr "" "відповідною сталою адресою MAC. Ця властивість не змінює MAC-адреси пристрою " "(таку зміну називають підміною MAC)." -#: src/libnmc-setting/settings-docs.h.in:373 +#: src/libnmc-setting/settings-docs.h.in:377 msgid "" "If specified, this connection will never apply to the Ethernet device whose " "permanent MAC address matches an address in the list. Each MAC address is " @@ -10083,9 +10108,9 @@ msgstr "" "адреси слід вказувати у стандартному позначенні із шістнадцяткових цифр і " "двокрапок (00:11:22:33:44:55)." -#: src/libnmc-setting/settings-docs.h.in:374 -#: src/libnmc-setting/settings-docs.h.in:401 -#: src/libnmc-setting/settings-docs.h.in:438 +#: src/libnmc-setting/settings-docs.h.in:378 +#: src/libnmc-setting/settings-docs.h.in:405 +#: src/libnmc-setting/settings-docs.h.in:442 msgid "" "If non-zero, only transmit packets of the specified size or smaller, " "breaking larger packets up into multiple Ethernet frames." @@ -10093,7 +10118,7 @@ msgstr "" "Якщо має ненульове значення, передавати пакети лише вказаного або меншого " "розміру, розбиваючи великі пакети на декілька кадрів Ethernet." -#: src/libnmc-setting/settings-docs.h.in:375 +#: src/libnmc-setting/settings-docs.h.in:379 msgid "" "Specific port type to use if the device supports multiple attachment " "methods. One of \"tp\" (Twisted Pair), \"aui\" (Attachment Unit Interface), " @@ -10106,7 +10131,7 @@ msgstr "" "Independent Interface). Якщо для пристрою передбачено підтримку лише одного " "типу порту, цей параметр буде проігноровано." -#: src/libnmc-setting/settings-docs.h.in:376 +#: src/libnmc-setting/settings-docs.h.in:380 msgid "" "s390 network device type; one of \"qeth\", \"lcs\", or \"ctc\", representing " "the different types of virtual network devices available on s390 systems." @@ -10115,7 +10140,7 @@ msgstr "" "відповідно до різних типів пристроїв віртуальної мережі, які доступні на " "системах s390." -#: src/libnmc-setting/settings-docs.h.in:377 +#: src/libnmc-setting/settings-docs.h.in:381 msgid "" "Dictionary of key/value pairs of s390-specific device options. Both keys " "and values must be strings. Allowed keys include \"portno\", \"layer2\", " @@ -10131,7 +10156,7 @@ msgstr "" "сам NetworkManager ніяк не використовує ці дані. Втім, до складу s390utils " "включено правило udev, яке обробляє ці дані і застосовує їх до інтерфейсу." -#: src/libnmc-setting/settings-docs.h.in:378 +#: src/libnmc-setting/settings-docs.h.in:382 msgid "" "Identifies specific subchannels that this network device uses for " "communication with z/VM or s390 host. Like the \"mac-address\" property for " @@ -10147,7 +10172,7 @@ msgstr "" "використовує вказані підканали. Список має містити точно три рядки, кожен з " "рядків може складатися лише із шістнадцяткових цифр та символів крапки (.)." -#: src/libnmc-setting/settings-docs.h.in:379 +#: src/libnmc-setting/settings-docs.h.in:383 msgid "" "When a value greater than 0 is set, configures the device to use the " "specified speed. If \"auto-negotiate\" is \"yes\" the specified speed will " @@ -10175,7 +10200,7 @@ msgstr "" "значенням властивості «duplex». Перш ніж встановлювати значення швидкості, " "переконайтеся, що у вашому пристрої передбачено її підтримку." -#: src/libnmc-setting/settings-docs.h.in:380 +#: src/libnmc-setting/settings-docs.h.in:384 msgid "" "The NMSettingWiredWakeOnLan options to enable. Not all devices support all " "options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), " @@ -10198,7 +10223,7 @@ msgstr "" "(використання загальних параметрів) та NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE " "(0x8000) (вимкнути керування Wake-on-LAN у NetworkManager)." -#: src/libnmc-setting/settings-docs.h.in:381 +#: src/libnmc-setting/settings-docs.h.in:385 msgid "" "If specified, the password used with magic-packet-based Wake-on-LAN, " "represented as an Ethernet MAC address. If NULL, no password will be " @@ -10208,7 +10233,7 @@ msgstr "" "магічних пакетах, представлений як MAC-адреса Ethernet. Якщо має значення " "NULL, пароль не потрібен." -#: src/libnmc-setting/settings-docs.h.in:382 +#: src/libnmc-setting/settings-docs.h.in:386 msgid "" "The use of fwmark is optional and is by default off. Setting it to 0 " "disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. Note " @@ -10220,7 +10245,7 @@ msgstr "" "fwmark для вихідних пакетів. Зауважте, що вмикання «ip4-auto-default-route» " "або «ip6-auto-default-route» неявним чином призводить до вибору fwmark." -#: src/libnmc-setting/settings-docs.h.in:383 +#: src/libnmc-setting/settings-docs.h.in:387 msgid "" "Whether to enable special handling of the IPv4 default route. If enabled, " "the IPv4 default route from wireguard.peer-routes will be placed to a " @@ -10254,11 +10279,11 @@ msgstr "" "непотрібно вмикати цей параметр явно. Втім, ви можете вимкнути його, якщо " "хочете налаштувати власну маршрутизацію та правила." -#: src/libnmc-setting/settings-docs.h.in:384 +#: src/libnmc-setting/settings-docs.h.in:388 msgid "Like ip4-auto-default-route, but for the IPv6 default route." msgstr "Те саме, що ip4-auto-default-route, але для типового маршруту IPv6." -#: src/libnmc-setting/settings-docs.h.in:385 +#: src/libnmc-setting/settings-docs.h.in:389 msgid "" "The listen-port. If listen-port is not specified, the port will be chosen " "randomly when the interface comes up." @@ -10266,7 +10291,7 @@ msgstr "" "Порт для очікування на дані. Якщо порт для очікування на дані не вказано, " "номер буде вибрано випадковим чином під час підняття інтерфейсу." -#: src/libnmc-setting/settings-docs.h.in:386 +#: src/libnmc-setting/settings-docs.h.in:390 msgid "" "If non-zero, only transmit packets of the specified size or smaller, " "breaking larger packets up into multiple fragments. If zero a default MTU is " @@ -10279,7 +10304,7 @@ msgstr "" "відміну від параметра MTU wg-quick, тут не беруться до уваги поточні " "маршрути на момент активації." -#: src/libnmc-setting/settings-docs.h.in:387 +#: src/libnmc-setting/settings-docs.h.in:391 msgid "" "Whether to automatically add routes for the AllowedIPs ranges of the peers. " "If TRUE (the default), NetworkManager will automatically add routes in the " @@ -10301,15 +10326,15 @@ msgstr "" "«0.0.0.0/0» або «::/0», а для профілю увімкнено ipv4.never-default або ipv6." "never-default, маршрут вузла для цього вузла не буде додано автоматично." -#: src/libnmc-setting/settings-docs.h.in:388 +#: src/libnmc-setting/settings-docs.h.in:392 msgid "The 256 bit private-key in base64 encoding." msgstr "256-бітовий закритий ключ у кодуванні base64." -#: src/libnmc-setting/settings-docs.h.in:389 +#: src/libnmc-setting/settings-docs.h.in:393 msgid "Flags indicating how to handle the \"private-key\" property." msgstr "Прапорці, які позначають, як обробляти властивість «private-key»." -#: src/libnmc-setting/settings-docs.h.in:390 +#: src/libnmc-setting/settings-docs.h.in:394 msgid "" "Configures AP isolation, which prevents communication between wireless " "devices connected to this AP. This property can be set to a value different " @@ -10337,7 +10362,7 @@ msgstr "" "загальні типові налаштування; якщо загальні типові налаштування не " "визначено, буде використано значення NM_TERNARY_FALSE (0)." -#: src/libnmc-setting/settings-docs.h.in:391 +#: src/libnmc-setting/settings-docs.h.in:395 msgid "" "802.11 frequency band of the network. One of \"a\" for 5GHz 802.11a or \"bg" "\" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to " @@ -10353,7 +10378,7 @@ msgstr "" "сумісними. Використання цього параметра залежить від можливостей певного " "драйвера і можливе не для усіх драйверів." -#: src/libnmc-setting/settings-docs.h.in:392 +#: src/libnmc-setting/settings-docs.h.in:396 msgid "" "If specified, directs the device to only associate with the given access " "point. This capability is highly driver dependent and not supported by all " @@ -10370,7 +10395,7 @@ msgstr "" "запобігатиме роумінґу, а також вимкне фонове сканування. Це може бути " "корисним, якщо для SSID визначено лише одну точку доступу." -#: src/libnmc-setting/settings-docs.h.in:393 +#: src/libnmc-setting/settings-docs.h.in:397 msgid "" "Wireless channel to use for the Wi-Fi connection. The device will only join " "(or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. " @@ -10383,7 +10408,7 @@ msgstr "" "різних смугах перекриваються, для використання цієї властивості має бути " "також встановлено властивість «band»." -#: src/libnmc-setting/settings-docs.h.in:394 +#: src/libnmc-setting/settings-docs.h.in:398 msgid "" "If specified, request that the device use this MAC address instead. This is " "known as MAC cloning or spoofing. Beside explicitly specifying a MAC " @@ -10413,7 +10438,7 @@ msgstr "" "використовуватися інше типове значення). У D-Bus це поле позначається як " "«assigned-mac-address», а у застарілих версіях, як «cloned-mac-address»." -#: src/libnmc-setting/settings-docs.h.in:396 +#: src/libnmc-setting/settings-docs.h.in:400 msgid "" "If TRUE, indicates that the network is a non-broadcasting network that hides " "its SSID. This works both in infrastructure and AP mode. In infrastructure " @@ -10437,7 +10462,7 @@ msgstr "" "інфраструктури) або клієнтських станцій (у режимі точки доступу), оскільки " "явне зондування можна буде легко виявити в ефірі." -#: src/libnmc-setting/settings-docs.h.in:397 +#: src/libnmc-setting/settings-docs.h.in:401 msgid "" "If specified, this connection will only apply to the Wi-Fi device whose " "permanent MAC address matches. This property does not change the MAC address " @@ -10447,7 +10472,7 @@ msgstr "" "відповідною сталою адресою MAC. Ця властивість не змінює MAC-адреси пристрою " "(таку зміну називають підміною MAC)." -#: src/libnmc-setting/settings-docs.h.in:398 +#: src/libnmc-setting/settings-docs.h.in:402 msgid "" "A list of permanent MAC addresses of Wi-Fi devices to which this connection " "should never apply. Each MAC address should be given in the standard hex-" @@ -10458,7 +10483,7 @@ msgstr "" "стандартного запису із шістнадцяткових цифр із двокрапками (наприклад, " "«00:11:22:33:44:55»)." -#: src/libnmc-setting/settings-docs.h.in:399 +#: src/libnmc-setting/settings-docs.h.in:403 msgid "" "One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless the " "user has set a global default to randomize and the supplicant supports " @@ -10474,7 +10499,7 @@ msgstr "" "NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (завжди вибирати MAC-адресу " "випадковим чином)." -#: src/libnmc-setting/settings-docs.h.in:400 +#: src/libnmc-setting/settings-docs.h.in:404 msgid "" "Wi-Fi network mode; one of \"infrastructure\", \"mesh\", \"adhoc\" or \"ap" "\". If blank, infrastructure is assumed." @@ -10482,7 +10507,7 @@ msgstr "" "Режим роботи мережі Wi-Fi. Одне з таких значень: «infrastructure», «mesh», " "«adhoc» або «ap». Якщо не вказано, використовується режим «infrastructure»." -#: src/libnmc-setting/settings-docs.h.in:402 +#: src/libnmc-setting/settings-docs.h.in:406 msgid "" "One of NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2) (disable Wi-Fi power " "saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi power " @@ -10497,7 +10522,7 @@ msgstr "" "або NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (використовувати налаштоване " "на загальному рівні значення). Усі інші значення поки зарезервовано." -#: src/libnmc-setting/settings-docs.h.in:403 +#: src/libnmc-setting/settings-docs.h.in:407 msgid "" "If non-zero, directs the device to only use the specified bitrate for " "communication with the access point. Units are in Kb/s, ie 5500 = 5.5 Mbit/" @@ -10510,7 +10535,7 @@ msgstr "" "властивості дуже залежить від драйвера. Підтримку встановлення статичної " "бітової швидкості передбачено не для усіх пристрої." -#: src/libnmc-setting/settings-docs.h.in:404 +#: src/libnmc-setting/settings-docs.h.in:408 msgid "" "A list of BSSIDs (each BSSID formatted as a MAC address like " "\"00:11:22:33:44:55\") that have been detected as part of the Wi-Fi " @@ -10525,11 +10550,11 @@ msgstr "" "NetworkManager. Зміни, які буде внесено до значення цієї властивості не " "зберігатимуться." -#: src/libnmc-setting/settings-docs.h.in:405 +#: src/libnmc-setting/settings-docs.h.in:409 msgid "SSID of the Wi-Fi network. Must be specified." msgstr "SSID мережі Wi-Fi. Має бути вказано." -#: src/libnmc-setting/settings-docs.h.in:406 +#: src/libnmc-setting/settings-docs.h.in:410 msgid "" "If non-zero, directs the device to use the specified transmit power. Units " "are dBm. This property is highly driver dependent and not all devices " @@ -10540,7 +10565,7 @@ msgstr "" "властивості дуже залежить від драйвера. Підтримку встановлення статичної " "потужності передавання передбачено не для усіх пристрої." -#: src/libnmc-setting/settings-docs.h.in:407 +#: src/libnmc-setting/settings-docs.h.in:411 msgid "" "The NMSettingWirelessWakeOnWLan options to enable. Not all devices support " "all options. May be any combination of NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY " @@ -10569,7 +10594,7 @@ msgstr "" "параметрів) і NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (0x8000) (для " "вимикання керування Wake-on-LAN у NetworkManager)." -#: src/libnmc-setting/settings-docs.h.in:408 +#: src/libnmc-setting/settings-docs.h.in:412 msgid "" "When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the " "802.11 authentication algorithm required by the AP here. One of \"open\" " @@ -10585,7 +10610,7 @@ msgstr "" "= \"leap\") слід вказати значення для властивостей «leap-username» і «leap-" "password»." -#: src/libnmc-setting/settings-docs.h.in:409 +#: src/libnmc-setting/settings-docs.h.in:413 msgid "" "Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the " "connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use " @@ -10607,7 +10632,7 @@ msgstr "" "NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0), а загальне типове значення не " "встановлено, буде, якщо можна, увімкнено FILS." -#: src/libnmc-setting/settings-docs.h.in:410 +#: src/libnmc-setting/settings-docs.h.in:414 msgid "" "A list of group/broadcast encryption algorithms which prevents connections " "to Wi-Fi networks that do not utilize one of the algorithms in the list. " @@ -10620,7 +10645,7 @@ msgstr "" "властивість порожньою. Кожен з елементів списку може мати одне зі значень, " "«wep40», «wep104», «tkip» або «ccmp»." -#: src/libnmc-setting/settings-docs.h.in:411 +#: src/libnmc-setting/settings-docs.h.in:415 msgid "" "Key management used for the connection. One of \"none\" (WEP or no password " "protection), \"ieee8021x\" (Dynamic WEP), \"owe\" (Opportunistic Wireless " @@ -10636,7 +10661,7 @@ msgstr "" "b-192» (лише промисловий WPA3). Значення цієї властивості слід встановити " "для усіх з'єднань Wi-Fi, для яких використовується захист." -#: src/libnmc-setting/settings-docs.h.in:412 +#: src/libnmc-setting/settings-docs.h.in:416 msgid "" "The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" " "and auth-alg = \"leap\")." @@ -10644,11 +10669,11 @@ msgstr "" "Пароль для застарілих з'єднань LEAP (тобто для key-mgmt = \"ieee8021x\" і " "auth-alg = \"leap\")." -#: src/libnmc-setting/settings-docs.h.in:413 +#: src/libnmc-setting/settings-docs.h.in:417 msgid "Flags indicating how to handle the \"leap-password\" property." msgstr "Прапорці, які позначають, як обробляти властивість «leap-password»." -#: src/libnmc-setting/settings-docs.h.in:414 +#: src/libnmc-setting/settings-docs.h.in:418 msgid "" "The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" " "and auth-alg = \"leap\")." @@ -10656,7 +10681,7 @@ msgstr "" "Ім'я користувача для застарілих з'єднань LEAP (тобто для key-mgmt = " "\"ieee8021x\" і auth-alg = \"leap\")." -#: src/libnmc-setting/settings-docs.h.in:415 +#: src/libnmc-setting/settings-docs.h.in:419 msgid "" "A list of pairwise encryption algorithms which prevents connections to Wi-Fi " "networks that do not utilize one of the algorithms in the list. For maximum " @@ -10668,7 +10693,7 @@ msgstr "" "максимальної сумісності залиште цю властивість порожньою. Кожен з елементів " "списку може мати одне зі значень, «tkip» або «ccmp»." -#: src/libnmc-setting/settings-docs.h.in:416 +#: src/libnmc-setting/settings-docs.h.in:420 msgid "" "Indicates whether Protected Management Frames (802.11w) must be enabled for " "the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use " @@ -10690,7 +10715,7 @@ msgstr "" "значення NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) і немає загального " "типового значення, додатково буде увімкнено PMF." -#: src/libnmc-setting/settings-docs.h.in:417 +#: src/libnmc-setting/settings-docs.h.in:421 msgid "" "List of strings specifying the allowed WPA protocol versions to use. Each " "element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN). If not " @@ -10701,7 +10726,7 @@ msgstr "" "або «rsn» (дозволити WPA2/RSN). Якщо не вказано буде дозволено як з'єднання " "WPA, так і з'єднання RSN." -#: src/libnmc-setting/settings-docs.h.in:418 +#: src/libnmc-setting/settings-docs.h.in:422 msgid "" "Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII " "passphrase of 8 to 63 characters that is (as specified in the 802.11i " @@ -10715,11 +10740,11 @@ msgstr "" "форматі 64-розрядного шістнадцяткового числа. У мережах WPA3-Personal для " "розпізнавання за SAE використовують пароль будь-якої довжини." -#: src/libnmc-setting/settings-docs.h.in:419 +#: src/libnmc-setting/settings-docs.h.in:423 msgid "Flags indicating how to handle the \"psk\" property." msgstr "Прапорці, які позначають, як обробляти властивість «psk»." -#: src/libnmc-setting/settings-docs.h.in:420 +#: src/libnmc-setting/settings-docs.h.in:424 msgid "" "Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", " "and \"wep-key3\" properties." @@ -10727,7 +10752,7 @@ msgstr "" "Прапорці, які позначають, як обробляти властивості «wep-key0», «wep-key1», " "«wep-key2» та «wep-key3»." -#: src/libnmc-setting/settings-docs.h.in:421 +#: src/libnmc-setting/settings-docs.h.in:425 msgid "" "Controls the interpretation of WEP keys. Allowed values are " "NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-" @@ -10742,7 +10767,7 @@ msgstr "" "вказано як текстовий рядок, який буде хешовано за допомогою фактичного " "методу MD5 для отримання справжнього ключа WEP." -#: src/libnmc-setting/settings-docs.h.in:422 +#: src/libnmc-setting/settings-docs.h.in:426 msgid "" "Index 0 WEP key. This is the WEP key used in most networks. See the \"wep-" "key-type\" property for a description of how this key is interpreted." @@ -10751,7 +10776,7 @@ msgstr "" "Опис інтерпретації цього ключа наведено у довідці щодо властивості «wep-key-" "type»." -#: src/libnmc-setting/settings-docs.h.in:423 +#: src/libnmc-setting/settings-docs.h.in:427 msgid "" "Index 1 WEP key. This WEP index is not used by most networks. See the " "\"wep-key-type\" property for a description of how this key is interpreted." @@ -10760,7 +10785,7 @@ msgstr "" "Опис інтерпретації цього ключа наведено у довідці щодо властивості «wep-key-" "type»." -#: src/libnmc-setting/settings-docs.h.in:424 +#: src/libnmc-setting/settings-docs.h.in:428 msgid "" "Index 2 WEP key. This WEP index is not used by most networks. See the " "\"wep-key-type\" property for a description of how this key is interpreted." @@ -10769,7 +10794,7 @@ msgstr "" "Опис інтерпретації цього ключа наведено у довідці щодо властивості «wep-key-" "type»." -#: src/libnmc-setting/settings-docs.h.in:425 +#: src/libnmc-setting/settings-docs.h.in:429 msgid "" "Index 3 WEP key. This WEP index is not used by most networks. See the " "\"wep-key-type\" property for a description of how this key is interpreted." @@ -10778,7 +10803,7 @@ msgstr "" "Опис інтерпретації цього ключа наведено у довідці щодо властивості «wep-key-" "type»." -#: src/libnmc-setting/settings-docs.h.in:426 +#: src/libnmc-setting/settings-docs.h.in:430 msgid "" "When static WEP is used (ie, key-mgmt = \"none\") and a non-default WEP key " "index is used by the AP, put that WEP key index here. Valid values are 0 " @@ -10791,7 +10816,7 @@ msgstr "" "на деяких поширених точках доступу (зокрема Linksys WRT54G) ключі " "нумеруються у діапазоні 1 - 4." -#: src/libnmc-setting/settings-docs.h.in:427 +#: src/libnmc-setting/settings-docs.h.in:431 msgid "" "Flags indicating which mode of WPS is to be used if any. There's little " "point in changing the default setting as NetworkManager will automatically " @@ -10804,7 +10829,7 @@ msgstr "" "можливо запустити засіб надання ролей WPS, на основі можливостей точки " "доступу. WPS можна вимкнути встановленням для цієї властивості значення 1." -#: src/libnmc-setting/settings-docs.h.in:428 +#: src/libnmc-setting/settings-docs.h.in:432 msgid "" "IEEE 802.15.4 channel. A positive integer or -1, meaning \"do not set, use " "whatever the device is already set to\"." @@ -10812,7 +10837,7 @@ msgstr "" "Канал IEEE 802.15.4. Додане ціле значення або -1, що означає «не " "встановлювати, використовувати той, який вже встановлено пристроєм»." -#: src/libnmc-setting/settings-docs.h.in:429 +#: src/libnmc-setting/settings-docs.h.in:433 msgid "" "If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) " "MAC layer device whose permanent MAC address matches." @@ -10820,7 +10845,7 @@ msgstr "" "Якщо вказано, це з'єднання застосовуватиметься лише до пристрою шару MAC " "IEEE 802.15.4 (WPAN) із відповідною сталою адресою MAC." -#: src/libnmc-setting/settings-docs.h.in:430 +#: src/libnmc-setting/settings-docs.h.in:434 msgid "" "IEEE 802.15.4 channel page. A positive integer or -1, meaning \"do not set, " "use whatever the device is already set to\"." @@ -10828,18 +10853,18 @@ msgstr "" "Сторінка каналу IEEE 80215.4. Додане ціле значення або -1, що означає «не " "встановлювати, використовувати ту, яку вже встановлено пристроєм»." -#: src/libnmc-setting/settings-docs.h.in:431 +#: src/libnmc-setting/settings-docs.h.in:435 msgid "IEEE 802.15.4 Personal Area Network (PAN) identifier." msgstr "Ідентифікатор Personal Area Network (PAN) IEEE 802.15.4." -#: src/libnmc-setting/settings-docs.h.in:432 +#: src/libnmc-setting/settings-docs.h.in:436 msgid "" "Short IEEE 802.15.4 address to be used within a restricted environment." msgstr "" "Коротка адреса IEEE 802.15.4, яку слід використовувати у обмеженому " "середовищі." -#: src/libnmc-setting/settings-docs.h.in:433 +#: src/libnmc-setting/settings-docs.h.in:437 msgid "" "The queue ID of this bond port. The maximum value of queue ID is the number " "of TX queues currently active in device." @@ -10848,7 +10873,7 @@ msgstr "" "ідентифікатора черги є кількість черг надсилання, які є у поточний момент " "активними на пристрої." -#: src/libnmc-setting/settings-docs.h.in:434 +#: src/libnmc-setting/settings-docs.h.in:438 msgid "" "Whether the system hostname can be determined from DHCP on this connection. " "When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is " @@ -10861,7 +10886,7 @@ msgstr "" "загальних налаштуваннях, NetworkManager припускає значення NM_TERNARY_TRUE " "(1)." -#: src/libnmc-setting/settings-docs.h.in:435 +#: src/libnmc-setting/settings-docs.h.in:439 msgid "" "Whether the system hostname can be determined from reverse DNS lookup of " "addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value " @@ -10875,7 +10900,7 @@ msgstr "" "значення у загальних налаштуваннях, NetworkManager припускає значення " "NM_TERNARY_TRUE (1)." -#: src/libnmc-setting/settings-docs.h.in:436 +#: src/libnmc-setting/settings-docs.h.in:440 msgid "" "If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname " "via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device " @@ -10896,7 +10921,7 @@ msgstr "" "значення у загальних налаштуваннях, NetworkManager припускає значення " "NM_TERNARY_FALSE (0)." -#: src/libnmc-setting/settings-docs.h.in:437 +#: src/libnmc-setting/settings-docs.h.in:441 msgid "" "The relative priority of this connection to determine the system hostname. A " "lower numerical value is better (higher priority). A connection with higher " @@ -10920,11 +10945,22 @@ msgstr "" "пріоритетністю, для визначення назви вузла буде використано лише з'єднання " "із найнижчим значенням пріоритетності." -#: src/libnmc-setting/settings-docs.h.in:439 -msgid "A dictionary of key/value pairs with exernal-ids for OVS." +#: src/libnmc-setting/settings-docs.h.in:443 +#| msgid "A dictionary of key/value pairs with exernal-ids for OVS." +msgid "A dictionary of key/value pairs with external-ids for OVS." msgstr "Словник з пар ключ/значення із зовнішніми ідентифікаторами для OVS." -#: src/libnmc-setting/settings-docs.h.in:440 +#: src/libnmc-setting/settings-docs.h.in:444 +msgid "" +"A dictionary of key/value pairs with other_config settings for OVS. See also " +"\"other_config\" in the \"ovs-vswitchd.conf.db\" manual for the keys that " +"OVS supports." +msgstr "" +"Словник пар «ключ/значення із параметрами other_config для OVS. Див. також" +" «other_config» у підручнику з «ovs-vswitchd.conf.db», щоб дізнатися більше" +" про ключі, підтримку яких передбачено у OVS." + +#: src/libnmc-setting/settings-docs.h.in:445 msgid "" "This property specifies the peer interface name of the veth. This property " "is mandatory." @@ -12017,9 +12053,9 @@ msgstr "Помилка: «connection show»: %s" msgid "Active connection details" msgstr "Активувати параметри з'єднання" -#: src/nmcli/connections.c:1795 src/nmcli/devices.c:1663 -#: src/nmcli/devices.c:1680 src/nmcli/devices.c:1698 src/nmcli/devices.c:1717 -#: src/nmcli/devices.c:1781 src/nmcli/devices.c:1910 +#: src/nmcli/connections.c:1795 src/nmcli/devices.c:1660 +#: src/nmcli/devices.c:1677 src/nmcli/devices.c:1695 src/nmcli/devices.c:1714 +#: src/nmcli/devices.c:1778 src/nmcli/devices.c:1907 msgid "NAME" msgstr "НАЗВА" @@ -12072,14 +12108,14 @@ msgstr "Профілі з'єднань NetworkManager" #: src/nmcli/connections.c:2432 src/nmcli/connections.c:3153 #: src/nmcli/connections.c:3165 src/nmcli/connections.c:3177 #: src/nmcli/connections.c:3413 src/nmcli/connections.c:9641 -#: src/nmcli/connections.c:9660 src/nmcli/devices.c:3372 -#: src/nmcli/devices.c:3385 src/nmcli/devices.c:3397 src/nmcli/devices.c:3701 -#: src/nmcli/devices.c:3712 src/nmcli/devices.c:3731 src/nmcli/devices.c:3740 -#: src/nmcli/devices.c:3762 src/nmcli/devices.c:3773 src/nmcli/devices.c:3794 -#: src/nmcli/devices.c:4358 src/nmcli/devices.c:4369 src/nmcli/devices.c:4378 -#: src/nmcli/devices.c:4392 src/nmcli/devices.c:4410 src/nmcli/devices.c:4419 -#: src/nmcli/devices.c:4575 src/nmcli/devices.c:4586 src/nmcli/devices.c:4805 -#: src/nmcli/devices.c:4984 src/nmcli/devices.c:5205 +#: src/nmcli/connections.c:9660 src/nmcli/devices.c:3369 +#: src/nmcli/devices.c:3382 src/nmcli/devices.c:3394 src/nmcli/devices.c:3698 +#: src/nmcli/devices.c:3709 src/nmcli/devices.c:3728 src/nmcli/devices.c:3737 +#: src/nmcli/devices.c:3759 src/nmcli/devices.c:3770 src/nmcli/devices.c:3791 +#: src/nmcli/devices.c:4355 src/nmcli/devices.c:4366 src/nmcli/devices.c:4375 +#: src/nmcli/devices.c:4389 src/nmcli/devices.c:4407 src/nmcli/devices.c:4416 +#: src/nmcli/devices.c:4572 src/nmcli/devices.c:4583 src/nmcli/devices.c:4802 +#: src/nmcli/devices.c:4981 src/nmcli/devices.c:5202 #, c-format msgid "Error: %s argument is missing." msgstr "Помилка: пропущено аргумент %s." @@ -12092,14 +12128,14 @@ msgstr "Помилка: профілю з'єднання %s не існує." #: src/nmcli/connections.c:2559 src/nmcli/connections.c:3139 #: src/nmcli/connections.c:3213 src/nmcli/connections.c:9147 #: src/nmcli/connections.c:9231 src/nmcli/connections.c:9765 -#: src/nmcli/devices.c:2010 src/nmcli/devices.c:2312 src/nmcli/devices.c:2479 -#: src/nmcli/devices.c:2605 src/nmcli/devices.c:2789 src/nmcli/devices.c:3572 -#: src/nmcli/devices.c:4539 src/nmcli/devices.c:4991 src/nmcli/general.c:1068 +#: src/nmcli/devices.c:2007 src/nmcli/devices.c:2309 src/nmcli/devices.c:2476 +#: src/nmcli/devices.c:2602 src/nmcli/devices.c:2786 src/nmcli/devices.c:3569 +#: src/nmcli/devices.c:4536 src/nmcli/devices.c:4988 src/nmcli/general.c:1068 #, c-format msgid "Error: %s." msgstr "Помилка: %s." -#: src/nmcli/connections.c:2651 src/nmcli/devices.c:4758 +#: src/nmcli/connections.c:2651 src/nmcli/devices.c:4755 #, c-format msgid "no active connection on device '%s'" msgstr "на пристрої «%s» немає активних з'єднань" @@ -12174,10 +12210,10 @@ msgid "invalid passwd-file '%s': %s" msgstr "некоректний файл passwd «%s»: %s" #: src/nmcli/connections.c:3187 src/nmcli/connections.c:9669 -#: src/nmcli/devices.c:1967 src/nmcli/devices.c:2016 src/nmcli/devices.c:2485 -#: src/nmcli/devices.c:2677 src/nmcli/devices.c:2744 src/nmcli/devices.c:2944 -#: src/nmcli/devices.c:3432 src/nmcli/devices.c:3810 src/nmcli/devices.c:4429 -#: src/nmcli/devices.c:4592 src/nmcli/devices.c:4813 src/nmcli/devices.c:4996 +#: src/nmcli/devices.c:1964 src/nmcli/devices.c:2013 src/nmcli/devices.c:2482 +#: src/nmcli/devices.c:2674 src/nmcli/devices.c:2741 src/nmcli/devices.c:2941 +#: src/nmcli/devices.c:3429 src/nmcli/devices.c:3807 src/nmcli/devices.c:4426 +#: src/nmcli/devices.c:4589 src/nmcli/devices.c:4810 src/nmcli/devices.c:4993 #, c-format msgid "Error: invalid extra argument '%s'." msgstr "Помилка: некоректний додатковий аргумент, «%s»." @@ -12232,13 +12268,11 @@ msgstr "Помилка: некоректна властивість, «%s»: %s. #: src/nmcli/connections.c:4347 #, c-format -#| msgid "Error: failed to %s %s.%s: %s." msgid "Error: failed to modify %s.%s: %s." msgstr "Помилка: не вдалося змінити %s.%s: %s." #: src/nmcli/connections.c:4348 #, c-format -#| msgid "Error: failed to remove value of '%s': %s\n" msgid "Error: failed to remove a value from %s.%s: %s." msgstr "Помилка: не вдалося вилучити значення з %s.%s: %s." @@ -12313,7 +12347,7 @@ msgstr "Помилка: «%s» є неоднозначним (%s.%s або %s.%s msgid "Error: invalid . '%s'." msgstr "Помилка: некоректний аргумент <параметр>.<властивість>, «%s»." -#: src/nmcli/connections.c:5430 src/nmcli/devices.c:2199 +#: src/nmcli/connections.c:5430 src/nmcli/devices.c:2196 #, c-format msgid "Warning: %s.\n" msgstr "Попередження: %s.\n" @@ -13331,7 +13365,7 @@ msgstr "Інтерфейс: " msgid "Interface(s): " msgstr "Інтерфейси: " -#: src/nmcli/devices.c:71 src/nmcli/devices.c:1442 +#: src/nmcli/devices.c:71 src/nmcli/devices.c:1439 msgid "(none)" msgstr "(немає)" @@ -13801,219 +13835,219 @@ msgstr "Попередження: аргумент «%s» дубльовано.\ msgid "Error: Device '%s' not found.\n" msgstr "Помилка: не знайдено пристрій «%s».\n" -#: src/nmcli/devices.c:1184 src/nmcli/devices.c:5229 +#: src/nmcli/devices.c:1184 src/nmcli/devices.c:5226 msgid "Error: not all devices found." msgstr "Помилка: знайдено не усі пристрої." -#: src/nmcli/devices.c:1216 +#: src/nmcli/devices.c:1213 msgid "No interface specified" msgstr "Не вказано інтерфейс" -#: src/nmcli/devices.c:1237 +#: src/nmcli/devices.c:1234 #, c-format msgid "Device '%s' not found" msgstr "Не знайдено пристрою «%s»" -#: src/nmcli/devices.c:1349 +#: src/nmcli/devices.c:1346 #, c-format msgid "%u MHz" msgstr "%u МГц" -#: src/nmcli/devices.c:1350 +#: src/nmcli/devices.c:1347 #, c-format msgid "%u Mbit/s" msgstr "%u МБ/с" -#: src/nmcli/devices.c:1395 +#: src/nmcli/devices.c:1392 msgid "Ad-Hoc" msgstr "Ad-Hoc" -#: src/nmcli/devices.c:1396 +#: src/nmcli/devices.c:1393 msgid "Infra" msgstr "Інфраструктура" -#: src/nmcli/devices.c:1398 +#: src/nmcli/devices.c:1395 msgid "N/A" msgstr "н/д" -#: src/nmcli/devices.c:1590 +#: src/nmcli/devices.c:1587 msgid "Device details" msgstr "Дані щодо пристрою" -#: src/nmcli/devices.c:1607 +#: src/nmcli/devices.c:1604 #, c-format msgid "Error: 'device show': %s" msgstr "Помилка: «device show»: %s" -#: src/nmcli/devices.c:1984 +#: src/nmcli/devices.c:1981 msgid "Status of devices" msgstr "Стан пристрою" -#: src/nmcli/devices.c:1988 +#: src/nmcli/devices.c:1985 #, c-format msgid "Error: 'device status': %s" msgstr "Помилка: «device status»: %s" -#: src/nmcli/devices.c:2051 src/nmcli/general.c:527 +#: src/nmcli/devices.c:2048 src/nmcli/general.c:527 #, c-format msgid "Error: Timeout %d sec expired." msgstr "Помилка: перевищено час очікування у %d с." -#: src/nmcli/devices.c:2128 +#: src/nmcli/devices.c:2125 #, c-format msgid "Device '%s' successfully activated with '%s'.\n" msgstr "Пристрій «%s» успішно активовано з «%s».\n" -#: src/nmcli/devices.c:2134 +#: src/nmcli/devices.c:2131 msgid "" "Hint: \"nmcli dev wifi show-password\" shows the Wi-Fi name and password.\n" msgstr "" "Підказка: за допомогою команди «nmcli dev wifi show-password» можна " "переглянути ім'я користувача Wi-Fi і пароль.\n" -#: src/nmcli/devices.c:2138 +#: src/nmcli/devices.c:2135 #, c-format msgid "Error: Connection activation failed: %s." msgstr "Помилка: не вдалося активувати з'єднання: %s." -#: src/nmcli/devices.c:2180 +#: src/nmcli/devices.c:2177 #, c-format msgid "Error: Failed to setup a Wi-Fi hotspot: %s" msgstr "Помилка: не вдалося налаштувати точку доступу Wi-Fi: %s" -#: src/nmcli/devices.c:2184 +#: src/nmcli/devices.c:2181 #, c-format msgid "Error: Failed to add/activate new connection: %s" msgstr "Помилка: не вдалося додати або задіяти нове з'єднання: %s" -#: src/nmcli/devices.c:2188 +#: src/nmcli/devices.c:2185 #, c-format msgid "Error: Failed to activate connection: %s" msgstr "Помилка: не вдалося задіяти з'єднання: %s" -#: src/nmcli/devices.c:2262 +#: src/nmcli/devices.c:2259 #, c-format msgid "Error: Device activation failed: %s" msgstr "Помилка: не вдалося активувати пристрій: %s" -#: src/nmcli/devices.c:2318 +#: src/nmcli/devices.c:2315 #, c-format msgid "Error: extra argument not allowed: '%s'." msgstr "Помилка: некоректний додатковий аргумент, «%s»." -#: src/nmcli/devices.c:2387 src/nmcli/devices.c:2400 src/nmcli/devices.c:2655 +#: src/nmcli/devices.c:2384 src/nmcli/devices.c:2397 src/nmcli/devices.c:2652 #, c-format msgid "Device '%s' successfully disconnected.\n" msgstr "Пристрій «%s» успішно від'єднано.\n" -#: src/nmcli/devices.c:2389 src/nmcli/devices.c:2725 +#: src/nmcli/devices.c:2386 src/nmcli/devices.c:2722 #, c-format msgid "Device '%s' successfully removed.\n" msgstr "Пристрій «%s» успішно вилучено.\n" -#: src/nmcli/devices.c:2449 src/nmcli/devices.c:2531 +#: src/nmcli/devices.c:2446 src/nmcli/devices.c:2528 #, c-format msgid "Error: Reapplying connection to device '%s' (%s) failed: %s" msgstr "" "Помилка: не вдалося повторно застосувати з'єднання із пристроєм «%s» (%s): %s" -#: src/nmcli/devices.c:2459 src/nmcli/devices.c:2540 +#: src/nmcli/devices.c:2456 src/nmcli/devices.c:2537 #, c-format msgid "Connection successfully reapplied to device '%s'.\n" msgstr "З'єднання успішно повторно застосовано до пристрою «%s».\n" -#: src/nmcli/devices.c:2562 +#: src/nmcli/devices.c:2559 #, c-format msgid "Error: Reading applied connection from device '%s' (%s) failed: %s" msgstr "" "Помилка: спроба читання застосованого з'єднання з пристрою «%s» (%s) зазнала " "невдачі: %s" -#: src/nmcli/devices.c:2639 +#: src/nmcli/devices.c:2636 msgid "Error: not all devices disconnected." msgstr "Помилка: не усі пристрої від'єднано." -#: src/nmcli/devices.c:2640 +#: src/nmcli/devices.c:2637 #, c-format msgid "Error: Device '%s' (%s) disconnecting failed: %s\n" msgstr "Помилка: невдала спроба від'єднання «%s» (%s): %s\n" -#: src/nmcli/devices.c:2716 +#: src/nmcli/devices.c:2713 msgid "Error: not all devices deleted." msgstr "Помилка: вилучено не усі пристрої." -#: src/nmcli/devices.c:2717 +#: src/nmcli/devices.c:2714 #, c-format msgid "Error: Device '%s' (%s) deletion failed: %s\n" msgstr "Помилка: помилка під час спроби вилучення пристрою «%s» (%s): %s\n" -#: src/nmcli/devices.c:2795 +#: src/nmcli/devices.c:2792 msgid "Error: No property specified." msgstr "Помилка: не вказано властивості." -#: src/nmcli/devices.c:2812 src/nmcli/devices.c:2831 src/nmcli/general.c:797 +#: src/nmcli/devices.c:2809 src/nmcli/devices.c:2828 src/nmcli/general.c:797 #: src/nmcli/general.c:819 #, c-format msgid "Error: '%s' argument is missing." msgstr "Помилка: пропущено параметр %s." -#: src/nmcli/devices.c:2820 +#: src/nmcli/devices.c:2817 #, c-format msgid "Error: 'managed': %s." msgstr "Помилка: «managed»: %s." -#: src/nmcli/devices.c:2839 +#: src/nmcli/devices.c:2836 #, c-format msgid "Error: 'autoconnect': %s." msgstr "Помилка: «autoconnect»: %s." -#: src/nmcli/devices.c:2846 src/nmcli/general.c:869 +#: src/nmcli/devices.c:2843 src/nmcli/general.c:869 #, c-format msgid "Error: property '%s' is not known." msgstr "Помилка: властивість «%s» є невідомою." -#: src/nmcli/devices.c:2893 +#: src/nmcli/devices.c:2890 #, c-format msgid "%s: using connection '%s'\n" msgstr "%s: використовуємо з'єднання «%s»\n" -#: src/nmcli/devices.c:2919 +#: src/nmcli/devices.c:2916 #, c-format msgid "%s: device created\n" msgstr "%s: створено запис пристрою\n" -#: src/nmcli/devices.c:2926 +#: src/nmcli/devices.c:2923 #, c-format msgid "%s: device removed\n" msgstr "%s: пристрій вилучено\n" -#: src/nmcli/devices.c:3106 +#: src/nmcli/devices.c:3103 msgid "Wi-Fi scan list" msgstr "Список сканування Wi-Fi" -#: src/nmcli/devices.c:3223 src/nmcli/devices.c:3504 +#: src/nmcli/devices.c:3220 src/nmcli/devices.c:3501 #, c-format msgid "Error: Access point with bssid '%s' not found." msgstr "Помилка: не знайдено точки доступу з bssid «%s»." -#: src/nmcli/devices.c:3425 +#: src/nmcli/devices.c:3422 #, c-format msgid "Error: 'device wifi': %s" msgstr "Помилка: «device wifi»: %s" -#: src/nmcli/devices.c:3445 +#: src/nmcli/devices.c:3442 #, c-format msgid "Error: invalid rescan argument: '%s' not among [auto, no, yes]" msgstr "" "Помилка: некоректний аргумент rescan: «%s» не належить до набору [auto, no, " "yes]" -#: src/nmcli/devices.c:3484 +#: src/nmcli/devices.c:3481 #, c-format msgid "Error: Device '%s' not found." msgstr "Помилка: не знайдено пристрій «%s»." -#: src/nmcli/devices.c:3488 +#: src/nmcli/devices.c:3485 #, c-format msgid "" "Error: Device '%s' was not recognized as a Wi-Fi device, check " @@ -14022,26 +14056,26 @@ msgstr "" "Помилка: пристрій «%s» не розпізнано як пристрій Wi-Fi, перевірте, чи працює " "додаток Wi-Fi NetworkManager." -#: src/nmcli/devices.c:3493 src/nmcli/devices.c:3845 src/nmcli/devices.c:4474 -#: src/nmcli/devices.c:4609 src/nmcli/devices.c:4744 +#: src/nmcli/devices.c:3490 src/nmcli/devices.c:3842 src/nmcli/devices.c:4471 +#: src/nmcli/devices.c:4606 src/nmcli/devices.c:4741 #, c-format msgid "Error: Device '%s' is not a Wi-Fi device." msgstr "Помилка: пристрій «%s» не є пристроєм Wi-Fi." -#: src/nmcli/devices.c:3673 +#: src/nmcli/devices.c:3670 msgid "SSID or BSSID: " msgstr "SSID або BSSID: " -#: src/nmcli/devices.c:3678 +#: src/nmcli/devices.c:3675 msgid "Error: SSID or BSSID are missing." msgstr "Помилка: не вистачає SSID або BSSID." -#: src/nmcli/devices.c:3722 +#: src/nmcli/devices.c:3719 #, c-format msgid "Error: bssid argument value '%s' is not a valid BSSID." msgstr "Помилка: значення параметра bssid, «%s», не є коректним BSSID." -#: src/nmcli/devices.c:3753 +#: src/nmcli/devices.c:3750 #, c-format msgid "" "Error: wep-key-type argument value '%s' is invalid, use 'key' or 'phrase'." @@ -14049,48 +14083,48 @@ msgstr "" "Помилка: значення параметра wep-key-type, «%s», є некоректним, слід " "використовувати «key» або «phrase»." -#: src/nmcli/devices.c:3781 src/nmcli/devices.c:3802 +#: src/nmcli/devices.c:3778 src/nmcli/devices.c:3799 #, c-format msgid "Error: %s: %s." msgstr "Помилка: %s: %s." -#: src/nmcli/devices.c:3824 +#: src/nmcli/devices.c:3821 #, c-format msgid "Error: BSSID to connect to (%s) differs from bssid argument (%s)." msgstr "" "Помилка: BSSID для з'єднання з (%s) відрізняється від параметра bssid (%s)." -#: src/nmcli/devices.c:3832 +#: src/nmcli/devices.c:3829 #, c-format msgid "Error: Parameter '%s' is neither SSID nor BSSID." msgstr "Помилка: параметр «%s» не дорівнює ні SSID, ні BSSID." -#: src/nmcli/devices.c:3848 src/nmcli/devices.c:4477 src/nmcli/devices.c:4612 -#: src/nmcli/devices.c:4844 +#: src/nmcli/devices.c:3845 src/nmcli/devices.c:4474 src/nmcli/devices.c:4609 +#: src/nmcli/devices.c:4841 msgid "Error: No Wi-Fi device found." msgstr "Помилка: не знайдено жодного пристрою Wi-Fi." -#: src/nmcli/devices.c:3870 +#: src/nmcli/devices.c:3867 #, c-format msgid "Error: Failed to scan hidden SSID: %s." msgstr "Помилка: неможливо виконати сканування прихованого SSID: %s." -#: src/nmcli/devices.c:3902 +#: src/nmcli/devices.c:3899 #, c-format msgid "Error: No network with SSID '%s' found." msgstr "Помилка: не знайдено мережі з SSID «%s»." -#: src/nmcli/devices.c:3906 +#: src/nmcli/devices.c:3903 #, c-format msgid "Error: No access point with BSSID '%s' found." msgstr "Помилка: не знайдено точки доступу з BSSID «%s»." -#: src/nmcli/devices.c:3935 +#: src/nmcli/devices.c:3932 #, c-format msgid "Error: Connection '%s' exists but properties don't match." msgstr "Помилка: існує з'єднання «%s», але його властивості є невідповідними." -#: src/nmcli/devices.c:3984 +#: src/nmcli/devices.c:3981 #, c-format msgid "" "Warning: '%s' should be SSID for hidden APs; but it looks like a BSSID.\n" @@ -14098,116 +14132,116 @@ msgstr "" "Попередження: «%s» має бути SSID для прихованих точок доступу; втім, " "здається, маємо BSSID.\n" -#: src/nmcli/devices.c:4026 +#: src/nmcli/devices.c:4023 msgid "Password: " msgstr "Пароль: " -#: src/nmcli/devices.c:4164 +#: src/nmcli/devices.c:4161 #, c-format msgid "'%s' is not valid WPA PSK" msgstr "«%s» не є коректним PSK WPA" -#: src/nmcli/devices.c:4185 +#: src/nmcli/devices.c:4182 #, c-format msgid "'%s' is not valid WEP key (it should be 5 or 13 ASCII chars)" msgstr "" "«%s» не є коректним ключем WEP (коректний ключ має складатися з 5 або 13 " "символів ASCII)" -#: src/nmcli/devices.c:4204 +#: src/nmcli/devices.c:4201 #, c-format msgid "Hotspot password: %s\n" msgstr "Пароль до точки доступу: %s\n" -#: src/nmcli/devices.c:4383 +#: src/nmcli/devices.c:4380 msgid "Error: ssid is too long." msgstr "Помилка: SSID є надто довгим." -#: src/nmcli/devices.c:4401 +#: src/nmcli/devices.c:4398 #, c-format msgid "Error: band argument value '%s' is invalid; use 'a' or 'bg'." msgstr "" "Помилка: значення аргументу «band» «%s» є некоректним; має бути «a» або «bg»." -#: src/nmcli/devices.c:4452 +#: src/nmcli/devices.c:4449 msgid "Error: channel requires band too." msgstr "Помилка: разом із каналом слід вказати смугу." -#: src/nmcli/devices.c:4459 +#: src/nmcli/devices.c:4456 #, c-format msgid "Error: channel '%s' not valid for band '%s'." msgstr "Помилка: не можна використовувати канал «%s» для смуги «%s»." -#: src/nmcli/devices.c:4490 +#: src/nmcli/devices.c:4487 #, c-format msgid "Error: Device '%s' supports neither AP nor Ad-Hoc mode." msgstr "" "Помилка: для пристрою «%s» не передбачено ні режиму точки доступу, ні режиму " "Ad-Hoc." -#: src/nmcli/devices.c:4517 +#: src/nmcli/devices.c:4514 #, c-format msgid "Error: Invalid 'password': %s." msgstr "Помилка: некоректне значення «password»: %s." -#: src/nmcli/devices.c:4568 src/nmcli/devices.c:4798 +#: src/nmcli/devices.c:4565 src/nmcli/devices.c:4795 #, c-format msgid "Error: '%s' cannot repeat." msgstr "Помилка: не можна повторювати «%s»." -#: src/nmcli/devices.c:4703 src/nmcli/devices.c:4706 src/nmcli/devices.c:4710 -#: src/nmcli/devices.c:4713 src/nmtui/nmt-page-wifi.c:269 +#: src/nmcli/devices.c:4700 src/nmcli/devices.c:4703 src/nmcli/devices.c:4707 +#: src/nmcli/devices.c:4710 src/nmtui/nmt-page-wifi.c:269 msgid "Security" msgstr "Захист" -#: src/nmcli/devices.c:4703 +#: src/nmcli/devices.c:4700 msgid "None" msgstr "Немає" #. Main header name -#: src/nmcli/devices.c:4885 +#: src/nmcli/devices.c:4882 msgid "Device LLDP neighbors" msgstr "LLDP-сусіди пристрою" -#: src/nmcli/devices.c:5018 +#: src/nmcli/devices.c:5015 #, c-format msgid "Error: 'device lldp list': %s" msgstr "Помилка: «device lldp list»: %s" -#: src/nmcli/devices.c:5086 +#: src/nmcli/devices.c:5083 msgid "Checkpoint was removed." msgstr "Контрольну точку було вилучено." #. The command is done, we're in the confirmation prompt. -#: src/nmcli/devices.c:5093 +#: src/nmcli/devices.c:5090 msgid "No" msgstr "Ні" -#: src/nmcli/devices.c:5106 +#: src/nmcli/devices.c:5103 #, c-format msgid "Error: Destroying a checkpoint failed: %s" msgstr "Помилка: не вдалося знищити контрольну точку: %s" -#: src/nmcli/devices.c:5128 src/nmcli/devices.c:5129 +#: src/nmcli/devices.c:5125 src/nmcli/devices.c:5126 msgid "Yes" msgstr "Так" -#: src/nmcli/devices.c:5155 +#: src/nmcli/devices.c:5152 #, c-format msgid "Error: Creating a checkpoint failed: %s" msgstr "Помилка: не вдалося створити контрольну точку: %s" -#: src/nmcli/devices.c:5171 +#: src/nmcli/devices.c:5168 #, c-format msgid "Error: %s" msgstr "Помилка: %s" -#: src/nmcli/devices.c:5210 src/nmcli/nmcli.c:885 +#: src/nmcli/devices.c:5207 src/nmcli/nmcli.c:885 #, c-format msgid "Error: '%s' is not a valid timeout." msgstr "Помилка: «%s» не є коректним часом очікування." -#: src/nmcli/devices.c:5237 +#: src/nmcli/devices.c:5234 msgid "Error: Expected a command to run after '--'" msgstr "Помилка: після «--» мало бути вказано команду, яку слід запустити" @@ -14692,12 +14726,10 @@ msgid "WWAN radio switch" msgstr "Перемикач WWAN" #: src/nmcli/general.c:1236 -#| msgid "NetworkManager is not running" msgid "NetworkManager is running" msgstr "NetworkManager запущено" #: src/nmcli/general.c:1236 -#| msgid "NetworkManager has stopped" msgid "NetworkManager is stopped" msgstr "NetworkManager зупинено" @@ -15017,7 +15049,6 @@ msgstr "«%s» не є профілем з'єднання VPN" #: src/nmcli/settings.c:388 #, c-format -#| msgid "'%s' is not a name of any exiting profile" msgid "'%s' is not a name of any existing profile" msgstr "«%s» не є назвою жодного з наявних профілів" @@ -15279,7 +15310,7 @@ msgstr "TTLS" msgid "PEAP" msgstr "PEAP" -#: src/nmtui/nmt-device-entry.c:348 +#: src/nmtui/nmt-device-entry.c:350 msgid "Select..." msgstr "Вибрати…" -- cgit v1.2.1 From f2f806f77d96b2094a23ef1c67a9f07bd8ae6fff Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 12 Sep 2022 13:17:34 +0200 Subject: dns-manager: style fix --- src/core/dns/nm-dns-manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index ea02d4f7c8..457b82a098 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1311,9 +1311,9 @@ _collect_resolv_conf_data(NMDnsManager *self, priv = NM_DNS_MANAGER_GET_PRIVATE(self); - if (global_config) + if (global_config) { merge_global_dns_config(&rc, global_config); - else { + } else { nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE); int first_prio = 0; const NMDnsConfigIPData *ip_data; -- cgit v1.2.1 From 051819a78e6d2c4b4a5a158f78a50e1ff524fe9c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 12 Sep 2022 13:47:35 +0200 Subject: config-data: style fix --- src/core/nm-config-data.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index 61cf111894..1504b15659 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -1125,10 +1125,13 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) gboolean default_found = FALSE; char **strv; - group = - internal ? NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS : NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS; - domain_prefix = internal ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN - : NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN; + if (internal) { + group = NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS; + domain_prefix = NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN; + } else { + group = NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS; + domain_prefix = NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN; + } domain_prefix_len = strlen(domain_prefix); if (!nm_config_keyfile_has_global_dns_config(keyfile, internal)) -- cgit v1.2.1 From de1c06daab7691986d16925c2107b1e8c30d0f47 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 12 Sep 2022 13:17:50 +0200 Subject: config: fix a reversed conditional This effectively makes [*global-dns-domain-*] sections in configuration be ignored unless [*global-dns] is also present. This happens because nm_config_keyfile_has_global_dns_config() mixes the group names up and attempts to loop up [.intern.global-dns-domain-*] in user configuration and [global-dns-domain-*] in the internal one. Fixes: da0ded49279c ('config: drop global-dns.enable option in favor of .config.enable') --- src/core/nm-config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/nm-config.c b/src/core/nm-config.c index 807399783c..b74453628a 100644 --- a/src/core/nm-config.c +++ b/src/core/nm-config.c @@ -1509,8 +1509,8 @@ nm_config_keyfile_has_global_dns_config(GKeyFile *keyfile, gboolean internal) if (!keyfile) return FALSE; if (g_key_file_has_group(keyfile, - internal ? NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS - : NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS)) + internal ? NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS + : NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS)) return TRUE; groups = g_key_file_get_groups(keyfile, NULL); -- cgit v1.2.1 From 1f0d1d78d2a28ef82764a801c344e22816b06f67 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 12 Sep 2022 13:21:51 +0200 Subject: dns-manager: always apply options from [global-dns] Currently, the use of [global-dns] section for setting DNS options is conditioned on presence of a nameserver in a [global-dns-domain-*] section. Attempt to use the section for options alone results in an error: [global-dns] options=timeout:1 Or via D-Bus API: # busctl set-property org.freedesktop.NetworkManager \ /org/freedesktop/NetworkManager org.freedesktop.NetworkManager \ GlobalDnsConfiguration 'a{sv}' 2 \ "options" as 1 "timeout:1" \ "domains" a{sv} 0 ... Nov 24 13:15:21 zmok.local NetworkManager[501184]: [1669292121.3904] manager: set global DNS failed with error: Global DNS configuration is missing the default domain The insistence on existence of [global-dns-domain-*] would make sense if other [global-dns-domain-...] sections were present. However, the user might only want to set the options in resolv.conf and still use connection-provide nameservers for the actual resolving. Lift the limitation by allowing the [global-dns] to be used alone, while still insist on [global-dns-domain-*] being there in presence of other domain-specific options. https://bugzilla.redhat.com/show_bug.cgi?id=2019306 --- Makefile.am | 2 ++ src/core/dns/nm-dns-manager.c | 41 +++++++++++++-------------- src/core/nm-config-data.c | 2 +- src/core/tests/config/global-dns-good.conf | 13 +++++++++ src/core/tests/config/global-dns-options.conf | 5 ++++ src/core/tests/config/test-config.c | 16 ++++++++++- 6 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 src/core/tests/config/global-dns-good.conf create mode 100644 src/core/tests/config/global-dns-options.conf diff --git a/Makefile.am b/Makefile.am index aa79967e1b..3d43c010a7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4497,7 +4497,9 @@ EXTRA_DIST += \ src/core/tests/config/NetworkManager-warn.conf \ src/core/tests/config/NetworkManager.state \ src/core/tests/config/bad.conf \ + src/core/tests/config/global-dns-good.conf \ src/core/tests/config/global-dns-invalid.conf \ + src/core/tests/config/global-dns-options.conf \ src/core/tests/config/conf.d/00-overrides.conf \ src/core/tests/config/conf.d/10-more.conf \ src/core/tests/config/conf.d/20-config-enable-1.conf \ diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 457b82a098..42519e64fe 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1201,7 +1201,8 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[ if (global) nm_global_dns_config_update_checksum(global, sum); - else { + + if (!global || !nm_global_dns_config_lookup_domain(global, "*")) { const CList *head; /* FIXME(ip-config-checksum): this relies on the fact that an IP @@ -1244,13 +1245,15 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) } default_domain = nm_global_dns_config_lookup_domain(global_conf, "*"); - nm_assert(default_domain); + if (!default_domain) + return TRUE; servers = nm_global_dns_domain_get_servers(default_domain); - if (servers) { - for (i = 0; servers[i]; i++) - add_string_item(rc->nameservers, servers[i], TRUE); - } + if (!servers) + return TRUE; + + for (i = 0; servers[i]; i++) + add_string_item(rc->nameservers, servers[i], TRUE); return TRUE; } @@ -1311,9 +1314,10 @@ _collect_resolv_conf_data(NMDnsManager *self, priv = NM_DNS_MANAGER_GET_PRIVATE(self); - if (global_config) { + if (global_config) merge_global_dns_config(&rc, global_config); - } else { + + if (!global_config || !nm_global_dns_config_lookup_domain(global_config, "*")) { nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE); int first_prio = 0; const NMDnsConfigIPData *ip_data; @@ -2556,14 +2560,12 @@ config_changed_cb(NMConfig *config, } } -static GVariant * -_get_global_config_variant(NMGlobalDnsConfig *global) +static void +_get_global_config_variant(GVariantBuilder *builder, NMGlobalDnsConfig *global) { NMGlobalDnsDomain *domain; - GVariantBuilder builder; guint i, num; - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); num = nm_global_dns_config_get_num_domains(global); for (i = 0; i < num; i++) { GVariantBuilder conf_builder; @@ -2599,10 +2601,8 @@ _get_global_config_variant(NMGlobalDnsConfig *global) "priority", g_variant_new_int32(NM_DNS_PRIORITY_DEFAULT_NORMAL)); - g_variant_builder_add(&builder, "a{sv}", &conf_builder); + g_variant_builder_add(builder, "a{sv}", &conf_builder); } - - return g_variant_ref_sink(g_variant_builder_end(&builder)); } static GVariant * @@ -2619,15 +2619,12 @@ _get_config_variant(NMDnsManager *self) if (priv->config_variant) return priv->config_variant; - global_config = nm_config_data_get_global_dns_config(nm_config_get_data(priv->config)); - if (global_config) { - priv->config_variant = _get_global_config_variant(global_config); - _LOGT("current configuration: %s", (str = g_variant_print(priv->config_variant, TRUE))); - return priv->config_variant; - } - g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + global_config = nm_config_data_get_global_dns_config(nm_config_get_data(priv->config)); + if (global_config) + _get_global_config_variant(&builder, global_config); + head = _mgr_get_ip_data_lst_head(self); c_list_for_each_entry (ip_data, head, ip_data_lst) { GVariantBuilder entry_builder; diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index 1504b15659..c6ab998f94 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -1233,7 +1233,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal) default_found = TRUE; } - if (!default_found) { + if (!default_found && g_hash_table_size(dns_config->domains)) { nm_log_dbg(LOGD_CORE, "%s global DNS configuration is missing default domain, ignore it", internal ? "internal" : "user"); diff --git a/src/core/tests/config/global-dns-good.conf b/src/core/tests/config/global-dns-good.conf new file mode 100644 index 0000000000..6265a611cf --- /dev/null +++ b/src/core/tests/config/global-dns-good.conf @@ -0,0 +1,13 @@ +# Good configuration, since there is a default domain section + +[global-dns] +searches=foo.com +options=timeout:5 + +[global-dns-domain-*] +servers=4.5.6.7 +options=myoption1 + +[global-dns-domain-test.com] +servers=1.2.3.4 +options=myoption2 diff --git a/src/core/tests/config/global-dns-options.conf b/src/core/tests/config/global-dns-options.conf new file mode 100644 index 0000000000..0be1773525 --- /dev/null +++ b/src/core/tests/config/global-dns-options.conf @@ -0,0 +1,5 @@ +# Good configuration, since there is no domain section + +[global-dns] +searches=foo.com +options=timeout:5 diff --git a/src/core/tests/config/test-config.c b/src/core/tests/config/test-config.c index fa7fae0757..054b9003f4 100644 --- a/src/core/tests/config/test-config.c +++ b/src/core/tests/config/test-config.c @@ -370,7 +370,21 @@ test_config_global_dns(void) g_object_unref(config); - /* Check that a file without a default domain section gives a NULL configuration */ + /* Check that a file with a default domain section gives a good configuration */ + config = + setup_config(NULL, TEST_DIR "/global-dns-good.conf", "", NULL, "/no/such/dir", "", NULL); + dns = nm_config_data_get_global_dns_config(nm_config_get_data_orig(config)); + g_assert(dns); + g_object_unref(config); + + /* Check that a file with options but no domains gives a good configuration */ + config = + setup_config(NULL, TEST_DIR "/global-dns-options.conf", "", NULL, "/no/such/dir", "", NULL); + dns = nm_config_data_get_global_dns_config(nm_config_get_data_orig(config)); + g_assert(dns); + g_object_unref(config); + + /* Check that a file with a domain domain, but without a default one gives a NULL configuration */ config = setup_config(NULL, TEST_DIR "/global-dns-invalid.conf", "", NULL, "/no/such/dir", "", NULL); dns = nm_config_data_get_global_dns_config(nm_config_get_data_orig(config)); -- cgit v1.2.1 From fd7175969c8819599d8ba099a35c731ff24e5eb8 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 16 Jan 2023 08:09:55 +0100 Subject: libnm/client: drop an unused argument https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1502 --- src/libnm-client-impl/nm-client.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libnm-client-impl/nm-client.c b/src/libnm-client-impl/nm-client.c index 44a9699423..7441ee25c8 100644 --- a/src/libnm-client-impl/nm-client.c +++ b/src/libnm-client-impl/nm-client.c @@ -3079,11 +3079,10 @@ _dbus_handle_interface_added(NMClient *self, const char *object_path, GVariant *ifaces) { - gboolean changed = FALSE; - const char *interface_name; - GVariant *changed_properties; - GVariantIter iter_ifaces; - NMLDBusObject *dbobj = NULL; + gboolean changed = FALSE; + const char *interface_name; + GVariant *changed_properties; + GVariantIter iter_ifaces; nm_assert(g_variant_is_of_type(ifaces, G_VARIANT_TYPE("a{sa{sv}}"))); @@ -3097,7 +3096,7 @@ _dbus_handle_interface_added(NMClient *self, interface_name, TRUE, changed_properties, - &dbobj)) + NULL)) changed = TRUE; } -- cgit v1.2.1 From 5e234fa0c9cfe55e3467e4512b84ce62a3d56dac Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 16 Jan 2023 08:10:37 +0100 Subject: libnm/client: don't consider client running if we got no NMManager We silently tolerate NetworkManager not responding at all (easily reproduced with e.g. pkill -STOP NetworkManager): $ LIBNM_CLIENT_DEBUG=trace nmcli c show dummy666 libnm-dbus[23540]: [3316.81989] nmclient[ddafb84b8deebe4a]: new NMClient instance libnm-dbus[23540]: [3316.81998] nmclient[ddafb84b8deebe4a]: starting async initialization... libnm-dbus[23540]: [3316.82461] nmclient[ddafb84b8deebe4a]: name owner changed: (null) -> ":1.2" libnm-dbus[23540]: [3316.82464] nmclient[ddafb84b8deebe4a]: fetch all libnm-dbus[23540]: [3341.85715] nmclient[ddafb84b8deebe4a]: GetManagedObjects() call failed: Timeout was reached libnm-dbus[23540]: [3341.85740] nmclient[ddafb84b8deebe4a]: async init complete with success Error: dummy666 - no such connection profile. libnm-dbus[23540]: [3341.86723] nmclient[ddafb84b8deebe4a]: release all libnm-dbus[23540]: [3341.86798] nmclient[ddafb84b8deebe4a]: disposed $ As a comment in _dbus_get_managed_objects_cb() explains, this is sort of intentional. NetworkManager might just be shutting down and the libnm users will eventually see the objects once a new daemon starts up. This may make some sense for long-running clients ("nmcli monitor", various desktop environments), but not for one-shot invocations that require the daemon running, such as those of "nmcli c ...". Let's not consider the client running unless we actually got the manager object. That way the error message will make more sense: $ LIBNM_CLIENT_DEBUG=trace nmcli c show dummy666 libnm-dbus[24730]: [5360.95480] nmclient[8cb898d3c891e210]: new NMClient instance libnm-dbus[24730]: [5360.95487] nmclient[8cb898d3c891e210]: starting async initialization... libnm-dbus[24730]: [5360.95901] nmclient[8cb898d3c891e210]: name owner changed: (null) -> ":1.2" libnm-dbus[24730]: [5360.95904] nmclient[8cb898d3c891e210]: fetch all libnm-dbus[24730]: [5385.98487] nmclient[8cb898d3c891e210]: GetManagedObjects() call failed: Timeout was reached libnm-dbus[24730]: [5385.98497] nmclient[8cb898d3c891e210]: async init complete with success Error: NetworkManager is not running. libnm-dbus[24730]: [5385.98571] nmclient[8cb898d3c891e210]: release all libnm-dbus[24730]: [5385.98698] nmclient[8cb898d3c891e210]: disposed $ https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1502 --- src/libnm-client-impl/nm-client.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libnm-client-impl/nm-client.c b/src/libnm-client-impl/nm-client.c index 7441ee25c8..f19343f056 100644 --- a/src/libnm-client-impl/nm-client.c +++ b/src/libnm-client-impl/nm-client.c @@ -378,7 +378,7 @@ static void name_owner_changed_cb(GDBusConnection *connection, static void name_owner_get_call(NMClient *self); -static void _set_nm_running(NMClient *self); +static void _set_nm_running(NMClient *self, gboolean queue_notify); /*****************************************************************************/ @@ -2724,6 +2724,7 @@ _obj_handle_dbus_changes(NMClient *self, NMLDBusObject *dbobj) if (dbobj->dbus_path == _dbus_path_nm) { nm_assert(!priv->dbobj_nm); priv->dbobj_nm = dbobj; + _set_nm_running(self, TRUE); } else if (dbobj->dbus_path == _dbus_path_settings) { nm_assert(!priv->dbobj_settings); priv->dbobj_settings = dbobj; @@ -2783,6 +2784,7 @@ _obj_handle_dbus_changes(NMClient *self, NMLDBusObject *dbobj) if (dbobj->dbus_path == _dbus_path_nm) { nm_assert(priv->dbobj_nm == dbobj); priv->dbobj_nm = NULL; + _set_nm_running(self, TRUE); nml_dbus_property_o_clear_many(priv->nm.property_o, G_N_ELEMENTS(priv->nm.property_o), self); @@ -2936,7 +2938,7 @@ _dbus_handle_changes_commit(NMClient *self, gboolean allow_init_start_check_comp _nm_client_notify_event_emit(self); - _set_nm_running(self); + _set_nm_running(self, FALSE); if (allow_init_start_check_complete) _init_start_check_complete(self); @@ -4083,15 +4085,18 @@ nm_client_get_startup(NMClient *client) } static void -_set_nm_running(NMClient *self) +_set_nm_running(NMClient *self, gboolean queue_notify) { NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE(self); gboolean nm_running; - nm_running = priv->name_owner && !priv->get_managed_objects_cancellable; + nm_running = priv->dbobj_nm && priv->name_owner && !priv->get_managed_objects_cancellable; if (priv->nm_running != nm_running) { priv->nm_running = nm_running; - _notify(self, PROP_NM_RUNNING); + if (queue_notify) { + _nm_client_queue_notify_object(self, self, obj_properties[PROP_NM_RUNNING]); + } else + _notify(self, PROP_NM_RUNNING); } } @@ -7171,7 +7176,7 @@ name_owner_changed(NMClient *self, const char *name_owner) if (changed && priv->name_owner) _init_fetch_all(self); - _set_nm_running(self); + _set_nm_running(self, FALSE); if (priv->init_data) { nm_auto_pop_gmaincontext GMainContext *main_context = NULL; -- cgit v1.2.1 From b36af7ce3fece47ec7d30865fb2c0290344bf154 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 26 Jan 2023 09:05:56 +0100 Subject: release: bump version to 1.43.1 (development) --- configure.ac | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 69e6c67272..fd61ea9046 100644 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ dnl "shared/nm-version-macros.h.in" dnl - update number in meson.build m4_define([nm_major_version], [1]) m4_define([nm_minor_version], [43]) -m4_define([nm_micro_version], [0]) +m4_define([nm_micro_version], [1]) m4_define([nm_version], [nm_major_version.nm_minor_version.nm_micro_version]) diff --git a/meson.build b/meson.build index e6f0327d87..cbd6eb2553 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ project( # - add corresponding NM_VERSION_x_y_z macros in # "src/libnm-core-public/nm-version-macros.h.in" # - update number in configure.ac - version: '1.43.0', + version: '1.43.1', license: 'GPL2+', default_options: [ 'buildtype=debugoptimized', -- cgit v1.2.1 From 9c492c6fc40e7224073811f34ab22a5ba11caeef Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Tue, 24 Jan 2023 14:56:47 +0100 Subject: Revert "l3cfg: do not add dependent routes for non-default routes" We must trust l3cfg when generating dependent onlink routes for all kind of routes not default routes only. This was done by "nm_platform_ip_route_sync()" so there is not change in behaviour at all. "nm_platform_ip_route_sync()" could be needed for other situation where l3cfg cannot add the dependent onlink routes, so we are not removing that logic. This reverts commit 6b4123db1ce7aff16254976f7bc558b2fe4a9b69. --- src/core/nm-l3-config-data.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 53896839f7..d7ffe126d3 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2569,8 +2569,7 @@ nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_fam if (nm_ip_addr_is_null(addr_family, p_gateway)) continue; - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route_src) - || _data_get_direct_route_for_host( + if (_data_get_direct_route_for_host( self, addr_family, p_gateway, -- cgit v1.2.1 From cbf70b4dca4ff520ab33c1b944f95fc52eae52e1 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Tue, 24 Jan 2023 15:41:50 +0100 Subject: Revert "nm-netns: add onlink routes for ECMP routes" ECMP IPv4 route nexthops requires an onlink route but we should trust l3cfg when generating and managing such routes. This reverts commit 737cb5d424e397901a5ad979907a084f770dd8d4. --- src/core/nm-netns.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index b5c150c0f3..ca9f66c056 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -780,8 +780,6 @@ _netns_ip_route_ecmp_update_mh(NMNetns *self, const NMPObject *obj = mhrts_add->pdata[i]; nm_auto_nmpobj const NMPObject *obj_old = NULL; gpointer unused; - const NMPlatformIP4Route *route_src; - guint j; if (g_hash_table_steal_extended(priv->ecmp_routes, obj, @@ -794,35 +792,6 @@ _netns_ip_route_ecmp_update_mh(NMNetns *self, if (!g_hash_table_add(priv->ecmp_routes, (gpointer) nmp_object_ref(obj))) nm_assert_not_reached(); - /* for each nexthop we need to configure the onlink route for the gateway */ - route_src = NMP_OBJECT_CAST_IP4_ROUTE(obj); - for (j = 0; j < route_src->n_nexthops; j++) { - NMPObject *new_onlink_obj; - NMPlatformIP4Route *new_onlink_route; - in_addr_t gateway; - int ifindex; - - new_onlink_obj = nmp_object_clone(obj, TRUE); - new_onlink_route = NMP_OBJECT_CAST_IP4_ROUTE(new_onlink_obj); - if (j == 0) { - gateway = route_src->gateway; - ifindex = route_src->ifindex; - } else { - gateway = obj->_ip4_route.extra_nexthops[j - 1].gateway; - ifindex = obj->_ip4_route.extra_nexthops[j - 1].ifindex; - } - - new_onlink_route->network = gateway; - new_onlink_route->plen = 32; - new_onlink_route->gateway = 0; - new_onlink_route->ifindex = ifindex; - new_onlink_route->weight = 0; - new_onlink_route->n_nexthops = 0; - - /* we configure the onlink route and l3cfg will take the ownership and remove it if not needed */ - nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, new_onlink_obj); - } - nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, obj); } } -- cgit v1.2.1 From f187e63fa8607f09e8a93a1df27d7b1ff639ffe3 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Tue, 24 Jan 2023 15:07:04 +0100 Subject: l3-config-data: do not check route table to get direct routes Kernel enforces that all route nexthop are reachable but it doesn't care if the drect route to the nexthop is in a different route table. --- src/core/nm-l3-config-data.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index d7ffe126d3..1c8200c248 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2408,10 +2408,7 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a, /*****************************************************************************/ static const NMPObject * -_data_get_direct_route_for_host(const NML3ConfigData *self, - int addr_family, - gconstpointer host, - guint32 route_table) +_data_get_direct_route_for_host(const NML3ConfigData *self, int addr_family, gconstpointer host) { const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMPObject *best_route_obj = NULL; @@ -2439,9 +2436,6 @@ _data_get_direct_route_for_host(const NML3ConfigData *self, if (best_route && best_route->rx.plen > item->rx.plen) continue; - if (nm_platform_route_table_uncoerce(item->rx.table_coerced, TRUE) != route_table) - continue; - if (!nm_ip_addr_same_prefix(addr_family, host, item->rx.network_ptr, item->rx.plen)) continue; @@ -2569,11 +2563,7 @@ nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_fam if (nm_ip_addr_is_null(addr_family, p_gateway)) continue; - if (_data_get_direct_route_for_host( - self, - addr_family, - p_gateway, - nm_platform_route_table_uncoerce(route_src->rx.table_coerced, TRUE))) + if (_data_get_direct_route_for_host(self, addr_family, p_gateway)) continue; new_route = nmp_object_clone(obj_src, FALSE); -- cgit v1.2.1 From 8132045d5feb6bb855079b8476b119bfa8fbdab2 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 26 Jan 2023 21:49:03 +0100 Subject: nmcli: fix typos in nmcli output Spotted by lintian: I: network-manager: spelling-error-in-binary writting writing [usr/bin/nmcli] I: network-manager: spelling-error-in-binary wihout without [usr/lib/x86_64-linux-gnu/NetworkManager/1.40.12/libnm-device-plugin-wifi.so] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1515 --- src/core/devices/wifi/nm-wifi-utils.c | 2 +- src/nmcli/connections.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 829cf1b46b..8a8d062f3a 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -1004,7 +1004,7 @@ psk_setting_to_iwd_config(GKeyFile *file, NMSettingWirelessSecurity *s_wsec, GEr if (NM_FLAGS_ANY(psk_flags, SECRETS_DONT_STORE_FLAGS)) { nm_log_info( LOGD_WIFI, - "IWD network config is being created wihout the PSK but IWD will save the PSK on " + "IWD network config is being created without the PSK but IWD will save the PSK on " "successful activation not honoring the psk-flags property"); } return TRUE; diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index c0b7d8f1dc..d5d569083a 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -170,7 +170,7 @@ print_connection_done(GObject *source_object, GAsyncResult *res, gpointer user_d written = g_output_stream_write_finish(stream, res, &error); if (written == -1) { g_string_printf(nmc->return_text, - _("Error: Error writting connection: %s"), + _("Error: Error writing connection: %s"), error->message); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; nmc->should_wait--; @@ -230,7 +230,7 @@ nmc_print_connection_and_quit(NmCli *nmc, NMConnection *connection) return; error: - g_string_printf(nmc->return_text, _("Error: Error writting connection: %s"), error->message); + g_string_printf(nmc->return_text, _("Error: Error writing connection: %s"), error->message); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; nmc->should_wait--; quit(); -- cgit v1.2.1 From 108ab677e4121c97bb641068f656502cbcd33dd3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 27 Jan 2023 08:32:33 +0100 Subject: nmcli/style: fix clang-format style Fixes: 8132045d5feb ('nmcli: fix typos in nmcli output') --- src/nmcli/connections.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index d5d569083a..00cc57acb7 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -169,9 +169,7 @@ print_connection_done(GObject *source_object, GAsyncResult *res, gpointer user_d written = g_output_stream_write_finish(stream, res, &error); if (written == -1) { - g_string_printf(nmc->return_text, - _("Error: Error writing connection: %s"), - error->message); + g_string_printf(nmc->return_text, _("Error: Error writing connection: %s"), error->message); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; nmc->should_wait--; quit(); -- cgit v1.2.1 From 9934be52cd453202248cb5f7f7dadbe05a2412de Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Fri, 27 Jan 2023 11:22:43 +0100 Subject: device: use NMUnmanFlagOp enum members instead of literals Replace TRUE or FALSE for their NMUnmanFlagOp enum member. It is more intuitive for newcomers so they can understand what is being set without looking at the values or function logic. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1516 --- src/core/devices/nm-device.c | 9 ++++++--- src/core/devices/nm-device.h | 6 +++--- src/core/nm-checkpoint.c | 4 ++-- src/core/nm-manager.c | 14 +++++++------- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 93399cafb2..248f2364f5 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -6811,7 +6811,10 @@ device_link_changed(gpointer user_data) * sync state transition. */ nm_device_queue_recheck_assume(self); - nm_device_set_unmanaged_by_flags_queue(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); + nm_device_set_unmanaged_by_flags_queue(self, + NM_UNMANAGED_PLATFORM_INIT, + NM_UNMAN_FLAG_OP_SET_MANAGED, + reason); } _dev_unmanaged_check_external_down(self, FALSE, FALSE); @@ -7867,7 +7870,7 @@ nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure) g_warn_if_fail(!NM_FLAGS_HAS(slave_priv->unmanaged_mask, NM_UNMANAGED_IS_SLAVE)); nm_device_set_unmanaged_by_flags(slave, NM_UNMANAGED_IS_SLAVE, - FALSE, + NM_UNMAN_FLAG_OP_SET_MANAGED, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); changed = TRUE; } else @@ -14687,7 +14690,7 @@ nm_device_set_unmanaged_by_quitting(NMDevice *self) nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_QUITTING, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED : NM_DEVICE_STATE_REASON_NOW_UNMANAGED); } diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index f54457d12e..fd6b9d93f8 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -608,9 +608,9 @@ typedef enum { } NMUnmanagedFlags; typedef enum { - NM_UNMAN_FLAG_OP_SET_MANAGED = FALSE, - NM_UNMAN_FLAG_OP_SET_UNMANAGED = TRUE, - NM_UNMAN_FLAG_OP_FORGET = 2, + NM_UNMAN_FLAG_OP_SET_MANAGED = 0, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, + NM_UNMAN_FLAG_OP_FORGET, } NMUnmanFlagOp; const char *nm_unmanaged_flags2str(NMUnmanagedFlags flags, char *buf, gsize len); diff --git a/src/core/nm-checkpoint.c b/src/core/nm-checkpoint.c index cd0e17fa87..0beeb4ba26 100644 --- a/src/core/nm-checkpoint.c +++ b/src/core/nm-checkpoint.c @@ -368,7 +368,7 @@ nm_checkpoint_rollback(NMCheckpoint *self) _LOGD("rollback: device was not realized, unmanage it"); nm_device_set_unmanaged_by_flags_queue(device, NM_UNMANAGED_USER_EXPLICIT, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); goto next_dev; } @@ -402,7 +402,7 @@ nm_checkpoint_rollback(NMCheckpoint *self) _LOGD("rollback: explicitly unmanage device"); nm_device_set_unmanaged_by_flags_queue(device, NM_UNMANAGED_USER_EXPLICIT, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); } goto next_dev; diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 665472941f..9d444e45f3 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -1804,7 +1804,7 @@ remove_device(NMManager *self, NMDevice *device, gboolean quitting) nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_PLATFORM_INIT, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_REMOVED); } } @@ -4942,12 +4942,12 @@ unmanaged_to_disconnected(NMDevice *device) * and force the device to be managed. */ nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_PLATFORM_INIT, - FALSE, + NM_UNMAN_FLAG_OP_SET_MANAGED, NM_DEVICE_STATE_REASON_USER_REQUESTED); nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_USER_EXPLICIT, - FALSE, + NM_UNMAN_FLAG_OP_SET_MANAGED, NM_DEVICE_STATE_REASON_USER_REQUESTED); if (!nm_device_get_managed(device, FALSE)) { @@ -6500,7 +6500,7 @@ device_sleep_cb(NMDevice *device, GParamSpec *pspec, NMManager *self) _LOGD(LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface(device)); nm_device_set_unmanaged_by_flags_queue(device, NM_UNMANAGED_SLEEPING, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_SLEEPING); break; case NM_DEVICE_STATE_UNMANAGED: @@ -6562,7 +6562,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) } else { nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_SLEEPING, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_SLEEPING); } } @@ -6582,7 +6582,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) if (device_is_wake_on_lan(priv->platform, device)) nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_SLEEPING, - TRUE, + NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_SLEEPING); /* Check if the device is unmanaged but the state transition is still pending. @@ -6638,7 +6638,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_SLEEPING, - FALSE, + NM_UNMAN_FLAG_OP_SET_MANAGED, NM_DEVICE_STATE_REASON_NOW_MANAGED); } -- cgit v1.2.1 From 88c08721c31607c2add7ef8647fd1ada2fa43d7f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 30 Jan 2023 07:54:58 +0100 Subject: po: fix marking "nm-setting-ovs-dpdk.c" for translation Fixes: f930d55fea4a ('all: add support for ovs-dpdk n-rxq-desc and n-txq-desc') --- po/POTFILES.in | 1 + 1 file changed, 1 insertion(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index dcd2983d38..70a48dd753 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -100,6 +100,7 @@ src/libnm-core-impl/nm-setting-macvlan.c src/libnm-core-impl/nm-setting-match.c src/libnm-core-impl/nm-setting-olpc-mesh.c src/libnm-core-impl/nm-setting-ovs-bridge.c +src/libnm-core-impl/nm-setting-ovs-dpdk.c src/libnm-core-impl/nm-setting-ovs-external-ids.c src/libnm-core-impl/nm-setting-ovs-interface.c src/libnm-core-impl/nm-setting-ovs-other-config.c -- cgit v1.2.1 From 65ea47580fa0043906c02dcb00ffe25a5a02d475 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 27 Jan 2023 08:18:11 +0100 Subject: client/tests: temporarily disable failing test test_monitor() --- src/tests/client/test-client.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index f4ecd2a0d5..e936c4c452 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -1889,6 +1889,11 @@ class TestNmcli(NmTestBase): @skip_without_pexpect @nm_test def test_monitor(self): + + # FIXME: this test is currently known to fail. Skip it. + # https://bugzilla.redhat.com/show_bug.cgi?id=2154288 + raise unittest.SkipTest("test is known to randomly fail (rhbz#2154288)") + def start_mon(): nmc = self.call_nmcli_pexpect(["monitor"]) nmc.expect("NetworkManager is running") -- cgit v1.2.1 From 14b1a7ba300a6b52651b2217e835375b91d66602 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 27 Jan 2023 17:09:52 +0100 Subject: l3cfg/tests: temporarily disable failing tests "/l3cfg/$N" Seems this test fails easily under gitlab-ci, if we set NMTST_SEED_RAND to something else than "0". There is nothing particular special about "0", except that a randomly different code paths are chosen. A randomized test that doesn't pass on all systems with all random paths, is broken. Disable for now. Needs to be fixed. See-also: https://bugzilla.redhat.com/show_bug.cgi?id=2165141 --- src/core/tests/test-l3cfg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/tests/test-l3cfg.c b/src/core/tests/test-l3cfg.c index ba0c1b5772..962b2eecdf 100644 --- a/src/core/tests/test-l3cfg.c +++ b/src/core/tests/test-l3cfg.c @@ -339,6 +339,10 @@ test_l3cfg(gconstpointer test_data) _LOGD("test start (/l3cfg/%d)", TEST_IDX); + /* FIXME: https://bugzilla.redhat.com/show_bug.cgi?id=2165141 */ + g_test_skip("Skip: this test is currently known to fail (rhbz#2165141)"); + return; + if (nmtst_test_quick()) { gs_free char *msg = g_strdup_printf("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", -- cgit v1.2.1 From 67da2b8e429beaa003c48b196348786722da3fb9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Jan 2023 13:33:57 +0100 Subject: gitlab-ci: fix test script to abort on failing first test Fixes: 89cfd34ae0f5 ('gitlab-ci: extend run-test.sh script to manually select certain build steps to run') --- .gitlab-ci/run-test.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci/run-test.sh b/.gitlab-ci/run-test.sh index c8fe8016f0..d991010dc1 100755 --- a/.gitlab-ci/run-test.sh +++ b/.gitlab-ci/run-test.sh @@ -64,8 +64,11 @@ check_run_clean() { return 0 } -check_run_clean 1 && BUILD_TYPE=autotools CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh \ - && mv build/INST/share/gtk-doc/html "$ARTIFACT_DIR/docs-html" +if check_run_clean 1 ; then + BUILD_TYPE=autotools CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh + mv build/INST/share/gtk-doc/html "$ARTIFACT_DIR/docs-html" +fi + check_run_clean 2 && BUILD_TYPE=meson CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh check_run_clean 3 && BUILD_TYPE=autotools CC=clang WITH_DOCS=0 contrib/scripts/nm-ci-run.sh check_run_clean 4 && BUILD_TYPE=meson CC=clang WITH_DOCS=0 contrib/scripts/nm-ci-run.sh -- cgit v1.2.1 From 3bad3f8b241f643621a5ea8cb9816abcb6bc939c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Jan 2023 13:24:07 +0100 Subject: gitlab-ci: fix randomizing tests in "nm-ci-run.sh" The code was just wrong. Usually in gitlab-ci, NMTST_SEED_RANDOM is unset, so the previous code would not have set it. Which means that our tests run with NMTST_SEED_RANDOM="0". Fuzzing (or randomizing tests) is very useful, we should do that for the unit tests that run in gitlab-ci. Fix this. But don't let the test choose a random number. Instead, let the calling script choose it. That is, because we might run the tests more than once (without debugging and no valgrind; in case of failure return with debugging; with valgrind). Those runs should use the same seed. This fixes commit 70487d9ff8a0 ('ci: randomize tests during our CI'), but as fixing randomization can break previously running tests, we may only want to backport this commit after careful evaluation. --- contrib/scripts/nm-ci-run.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/scripts/nm-ci-run.sh b/contrib/scripts/nm-ci-run.sh index 00adba85e1..14a4a2fe53 100755 --- a/contrib/scripts/nm-ci-run.sh +++ b/contrib/scripts/nm-ci-run.sh @@ -69,9 +69,13 @@ if [ $IS_ALPINE = 1 ]; then _WITH_SYSTEMD_LOGIND="$_FALSE" fi -if [ "$NMTST_SEED_RAND" != "" ]; then - export NMTST_SEED_RAND= +if [ -z "${NMTST_SEED_RAND+x}" ]; then + NMTST_SEED_RAND="$SRANDOM" + if [ -z "$NMTST_SEED_RAND" ]; then + NMTST_SEED_RAND="$(( ( (RANDOM<<15|RANDOM)<<15|RANDOM ) % 0xfffffffe ))" + fi fi +export NMTST_SEED_RAND case "$CI" in ""|"true"|"default"|"gitlab") -- cgit v1.2.1 From 3f2ad76363e2f53078829fb31406d5950de5e6f7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Jan 2023 13:50:33 +0100 Subject: gitlab-ci: explicitly set "NMTST_DEBUG=debug,..." for second debug run "debug" is implied when setting NMTST_DEBUG, but not specifying "no-debug". This change has thus no effect, but it seems clearer to be explicit. The "debug" flag affects nmtst_is_debug(). Note that tests *must* not result in different code paths based on debug, they may only 1) print more debug logging 2) do more assertion checks. Having more assertion checks can result in different outcome of the test, that is, that the additional assertion fails first. That is acceptable, because failing earlier is possibly closer to the issue and helps debugging. Also, when the additional failure is fixed and passes, we still will fail at the assertion we are trying to debug. In particular, an access to nmtst_get_rand*()/nmtst_rand*() must not depend on nmtst_is_debug(), because then different randomized paths are taken based on whether debugging is enabled. --- contrib/scripts/nm-ci-run.sh | 2 +- src/libnm-glib-aux/nm-test-utils.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/contrib/scripts/nm-ci-run.sh b/contrib/scripts/nm-ci-run.sh index 14a4a2fe53..22450d40c7 100755 --- a/contrib/scripts/nm-ci-run.sh +++ b/contrib/scripts/nm-ci-run.sh @@ -201,7 +201,7 @@ run_autotools() { _print_test_logs "first-test" echo ">>>> RUN SECOND TEST (start)" - NMTST_DEBUG=TRACE,no-expect-message make check -k || : + NMTST_DEBUG="debug,TRACE,no-expect-message" make check -k || : echo ">>>> RUN SECOND TEST (done)" _print_test_logs "second-test" diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h index b35eeb4b09..41e1a6cedf 100644 --- a/src/libnm-glib-aux/nm-test-utils.h +++ b/src/libnm-glib-aux/nm-test-utils.h @@ -772,6 +772,12 @@ nmtst_init(int *argc, char ***argv, gboolean assert_logging) static inline gboolean nmtst_is_debug(void) { + /* This is based on the "debug"/"no-debug" flag in "$NMTST_DEBUG". + * + * If debugging is enabled, print more information. However, make sure + * that the test behaves still in a similar manner and that the same code + * path are taken where it matters (it matters for example, if the code path + * consumes random numbers). */ g_assert(nmtst_initialized()); return __nmtst_internal.is_debug; } -- cgit v1.2.1 From 13d9cf75ed6e0daea22205b28f218c53bc604ba8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Jan 2023 12:51:17 +0100 Subject: gitlab-ci: rerun meson test on failure with debugging Like done for autotools. First we run the test without debugging option. If it fails, we run it again to possibly trigger the failure again and get better logs. --- contrib/scripts/nm-ci-run.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/contrib/scripts/nm-ci-run.sh b/contrib/scripts/nm-ci-run.sh index 22450d40c7..374dde95b3 100755 --- a/contrib/scripts/nm-ci-run.sh +++ b/contrib/scripts/nm-ci-run.sh @@ -197,21 +197,18 @@ run_autotools() { export NM_TEST_CLIENT_CHECK_L10N=1 if ! make check -j 6 -k ; then - _print_test_logs "first-test" - echo ">>>> RUN SECOND TEST (start)" NMTST_DEBUG="debug,TRACE,no-expect-message" make check -k || : echo ">>>> RUN SECOND TEST (done)" - _print_test_logs "second-test" - die "test failed" + die "autotools test failed" fi if _with_valgrind; then if ! NMTST_USE_VALGRIND=1 make check -j 3 -k ; then _print_test_logs "(valgrind test)" - die "valgrind test failed" + die "autotools+valgrind test failed" fi fi popd @@ -267,12 +264,18 @@ run_meson() { ninja -C build ninja -C build install - ninja -C build test + + if ! ninja -C build test ; then + echo ">>>> RUN SECOND TEST (start)" + NMTST_DEBUG="debug,TRACE,no-expect-message" ninja -C build test || : + echo ">>>> RUN SECOND TEST (done)" + die "meson test failed" + fi if _with_valgrind; then if ! NMTST_USE_VALGRIND=1 ninja -C build test; then _print_test_logs "(valgrind test)" - die "valgrind test failed" + die "meson+valgrind test failed" fi fi } -- cgit v1.2.1 From dba2fb5fff318b797c424c82c4e92508de4b8de2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 27 Jan 2023 17:23:07 +0100 Subject: gitlab-ci: use "meson test" for running unit tests It seems that `meson test` is preferred over `ninja test`. Also, pass "--print-errorlogs" to meson, and pass "-v" to the build steps. Note that `ninja test` already ends up calling `meson test --print-errorlogs`, but it doesn't use "-v", so the logs are truncated. --- contrib/scripts/nm-ci-run.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/scripts/nm-ci-run.sh b/contrib/scripts/nm-ci-run.sh index 374dde95b3..676780b2c8 100755 --- a/contrib/scripts/nm-ci-run.sh +++ b/contrib/scripts/nm-ci-run.sh @@ -262,18 +262,19 @@ run_meson() { export NM_TEST_CLIENT_CHECK_L10N=1 - ninja -C build + ninja -C build -v ninja -C build install - if ! ninja -C build test ; then + if ! meson test -C build -v --print-errorlogs ; then echo ">>>> RUN SECOND TEST (start)" - NMTST_DEBUG="debug,TRACE,no-expect-message" ninja -C build test || : + NMTST_DEBUG="debug,TRACE,no-expect-message" \ + meson test -C build -v --print-errorlogs || : echo ">>>> RUN SECOND TEST (done)" die "meson test failed" fi if _with_valgrind; then - if ! NMTST_USE_VALGRIND=1 ninja -C build test; then + if ! NMTST_USE_VALGRIND=1 meson test -C build -v --print-errorlogs ; then _print_test_logs "(valgrind test)" die "meson+valgrind test failed" fi -- cgit v1.2.1 From 4966f9d78454025b7497f3d800c0c4fbd37a4c61 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Jan 2023 15:39:06 +0100 Subject: platform/tests: fix nmtstp_link_{gre,ip6gre,ip6tnl,ipip}_add() to support missing parent --- src/core/platform/tests/test-common.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index e9c36a52dd..455b322470 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -2061,11 +2061,11 @@ nmtstp_link_gre_add(NMPlatform *platform, obj = lnk->is_tap ? "link" : "tunnel"; type = lnk->is_tap ? "type gretap" : "mode gre"; - success = !nmtstp_run_command("ip %s add %s %s %s local %s remote %s ttl %u tos %02x %s", + success = !nmtstp_run_command("ip %s add %s %s%s%s local %s remote %s ttl %u tos %02x %s", obj, name, type, - dev ?: "", + NM_PRINT_FMT_QUOTED2(dev, " ", dev, ""), nm_inet4_ntop(lnk->local, b1), nm_inet4_ntop(lnk->remote, b2), lnk->ttl, @@ -2127,11 +2127,11 @@ nmtstp_link_ip6tnl_add(NMPlatform *platform, tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); success = !nmtstp_run_command( - "ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %s encaplimit %s " + "ip -6 tunnel add %s mode %s%s%s local %s remote %s ttl %u tclass %s encaplimit %s " "flowlabel %x", name, mode, - dev, + NM_PRINT_FMT_QUOTED2(dev, " ", dev, ""), nm_inet6_ntop(&lnk->local, b1), nm_inet6_ntop(&lnk->remote, b2), lnk->ttl, @@ -2178,10 +2178,10 @@ nmtstp_link_ip6gre_add(NMPlatform *platform, tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); success = !nmtstp_run_command( - "ip link add %s type %s %s local %s remote %s ttl %u tclass %s flowlabel %x", + "ip link add %s type %s%s%s local %s remote %s ttl %u tclass %s flowlabel %x", name, lnk->is_tap ? "ip6gretap" : "ip6gre", - dev, + NM_PRINT_FMT_QUOTED2(dev, " ", dev, ""), nm_inet6_ntop(&lnk->local, b1), nm_inet6_ntop(&lnk->remote, b2), lnk->ttl, @@ -2232,9 +2232,9 @@ nmtstp_link_ipip_add(NMPlatform *platform, g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex)); success = !nmtstp_run_command( - "ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s", + "ip tunnel add %s mode ipip%s%s local %s remote %s ttl %u tos %02x %s", name, - dev, + NM_PRINT_FMT_QUOTED2(dev, " ", dev, ""), nm_inet4_ntop(lnk->local, b1), nm_inet4_ntop(lnk->remote, b2), lnk->ttl, -- cgit v1.2.1 From 451cedf2bf42a670ba0db1f32a470a124d974101 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Jan 2023 15:41:22 +0100 Subject: platform/tests: add nmtstp_ensure_module() helper This will make sure that the IP tunnel module is loaded. It does so by creating (and deleting) a tunnel interface. That is important, because those modules will create additional interfaces that show up in `ip link` (like "gre0"), and those interfaces can interfere with the tests. Also add nmtstp_link_is_iptunnel_special() to detect whether an interface is one of those special interfaces. --- src/core/platform/tests/test-common.c | 266 ++++++++++++++++++++++++++++++++++ src/core/platform/tests/test-common.h | 4 + 2 files changed, 270 insertions(+) diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 455b322470..18098234c8 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -15,6 +15,7 @@ #include #include "n-acd/src/n-acd.h" +#include "libnm-platform/nm-platform-utils.h" #define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)" #define SIGNAL_DATA_ARG(data) \ @@ -33,6 +34,52 @@ int NMTSTP_ENV1_EX = -1; /*****************************************************************************/ +typedef struct { + const char *module_name; + + NMLinkType iftype; + + /* These modules create additional interfaces, like + * "gre0" for "ip_gre" module. + * + * - actually some modules create multiple interfaces, like "ip_gre" + * creating "gre0", "gretap0", "erspan0". + * - if already an interface with such name exist, kernel would create + * names like "gre1" or "gretap1". We don't care for that, because + * we run in our own namespace and we control which interfaces are there. + * We wouldn't create an interface with such a conflicting name. + * + * Anyway. This is the name of *one* of the interfaces that the module would + * create. */ + const char *ifname; + + /* This only gets set, if iftype is NM_LINK_TYPE_UNKNOWN. It corresponds to + * NMPlatformLink.kind. */ + const char *ifkind; + +} IPTunnelModInfo; + +#define INF(_module_name, _iftype, _ifname, ...) \ + { \ + .module_name = ""_module_name, .iftype = _iftype, .ifname = ""_ifname, __VA_ARGS__ \ + } + +static const IPTunnelModInfo ip_tunnel_mod_infos[] = { + INF("ip_gre", NM_LINK_TYPE_GRE, "gre0"), + INF("ip_gre", NM_LINK_TYPE_GRETAP, "gretap0"), + INF("ip_gre", NM_LINK_TYPE_UNKNOWN, "erspan0", .ifkind = "erspan"), + INF("ipip", NM_LINK_TYPE_IPIP, "tunl0"), + INF("ip6_tunnel", NM_LINK_TYPE_IP6TNL, "ip6tnl0"), + INF("ip6_gre", NM_LINK_TYPE_IP6GRE, "ip6gre0"), + INF("sit", NM_LINK_TYPE_SIT, "sit0"), + INF("ip_vti", NM_LINK_TYPE_VTI, "ip_vti0"), + INF("ip6_vti", NM_LINK_TYPE_VTI6, "ip6_vti0"), +}; + +#undef INF + +/*****************************************************************************/ + void nmtstp_setup_platform(void) { @@ -912,6 +959,225 @@ _assert_platform_compare_arr(NMPObjectType obj_type, } } +/*****************************************************************************/ + +gboolean +nmtstp_link_is_iptunnel_special(const NMPlatformLink *link) +{ + int i; + + g_assert(link); + + /* These interfaces are autogenerated when loading the ip tunnel + * modules. For example, loading "ip_gre" results in interfaces + * "gre0", "gretap0", "erspan0". + * + * Actually, if the interface names are already taken ("gre0" already + * exists), it will create "gre1" and so on. We don't care about that, + * because in our test's netns that is not happening. */ + + for (i = 0; i < (int) G_N_ELEMENTS(ip_tunnel_mod_infos); i++) { + const IPTunnelModInfo *module_info = &ip_tunnel_mod_infos[i]; + + if (module_info->iftype != link->type) + continue; + if (!nm_streq(module_info->ifname, link->name)) + continue; + if (module_info->ifkind && !nm_streq(module_info->ifkind, link->kind)) + continue; + + return TRUE; + } + + return FALSE; +} + +/*****************************************************************************/ + +gboolean +nmtstp_ensure_module(const char *module_name) +{ + /* using iproute2 seems to fail sometimes? Force use of platform code. */ + const int EX = 0; + gs_free char *test_ifname = NULL; + const NMPlatformLink *link; + static int module_state[G_N_ELEMENTS(ip_tunnel_mod_infos)] = {0}; + int i_module_info; + const IPTunnelModInfo *module_info = NULL; + int i; + int ifindex; + gboolean result; + + if (!module_name) { + result = TRUE; + for (i = 0; i < (int) G_N_ELEMENTS(ip_tunnel_mod_infos); i++) { + if (!nmtstp_ensure_module(ip_tunnel_mod_infos[i].module_name)) + result = FALSE; + } + return result; + } + + for (i_module_info = 0; i_module_info < (int) G_N_ELEMENTS(ip_tunnel_mod_infos); + i_module_info++) { + if (nm_streq(module_name, ip_tunnel_mod_infos[i_module_info].module_name)) { + module_info = &ip_tunnel_mod_infos[i_module_info]; + break; + } + } + if (!module_info) + g_error("%s:%d: Module name \"%s\" not implemented!", __FILE__, __LINE__, module_name); + + test_ifname = g_strdup_printf("nm-mod-%s", module_info->ifname); + g_assert(nm_utils_ifname_valid_kernel(test_ifname, NULL)); + +again: + i = g_atomic_int_get(&module_state[i_module_info]); + if (i != 0) + return i > 0; + + /* When tunnel modules get loaded, then interfaces like "gre0", "gretap0" + * and "erspan0" (for "ip_gre" module) appear. For other modules, the interfaces + * are named differently. Of course, unless those interface name are already taken, + * in which case it will create "gre1", etc). So ugly. + * + * Anyway. as we run unit tests in parallel (`make check -j`), another + * test might just load the module just now, which results in the creation of + * those interfaces in our current namespace. That can break the test. + */ + + link = nmtstp_link_get_typed(NM_PLATFORM_GET, 0, test_ifname, module_info->iftype); + g_assert(!link); + + link = nmtstp_link_get_typed(NM_PLATFORM_GET, 0, module_info->ifname, module_info->iftype); + if (link) { + g_assert(nmtstp_link_is_iptunnel_special(link)); + /* An interface with this name exists. While technically this could not be the interface + * generated by the kernel module, in our test netns we can assume that it is. This is + * good enough. */ + result = TRUE; + goto out; + } + + /* Try to load the module. It probably won't work, because we don't have permissions. + * Ignore any failure. */ + nmp_utils_modprobe(NULL, TRUE, module_info->module_name, NULL); + + if (nm_streq(module_name, "ip_gre")) { + link = nmtstp_link_gre_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkGre){ + .local = nmtst_inet4_from_string("192.168.233.204"), + .remote = nmtst_inet4_from_string("172.168.10.25"), + .parent_ifindex = 0, + .ttl = 174, + .tos = 37, + .path_mtu_discovery = TRUE, + })); + } else if (nm_streq(module_name, "ipip")) { + link = nmtstp_link_ipip_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkIpIp){ + .local = nmtst_inet4_from_string("1.2.3.4"), + .remote = nmtst_inet4_from_string("5.6.7.8"), + .parent_ifindex = 0, + .tos = 32, + .path_mtu_discovery = FALSE, + })); + } else if (nm_streq(module_name, "ip6_tunnel")) { + link = nmtstp_link_ip6tnl_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkIp6Tnl){ + .local = nmtst_inet6_from_string("fd01::15"), + .remote = nmtst_inet6_from_string("fd01::16"), + .tclass = 20, + .encap_limit = 6, + .flow_label = 1337, + .proto = IPPROTO_IPV6, + })); + } else if (nm_streq(module_name, "ip6_gre")) { + link = nmtstp_link_ip6gre_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkIp6Tnl){ + .local = nmtst_inet6_from_string("fd01::42"), + .remote = nmtst_inet6_from_string("fd01::aaaa"), + .tclass = 21, + .flow_label = 1338, + .is_gre = TRUE, + })); + } else if (nm_streq(module_name, "sit")) { + link = nmtstp_link_sit_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkSit){ + .local = nmtst_inet4_from_string("192.168.200.1"), + .remote = nmtst_inet4_from_string("172.25.100.14"), + .ttl = 0, + .tos = 31, + .path_mtu_discovery = FALSE, + })); + } else if (nm_streq(module_name, "ip_vti")) { + link = nmtstp_link_vti_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkVti){ + .local = nmtst_inet4_from_string("192.168.212.204"), + .remote = nmtst_inet4_from_string("172.168.11.25"), + .ikey = 12, + .okey = 13, + })); + } else if (nm_streq(module_name, "ip6_vti")) { + link = nmtstp_link_vti6_add(NULL, + EX, + test_ifname, + &((const NMPlatformLnkVti6){ + .local = nmtst_inet6_from_string("fd01::1"), + .remote = nmtst_inet6_from_string("fd02::2"), + .ikey = 13, + .okey = 14, + })); + } else + g_error("%s:%d: Module name \"%s\" not implemented!", __FILE__, __LINE__, module_name); + + if (!link) { + /* We might be unable to add the interface, if the kernel module does not exist. + * Be graceful about that. */ + ifindex = 0; + g_assert(!nmtstp_link_get_typed(NM_PLATFORM_GET, 0, test_ifname, module_info->iftype)); + g_assert( + !nmtstp_link_get_typed(NM_PLATFORM_GET, 0, module_info->ifname, module_info->iftype)); + } else { + ifindex = link->ifindex; + + g_assert(link); + g_assert( + link + == nmtstp_link_get_typed(NM_PLATFORM_GET, ifindex, test_ifname, module_info->iftype)); + + nmtstp_link_delete(NULL, -1, link->ifindex, test_ifname, TRUE); + + link = nmtstp_link_get_typed(NM_PLATFORM_GET, 0, module_info->ifname, module_info->iftype); + g_assert(nmtstp_link_is_iptunnel_special(link)); + } + + result = ifindex > 0 ? 1 : -1; + +out: + if (!g_atomic_int_compare_and_exchange(&module_state[i_module_info], 0, result)) + goto again; + + if (!result) { + /* The function aims to be graceful about missing kernel modules. */ + + /* g_error("Failure to ensure module \"%s\"", module_name); */ + } + + return result; +} + void nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) { diff --git a/src/core/platform/tests/test-common.h b/src/core/platform/tests/test-common.h index 383a1fed47..7a4018a3bf 100644 --- a/src/core/platform/tests/test-common.h +++ b/src/core/platform/tests/test-common.h @@ -530,6 +530,10 @@ void nmtstp_link_delete(NMPlatform *platform, const char *name, gboolean require_exist); +gboolean nmtstp_link_is_iptunnel_special(const NMPlatformLink *link); + +gboolean nmtstp_ensure_module(const char *module_name); + /*****************************************************************************/ #define nmtst_object_new_mptcp_addr(...) \ -- cgit v1.2.1 From acc0cee28ea62e9919572d1afb599cc08c76c6c1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Jan 2023 15:42:47 +0100 Subject: platform/tests: use nmtstp_ensure_module() in test_software_detect() This helper function already loads the module and performs additional checks. Use it. --- src/core/platform/tests/test-link.c | 112 +++++++++++++----------------------- 1 file changed, 40 insertions(+), 72 deletions(-) diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index 6c61bac2d2..cc1ec6d1d4 100644 --- a/src/core/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -1290,6 +1290,7 @@ test_software_detect(gconstpointer user_data) NMPlatformLnkVti lnk_vti = {}; NMPlatformLnkVti6 lnk_vti6 = {}; nm_auto_close int tun_fd = -1; + gboolean module_loaded; nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME); ifindex_parent = @@ -1330,8 +1331,7 @@ test_software_detect(gconstpointer user_data) break; case NM_LINK_TYPE_GRE: - { - gboolean gracefully_skip = FALSE; + module_loaded = nmtstp_ensure_module("ip_gre"); lnk_gre.local = nmtst_inet4_from_string("192.168.233.204"); lnk_gre.remote = nmtst_inet4_from_string("172.168.10.25"); @@ -1340,13 +1340,8 @@ test_software_detect(gconstpointer user_data) lnk_gre.tos = 37; lnk_gre.path_mtu_discovery = TRUE; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gre0")) { - /* Seems that the ip_gre module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; - } - if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip( "Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)"); goto out_delete_parent; @@ -1354,10 +1349,9 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding GRE tunnel"); } break; - } + case NM_LINK_TYPE_GRETAP: - { - gboolean gracefully_skip = FALSE; + module_loaded = nmtstp_ensure_module("ip_gre"); lnk_gre.local = nmtst_inet4_from_string("192.168.1.133"); lnk_gre.remote = nmtst_inet4_from_string("172.168.101.2"); @@ -1367,13 +1361,8 @@ test_software_detect(gconstpointer user_data) lnk_gre.path_mtu_discovery = FALSE; lnk_gre.is_tap = TRUE; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gretap0")) { - /* Seems that the ip_gre module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; - } - if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip("Cannot create gretap tunnel because of missing ip_gre module " "(modprobe ip_gre)"); goto out_delete_parent; @@ -1381,16 +1370,12 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding GRETAP tunnel"); } break; - } + case NM_LINK_TYPE_IPIP: { - NMPlatformLnkIpIp lnk_ipip = {}; - gboolean gracefully_skip = FALSE; + NMPlatformLnkIpIp lnk_ipip = {}; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "tunl0")) { - /* Seems that the ipip module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ipip", NULL) != 0; - } + module_loaded = nmtstp_ensure_module("ipip"); lnk_ipip.local = nmtst_inet4_from_string("1.2.3.4"); lnk_ipip.remote = nmtst_inet4_from_string("5.6.7.8"); @@ -1399,7 +1384,7 @@ test_software_detect(gconstpointer user_data) lnk_ipip.path_mtu_discovery = FALSE; if (!nmtstp_link_ipip_add(NULL, ext, DEVICE_NAME, &lnk_ipip)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip( "Cannot create ipip tunnel because of missing ipip module (modprobe ipip)"); goto out_delete_parent; @@ -1408,15 +1393,12 @@ test_software_detect(gconstpointer user_data) } break; } + case NM_LINK_TYPE_IP6TNL: { - NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - gboolean gracefully_skip = FALSE; + NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6tnl0")) { - /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_tunnel", NULL) != 0; - } + module_loaded = nmtstp_ensure_module("ip6_tunnel"); switch (test_data->test_mode) { case 0: @@ -1441,7 +1423,7 @@ test_software_detect(gconstpointer user_data) } if (!nmtstp_link_ip6tnl_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip("Cannot create ip6tnl tunnel because of missing ip6_tunnel module " "(modprobe ip6_tunnel)"); goto out_delete_parent; @@ -1450,15 +1432,12 @@ test_software_detect(gconstpointer user_data) } break; } + case NM_LINK_TYPE_IP6GRE: { - NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - gboolean gracefully_skip = FALSE; + NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) { - /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; - } + module_loaded = nmtstp_ensure_module("ip6_gre"); lnk_ip6tnl.local = nmtst_inet6_from_string("fd01::42"); lnk_ip6tnl.remote = nmtst_inet6_from_string("fd01::aaaa"); @@ -1468,7 +1447,7 @@ test_software_detect(gconstpointer user_data) lnk_ip6tnl.is_gre = TRUE; if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip("Cannot create ip6gre tunnel because of missing ip6_gre module " "(modprobe ip6_gre)"); goto out_delete_parent; @@ -1477,15 +1456,12 @@ test_software_detect(gconstpointer user_data) } break; } + case NM_LINK_TYPE_IP6GRETAP: { - NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - gboolean gracefully_skip = FALSE; + NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) { - /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; - } + module_loaded = nmtstp_ensure_module("ip6_gre"); lnk_ip6tnl.local = nmtst_inet6_from_string("fe80::abcd"); lnk_ip6tnl.remote = nmtst_inet6_from_string("fc01::bbbb"); @@ -1497,7 +1473,7 @@ test_software_detect(gconstpointer user_data) lnk_ip6tnl.is_tap = TRUE; if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip("Cannot create ip6gretap tunnel because of missing ip6_gre module " "(modprobe ip6_gre)"); goto out_delete_parent; @@ -1506,6 +1482,7 @@ test_software_detect(gconstpointer user_data) } break; } + case NM_LINK_TYPE_MACVLAN: { NMPlatformLnkMacvlan lnk_macvlan = {}; @@ -1539,6 +1516,7 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding MACVLAN interface"); break; } + case NM_LINK_TYPE_MACVTAP: { NMPlatformLnkMacvlan lnk_macvtap = {}; @@ -1551,10 +1529,12 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding MACVTAP interface"); break; } + case NM_LINK_TYPE_SIT: { - NMPlatformLnkSit lnk_sit = {}; - gboolean gracefully_skip = FALSE; + NMPlatformLnkSit lnk_sit = {}; + + module_loaded = nmtstp_ensure_module("sit"); lnk_sit.local = nmtst_inet4_from_string("192.168.200.1"); lnk_sit.remote = nmtst_inet4_from_string("172.25.100.14"); @@ -1563,13 +1543,8 @@ test_software_detect(gconstpointer user_data) lnk_sit.tos = 31; lnk_sit.path_mtu_discovery = FALSE; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "sit0")) { - /* Seems that the sit module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "sit", NULL) != 0; - } - if (!nmtstp_link_sit_add(NULL, ext, DEVICE_NAME, &lnk_sit)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip( "Cannot create sit tunnel because of missing sit module (modprobe sit)"); goto out_delete_parent; @@ -1578,6 +1553,7 @@ test_software_detect(gconstpointer user_data) } break; } + case NM_LINK_TYPE_VLAN: { NMPlatformLnkVlan lnk_vlan = {}; @@ -1601,6 +1577,7 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding VLAN interface"); break; } + case NM_LINK_TYPE_VRF: { NMPlatformLnkVrf lnk_vrf = {}; @@ -1617,14 +1594,9 @@ test_software_detect(gconstpointer user_data) } break; } - case NM_LINK_TYPE_VTI: - { - gboolean gracefully_skip = FALSE; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip_vti0")) { - /* Seems that the ip_vti module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip_vti", NULL) != 0; - } + case NM_LINK_TYPE_VTI: + module_loaded = nmtstp_ensure_module("ip_vti"); lnk_vti.local = nmtst_inet4_from_string("192.168.212.204"); lnk_vti.remote = nmtst_inet4_from_string("172.168.11.25"); @@ -1633,7 +1605,7 @@ test_software_detect(gconstpointer user_data) lnk_vti.okey = 13; if (!nmtstp_link_vti_add(NULL, ext, DEVICE_NAME, &lnk_vti)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip( "Cannot create vti tunnel because of missing vti module (modprobe ip_vti)"); goto out_delete_parent; @@ -1641,15 +1613,9 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding VTI tunnel"); } break; - } - case NM_LINK_TYPE_VTI6: - { - gboolean gracefully_skip = FALSE; - if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6_vti0")) { - /* Seems that the ip6_vti module is not loaded... try to load it. */ - gracefully_skip = nmp_utils_modprobe(NULL, TRUE, "ip6_vti", NULL) != 0; - } + case NM_LINK_TYPE_VTI6: + module_loaded = nmtstp_ensure_module("ip6_vti"); lnk_vti6.local = nmtst_inet6_from_string("fd01::1"); lnk_vti6.remote = nmtst_inet6_from_string("fd02::2"); @@ -1658,7 +1624,7 @@ test_software_detect(gconstpointer user_data) lnk_vti6.okey = 14; if (!nmtstp_link_vti6_add(NULL, ext, DEVICE_NAME, &lnk_vti6)) { - if (gracefully_skip) { + if (!module_loaded) { g_test_skip( "Cannot create vti6 tunnel because of missing vti module (modprobe ip_vti)"); goto out_delete_parent; @@ -1666,7 +1632,7 @@ test_software_detect(gconstpointer user_data) g_error("Failed adding VTI6 tunnel"); } break; - } + case NM_LINK_TYPE_VXLAN: { NMPlatformLnkVxlan lnk_vxlan = {}; @@ -1698,6 +1664,7 @@ test_software_detect(gconstpointer user_data) g_assert(nmtstp_link_vxlan_add(NULL, ext, DEVICE_NAME, &lnk_vxlan)); break; } + case NM_LINK_TYPE_TUN: { gboolean owner_valid = nmtst_get_rand_bool(); @@ -1732,6 +1699,7 @@ test_software_detect(gconstpointer user_data) (!lnk_tun.persist || nmtst_get_rand_bool()) ? &tun_fd : NULL)); break; } + case NM_LINK_TYPE_WIREGUARD: { const NMPlatformLink *link; -- cgit v1.2.1 From 26592ebfe541bdc3b45eaf289b3b17d05808c4c5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Jan 2023 12:46:16 +0100 Subject: platform/tests: avoid recent route protocols in "/route/test_cache_consistency_routes" tests Ubuntu 18.04 comes with iproute2-4.15.0-2ubuntu1.3. The "/etc/iproute2/rt_protos" file from that version does not yet support the "bgp" entry. Also the "babel" entry is only from 2014. Just choose other entries. The point is that NetworkManager would ignore those, and that applies to "zebra" and "bird" alike. --- src/core/platform/tests/test-route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index 64f9ffd778..bae38f265c 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -2262,7 +2262,7 @@ test_cache_consistency_routes(gconstpointer test_data) if (s) { if (nmtst_get_rand_bool()) { s = nm_streq(s, "kernel") ? nmtst_rand_select_str("boot", "static", "ra") - : nmtst_rand_select_str("babel", "bgp"); + : nmtst_rand_select_str("zebra", "bird"); } extra_options[n_extra_options++] = "proto"; extra_options[n_extra_options++] = s; -- cgit v1.2.1 From e99433866d3d79a5e75947d396f705f2f8cbb6b3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 25 Jan 2023 16:51:46 +0100 Subject: platform/tests: ignore ip-tunnel interfaces in nmtstp_assert_platform() Certain ip-tunnel modules automatically create network interfaces (for example, "ip_gre" module creates "gre0" and others). Btw, that's not the same as `modprobe bonding max_bonds=1`, where loading the module merely automatically creates a "bond0" interface. In case of ip tunnel modules, these generated interfaces seem essential to how the tunnel works, for example they cannot be deleted. I don't understand the purpose of those interfaces, but they seem not just regular tunnel interfaces (unlike, "bond0" which is a regular bond interface, albeit automatically created). Btw, if at the time when loading the module, an interface with such name already exists, it will bump the name (for example, adding a "gre1" interfaces, and so on). That adds to the ugliness of the whole thing, but for our unit tests, that is no problem. Our unit tests run in a separate netns, and we don't create conflicting interfaces. That is, an interface named "gre0" is always the special tunnel interface and we can/do rely on that. Note that when the kernel module gets loaded, it adds those interfaces to all netns. Thus, even if "test-route-linux" does not do anything with ip tunnels, such an interface can always appear in a netns, simply by running "test-link-linux" (or any other tool that creates a tunnel) in parallel or even in another container. Theoretically, we could just ensure that we load all the conflicting ip-tunnel modules (with nmtstp_ensure_module()). There there are two problems. First, there might be other tunnel modules that interfere but are not covered by nmtstp_ensure_module(). Second, when kernel creates those interfaces, it does not send correct RTM_NEWLINK notifications (a bug), so our platform cache will not be correct, and nmtstp_assert_platform() will fail. The only solution is to detect and ignore those interfaces. Also, ignore all interfaces of link-type "unknown". Those might be from other modules that we don't know about and that exhibit the same problem. --- src/core/platform/tests/test-common.c | 53 ++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 18098234c8..8064ea4392 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -858,23 +858,56 @@ _assert_platform_normalize_all(GPtrArray *arr) gboolean normalized = FALSE; for (i = 0; i < nm_g_ptr_array_len(arr); i++) { - const NMPObject **ptr = (gpointer) &arr->pdata[i]; - NMPObject *new; + const NMPObject **ptr = (gpointer) &arr->pdata[i]; + nm_auto_nmpobj NMPObject *new = NULL; + gboolean skip = FALSE; switch (NMP_OBJECT_GET_TYPE(*ptr)) { case NMP_OBJECT_TYPE_LINK: - new = nmp_object_clone(*ptr, FALSE); - new->link.rx_packets = 0; - new->link.rx_bytes = 0; - new->link.tx_packets = 0; - new->link.tx_bytes = 0; - nmp_object_ref_set(ptr, new); - nmp_object_unref(new); - normalized = TRUE; + { + const NMPlatformLink *link = NMP_OBJECT_CAST_LINK(*ptr); + + if (nmtstp_link_is_iptunnel_special(link)) { + /* These are special interfaces for the ip tunnel modules, like + * "gre0" created by the "ip_gre" module. + * + * These interfaces can appear at any moment, when the module + * gets loaded (by anybody on the host). We might want to avoid + * that by calling nmtstp_ensure_module(), but it's worse. + * Kernel does not send correct RTM_NEWLINK events when those + * interfaces get created. So the cache content based on the + * events will differ from a new load from a dump. + * + * We need to ignore those interfaces. */ + skip = TRUE; + } else if (link->type == NM_LINK_TYPE_UNKNOWN) { + /* The link type is not detected. This might be a generated + * interface like nmtstp_link_is_iptunnel_special(), but for + * kernel modules that we don't know about. Ignore them too. */ + skip = TRUE; + } + + if (!skip) { + new = nmp_object_clone(*ptr, FALSE); + new->link.rx_packets = 0; + new->link.rx_bytes = 0; + new->link.tx_packets = 0; + new->link.tx_bytes = 0; + } + if (nmp_object_ref_set(ptr, new)) + normalized = TRUE; + break; + } default: break; } } + + while (g_ptr_array_remove(arr, NULL)) { + /* Remove NULL values. */ + normalized = TRUE; + } + return normalized; } -- cgit v1.2.1 From 00affc7b6f268d54f0205e325806ba9ab7e3da22 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 30 Jan 2023 08:56:36 +0100 Subject: contrib/release.sh: add hint about publishing documentation on website --- contrib/fedora/rpm/release.sh | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/contrib/fedora/rpm/release.sh b/contrib/fedora/rpm/release.sh index e653509869..c896a8ed0f 100755 --- a/contrib/fedora/rpm/release.sh +++ b/contrib/fedora/rpm/release.sh @@ -55,7 +55,14 @@ echo_color() { print_usage() { echo "Usage:" - echo " $BASH_SOURCE [devel|rc1|rc|major|major-post|minor] [--no-test] [--no-find-backports] [--no-cleanup] [--allow-local-branches] [--no-check-gitlab] [--no-check-news]" + echo " $BASH_SOURCE [devel|rc1|rc|major|major-post|minor]" + echo " [--no-test] \\" + echo " [--no-find-backports] \\" + echo " [--no-cleanup] \\" + echo " [--allow-local-branches] \\" + echo " [--no-check-gitlab] \\" + echo " [--no-check-news] \\" + echo " [--no-warn-publish-docs] \\" } die_help() { @@ -204,6 +211,7 @@ FIND_BACKPORTS=1 ALLOW_LOCAL_BRANCHES=0 HELP_AND_EXIT=1 CHECK_GITLAB=1 +WARN_PUBLISH_DOCS=1 CHECK_NEWS=1 while [ "$#" -ge 1 ]; do A="$1" @@ -228,6 +236,9 @@ while [ "$#" -ge 1 ]; do --no-check-gitlab) CHECK_GITLAB=0 ;; + --no-warn-publish-docs) + WARN_PUBLISH_DOCS=0 + ;; --no-check-news) CHECK_NEWS=0 ;; @@ -366,6 +377,24 @@ if ! check_news "$RELEASE_MODE" "@{VERSION_ARR[@]}" ; then echo "WARNING: NEWS file needs update to mention stable release (test skipped with --no-check-news)" fi +if [ "$RELEASE_MODE" = major -o "$RELEASE_MODE" = minor ]; then + echo + latest= + if [ "$RELEASE_MODE" = major ]; then + echo "Note that after the new major you have to publish the new documentation on" + latest=" -l" + else + echo "Note that after the stable release you maybe should publish the new documentation on" + fi + echo "$(echo_color 36 -n "https://gitlab.freedesktop.org/NetworkManager/networkmanager.pages.freedesktop.org.git") by running" + echo " \`$(echo_color 36 -n "./scripts/import-docs.sh ${VERSION_ARR[0]}.$((${VERSION_ARR[1]} + 1)).0$latest")\`" + echo + if [ $WARN_PUBLISH_DOCS = 1 ]; then + echo "Avoid this prompt via \"--no-warn-publish-docs\"" + read -p "Please confirm that you know [ENTER] " + fi +fi + if [ $FIND_BACKPORTS = 1 ]; then git show "$ORIGIN/main:contrib/scripts/find-backports" > ./.git/nm-find-backports \ && chmod +x ./.git/nm-find-backports \ -- cgit v1.2.1 From fb1d2da97927c2415773901a2548010e78575db8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 27 Jan 2023 12:28:54 +0100 Subject: glib-aux: add nm_random_u64_range() helper --- src/libnm-glib-aux/nm-random-utils.c | 50 ++++++++++++++++++++++++++ src/libnm-glib-aux/nm-random-utils.h | 35 ++++++++++++++++++ src/libnm-glib-aux/tests/test-shared-general.c | 50 ++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/src/libnm-glib-aux/nm-random-utils.c b/src/libnm-glib-aux/nm-random-utils.c index 93eee7c4d3..8930ed491b 100644 --- a/src/libnm-glib-aux/nm-random-utils.c +++ b/src/libnm-glib-aux/nm-random-utils.c @@ -447,3 +447,53 @@ again_getrandom: return nm_utils_fd_read_loop_exact(fd, p, n, FALSE); } + +guint64 +nm_random_u64_range_full(guint64 begin, guint64 end, gboolean crypto_bytes) +{ + gboolean bad_crypto_bytes = FALSE; + guint64 remainder; + guint64 maxvalue; + guint64 x; + guint64 m; + + /* Returns a random #guint64 equally distributed in the range [@begin..@end-1]. + * + * The function always set errno. It either sets it to zero or to EAGAIN + * (if crypto_bytes were requested but not obtained). In any case, the function + * will always return a random number in the requested range (worst case, it's + * not crypto_bytes despite being requested). Check errno if you care. */ + + if (begin >= end) { + /* systemd's random_u64_range(0) is an alias for random_u64_range((uint64_t)-1). + * Not for us. It's a caller error to request an element from an empty range. */ + return nm_assert_unreachable_val(begin); + } + + m = end - begin; + + if (m == 1) { + x = 0; + goto out; + } + + remainder = G_MAXUINT64 % m; + maxvalue = G_MAXUINT64 - remainder; + + do + if (crypto_bytes) { + if (nm_random_get_crypto_bytes(&x, sizeof(x)) < 0) { + /* Cannot get good crypto numbers. We will try our best, but fail + * and set errno below. */ + crypto_bytes = FALSE; + bad_crypto_bytes = TRUE; + continue; + } + } else + nm_random_get_bytes(&x, sizeof(x)); + while (x >= maxvalue); + +out: + errno = bad_crypto_bytes ? EAGAIN : 0; + return begin + (x % m); +} diff --git a/src/libnm-glib-aux/nm-random-utils.h b/src/libnm-glib-aux/nm-random-utils.h index ab8aee1b03..729d71a4d7 100644 --- a/src/libnm-glib-aux/nm-random-utils.h +++ b/src/libnm-glib-aux/nm-random-utils.h @@ -16,4 +16,39 @@ nm_random_get_bytes(void *p, size_t n) int nm_random_get_crypto_bytes(void *p, size_t n); +static inline guint32 +nm_random_u32(void) +{ + guint32 v; + + nm_random_get_bytes(&v, sizeof(v)); + return v; +} + +static inline guint64 +nm_random_u64(void) +{ + guint64 v; + + nm_random_get_bytes(&v, sizeof(v)); + return v; +} + +static inline bool +nm_random_bool(void) +{ + guint8 ch; + + nm_random_get_bytes(&ch, sizeof(ch)); + return ch % 2u; +} + +guint64 nm_random_u64_range_full(guint64 begin, guint64 end, gboolean crypto_bytes); + +static inline guint64 +nm_random_u64_range(guint64 end) +{ + return nm_random_u64_range_full(0, end, FALSE); +} + #endif /* __NM_RANDOM_UTILS_H__ */ diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c index 7503dc9b9f..3eaca5474a 100644 --- a/src/libnm-glib-aux/tests/test-shared-general.c +++ b/src/libnm-glib-aux/tests/test-shared-general.c @@ -137,6 +137,55 @@ test_nmhash(void) /*****************************************************************************/ +static void +test_nm_random(void) +{ + int i_run; + + for (i_run = 0; i_run < 1000; i_run++) { + guint64 begin; + guint64 end; + guint64 m; + guint64 x; + + m = nmtst_get_rand_uint64(); + m = m >> (nmtst_get_rand_uint32() % 64); + + if (m == 0) + continue; + + switch (nmtst_get_rand_uint32() % 4) { + case 0: + begin = 0; + break; + case 1: + begin = nmtst_get_rand_uint64() % 1000; + break; + case 2: + begin = ((G_MAXUINT64 - m) - 500) + (nmtst_get_rand_uint64() % 1000); + break; + default: + begin = nmtst_get_rand_uint64() % (G_MAXUINT64 - m); + break; + } + + end = (begin + m) - 10 + (nmtst_get_rand_uint64() % 5); + + if (begin >= end) + continue; + + if (begin == 0 && nmtst_get_rand_bool()) + x = nm_random_u64_range(end); + else + x = nm_random_u64_range_full(begin, end, nmtst_get_rand_bool()); + + g_assert_cmpuint(x, >=, begin); + g_assert_cmpuint(x, <, end); + } +} + +/*****************************************************************************/ + static const char * _make_strv_foo(void) { @@ -2417,6 +2466,7 @@ main(int argc, char **argv) g_test_add_func("/general/test_inet_utils", test_inet_utils); g_test_add_func("/general/test_garray", test_garray); g_test_add_func("/general/test_nm_prioq", test_nm_prioq); + g_test_add_func("/general/test_nm_random", test_nm_random); return g_test_run(); } -- cgit v1.2.1 From 6e96d7173168e2231cf576bc9f2aeb1f13529bca Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 27 Jan 2023 12:52:20 +0100 Subject: all: use nm_random_*() instead of g_random_*() g_random_*() is based on GRand, which is not a CSPRNG. Instead, rely on kernel to give us good random numbers, which is what nm_random_*() does. Note that nm_random_*() calls getrandom() (or reads /dev/urandom), which most likely is slower than GRand. It doesn't matter for our uses though. It is cumbersome to review all uses of g_rand_*() whether their usage of a non-cryptographically secure generator is appropriate. Instead, just always use an appropriate function, thereby avoiding this question. Even glib documentation refers to reading "/dev/urandom" as alternative. Which is what nm_random_*() does. These days, it seems unnecessary to not use the best random generator available, unless it's not fast enough or you need a stable/seedable stream of random numbers. In particular in nmcli, we used g_random_int_range() to generate passwords. That is not appropriate. Sure, it's *only* for the hotspot, but still. --- src/core/ndisc/nm-ndisc.c | 19 ++++++++++--------- src/core/nm-core-utils.c | 4 +--- src/libnm-client-aux-extern/nm-libnm-aux.c | 4 +++- src/nmcli/devices.c | 13 ++++++++----- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index 39a4df4824..20dd21212d 100644 --- a/src/core/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -10,6 +10,7 @@ #include #include +#include "libnm-glib-aux/nm-random-utils.h" #include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-netns.h" @@ -858,7 +859,7 @@ solicit_retransmit_time_jitter(gint32 solicit_retransmit_time_msec) ten_percent = NM_MAX(1, solicit_retransmit_time_msec / 10); return solicit_retransmit_time_msec - ten_percent - + ((gint32) (g_random_int() % (2u * ((guint32) ten_percent)))); + + ((gint32) (nm_random_u32() % (2u * ((guint32) ten_percent)))); } static gboolean @@ -936,7 +937,7 @@ solicit_timer_start(NMNDisc *ndisc) * a suitable delay in 2021. Wait only up to 250 msec instead. */ delay_msec = - g_random_int() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4)); + nm_random_u32() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4)); _LOGD("solicit: schedule sending first solicitation (of %d) in %.3f seconds", priv->config.router_solicitations, @@ -974,8 +975,9 @@ announce_router(NMNDisc *ndisc) /* Schedule next initial announcement retransmit. */ priv->send_ra_id = - g_timeout_add_seconds(g_random_int_range(NM_NDISC_ROUTER_ADVERT_DELAY, - NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL), + g_timeout_add_seconds(nm_random_u64_range_full(NM_NDISC_ROUTER_ADVERT_DELAY, + NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL, + FALSE), (GSourceFunc) announce_router, ndisc); } else { @@ -1009,10 +1011,9 @@ announce_router_initial(NMNDisc *ndisc) /* Schedule the initial send rather early. Clamp the delay by minimal * delay and not the initial advert internal so that we start fast. */ if (G_LIKELY(!priv->send_ra_id)) { - priv->send_ra_id = - g_timeout_add_seconds(g_random_int_range(0, NM_NDISC_ROUTER_ADVERT_DELAY), - (GSourceFunc) announce_router, - ndisc); + priv->send_ra_id = g_timeout_add_seconds(nm_random_u64_range(NM_NDISC_ROUTER_ADVERT_DELAY), + (GSourceFunc) announce_router, + ndisc); } } @@ -1028,7 +1029,7 @@ announce_router_solicited(NMNDisc *ndisc) nm_clear_g_source(&priv->send_ra_id); if (!priv->send_ra_id) { - priv->send_ra_id = g_timeout_add(g_random_int_range(0, NM_NDISC_ROUTER_ADVERT_DELAY_MS), + priv->send_ra_id = g_timeout_add(nm_random_u64_range(NM_NDISC_ROUTER_ADVERT_DELAY_MS), (GSourceFunc) announce_router, ndisc); } diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c index 9448ba7b03..53afaa547a 100644 --- a/src/core/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -3673,9 +3673,7 @@ _hw_addr_eth_complete(struct ether_addr *addr, nm_assert((ouis == NULL) ^ (ouis_len != 0)); if (ouis) { - /* g_random_int() is good enough here. It uses a static GRand instance - * that is seeded from /dev/urandom. */ - oui = ouis[g_random_int() % ouis_len]; + oui = ouis[nm_random_u64_range(ouis_len)]; g_free(ouis); } else { if (!nm_utils_hwaddr_aton(current_mac_address, &oui, ETH_ALEN)) diff --git a/src/libnm-client-aux-extern/nm-libnm-aux.c b/src/libnm-client-aux-extern/nm-libnm-aux.c index 82a75de697..5855bc299b 100644 --- a/src/libnm-client-aux-extern/nm-libnm-aux.c +++ b/src/libnm-client-aux-extern/nm-libnm-aux.c @@ -4,6 +4,8 @@ #include "nm-libnm-aux.h" +#include "libnm-glib-aux/nm-random-utils.h" + /*****************************************************************************/ NMClient * @@ -101,7 +103,7 @@ nmc_client_new_waitsync(GCancellable *cancellable, * code no longer uses that, we hardly test those code paths. But they should * work just the same. Randomly use instead the sync initialization in a debug * build... */ - if ((g_random_int() % 2) == 0) { + if (nm_random_bool()) { gboolean success; va_start(ap, first_property_name); diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index f71a7d036d..4a0c3ab8a8 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -17,6 +17,7 @@ #include #include "libnm-glib-aux/nm-secret-utils.h" +#include "libnm-glib-aux/nm-random-utils.h" #include "common.h" #include "connections.h" #include "libnmc-base/nm-client-utils.h" @@ -4098,10 +4099,11 @@ generate_wpa_key(char *key, size_t len) /* generate a 8-chars ASCII WPA key */ for (i = 0; i < WPA_PASSKEY_SIZE; i++) { int c; - c = g_random_int_range(33, 126); - /* too many non alphanumeric characters are hard to remember for humans */ - while (!g_ascii_isalnum(c)) - c = g_random_int_range(33, 126); + + do { + c = nm_random_u64_range_full(33, 126, TRUE); + /* too many non alphanumeric characters are hard to remember for humans */ + } while (g_ascii_isalnum(c)); key[i] = (char) c; } @@ -4120,7 +4122,8 @@ generate_wep_key(char *key, size_t len) /* generate a 10-digit hex WEP key */ for (i = 0; i < 10; i++) { int digit; - digit = g_random_int_range(0, 16); + + digit = nm_random_u64_range_full(0, 16, TRUE); key[i] = hexdigits[digit]; } key[10] = '\0'; -- cgit v1.2.1 From dbea79550fb6fad7a59e612f41bd33cbd69ced4d Mon Sep 17 00:00:00 2001 From: Wen Liang Date: Thu, 26 Jan 2023 15:34:36 -0500 Subject: version: add 1.44 macros --- src/libnm-core-public/nm-version-macros.h.in | 1 + src/libnm-core-public/nm-version.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/libnm-core-public/nm-version-macros.h.in b/src/libnm-core-public/nm-version-macros.h.in index 543edcf096..f44199a0d0 100644 --- a/src/libnm-core-public/nm-version-macros.h.in +++ b/src/libnm-core-public/nm-version-macros.h.in @@ -72,6 +72,7 @@ #define NM_VERSION_1_38 (NM_ENCODE_VERSION(1, 38, 0)) #define NM_VERSION_1_40 (NM_ENCODE_VERSION(1, 40, 0)) #define NM_VERSION_1_42 (NM_ENCODE_VERSION(1, 42, 0)) +#define NM_VERSION_1_44 (NM_ENCODE_VERSION(1, 44, 0)) /* For releases, NM_API_VERSION is equal to NM_VERSION. * diff --git a/src/libnm-core-public/nm-version.h b/src/libnm-core-public/nm-version.h index 0b2e6103a2..c7b7d34855 100644 --- a/src/libnm-core-public/nm-version.h +++ b/src/libnm-core-public/nm-version.h @@ -355,6 +355,20 @@ #define NM_AVAILABLE_IN_1_42 #endif +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_44 +#define NM_DEPRECATED_IN_1_44 G_DEPRECATED +#define NM_DEPRECATED_IN_1_44_FOR(f) G_DEPRECATED_FOR(f) +#else +#define NM_DEPRECATED_IN_1_44 +#define NM_DEPRECATED_IN_1_44_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_44 +#define NM_AVAILABLE_IN_1_44 G_UNAVAILABLE(1, 44) +#else +#define NM_AVAILABLE_IN_1_44 +#endif + /* * Synchronous API for calling D-Bus in libnm is deprecated. See * https://networkmanager.dev/docs/libnm/latest/usage.html#sync-api -- cgit v1.2.1 From 7a844ecba9e4fd50feec20b6876901b561f7cec5 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Tue, 31 Jan 2023 10:30:04 +0100 Subject: netns: fix configuring onlink routes for ECMP routes Kernel enforces that all nexthops must be reachable through a route. L3Cfg is generating dependent onlink routes to solve this problem but the IPv4 ECMP commit is happening before that. To solve this we introduce two boolean fields "is_new" and "is_ready" to know in which state is the L3Cfg affected. Initially, "is_new" is TRUE and "is_ready" is FALSE. Here we schedule a commit on idle and we set "is_new" to FALSE. When revisiting, we set "is_ready" to TRUE and then we set the ECMP IPv4 routes. When a reapply kicks in we reset the L3Cfg state by setting "is_new" to TRUE. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1520 --- src/core/nm-l3cfg.c | 5 +- src/core/nm-netns.c | 166 ++++++++++++++++++++++++---------------------------- src/core/nm-netns.h | 5 +- 3 files changed, 84 insertions(+), 92 deletions(-) diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index 81dabc0433..a49654feb5 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -1180,7 +1180,10 @@ loop_done: /* NMNetns will merge the routes. The ones that found a merge partner are true multihop * routes, with potentially a next hop on different interfaces. The routes * that didn't find a merge partner are returned in "singlehop_routes". */ - nm_netns_ip_route_ecmp_commit(self->priv.netns, self, &singlehop_routes); + nm_netns_ip_route_ecmp_commit(self->priv.netns, + self, + &singlehop_routes, + NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_REAPPLY)); if (singlehop_routes) { for (i = 0; i < singlehop_routes->len; i++) { diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index ca9f66c056..1c05506e40 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -29,7 +29,6 @@ typedef struct { NMPGlobalTracker *global_tracker; GHashTable *l3cfgs; GHashTable *shared_ips; - GHashTable *ecmp_routes; GHashTable *ecmp_track_by_obj; GHashTable *ecmp_track_by_ecmpid; CList l3cfg_signal_pending_lst_head; @@ -71,12 +70,6 @@ NM_DEFINE_SINGLETON_GETTER(NMNetns, nm_netns_get, NM_TYPE_NETNS); /*****************************************************************************/ -void _netns_ip_route_ecmp_update_mh(NMNetns *self, - const GPtrArray *mhrts_del, - const GPtrArray *mhrts_add); - -/*****************************************************************************/ - #define nm_assert_l3cfg(self, l3cfg) \ G_STMT_START \ { \ @@ -112,6 +105,8 @@ typedef struct { /* Calling nm_netns_ip_route_ecmp_register() will ensure that the tracked * entry is non-dirty. This can be used to remove stale entries. */ bool dirty : 1; + bool is_new : 1; + bool is_ready : 1; } EcmpTrackObj; static int @@ -607,6 +602,8 @@ nm_netns_ip_route_ecmp_register(NMNetns *self, NML3Cfg *l3cfg, const NMPObject * .l3cfg = l3cfg, .parent_track_ecmpid = track_ecmpid, .dirty = FALSE, + .is_new = TRUE, + .is_ready = FALSE, }; g_hash_table_add(priv->ecmp_track_by_obj, track_obj); @@ -624,17 +621,19 @@ nm_netns_ip_route_ecmp_register(NMNetns *self, NML3Cfg *l3cfg, const NMPObject * } void -nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **out_singlehop_routes) +nm_netns_ip_route_ecmp_commit(NMNetns *self, + NML3Cfg *l3cfg, + GPtrArray **out_singlehop_routes, + gboolean is_reapply) { - NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE(self); - EcmpTrackObj *track_obj; - EcmpTrackObj *track_obj_safe; - EcmpTrackEcmpid *track_ecmpid; - const NMPObject *route_obj; - const NMPlatformIP4Route *route; - char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; - gs_unref_ptrarray GPtrArray *mhrts_del = NULL; - gs_unref_ptrarray GPtrArray *mhrts_add = NULL; + NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE(self); + EcmpTrackObj *track_obj; + EcmpTrackObj *track_obj_safe; + EcmpTrackEcmpid *track_ecmpid; + const NMPObject *route_obj; + const NMPlatformIP4Route *route; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; + gboolean already_notified = FALSE; nm_assert_l3cfg(self, l3cfg); @@ -658,6 +657,41 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **out_sin /* This one is still in used. Keep it, but mark dirty, so that on the * next update cycle, it needs to be touched again or will be deleted. */ track_obj->dirty = TRUE; + if (is_reapply) { + track_obj->is_new = TRUE; + track_obj->is_ready = FALSE; + } + if (track_obj->is_new) { + /* This is a new route entry that was just added. Upon first + * addition, the route is not yet ready for configuration, + * because we need to make sure that the gateway is reachable + * via an onlink route. The calling l3cfg will configure that + * route, but only after returning from this function. So we + * need to go through one more commit. + * + * We also need to make sure that we are called back right + * after l3cfg configured that route. We achieve that by + * scheduling another idle commit on "l3cfg". */ + track_obj->is_new = FALSE; + if (c_list_length_is(&track_ecmpid->ecmpid_lst_head, 1)) { + /* This route has no merge partner and ends up being a + * single hop route. It will be returned and configured by + * the calling "l3cfg". + * + * Unlike for multi-hop routes, we don't need to be called + * again after the onlink route was added. We are done, and + * don't need to schedule an idle commit. */ + track_obj->is_ready = TRUE; + } else { + if (!already_notified) { + already_notified = TRUE; + nm_l3cfg_commit_on_idle_schedule(l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); + } + } + } else { + /* We see this entry the second time (or more) so it's ready. */ + track_obj->is_ready = TRUE; + } continue; } @@ -667,14 +701,8 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **out_sin if (c_list_is_empty(&track_ecmpid->ecmpid_lst_head)) { if (track_ecmpid->merged_obj) { - if (NMP_OBJECT_CAST_IP4_ROUTE(track_ecmpid->merged_obj)->n_nexthops > 1) { - if (!mhrts_del) - mhrts_del = - g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); - g_ptr_array_add(mhrts_del, - (gpointer) g_steal_pointer(&track_ecmpid->merged_obj)); - } else - nm_l3cfg_commit_on_idle_schedule(l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); + if (NMP_OBJECT_CAST_IP4_ROUTE(track_ecmpid->merged_obj)->n_nexthops > 1) + nm_platform_object_delete(priv->platform, track_ecmpid->merged_obj); } g_hash_table_remove(priv->ecmp_track_by_ecmpid, track_ecmpid); @@ -692,8 +720,10 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **out_sin c_list_for_each_entry (track_obj, &l3cfg->internal_netns.ecmp_track_ifindex_lst_head, ifindex_lst) { + EcmpTrackObj *track_obj2; nm_auto_nmpobj const NMPObject *obj_del = NULL; gboolean changed; + gboolean all_is_ready; track_ecmpid = track_obj->parent_track_ecmpid; if (track_ecmpid->already_visited) { @@ -703,23 +733,32 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **out_sin } track_ecmpid->already_visited = TRUE; + all_is_ready = TRUE; + c_list_for_each_entry (track_obj2, &track_ecmpid->ecmpid_lst_head, ecmpid_lst) { + if (!track_obj2->is_ready) { + all_is_ready = FALSE; + break; + } + } + if (!all_is_ready) { + /* Here we might have a merged_obj already which can have the wrong + * setting e.g the wrong nexthops. We leave them for the moment and + * then we reconfigure it when this entry is ready. */ + continue; + } + changed = _ecmp_track_init_merged_obj(track_obj->parent_track_ecmpid, &obj_del); nm_assert(!obj_del || changed); - route_obj = track_obj->parent_track_ecmpid->merged_obj; + route_obj = track_ecmpid->merged_obj; route = NMP_OBJECT_CAST_IP4_ROUTE(route_obj); if (obj_del) { - if (NMP_OBJECT_CAST_IP4_ROUTE(obj_del)->n_nexthops > 1) { - if (!mhrts_del) - mhrts_del = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); - g_ptr_array_add(mhrts_del, (gpointer) g_steal_pointer(&obj_del)); - } else { - if (track_obj->l3cfg != l3cfg) { - nm_l3cfg_commit_on_idle_schedule(track_obj->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); - } - } + if (NMP_OBJECT_CAST_IP4_ROUTE(obj_del)->n_nexthops > 1) + nm_platform_object_delete(priv->platform, obj_del); + else if (track_obj->l3cfg != l3cfg) + nm_l3cfg_commit_on_idle_schedule(track_obj->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); } if (route->n_nexthops <= 1) { @@ -742,57 +781,10 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **out_sin continue; } - if (changed) { + if (changed || is_reapply) { _LOGT("ecmp-route: multi-hop %s", nmp_object_to_string(route_obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); - if (!mhrts_add) { - /* mhrts_add doesn't own the pointers. It relies on them being alive long enough. */ - mhrts_add = g_ptr_array_new(); - } - g_ptr_array_add(mhrts_add, (gpointer) route_obj); - } - } - - _netns_ip_route_ecmp_update_mh(self, mhrts_del, mhrts_add); -} - -void -_netns_ip_route_ecmp_update_mh(NMNetns *self, - const GPtrArray *mhrts_del, - const GPtrArray *mhrts_add) -{ - NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE(self); - guint i; - - if (mhrts_del) { - for (i = 0; i < mhrts_del->len; i++) { - const NMPObject *obj = mhrts_del->pdata[i]; - - if (!g_hash_table_remove(priv->ecmp_routes, obj)) - nm_assert_not_reached(); - - nm_platform_object_delete(priv->platform, obj); - } - } - - if (mhrts_add) { - for (i = 0; i < mhrts_add->len; i++) { - const NMPObject *obj = mhrts_add->pdata[i]; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - gpointer unused; - - if (g_hash_table_steal_extended(priv->ecmp_routes, - obj, - (gpointer *) &obj_old, - &unused)) { - if (obj != obj_old) - nm_platform_object_delete(priv->platform, obj_old); - } - - if (!g_hash_table_add(priv->ecmp_routes, (gpointer) nmp_object_ref(obj))) - nm_assert_not_reached(); - - nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, obj); + nm_platform_ip_route_add(priv->platform, NMP_NLM_FLAG_APPEND, route_obj); } } } @@ -829,11 +821,6 @@ nm_netns_init(NMNetns *self) priv->_self_signal_user_data = self; c_list_init(&priv->l3cfg_signal_pending_lst_head); - priv->ecmp_routes = g_hash_table_new_full((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal, - (GDestroyNotify) nmp_object_unref, - NULL); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(EcmpTrackObj, obj) == 0); priv->ecmp_track_by_obj = g_hash_table_new_full(nm_pdirect_hash, nm_pdirect_equal, _ecmp_routes_by_obj_free, NULL); @@ -920,7 +907,6 @@ dispose(GObject *object) nm_assert(c_list_is_empty(&priv->l3cfg_signal_pending_lst_head)); nm_assert(!priv->shared_ips); - nm_clear_pointer(&priv->ecmp_routes, g_hash_table_destroy); nm_clear_pointer(&priv->ecmp_track_by_obj, g_hash_table_destroy); nm_clear_pointer(&priv->ecmp_track_by_ecmpid, g_hash_table_destroy); diff --git a/src/core/nm-netns.h b/src/core/nm-netns.h index cf2d963203..84a78f8363 100644 --- a/src/core/nm-netns.h +++ b/src/core/nm-netns.h @@ -54,6 +54,9 @@ void nm_netns_shared_ip_release(NMNetnsSharedIPHandle *handle); /*****************************************************************************/ void nm_netns_ip_route_ecmp_register(NMNetns *self, NML3Cfg *l3cfg, const NMPObject *obj); -void nm_netns_ip_route_ecmp_commit(NMNetns *self, NML3Cfg *l3cfg, GPtrArray **routes); +void nm_netns_ip_route_ecmp_commit(NMNetns *self, + NML3Cfg *l3cfg, + GPtrArray **routes, + gboolean is_reapply); #endif /* __NM_NETNS_H__ */ -- cgit v1.2.1 From ec0a83b224b313839357fb325ccede0f5a0c47c4 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Jan 2023 17:17:19 +0100 Subject: core: rename and move nm_ip_config_dns_hash() The function operates on a NML3ConfigData, rename it and move it to the right place. --- src/core/dns/nm-dns-manager.c | 2 +- src/core/nm-ip-config.c | 68 ----------------------------------------- src/core/nm-ip-config.h | 2 -- src/core/nm-l3-config-data.c | 70 +++++++++++++++++++++++++++++++++++++++++++ src/core/nm-l3-config-data.h | 2 ++ 5 files changed, 73 insertions(+), 71 deletions(-) diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 42519e64fe..a216ac13e1 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1209,7 +1209,7 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[ * configuration without DNS parameters gives a zero checksum. */ head = _mgr_get_ip_data_lst_head(self); c_list_for_each_entry (ip_data, head, ip_data_lst) - nm_ip_config_dns_hash(ip_data->l3cd, sum, ip_data->addr_family); + nm_l3_config_data_hash_dns(ip_data->l3cd, sum, ip_data->addr_family); } nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN); diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c index a87e4c3f17..f87840cc3e 100644 --- a/src/core/nm-ip-config.c +++ b/src/core/nm-ip-config.c @@ -509,74 +509,6 @@ nm_ip4_config_class_init(NMIP4ConfigClass *klass) g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip4, obj_properties_ip4); } -void -nm_ip_config_dns_hash(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family) -{ - guint i; - int val; - const char *const *strarr; - const in_addr_t *wins; - const char *const *domains; - const char *const *searches; - const char *const *options; - guint num_nameservers; - guint num_wins; - guint num_domains; - guint num_searches; - guint num_options; - - g_return_if_fail(l3cd); - g_return_if_fail(sum); - - strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); - for (i = 0; i < num_nameservers; i++) - g_checksum_update(sum, (gpointer) strarr[i], strlen(strarr[i])); - - if (addr_family == AF_INET) { - wins = nm_l3_config_data_get_wins(l3cd, &num_wins); - for (i = 0; i < num_wins; i++) - g_checksum_update(sum, (guint8 *) &wins[i], 4); - } - - domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains); - for (i = 0; i < num_domains; i++) { - g_checksum_update(sum, (const guint8 *) domains[i], strlen(domains[i])); - } - - searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches); - for (i = 0; i < num_searches; i++) { - g_checksum_update(sum, (const guint8 *) searches[i], strlen(searches[i])); - } - - options = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num_options); - for (i = 0; i < num_options; i++) { - g_checksum_update(sum, (const guint8 *) options[i], strlen(options[i])); - } - - val = nm_l3_config_data_get_mdns(l3cd); - if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT) - g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); - - val = nm_l3_config_data_get_llmnr(l3cd); - if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT) - g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); - - val = nm_l3_config_data_get_dns_over_tls(l3cd); - if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) - g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); - - /* FIXME(ip-config-checksum): the DNS priority should be considered relevant - * and added into the checksum as well, but this can't be done right now - * because in the DNS manager we rely on the fact that an empty - * configuration (i.e. just created) has a zero checksum. This is needed to - * avoid rewriting resolv.conf when there is no change. - * - * The DNS priority initial value depends on the connection type (VPN or - * not), so it's a bit difficult to add it to checksum maintaining the - * assumption of checksum(empty)=0 - */ -} - /*****************************************************************************/ /* public */ diff --git a/src/core/nm-ip-config.h b/src/core/nm-ip-config.h index 3a1d375e97..0dcea83b51 100644 --- a/src/core/nm-ip-config.h +++ b/src/core/nm-ip-config.h @@ -51,8 +51,6 @@ NMIPConfig *nm_ip_config_new(int addr_family, NML3Cfg *l3cfg); void nm_ip_config_take_and_unexport_on_idle(NMIPConfig *self_take); -void nm_ip_config_dns_hash(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family); - /*****************************************************************************/ static inline NML3Cfg * diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 1c8200c248..2b9e2207cb 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -3018,6 +3018,76 @@ nm_l3_config_data_new_from_platform(NMDedupMultiIndex *multi_idx, /*****************************************************************************/ +void +nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family) +{ + guint i; + int val; + const char *const *strarr; + const in_addr_t *wins; + const char *const *domains; + const char *const *searches; + const char *const *options; + guint num_nameservers; + guint num_wins; + guint num_domains; + guint num_searches; + guint num_options; + + g_return_if_fail(l3cd); + g_return_if_fail(sum); + + strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); + for (i = 0; i < num_nameservers; i++) + g_checksum_update(sum, (gpointer) strarr[i], strlen(strarr[i])); + + if (addr_family == AF_INET) { + wins = nm_l3_config_data_get_wins(l3cd, &num_wins); + for (i = 0; i < num_wins; i++) + g_checksum_update(sum, (guint8 *) &wins[i], 4); + } + + domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains); + for (i = 0; i < num_domains; i++) { + g_checksum_update(sum, (const guint8 *) domains[i], strlen(domains[i])); + } + + searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches); + for (i = 0; i < num_searches; i++) { + g_checksum_update(sum, (const guint8 *) searches[i], strlen(searches[i])); + } + + options = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num_options); + for (i = 0; i < num_options; i++) { + g_checksum_update(sum, (const guint8 *) options[i], strlen(options[i])); + } + + val = nm_l3_config_data_get_mdns(l3cd); + if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT) + g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + + val = nm_l3_config_data_get_llmnr(l3cd); + if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT) + g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + + val = nm_l3_config_data_get_dns_over_tls(l3cd); + if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + + /* FIXME(ip-config-checksum): the DNS priority should be considered relevant + * and added into the checksum as well, but this can't be done right now + * because in the DNS manager we rely on the fact that an empty + * configuration (i.e. just created) has a zero checksum. This is needed to + * avoid rewriting resolv.conf when there is no change. + * + * The DNS priority initial value depends on the connection type (VPN or + * not), so it's a bit difficult to add it to checksum maintaining the + * assumption of checksum(empty)=0 + */ +} + +/*****************************************************************************/ + void nm_l3_config_data_merge(NML3ConfigData *self, const NML3ConfigData *src, diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index 1a181e5cc1..14d0766aa7 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -604,4 +604,6 @@ nmtst_l3_config_data_get_best_gateway(const NML3ConfigData *self, int addr_famil return nm_platform_ip_route_get_gateway(addr_family, NMP_OBJECT_CAST_IP_ROUTE(rt)); } +void nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family); + #endif /* __NM_L3_CONFIG_DATA_H__ */ -- cgit v1.2.1 From 8a4632b56a1050ae155fef473582cae713321bce Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Jan 2023 17:20:44 +0100 Subject: core,libnm: move enum NMDnsIPConfigType The enum will be used outside of core/dns. --- src/core/dns/nm-dns-manager.h | 10 ---------- src/libnm-base/nm-base.h | 8 ++++++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h index 81121d7e5a..42f9dec588 100644 --- a/src/core/dns/nm-dns-manager.h +++ b/src/core/dns/nm-dns-manager.h @@ -12,16 +12,6 @@ #include "nm-setting-connection.h" #include "nm-dns-plugin.h" -typedef enum { - NM_DNS_IP_CONFIG_TYPE_REMOVED = -1, - - NM_DNS_IP_CONFIG_TYPE_DEFAULT = 0, - NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, - NM_DNS_IP_CONFIG_TYPE_VPN, -} NMDnsIPConfigType; - -/*****************************************************************************/ - struct _NMDnsConfigData; struct _NMDnsManager; diff --git a/src/libnm-base/nm-base.h b/src/libnm-base/nm-base.h index a8d6b2c892..74e8142f21 100644 --- a/src/libnm-base/nm-base.h +++ b/src/libnm-base/nm-base.h @@ -415,4 +415,12 @@ typedef struct { #define _NM_CRYPTO_ERROR _nm_crypto_error_quark() GQuark _nm_crypto_error_quark(void); +typedef enum { + NM_DNS_IP_CONFIG_TYPE_REMOVED = -1, + + NM_DNS_IP_CONFIG_TYPE_DEFAULT = 0, + NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, + NM_DNS_IP_CONFIG_TYPE_VPN, +} NMDnsIPConfigType; + #endif /* __NM_LIBNM_BASE_H__ */ -- cgit v1.2.1 From 46ccc82a81146132e4bc9c6cc96d7b8b2305f85f Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Jan 2023 17:29:52 +0100 Subject: dns: consider the dns-type and the priority when hashing DNS configs The dns-type must be included in the hash because it contributes to the generated composite configuration. Without this, when the type of a configuration changes (e.g. from DEFAULT to BEST), the DNS manager would determine that there was no change and it wouldn't call update_dns(). https://bugzilla.redhat.com/show_bug.cgi?id=2161957 Fixes: 8995d44a0bae ('core: compare the DNS configurations before updating DNS') --- src/core/dns/nm-dns-manager.c | 8 ++++++-- src/core/nm-l3-config-data.c | 43 +++++++++++++++++++++++++++++++++++++------ src/core/nm-l3-config-data.h | 5 ++++- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index a216ac13e1..6ee2e816a0 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1208,8 +1208,12 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[ /* FIXME(ip-config-checksum): this relies on the fact that an IP * configuration without DNS parameters gives a zero checksum. */ head = _mgr_get_ip_data_lst_head(self); - c_list_for_each_entry (ip_data, head, ip_data_lst) - nm_l3_config_data_hash_dns(ip_data->l3cd, sum, ip_data->addr_family); + c_list_for_each_entry (ip_data, head, ip_data_lst) { + nm_l3_config_data_hash_dns(ip_data->l3cd, + sum, + ip_data->addr_family, + ip_data->ip_config_type); + } } nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN); diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 2b9e2207cb..2865d9e1c3 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -3019,7 +3019,10 @@ nm_l3_config_data_new_from_platform(NMDedupMultiIndex *multi_idx, /*****************************************************************************/ void -nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family) +nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, + GChecksum *sum, + int addr_family, + NMDnsIPConfigType dns_ip_config_type) { guint i; int val; @@ -3033,46 +3036,74 @@ nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, GChecksum *sum, int addr_ guint num_domains; guint num_searches; guint num_options; + gboolean empty = TRUE; g_return_if_fail(l3cd); g_return_if_fail(sum); strarr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers); - for (i = 0; i < num_nameservers; i++) + for (i = 0; i < num_nameservers; i++) { g_checksum_update(sum, (gpointer) strarr[i], strlen(strarr[i])); + empty = FALSE; + } if (addr_family == AF_INET) { wins = nm_l3_config_data_get_wins(l3cd, &num_wins); - for (i = 0; i < num_wins; i++) + for (i = 0; i < num_wins; i++) { g_checksum_update(sum, (guint8 *) &wins[i], 4); + empty = FALSE; + } } domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains); for (i = 0; i < num_domains; i++) { g_checksum_update(sum, (const guint8 *) domains[i], strlen(domains[i])); + empty = FALSE; } searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches); for (i = 0; i < num_searches; i++) { g_checksum_update(sum, (const guint8 *) searches[i], strlen(searches[i])); + empty = FALSE; } options = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num_options); for (i = 0; i < num_options; i++) { g_checksum_update(sum, (const guint8 *) options[i], strlen(options[i])); + empty = FALSE; } val = nm_l3_config_data_get_mdns(l3cd); - if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT) + if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT) { g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + empty = FALSE; + } val = nm_l3_config_data_get_llmnr(l3cd); - if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT) + if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT) { g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + empty = FALSE; + } val = nm_l3_config_data_get_dns_over_tls(l3cd); - if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) { g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + empty = FALSE; + } + + if (!empty) { + int prio = 0; + + /* In the DNS manager we rely on the fact that an empty (i.e. without + * any name server, domain, option, etc. parameters) configuration + * has a zero checksum. This is needed to avoid rewriting resolv.conf + * when not needed. Since the dns-type and the priority are always + * present, hash them only when the rest of configuration is not empty. + */ + g_checksum_update(sum, (const guint8 *) &dns_ip_config_type, sizeof(dns_ip_config_type)); + nm_l3_config_data_get_dns_priority(l3cd, addr_family, &prio); + g_checksum_update(sum, (const guint8 *) &prio, sizeof(prio)); + } /* FIXME(ip-config-checksum): the DNS priority should be considered relevant * and added into the checksum as well, but this can't be done right now diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index 14d0766aa7..bfab04d9ce 100644 --- a/src/core/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -604,6 +604,9 @@ nmtst_l3_config_data_get_best_gateway(const NML3ConfigData *self, int addr_famil return nm_platform_ip_route_get_gateway(addr_family, NMP_OBJECT_CAST_IP_ROUTE(rt)); } -void nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family); +void nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd, + GChecksum *sum, + int addr_family, + NMDnsIPConfigType dns_ip_config_type); #endif /* __NM_L3_CONFIG_DATA_H__ */ -- cgit v1.2.1 From 362a96ff52363cfaf537d3c34e1a39e7f130942e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Feb 2023 11:05:13 +0100 Subject: contrib: setup "systemd" in makerepo.sh script --- contrib/fedora/utils/makerepo.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/fedora/utils/makerepo.sh b/contrib/fedora/utils/makerepo.sh index 47778b405b..db5c3be48c 100755 --- a/contrib/fedora/utils/makerepo.sh +++ b/contrib/fedora/utils/makerepo.sh @@ -398,6 +398,8 @@ pushd "$DIRNAME" git remote add origin "git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git" elif [[ "$BUILD_TYPE" == "dracut" ]]; then git remote add origin "https://github.com/dracutdevs/dracut.git" + elif [[ "$BUILD_TYPE" == "systemd" ]]; then + git remote add origin "https://github.com/systemd/systemd.git" elif [[ "$BUILD_TYPE" == "vpnc" ]]; then git_remote_add_github ndpgroup/vpnc fi @@ -515,6 +517,9 @@ cc304f05edab6c408a0f061eb1a104f9f06b8587 86ef789876b65c61751ce854835b91d4 init # dracut 00efe708cab023bfe6eaf530d8ac8ea97b440de2 SHA512 (dracut-050.tar.xz) = 9d9a66acfd6b9d2fd50855a59a2393e0602c2ef97119db046f68d6167ea84d1423fa465b8b4d96339febb38d5a96df26dec7862c4b3397c3d726db18d280eee4 + +# systemd +903dd65b5eb63257393955cb79777beb8c71afc1 SHA512 (systemd-253-rc1.tar.gz) = aaf0a6bf21bbc50a42015c9cb17f69d1aaf6cab6cabfba5140a94212fb864e38d638dace9a70447f62b4d2a817a0d3bd6f4ae8d9b3c2e741cdeb1cb332f70b65 EOF )" OLDIFS="$IFS" -- cgit v1.2.1 From de1dccba189ae3689fc9c41e34005ce15c790742 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 31 Jan 2023 18:32:31 +0100 Subject: platform/tests: suppress noisy output in test_cache_consistency_routes() test --- src/core/platform/tests/test-route.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index bae38f265c..0d8449b117 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -2166,8 +2166,12 @@ _ensure_onlink_routes(void) int i; for (i = 0; i < G_N_ELEMENTS(NMTSTP_ENV1_DEVICE_NAME) && NMTSTP_ENV1_DEVICE_NAME[i]; i++) { - nmtstp_run_command("ip route append 7.7.7.0/24 dev %s", NMTSTP_ENV1_DEVICE_NAME[i]); - nmtstp_run_command("ip route append 7:7:7::/64 dev %s", NMTSTP_ENV1_DEVICE_NAME[i]); + nmtstp_run_command("ip route append 7.7.7.0/24 dev %s%s", + NMTSTP_ENV1_DEVICE_NAME[i], + nmtst_is_debug() ? "" : " &>/dev/null"); + nmtstp_run_command("ip route append 7:7:7::/64 dev %s%s", + NMTSTP_ENV1_DEVICE_NAME[i], + nmtst_is_debug() ? "" : " &>/dev/null"); } } -- cgit v1.2.1 From 8089133f1c8418bc76f8b63f968477c0873bc9ef Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 30 Jan 2023 17:40:16 +0100 Subject: platform/tests: flush all tables in test_cache_consistency_routes() test --- src/core/platform/tests/test-route.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index 0d8449b117..569d371db0 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -2234,10 +2234,12 @@ test_cache_consistency_routes(gconstpointer test_data) continue; } nmtstp_run_command("ip -%c route flush dev %s" - "%s" /* redirect */ + " table %s" /* table */ + "%s" /* redirect */ "", addr_family_char[IS_IPv4], ifname, + nmtst_rand_select_str("main", "10222", "10223", "all"), nmtst_is_debug() ? "" : " &>/dev/null"); _ensure_onlink_routes(); goto done; -- cgit v1.2.1 From 0347dc7ddc1c7f3b55d2273c11f93e8b58c71548 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 30 Jan 2023 21:52:13 +0100 Subject: platform/tests: disable check for sorted IPv4 routes by weak-id Due to a kernel bug, this assert can fail and I don't think it can be fixed in NetworkManager. Disable the check. See-also: https://bugzilla.redhat.com/show_bug.cgi?id=2165720 --- src/core/platform/tests/test-common.c | 23 ++++++++++++++++------- src/core/platform/tests/test-route.c | 12 +++++++++++- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index 8064ea4392..a1ac373fee 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -1329,14 +1329,23 @@ nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) /* For IPv4, it also does not reliably always work. This may * be a bug we want to fix. For now, ignore the check. * - * This is probably caused by kernel bug - * https://bugzilla.redhat.com/show_bug.cgi?id=2162315 - * for which I think there is no workaround. + * a) Kernel can wrongly allow to configure the same route twice. + * That means, the same route is visible in `ip route` output, + * meaning, it would be added twice to the platform cache. + * At least due to that problem, may the weak-id not be properly sorted. + * See https://bugzilla.redhat.com/show_bug.cgi?id=2165720 which is + * a bug of kernel allowing to configure the exact same route twice. * - * Also, rhbz#2162315 means NMPlatform will merge two different - * routes together, if one of them were deleted, the RTM_DELROUTE - * message would wrongly delete single entry, leading to cache - * inconsistency. */ + * b) See https://bugzilla.redhat.com/show_bug.cgi?id=2162315 which is + * a bug where kernel does allow to configure single-hop routes that differ by + * their next-hop weight, but on the netlink API those routes look the same. + * + * Due to a) and b), the platform cache may contain only one instance + * of a route, which is visible more than once in `ip route` output. + * This merging of different routes causes problems, and it also means + * that the RTM_NEWROUTE events are wrongly interpreted and the weak-id + * is not properly sorted. + */ } else { /* Assert that also the original, not-sorted lists agree. */ _assert_platform_compare_arr(obj_type, diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index 569d371db0..d52e6e61ac 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -2312,7 +2312,17 @@ test_cache_consistency_routes(gconstpointer test_data) } extra_options[n_extra_options++] = "dev"; extra_options[n_extra_options++] = NMTSTP_ENV1_DEVICE_NAME[nmtst_get_rand_bool()]; - if (nmtst_get_rand_one_case_in(3)) { + if (IS_IPv4 && i == 0) { + /* For IPv4, there is a problem if we configure a route with + * only one next-hop and a weight. In that case, kernel allows + * to add duplicates (that only differ by weight), but on netlink + * the weight is not exposed, so the routes look identical and + * are deduplicated by the hash. + * See https://bugzilla.redhat.com/show_bug.cgi?id=2162315 + * + * This needs a kernel fix. Workaround that issue here, otherwise the test + * will randomly fail. */ + } else if (nmtst_get_rand_one_case_in(3)) { extra_options[n_extra_options++] = "weight"; extra_options[n_extra_options++] = "5"; } -- cgit v1.2.1 From 82e21a490625d038ef46f57040326391a23f38ea Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 31 Jan 2023 18:19:30 +0100 Subject: platform/tests: workaround failure of nmtstp_assert_platform() --- src/core/platform/tests/test-common.c | 172 ++++++++++++++++++++++------------ src/core/platform/tests/test-common.h | 5 +- src/core/platform/tests/test-route.c | 2 +- 3 files changed, 116 insertions(+), 63 deletions(-) diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index a1ac373fee..a37982fc69 100644 --- a/src/core/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -911,13 +911,14 @@ _assert_platform_normalize_all(GPtrArray *arr) return normalized; } -static void +static gboolean _assert_platform_compare_arr(NMPObjectType obj_type, const char *detail_type, GPtrArray *arr1, GPtrArray *arr2, gboolean normalized, - gboolean share_multi_idx) + gboolean share_multi_idx, + gboolean do_assert) { const NMPClass *obj_class = nmp_class_from_type(obj_type); char sbuf1[NM_UTILS_TO_STRING_BUFFER_SIZE]; @@ -925,48 +926,64 @@ _assert_platform_compare_arr(NMPObjectType obj_type, int idx; int idx_pointer_comp = -1; +#define _fail_msg(do_assert, ...) \ + G_STMT_START \ + { \ + if (do_assert) { \ + g_error(__VA_ARGS__); \ + } else { \ + _LOGW(__VA_ARGS__); \ + return FALSE; \ + } \ + } \ + G_STMT_END + for (idx = 0; TRUE; idx++) { if (nm_g_ptr_array_len(arr1) == idx && nm_g_ptr_array_len(arr2) == idx) break; if (idx >= nm_g_ptr_array_len(arr1)) { _assert_platform_printarr(obj_type, arr1, arr2); - g_error("Comparing %s (%s) for platform fails. Platform now shows entry #%u which is " - "not in the cache but expected %s", - obj_class->obj_type_name, - detail_type, - idx, - nmp_object_to_string(arr2->pdata[idx], - NMP_OBJECT_TO_STRING_ALL, - sbuf1, - sizeof(sbuf1))); + _fail_msg(do_assert, + "Comparing %s (%s) for platform fails. Platform now shows entry #%u which is " + "not in the cache but expected %s", + obj_class->obj_type_name, + detail_type, + idx, + nmp_object_to_string(arr2->pdata[idx], + NMP_OBJECT_TO_STRING_ALL, + sbuf1, + sizeof(sbuf1))); } if (idx >= nm_g_ptr_array_len(arr2)) { _assert_platform_printarr(obj_type, arr1, arr2); - g_error("Comparing %s (%s) for platform fails. Platform has no more entry #%u which is " - "still in the cache as %s", - obj_class->obj_type_name, - detail_type, - idx, - nmp_object_to_string(arr1->pdata[idx], - NMP_OBJECT_TO_STRING_ALL, - sbuf1, - sizeof(sbuf1))); + _fail_msg( + do_assert, + "Comparing %s (%s) for platform fails. Platform has no more entry #%u which is " + "still in the cache as %s", + obj_class->obj_type_name, + detail_type, + idx, + nmp_object_to_string(arr1->pdata[idx], + NMP_OBJECT_TO_STRING_ALL, + sbuf1, + sizeof(sbuf1))); } if (!nmp_object_equal(arr1->pdata[idx], arr2->pdata[idx])) { _assert_platform_printarr(obj_type, arr1, arr2); - g_error("Comparing %s (%s) for platform fails. Platform entry #%u is now %s but in " - "cache is %s", - obj_class->obj_type_name, - detail_type, - idx, - nmp_object_to_string(arr2->pdata[idx], - NMP_OBJECT_TO_STRING_ALL, - sbuf1, - sizeof(sbuf1)), - nmp_object_to_string(arr1->pdata[idx], - NMP_OBJECT_TO_STRING_ALL, - sbuf2, - sizeof(sbuf2))); + _fail_msg(do_assert, + "Comparing %s (%s) for platform fails. Platform entry #%u is now %s but in " + "cache is %s", + obj_class->obj_type_name, + detail_type, + idx, + nmp_object_to_string(arr2->pdata[idx], + NMP_OBJECT_TO_STRING_ALL, + sbuf1, + sizeof(sbuf1)), + nmp_object_to_string(arr1->pdata[idx], + NMP_OBJECT_TO_STRING_ALL, + sbuf2, + sizeof(sbuf2))); } if (!normalized && (share_multi_idx != (arr1->pdata[idx] == arr2->pdata[idx])) @@ -976,20 +993,23 @@ _assert_platform_compare_arr(NMPObjectType obj_type, if (idx_pointer_comp != -1) { _assert_platform_printarr(obj_type, arr1, arr2); - g_error("Comparing %s (%s) for platform fails for pointer comparison. Platform entry " - "#%u is now %s but in cache is %s", - obj_class->obj_type_name, - detail_type, - idx_pointer_comp, - nmp_object_to_string(arr2->pdata[idx_pointer_comp], - NMP_OBJECT_TO_STRING_ALL, - sbuf1, - sizeof(sbuf1)), - nmp_object_to_string(arr1->pdata[idx_pointer_comp], - NMP_OBJECT_TO_STRING_ALL, - sbuf2, - sizeof(sbuf2))); + _fail_msg(do_assert, + "Comparing %s (%s) for platform fails for pointer comparison. Platform entry " + "#%u is now %s but in cache is %s", + obj_class->obj_type_name, + detail_type, + idx_pointer_comp, + nmp_object_to_string(arr2->pdata[idx_pointer_comp], + NMP_OBJECT_TO_STRING_ALL, + sbuf1, + sizeof(sbuf1)), + nmp_object_to_string(arr1->pdata[idx_pointer_comp], + NMP_OBJECT_TO_STRING_ALL, + sbuf2, + sizeof(sbuf2))); } + + return TRUE; } /*****************************************************************************/ @@ -1211,8 +1231,8 @@ out: return result; } -void -nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) +gboolean +nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolean do_assert) { static const NMPObjectType obj_types[] = { NMP_OBJECT_TYPE_IP4_ADDRESS, @@ -1275,7 +1295,14 @@ nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) g_ptr_array_sort(arr2, _assert_platform_sort_objs); } - _assert_platform_compare_arr(obj_type, "main", arr1, arr2, normalized, share_multi_idx); + if (!_assert_platform_compare_arr(obj_type, + "main", + arr1, + arr2, + normalized, + share_multi_idx, + do_assert)) + return FALSE; if (NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) { /* For routes, the WEAK_ID needs to be sorted and match the expected order. Check that. */ @@ -1309,12 +1336,14 @@ nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) arr2b_sorted = nm_g_ptr_array_new_clone(arr2b, NULL, NULL, NULL); g_ptr_array_sort(arr1b_sorted, _assert_platform_sort_objs); g_ptr_array_sort(arr2b_sorted, _assert_platform_sort_objs); - _assert_platform_compare_arr(obj_type, - "weak-id-sorted", - arr1b_sorted, - arr2b_sorted, - normalized, - share_multi_idx); + if (!_assert_platform_compare_arr(obj_type, + "weak-id-sorted", + arr1b_sorted, + arr2b_sorted, + normalized, + share_multi_idx, + do_assert)) + return FALSE; if (obj_type == NMP_OBJECT_TYPE_IP6_ROUTE) { /* For IPv6, the weak-ids are actually not sorted correctly. @@ -1348,12 +1377,14 @@ nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) */ } else { /* Assert that also the original, not-sorted lists agree. */ - _assert_platform_compare_arr(obj_type, - "weak-id", - arr1b, - arr2b, - normalized, - share_multi_idx); + if (!_assert_platform_compare_arr(obj_type, + "weak-id", + arr1b, + arr2b, + normalized, + share_multi_idx, + do_assert)) + return FALSE; } for (i = 0; i < arr1b->len; i++) { @@ -1374,6 +1405,25 @@ nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags) _LOGD("assert-platform: done"); g_assert_cmpint(obj_type_flags, ==, 0u); + + return TRUE; +} + +void +nmtstp_check_platform(NMPlatform *platform, guint32 obj_type_flags) +{ + if (!nmtstp_check_platform_full(platform, obj_type_flags, FALSE)) { + /* It's unclear why this failure sometimes happens. It happens + * on gitlab-ci on Ubuntu/Debian(??). + * + * Retrying shortly after seems to avoid it. */ + g_usleep(20 * 1000); + nm_platform_process_events(platform); + nmtstp_run_command("ip route"); + nm_platform_process_events(platform); + + nmtstp_check_platform_full(platform, obj_type_flags, TRUE); + } } /*****************************************************************************/ diff --git a/src/core/platform/tests/test-common.h b/src/core/platform/tests/test-common.h index 7a4018a3bf..2802d8fda0 100644 --- a/src/core/platform/tests/test-common.h +++ b/src/core/platform/tests/test-common.h @@ -139,7 +139,10 @@ int nmtstp_run_command(const char *format, ...) _nm_printf(1, 2); /*****************************************************************************/ -void nmtstp_assert_platform(NMPlatform *platform, guint32 obj_type_flags); +gboolean +nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolean do_assert); + +void nmtstp_check_platform(NMPlatform *platform, guint32 obj_type_flags); /*****************************************************************************/ diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index d52e6e61ac..2c9737bead 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -2367,7 +2367,7 @@ done: nm_platform_process_events(platform); if (!is_test_quick || (i_run + 1 == N_RUN) || nmtst_get_rand_one_case_in(5)) { - nmtstp_assert_platform( + nmtstp_check_platform( platform, nmtst_get_rand_one_case_in(5) ? 0u -- cgit v1.2.1 From 5c324adc7c3b35e63c7f04f6230326901c0403c0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 19 Jan 2023 20:25:21 +0100 Subject: platform/tests: re-enable and fix "/route/test_cache_consistency_routes" tests The tests failed in certain cases on gitlab-ci and were temporarily disabled. These issues should be fixed now and the test pass. Reenable. --- src/core/platform/tests/test-route.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index 2c9737bead..bd8fdc271c 100644 --- a/src/core/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -2185,9 +2185,6 @@ test_cache_consistency_routes(gconstpointer test_data) int i_run; gs_unref_ptrarray GPtrArray *keeper = g_ptr_array_new_with_free_func(g_free); - g_test_skip("Test is currently known to fail. TODO. SKIP"); - return; - _ensure_onlink_routes(); for (i_run = 0; i_run < N_RUN; i_run++) { -- cgit v1.2.1 From 13bd3f7526c0341d8c840cc00213130ab9698834 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 2 Feb 2023 11:46:20 +0100 Subject: mailmap: update mailmap entry for Ana --- .mailmap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index fd6fba5a2b..b66016ad04 100644 --- a/.mailmap +++ b/.mailmap @@ -3,7 +3,8 @@ Adrian Freihofer Aleksander Morgado Alfonso Sánchez-Beato Amitakhya Phukan -Ana Cabral +Ana Cabral <30404-acabral@users.noreply.gitlab.freedesktop.org> +Ana Cabral Antony Mee Antony Mee Artur Flinta -- cgit v1.2.1 From 5ffc9e14f929ea4b70be6800e7ab9f94a5d74695 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 2 Feb 2023 11:51:28 +0100 Subject: mailmap: update mailmap entry for Fernando --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index b66016ad04..695c9cc807 100644 --- a/.mailmap +++ b/.mailmap @@ -20,6 +20,7 @@ Dan Williams Dan Winship Daniel Nylander David Zeuthen +Fernando Fernandez Mancera Fran Diéguez Fran Diéguez Francisco Javier F. Serrador -- cgit v1.2.1 From c8c2e51916ba4743ab2f370ec2bd32bcc53beaf3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 2 Feb 2023 11:51:28 +0100 Subject: mailmap: update mailmap entry for gaoxingwang --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 695c9cc807..b5f7a002b7 100644 --- a/.mailmap +++ b/.mailmap @@ -82,5 +82,6 @@ Tomasz Dominikowski William Jon McCann Wouter Bolsterlee Wouter Bolsterlee +gaoxingwang Øivind Hoel Žygimantas Beručka -- cgit v1.2.1 From 0ee784f1f05e935b9d2fe7f6c54f1930059ea5b8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 2 Feb 2023 18:24:36 +0100 Subject: contrib: add "git-backport-merge" script for backporting merge commits in NetworkManager On the main branch, we commonly rebase our WIP branches to latest HEAD, before merging them with "--no-ff". The effect is to have a merge commit that acts as a parentheses around the set of patches. When backporting such a branch, we should preserve that structure and take the merge commit too. We should must use `git cherry-pick -x` to record the commit IDs of the original patch. This script helps with that. Also hook it up in "contrib/scripts/nm-setup-git.sh" to create an alias for it. This alias has the advantage, of fetching the latest version of the script from "main" or "origin/main", so it also works on older branches. --- contrib/scripts/git-backport-merge | 58 ++++++++++++++++++++++++++++++++++++++ contrib/scripts/nm-setup-git.sh | 1 + 2 files changed, 59 insertions(+) create mode 100755 contrib/scripts/git-backport-merge diff --git a/contrib/scripts/git-backport-merge b/contrib/scripts/git-backport-merge new file mode 100755 index 0000000000..8ba2244f21 --- /dev/null +++ b/contrib/scripts/git-backport-merge @@ -0,0 +1,58 @@ +#!/bin/bash + +# Uses `git cherry-pick -x` to backport a merge commit to an older branch. +# +# Usage: +# First checkout the old-stable branch, that is the target for the backport. +# Then `git-backport-merge MERGE_REF [REFS...]` +# MERGE_REF is the merge commit that should be backported. +# [REFS...] is the commits that should be backported. If omitted, +# it automatically takes the parent commits of the merge commit. + +die() { + printf '%s\n' "$*" >&2 + exit 1 +} + +backport_merge() { + test "$#" -gt 0 || die "Requires the commit ref to backport (and optimally select the commits to include)" + + local M="${@:$#}" + local h + + if test "$#" -eq 1; then + local C=($(git log --reverse "--pretty=%H" "$M"^1.."$M"^2)) + else + local C=("${@:1:$#-1}") + fi + + local OLD_HEAD="$(git rev-parse HEAD)" || die "failed to get current HEAD" + + test -n "$(git status --porcelain --untracked-files=no)" && die "Working directory contains changes. Abort." + + local M_ID="$(git rev-parse "$M"^{commit})" || die "\"$M\" is not a valid commit" + + trap EXIT 'test -z "$OLD_HEAD" || git reset "$OLD_HEAD" --hard' + + for h in "${C[@]}"; do + if ! git cherry-pick --allow-empty -x "$h" ; then + git cherry-pick --abort + die "failed to cherry-pick commit \"$h\" on top of \"$(git rev-parse HEAD)\"" + fi + done + + local NEW_HEAD="$(git rev-parse HEAD)" || die "failed to get new HEAD" + + git reset --hard "$OLD_HEAD" || die "Failed to reset to previous HEAD \"$OLD_HEAD\"" + + git merge --no-ff --no-edit "$NEW_HEAD" || die "Failed to merge old HEAD \"$OLD_HEAD\" with new \"$NEW_HEAD\"" + + git commit --amend --allow-empty -C "$M" || die "Failed to amend merge commit \"$(git rev-parse HEAD)\" with commit message from \"$M\"" + + git rev-parse "$M" | sed 's/.*/(cherry picked from commit \0)/' | GIT_EDITOR='sh -c "cat >> \"$1\""' git commit --allow-empty --amend || \ + die "Failed to amend merge commit \"$(git rev-parse HEAD)\" with cherry-picked-from message from \"$M\"" + + OLD_HEAD= +} + +backport_merge "$@" diff --git a/contrib/scripts/nm-setup-git.sh b/contrib/scripts/nm-setup-git.sh index 24d9c7bc2c..392e3f36cc 100755 --- a/contrib/scripts/nm-setup-git.sh +++ b/contrib/scripts/nm-setup-git.sh @@ -109,6 +109,7 @@ git_config_reset blame.markUnblamableLines true git_config_add notes.displayref 'refs/notes/bugs' git_config_add remote.origin.fetch 'refs/notes/bugs:refs/notes/bugs' git_config_reset remote.origin.pushurl 'git@gitlab.freedesktop.org:NetworkManager/NetworkManager.git' +git_config_add 'alias.backport-merge' '! (git show main:contrib/scripts/git-backport-merge || git show origin/main:contrib/scripts/git-backport-merge) | bash -s -' if [ "$NO_TEST" != 1 ]; then printf "Run with \"--no-test\" or see \"-h\"\n" >&2 -- cgit v1.2.1 From f7f0e181754f78d85a05f756d952847b61eaa037 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Feb 2023 14:02:32 +0100 Subject: CONTRIBUTING: fix example command line about git-notes --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe195b4aa9..7b927307f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -404,7 +404,7 @@ $ git config --add 'notes.displayref' 'refs/notes/bugs' For example, set notes with ``` -$ git notes --ref refs/notes/bugs add -m "(cherry picked from $COMMIT_SHA)" HEAD +$ git notes --ref refs/notes/bugs add -m "(cherry picked from commit $COMMIT_SHA)" HEAD ``` You should see the notes in git-log output as well. -- cgit v1.2.1 From 8b148498776c6d76a2f355e95a9ee4c07f3646f6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Feb 2023 21:42:03 +0100 Subject: platform: fix handling the onlink route attribute for routes without gateway For IPv6, kernel doesn't care. If the gateway is ::, you may or may not set the onlink attribute. But for IPv4 routes, that gets rejected: # ip route add 1.2.3.4/32 dev v onlink Error: Invalid flags for nexthop - PERVASIVE and ONLINK can not be set. Silently suppress setting the flag in that case and ignore the user request. After all, the effect is probably the same (that is, the route is onlink anyway). --- src/libnm-platform/nm-linux-platform.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 41d7163ae6..7dc0f81a40 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -5346,7 +5346,7 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob const guint32 lock = ip_route_get_lock_flag(NMP_OBJECT_CAST_IP_ROUTE(obj)); const guint32 table = nm_platform_route_table_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced, TRUE); - const struct rtmsg rtmsg = { + struct rtmsg rtmsg = { .rtm_family = klass->addr_family, .rtm_tos = IS_IPv4 ? obj->ip4_route.tos : 0, .rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC, @@ -5354,7 +5354,7 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob .rtm_scope = IS_IPv4 ? nm_platform_route_scope_inv(obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, .rtm_type = nm_platform_route_type_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced), - .rtm_flags = obj->ip_route.r_rtm_flags & ((unsigned) (RTNH_F_ONLINK)), + .rtm_flags = 0, .rtm_dst_len = obj->ip_route.plen, .rtm_src_len = IS_IPv4 ? 0 : NMP_OBJECT_CAST_IP6_ROUTE(obj)->src_plen, }; @@ -5365,6 +5365,17 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); nm_assert(NM_IN_SET(nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE)); + if (NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, ((unsigned) (RTNH_F_ONLINK)))) { + if (IS_IPv4 && obj->ip4_route.gateway == 0) { + /* Kernel does not allow setting the onlink flag, if there is no gateway. + * We silently don't configure the flag. + * + * For multi-hop routes, we will set the flag for each next-hop (which + * has a gateway set). */ + } else + rtmsg.rtm_flags |= ((unsigned) RTNH_F_ONLINK); + } + msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags); if (nlmsg_append_struct(msg, &rtmsg) < 0) -- cgit v1.2.1 From 93b46c890627ca148c3477c4211ef94a69711407 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Feb 2023 21:33:06 +0100 Subject: core: don't create dependent onlink route for onlink routes If the route with a next hop is already onlink, we don't need to add a direct route to the gateway. It also wouldn't work previously, because the onlink route to the gateway that we would add, would have no gateway and the RTNH_F_ONLINK set. Kernel would reject that with an error. We would have to clear the RTNH_F_ONLINK flag, if there is no gateway. --- src/core/nm-l3-config-data.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 2865d9e1c3..30a9b54448 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2563,6 +2563,9 @@ nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_fam if (nm_ip_addr_is_null(addr_family, p_gateway)) continue; + if (NM_FLAGS_HAS(route_src->rx.r_rtm_flags, (unsigned) RTNH_F_ONLINK)) + continue; + if (_data_get_direct_route_for_host(self, addr_family, p_gateway)) continue; -- cgit v1.2.1 From 6081e61d91845ef884b38a320c965aa1e9b04ff3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Feb 2023 08:37:51 +0100 Subject: core: don't postpone configuring onlink ECMP routes Also add some code comments. Fixes: 7a844ecba9e4 ('netns: fix configuring onlink routes for ECMP routes') --- src/core/nm-netns.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index 1c05506e40..f273c0885f 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -105,7 +105,19 @@ typedef struct { /* Calling nm_netns_ip_route_ecmp_register() will ensure that the tracked * entry is non-dirty. This can be used to remove stale entries. */ bool dirty : 1; + + /* This flag is set during nm_netns_ip_route_ecmp_register(), when first tracking the + * route. It is cleared on the next nm_netns_ip_route_ecmp_commit(). It thus only + * exists for a short time, to know during a commit that the route is new and + * we need to do something special. */ bool is_new : 1; + + /* The entry is ready to be configured. This exists, because the nexthop of + * a route must be reachable directly (being onlink). That is, we may need + * to add a direct, single-hop route to the gateway, which is done by + * the NML3Cfg of that interface. Since the NML3Cfg calls nm_netns_ip_route_ecmp_commit() + * and only adds the direct route afterwards, the ECMP route may not be ready + * right away, but only upon seeing the entry a second time. */ bool is_ready : 1; } EcmpTrackObj; @@ -626,14 +638,13 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, GPtrArray **out_singlehop_routes, gboolean is_reapply) { - NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE(self); - EcmpTrackObj *track_obj; - EcmpTrackObj *track_obj_safe; - EcmpTrackEcmpid *track_ecmpid; - const NMPObject *route_obj; - const NMPlatformIP4Route *route; - char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; - gboolean already_notified = FALSE; + NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE(self); + EcmpTrackObj *track_obj; + EcmpTrackObj *track_obj_safe; + EcmpTrackEcmpid *track_ecmpid; + const NMPObject *route_obj; + char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; + gboolean already_notified = FALSE; nm_assert_l3cfg(self, l3cfg); @@ -662,6 +673,9 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, track_obj->is_ready = FALSE; } if (track_obj->is_new) { + const NMPlatformIP4Route *route = + NMP_OBJECT_CAST_IP4_ROUTE(track_ecmpid->merged_obj); + /* This is a new route entry that was just added. Upon first * addition, the route is not yet ready for configuration, * because we need to make sure that the gateway is reachable @@ -673,7 +687,11 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, * after l3cfg configured that route. We achieve that by * scheduling another idle commit on "l3cfg". */ track_obj->is_new = FALSE; - if (c_list_length_is(&track_ecmpid->ecmpid_lst_head, 1)) { + if (route && route->gateway == 0) { + /* This route is onlink. We don't need to configure an onlink route + * to the gateway, and the route is immediately ready for configuration. */ + track_obj->is_ready = TRUE; + } else if (c_list_length_is(&track_ecmpid->ecmpid_lst_head, 1)) { /* This route has no merge partner and ends up being a * single hop route. It will be returned and configured by * the calling "l3cfg". @@ -683,7 +701,15 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, * don't need to schedule an idle commit. */ track_obj->is_ready = TRUE; } else { + /* This is a new route which has a gateway. We need for the "l3cfg" + * to first configure the onlink route. It's not yet ready for configuration. + * + * Instead, schedule an idle commit to make sure we get called back + * again, and then (upon seeing the entry the second time) the onlink + * route is already configured and we will be ready. */ if (!already_notified) { + /* Some micro optimization with already_notified to avoid calling + * schedule unnecessarily. */ already_notified = TRUE; nm_l3cfg_commit_on_idle_schedule(l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); } @@ -720,6 +746,7 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, c_list_for_each_entry (track_obj, &l3cfg->internal_netns.ecmp_track_ifindex_lst_head, ifindex_lst) { + const NMPlatformIP4Route *route; EcmpTrackObj *track_obj2; nm_auto_nmpobj const NMPObject *obj_del = NULL; gboolean changed; -- cgit v1.2.1 From 6ed966258c0acc5bcf0c1dfa7d0cbcdb65b84b56 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Feb 2023 08:58:15 +0100 Subject: platform,core: better handle onlink flag for ECMP routes The onlink flag is part of each next hop. When NetworkManager configures ECMP routes, we won't support that. All next hops of an ECMP route must share the same onlink flag. That is fine and fixed by this commit. What is not fine, is that we don't track the rtnh_flags flags in NMPlatformIP4RtNextHop, and consequently our nmp_object_id_cmp() is wrong. Fixes: 5b5ce4268211 ('nm-netns: track ECMP routes') --- src/core/NetworkManagerUtils.c | 6 +++++- src/core/nm-netns.c | 6 +++++- src/libnm-core-impl/nm-setting-ip4-config.c | 14 +++++++++----- src/libnm-platform/nm-linux-platform.c | 18 +++++++++++++++--- src/libnm-platform/nm-platform.c | 6 ++++++ src/libnm-platform/nm-platform.h | 5 +++++ 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 15a3e5ddcf..6f4c60f876 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -1386,8 +1386,12 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, r4->scope_inv = nm_platform_route_scope_inv(scope); } + /* Note that for IPv4 routes in kernel, the onlink flag can be set for + * each next hop separately (rtnh_flags). Not for NetworkManager. We can + * only merge routes as ECMP routes (when setting a weight) if they all + * share the same onlink flag. See NM_PLATFORM_IP_ROUTE_CMP_TYPE_ECMP_ID. + * That simplifies the code. */ GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE); - r->r_rtm_flags = ((onlink) ? (unsigned) RTNH_F_ONLINK : 0u); GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_ADVMSS, r->mss, UINT32, uint32, 0); diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index f273c0885f..12ca850898 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -7,6 +7,8 @@ #include "nm-netns.h" +#include + #include "libnm-glib-aux/nm-dedup-multi.h" #include "libnm-glib-aux/nm-c-list.h" @@ -687,7 +689,9 @@ nm_netns_ip_route_ecmp_commit(NMNetns *self, * after l3cfg configured that route. We achieve that by * scheduling another idle commit on "l3cfg". */ track_obj->is_new = FALSE; - if (route && route->gateway == 0) { + if (route + && (route->gateway == 0 + || NM_FLAGS_HAS(route->r_rtm_flags, (unsigned) RTNH_F_ONLINK))) { /* This route is onlink. We don't need to configure an onlink route * to the gateway, and the route is immediately ready for configuration. */ track_obj->is_ready = TRUE; diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index db1416483b..d2ca88241f 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -1143,11 +1143,15 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * The default is unicast. * * - * "weight" - an unsigned 32 bit integer ranging from 0 to 256. This indicates - * that the IPv4 route is a ECMP route and is only allowed for routes that specify a next-hop. - * NetworkManager will automatically merge compatible routes into ECMP multi-hop routes. - * Setting to zero or omitting the attribute configures single hop routes that won't get - * merged. If the route finds no merge partner, it is configured as single hop route. + * "weight" - an unsigned 32 bit integer + * ranging from 0 to 256. A non-zero weight indicates that the IPv4 + * route is an ECMP IPv4 route. NetworkManager will automatically + * merge compatible ECMP routes into multi-hop routes. Setting to + * zero or omitting the attribute configures single hop routes that + * won't get merged. If the route finds no merge partner, it is + * configured as single hop route. Note that in + * NetworkManager, currently all nexthops of a ECMP route must share + * the same "onlink" flag in order to be mergable. * * * "window" - an unsigned 32 bit integer. diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 7dc0f81a40..d4ab36f93d 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -5419,6 +5419,7 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob for (i = 0u; i < obj->ip4_route.n_nexthops; i++) { struct rtnexthop *rtnh; + in_addr_t gw; rtnh = nlmsg_reserve(msg, sizeof(*rtnh), NLMSG_ALIGNTO); if (!rtnh) @@ -5430,17 +5431,28 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob if (i == 0u) { rtnh->rtnh_hops = NM_MAX(obj->ip4_route.weight, 1u) - 1u; rtnh->rtnh_ifindex = obj->ip4_route.ifindex; - NLA_PUT_U32(msg, RTA_GATEWAY, obj->ip4_route.gateway); + gw = obj->ip4_route.gateway; } else { const NMPlatformIP4RtNextHop *n = &obj->_ip4_route.extra_nexthops[i - 1u]; rtnh->rtnh_hops = NM_MAX(n->weight, 1u) - 1u; rtnh->rtnh_ifindex = n->ifindex; - NLA_PUT_U32(msg, RTA_GATEWAY, n->gateway); + gw = n->gateway; } + NLA_PUT_U32(msg, RTA_GATEWAY, gw); rtnh->rtnh_flags = 0; - rtnh->rtnh_len = (char *) nlmsg_tail(nlmsg_hdr(msg)) - (char *) rtnh; + + if (obj->ip4_route.n_nexthops > 1 + && NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, (unsigned) (RTNH_F_ONLINK)) && gw != 0) { + /* Unlike kernel, we only track the onlink flag per NMPlatformIP4Address, and + * not per nexthop. That is fine for NetworkManager configuring addresses. + * It is not fine for tracking addresses from kernel in platform cache, + * because the rtnh_flags of the nexthops need to be part of nmp_object_id_cmp(). */ + rtnh->rtnh_flags |= RTNH_F_ONLINK; + } + + rtnh->rtnh_len = (char *) nlmsg_tail(nlmsg_hdr(msg)) - (char *) rtnh; } nla_nest_end(msg, multipath); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 6fad736cce..c80d964851 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -8601,7 +8601,13 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, NM_CMP_FIELD(a, b, initrwnd); NM_CMP_FIELD(a, b, mtu); NM_CMP_FIELD(a, b, rto_min); + + /* Note that for NetworkManager, the onlink flag is only part of the entire route. + * For kernel, each next hop has it's own onlink flag (rtnh_flags). This means, + * we can only merge ECMP routes, if they agree with their onlink flag, and then + * all next hops are onlink (or not). */ NM_CMP_DIRECT(a->r_rtm_flags & RTNH_F_ONLINK, b->r_rtm_flags & RTNH_F_ONLINK); + NM_CMP_FIELD_UNSAFE(a, b, quickack); NM_CMP_FIELD_UNSAFE(a, b, lock_window); NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index dec38c1c93..1cd9c6c6f9 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -680,6 +680,11 @@ typedef struct { * zero. */ guint16 weight; + + /* FIXME: each next hop in kernel also has a rtnh_flags (for example to + * set RTNH_F_ONLINK). As the next hop is part of the identifier of an + * IPv4 route, so is their flags. We must also track the flag, otherwise + * two routes that look different for kernel, get merged by platform cache. */ } NMPlatformIP4RtNextHop; typedef struct { -- cgit v1.2.1 From e59d09b05308353c56211c4a6ea66a8c6bf1bb6a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 1 Feb 2023 22:40:38 +0100 Subject: core: suppress onlink flag for IPv4 routes without gateway --- src/core/nm-l3-config-data.c | 16 ++++++++++++++++ src/libnm-core-impl/nm-setting-ip4-config.c | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 30a9b54448..17bb9db87d 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2851,6 +2851,22 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co nm_utils_ip_route_attribute_to_platform(addr_family, s_route, &r.rx, -1); + if (IS_IPv4 && r.r4.gateway == 0) { + /* As far as kernel is concerned, an IPv4 without gateway cannot have + * the onlink flag set, we need to clear it. If we wouldn't clear it, + * then the address we would add in kernel would be entirely different than + * the one we create here (because the "onlink" flag is part of the + * identifier of a route, see nm_platform_ip4_route_cmp()). + * + * Note however that for ECMP routes we currently can only merge routes + * that agree in their onlink flag. So a route without gateway cannot + * merge with an onlink route that has a gateway. That needs fixing, + * by not treating the onlink flag as for the entire route, but allowing + * to merge ECMP routes with different onlink flag. And first, we need + * to track the onlink flag for the nexthop (NMPlatformIP4RtNextHop). */ + r.r4.r_rtm_flags &= ~((unsigned) RTNH_F_ONLINK); + } + nm_l3_config_data_add_route(self, addr_family, NULL, &r.rx); } diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index d2ca88241f..f847918eda 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -1116,7 +1116,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * "mtu" - an unsigned 32 bit integer. * * - * "onlink" - a boolean value. + * "onlink" - a boolean value. The onlink flag + * is ignored for IPv4 routes without a gateway. That also means, + * with a positive "weight" the route cannot merge with ECMP routes + * which are onlink and have a gateway. + * * * * "quickack" - a boolean value. -- cgit v1.2.1 From fb9c2c9a193df2dc8bfb2fd710be36fb74e6ee6d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 12:59:07 +0100 Subject: hostname: combine implementations of read_hostname() for Gentoo and Slackware --- src/core/nm-hostname-manager.c | 58 ++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/src/core/nm-hostname-manager.c b/src/core/nm-hostname-manager.c index 26e073b36e..b036590fb3 100644 --- a/src/core/nm-hostname-manager.c +++ b/src/core/nm-hostname-manager.c @@ -99,53 +99,32 @@ _file_monitor_new(const char *path) /*****************************************************************************/ -#if defined(HOSTNAME_PERSIST_GENTOO) static char * -read_hostname_gentoo(const char *path) +read_hostname(const char *path, gboolean is_gentoo) { - gs_free char *contents = NULL; - gs_strfreev char **all_lines = NULL; - const char *tmp; - guint i; + gs_free char *contents = NULL; + gs_free const char **all_lines = NULL; + const char *tmp; + gsize i; if (!g_file_get_contents(path, &contents, NULL, NULL)) return NULL; - all_lines = g_strsplit(contents, "\n", 0); - for (i = 0; all_lines[i]; i++) { - g_strstrip(all_lines[i]); - if (all_lines[i][0] == '#' || all_lines[i][0] == '\0') - continue; - if (g_str_has_prefix(all_lines[i], "hostname=")) { - tmp = &all_lines[i][NM_STRLEN("hostname=")]; - return g_shell_unquote(tmp, NULL); + all_lines = nm_strsplit_set_full(contents, "\n", NM_STRSPLIT_SET_FLAGS_STRSTRIP); + for (i = 0; (tmp = all_lines[i]); i++) { + if (is_gentoo) { + if (!NM_STR_HAS_PREFIX(tmp, "hostname=")) + continue; + tmp = &tmp[NM_STRLEN("hostname=")]; + } else { + if (tmp[0] == '#') + continue; } + nm_assert(tmp && tmp[0] != '\0'); + return g_shell_unquote(tmp, NULL); } return NULL; } -#endif - -#if defined(HOSTNAME_PERSIST_SLACKWARE) -static char * -read_hostname_slackware(const char *path) -{ - gs_free char *contents = NULL; - gs_strfreev char **all_lines = NULL; - guint i = 0; - - if (!g_file_get_contents(path, &contents, NULL, NULL)) - return NULL; - - all_lines = g_strsplit(contents, "\n", 0); - for (i = 0; all_lines[i]; i++) { - g_strstrip(all_lines[i]); - if (all_lines[i][0] == '#' || all_lines[i][0] == '\0') - continue; - return g_shell_unquote(&all_lines[i][0], NULL); - } - return NULL; -} -#endif #if defined(HOSTNAME_PERSIST_SUSE) static gboolean @@ -237,10 +216,11 @@ _set_hostname_read_file(NMHostnameManager *self) #endif #if defined(HOSTNAME_PERSIST_GENTOO) - hostname = read_hostname_gentoo(HOSTNAME_FILE); + hostname = read_hostname(HOSTNAME_FILE, TRUE); #elif defined(HOSTNAME_PERSIST_SLACKWARE) - hostname = read_hostname_slackware(HOSTNAME_FILE); + hostname = read_hostname(HOSTNAME_FILE, FALSE); #else + (void) read_hostname; if (g_file_get_contents(HOSTNAME_FILE, &hostname, NULL, NULL)) g_strchomp(hostname); #endif -- cgit v1.2.1 From 89734c75539b7a0b1e5918eb9a785f144dd3abe9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 15:38:22 +0100 Subject: cli: avoid leak in readline_cb() overwriting previous line Such leaks show up in valgrind, and are simply bugs. Also, various callers (not all of them, which is another bug!) like to take ownership of the returned string and free it. That means, we leave a dangling pointer in the global variable, which is very ugly and error prone. Also, the callers like to free the string with g_free(), which is not appropriate for the "rl_string" memory which was allocated by readline. It must be freed with free(). Avoid that, by cloning the string using the glib allocator. Fixes: 995229181cac ('cli: remove editor thread') --- src/nmcli/common.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/nmcli/common.c b/src/nmcli/common.c index 9fdc412720..008a3cec28 100644 --- a/src/nmcli/common.c +++ b/src/nmcli/common.c @@ -895,7 +895,10 @@ static void readline_cb(char *line) { rl_got_line = TRUE; - rl_string = line; + + free(rl_string); + rl_string = line; + rl_callback_handler_remove(); } @@ -910,13 +913,15 @@ static char * nmc_readline_helper(const NmcConfig *nmc_config, const char *prompt) { GSource *io_source; + char *result; nmc_set_in_readline(TRUE); io_source = nm_g_unix_fd_add_source(STDIN_FILENO, G_IO_IN, stdin_ready_cb, NULL); read_again: - rl_string = NULL; + nm_clear_free(&rl_string); + rl_got_line = FALSE; rl_callback_handler_install(prompt, readline_cb); @@ -964,7 +969,12 @@ read_again: nmc_set_in_readline(FALSE); - return rl_string; + if (!rl_string) + return NULL; + + result = g_strdup(rl_string); + nm_clear_free(&rl_string); + return result; } /** -- cgit v1.2.1 From 5dc07174d31e4b4beac388f77ad30684dc4014f8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 15:43:03 +0100 Subject: cli: use "free()" for string from readline Since glib 2.45, we are guaranteed that g_free() just calls free(), so both can be used interchangeably. However, we still only depend on glib 2.40. In any case, it's ugly to mix the two. Memory allocated by plain malloc(), should be only freed with free(). The buffer in question comes from readline, which allocates it using the system allocator. Fixes: 995229181cac ('cli: remove editor thread') --- src/nmcli/common.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/nmcli/common.c b/src/nmcli/common.c index 008a3cec28..4229f66034 100644 --- a/src/nmcli/common.c +++ b/src/nmcli/common.c @@ -947,7 +947,6 @@ read_again: if (nmc_config->in_editor || (rl_string && *rl_string)) { /* In editor, or the line is not empty */ /* Call readline again to get new prompt (repeat) */ - g_free(rl_string); goto read_again; } else { /* Not in editor and line is empty, exit */ @@ -960,10 +959,8 @@ read_again: } /* Return NULL, not empty string */ - if (rl_string && *rl_string == '\0') { - g_free(rl_string); - rl_string = NULL; - } + if (rl_string && *rl_string == '\0') + nm_clear_free(&rl_string); nm_clear_g_source_inst(&io_source); -- cgit v1.2.1 From ea3e61047f8e5010d3aac8d074f2b2a55952d2d1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 15:53:31 +0100 Subject: cli: fix leaking "value" string in ask_option() Fixes: c5324ed285af ('nmcli: streamline connection addition') --- src/nmcli/connections.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index 00cc57acb7..610248c865 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -5594,8 +5594,8 @@ next: static void ask_option(NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstract_info) { - char *value; - GError *error = NULL; + gs_free char *value = NULL; + gs_free_error GError *error = NULL; gs_free char *prompt = NULL; gboolean multi; const char *setting_name, *property_name; @@ -5631,11 +5631,13 @@ ask_option(NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstr g_print(_("You can specify this option more than once. Press when you're done.\n")); again: + nm_clear_g_free(&value); + g_clear_error(&error); + value = nmc_readline(&nmc->nmc_config, "%s", prompt); if (!set_option(nmc, connection, abstract_info, value, FALSE, &error)) { g_printerr("%s\n", error->message); - g_clear_error(&error); goto again; } -- cgit v1.2.1 From f6805debee86a603ef290fe0242548990075cf19 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 13:36:00 +0100 Subject: contrib: avoid using "sudo" in REQUIRED_PACKAGES scripts It's often not installed, and usually we are already root. Avoid using sudo. --- .gitlab-ci.yml | 8 ++++---- contrib/debian/REQUIRED_PACKAGES | 5 ++++- contrib/fedora/REQUIRED_PACKAGES | 5 ++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f3bd3561e3..68d28c1942 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,10 +53,10 @@ variables: # # This is done by running `ci-fairy generate-template` and possibly bumping # ".default_tag". - FEDORA_TAG: '2023-01-18.0-296fbfd97862' - UBUNTU_TAG: '2023-01-18.0-08fb4e6eb861' - DEBIAN_TAG: '2023-01-18.0-08fb4e6eb861' - CENTOS_TAG: '2023-01-18.0-296fbfd97862' + FEDORA_TAG: '2023-01-18.0-82ad875db2dc' + UBUNTU_TAG: '2023-01-18.0-1218be1cbc9d' + DEBIAN_TAG: '2023-01-18.0-1218be1cbc9d' + CENTOS_TAG: '2023-01-18.0-82ad875db2dc' ALPINE_TAG: '2023-01-18.0-14c807942fa4' FEDORA_EXEC: 'bash .gitlab-ci/fedora-install.sh' diff --git a/contrib/debian/REQUIRED_PACKAGES b/contrib/debian/REQUIRED_PACKAGES index 34e591ddc7..4e8bb8c603 100755 --- a/contrib/debian/REQUIRED_PACKAGES +++ b/contrib/debian/REQUIRED_PACKAGES @@ -12,11 +12,14 @@ set -xe # Not all of these packages are strictly speaking necessary. # This is a generous list of related packages. +SUDO= +[ "$EUID" -eq 0 ] || SUDO=sudo + install() { if [ "$NM_INSTALL" != "" ]; then $NM_INSTALL "$@" else - sudo apt-get install -y "$@" + $SUDO apt-get install -y "$@" fi } diff --git a/contrib/fedora/REQUIRED_PACKAGES b/contrib/fedora/REQUIRED_PACKAGES index c77f4ccdc1..644e518b1b 100755 --- a/contrib/fedora/REQUIRED_PACKAGES +++ b/contrib/fedora/REQUIRED_PACKAGES @@ -14,11 +14,14 @@ set -xe DNF="$(command -v dnf &>/dev/null && echo dnf || echo yum)" +SUDO= +[ "$EUID" -eq 0 ] || SUDO=sudo + install() { if [ "$NM_INSTALL" != "" ]; then $NM_INSTALL "$@" else - sudo "$DNF" install -y "$@" + $SUDO "$DNF" install -y "$@" fi } -- cgit v1.2.1 From b76bb7333e11448b4692bf57c123d564eaf0864e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 11:05:33 +0100 Subject: test-client: pass extra argument in "test-client.sh" to python test For example: $ src/tests/client/test-client.sh -- TestNmcli.test_004 $ src/tests/client/test-client.sh -- -k monitor --- Makefile.am | 2 +- src/tests/client/meson.build | 1 + src/tests/client/test-client.sh | 61 ++++++++++++++++++++++++++++++++++------- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3d43c010a7..43c82a9088 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5456,7 +5456,7 @@ endif ############################################################################### check-local-tests-client: src/nmcli/nmcli src/tests/client/test-client.py - "$(srcdir)/src/tests/client/test-client.sh" "$(builddir)" "$(srcdir)" "$(PYTHON)" + "$(srcdir)/src/tests/client/test-client.sh" "$(builddir)" "$(srcdir)" "$(PYTHON)" -- check_local += check-local-tests-client diff --git a/src/tests/client/meson.build b/src/tests/client/meson.build index b2e455bbbd..9dd58623a6 100644 --- a/src/tests/client/meson.build +++ b/src/tests/client/meson.build @@ -7,6 +7,7 @@ test( build_root, source_root, python.path(), + '--', ], timeout: 120, ) diff --git a/src/tests/client/test-client.sh b/src/tests/client/test-client.sh index 985d07c91a..a636f5fb93 100755 --- a/src/tests/client/test-client.sh +++ b/src/tests/client/test-client.sh @@ -1,5 +1,30 @@ #!/bin/bash +# Runs the "test-python.sh" test, setting proper environment variables +# for the build tree. +# +# - the first three arguments are the BUILDDIR, SRCDIR and PYTHON paths. +# The following arguments are passed on to "test-python.sh". +# +# - you can use "--" to separate the extra arguments. +# +# The full format is +# +# $ src/tests/client/test-client.sh "$BUILDDIR" "$SRCDIR" "$PYTHON" -- "${EXTRA[@]}" +# +# - "$BUILDDIR" "$SRCDIR" and "$PYTHON" can be set to "", to fallback +# to a default. +# +# The safe way to call it is thus +# +# $ src/tests/client/test-client.sh "" "" "" -- "${EXTRA[@]}" +# +# but for brevity, you can also call +# +# $ src/tests/client/test-client.sh -- "${EXTRA[@]}" +# +# if (and only if) "${EXTRA[@]}" does not contain "--". + set -e die() { @@ -7,29 +32,45 @@ die() { exit 1 } -if [ "$2" != "" ]; then - SRCDIR="$(realpath "$2")" +if [ "$4" = "--" ] ; then + ARGS=("${@:1:3}") + EXTRA=("${@:5}") +elif [ "$3" = "--" ]; then + ARGS=("${@:1:2}") + EXTRA=("${@:4}") +elif [ "$2" = "--" ]; then + ARGS=("${@:1:1}") + EXTRA=("${@:3}") +elif [ "$1" = "--" ]; then + ARGS=() + EXTRA=("${@:2}") +else + ARGS=("${@:1:3}") + EXTRA=("${@:4}") +fi + +if [ "${ARGS[1]}" != "" ]; then + SRCDIR="$(realpath "${ARGS[1]}")" else SRCDIR="$(realpath "$(dirname "$BASH_SOURCE")/../../..")" fi -if [ "$1" != "" ]; then - BUILDDIR="$(realpath "$1")" +if [ "${ARGS[0]}" != "" ]; then + BUILDDIR="$(realpath "${ARGS[0]}")" elif test -d "$SRCDIR/build" ; then BUILDDIR="$(realpath "$SRCDIR/build")" else BUILDDIR="$SRCDIR" fi -test -d "$BUILDDIR" || die "BUILDDIR \"$BUILDDIR\" does not exist?" -test -d "$SRCDIR" || die "SRCDIR \"$SRCDIR\" does not exist?" - -if [ "$3" != "" ]; then - PYTHON="$3" +if [ "${ARGS[2]}" != "" ]; then + PYTHON="${ARGS[2]}" elif [ "$PYTHON" == "" ]; then PYTHON="$(command -v python)" || die "python not found?" fi +test -d "$BUILDDIR" || die "BUILDDIR \"$BUILDDIR\" does not exist?" +test -d "$SRCDIR" || die "SRCDIR \"$SRCDIR\" does not exist?" test -f "$BUILDDIR/src/nmcli/nmcli" || die "\"$BUILDDIR/src/nmcli/nmcli\" does not exist?" if test -f "$BUILDDIR/src/libnm-client-impl/.libs/libnm.so" ; then @@ -57,7 +98,7 @@ export NM_TEST_CLIENT_BUILDDIR="$BUILDDIR" # test output is grouped together. r="ok" -"$PYTHON" "$SRCDIR/src/tests/client/test-client.py" -v &> "$BUILDDIR/src/tests/client/test-client.log" || r=fail +"$PYTHON" "$SRCDIR/src/tests/client/test-client.py" -v "${EXTRA[@]}" &> "$BUILDDIR/src/tests/client/test-client.log" || r=fail cat "$BUILDDIR/src/tests/client/test-client.log" -- cgit v1.2.1 From 5da7301ec981f8887ddb1dd2a7447d5a566263d9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 13:26:32 +0100 Subject: test-client: add Util.shlex_join() helper --- src/tests/client/test-client.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index e936c4c452..66212501eb 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -251,7 +251,8 @@ class Util: ).search @staticmethod - def quote(s): + def shlex_quote(s): + # Reimplement shlex.quote(). if Util.python_has_version(3, 3): return shlex.quote(s) if not s: @@ -260,6 +261,11 @@ class Util: return s return "'" + s.replace("'", "'\"'\"'") + "'" + @staticmethod + def shlex_join(args): + # Reimplement shlex.join() + return " ".join(Util.shlex_quote(s) for s in args) + @staticmethod def popen_wait(p, timeout=0): (res, b_stdout, b_stderr) = Util.popen_wait_read( @@ -1024,7 +1030,7 @@ class TestNmcli(NmTestBase): self.assertEqual(returncode, -5) if check_on_disk: - cmd = "$NMCLI %s" % (" ".join([Util.quote(a) for a in args[1:]])) + cmd = "$NMCLI %s" % (Util.shlex_join(args[1:]),) cmd = Util.replace_text(cmd, replace_cmd) if returncode < 0: @@ -1971,16 +1977,13 @@ def main(): "eval `dbus-launch --sh-syntax`;\n" + 'trap "kill $DBUS_SESSION_BUS_PID" EXIT;\n' + "\n" - + " ".join( + + Util.shlex_join( [ - Util.quote(a) - for a in [ - sys.executable, - __file__, - "--started-with-dbus-session", - ] - + sys.argv[1:] + sys.executable, + __file__, + "--started-with-dbus-session", ] + + sys.argv[1:] ) + " \n" + "", -- cgit v1.2.1 From b08f7a9c1935198cafd490303e61ae59e2b28978 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 14:06:46 +0100 Subject: test-client: accept yes/true/no/false for boolean arguments --- src/tests/client/test-client.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index 66212501eb..0202d86e0e 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -228,6 +228,19 @@ class Util: t = basestring return isinstance(s, t) + @staticmethod + def is_bool(s, defval=False): + if s is None: + return defval + if isinstance(s, int): + return s != 0 + if isinstance(s, str): + if s.lower() in ["1", "y", "yes", "true", "on"]: + return True + if s.lower() in ["0", "n", "no", "false", "off"]: + return False + raise ValueError('Argument "%s" is not a boolean' % (s,)) + @staticmethod def as_bytes(s): if Util.is_string(s): @@ -499,14 +512,14 @@ class Configuration: # # Only by setting NM_TEST_CLIENT_CHECK_L10N=1, these tests are included # as well. - v = os.environ.get(ENV_NM_TEST_CLIENT_CHECK_L10N, "0") == "1" + v = Util.is_bool(os.environ.get(ENV_NM_TEST_CLIENT_CHECK_L10N, None)) elif name == ENV_NM_TEST_REGENERATE: # in the "regenerate" mode, the tests will rewrite the files on disk against # which we assert. That is useful, if there are intentional changes and # we want to regenerate the expected output. - v = os.environ.get(ENV_NM_TEST_REGENERATE, "0") == "1" + v = Util.is_bool(os.environ.get(ENV_NM_TEST_REGENERATE, None)) elif name == ENV_NM_TEST_WITH_LINENO: - v = os.environ.get(ENV_NM_TEST_WITH_LINENO, "0") == "1" + v = Util.is_bool(os.environ.get(ENV_NM_TEST_WITH_LINENO, None)) elif name in [ ENV_NM_TEST_ASAN_OPTIONS, ENV_NM_TEST_LSAN_OPTIONS, -- cgit v1.2.1 From 3e574dda220afa52496aa0ae814eb207a7e25db8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Feb 2023 11:56:38 +0100 Subject: test-client: cleanup start/shutdown of stub service --- src/tests/client/test-client.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index 0202d86e0e..15f450af79 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -754,6 +754,16 @@ MAX_JOBS = 15 class TestNmcli(NmTestBase): + def srv_start(self): + self.srv_shutdown() + self.srv = NMStubServer(self._testMethodName) + + def srv_shutdown(self): + if self.srv is not None: + srv = self.srv + self.srv = None + srv.shutdown() + def ReplaceTextConUuid(self, con_name, replacement): return Util.ReplaceTextSimple( Util.memoize_nullary(lambda: self.srv.findConnectionUuid(con_name)), @@ -1130,9 +1140,7 @@ class TestNmcli(NmTestBase): self.async_wait() - if self.srv is not None: - self.srv.shutdown() - self.srv = None + self.srv_shutdown() self._calling_num = None @@ -1248,7 +1256,7 @@ class TestNmcli(NmTestBase): def nm_test(func): def f(self): - self.srv = NMStubServer(self._testMethodName) + self.srv_start() func(self) self._nm_test_post() @@ -1935,8 +1943,7 @@ class TestNmcli(NmTestBase): end_mon(nmc) nmc = start_mon() - self.srv.shutdown() - self.srv = None + self.srv_shutdown() nmc.expect("eth0: device removed") nmc.expect("con-1: connection profile removed") nmc.expect("NetworkManager is stopped") -- cgit v1.2.1 From d1e6d530130fd06a83ea440a5b244f0c68fcfd2f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Feb 2023 12:14:31 +0100 Subject: test-client: drop unused NmTestBase base class The base class is not used, and it's not clear that it would be useful. Sure, we could extend "test-client.py" will various non-nmcli tests. That might make sense. And then it might make sense to have more unit test classes. So far, we don't need that. Drop the unused base class NmTestBase. --- src/tests/client/test-client.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index 15f450af79..dc8252ce7c 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -740,20 +740,18 @@ class AsyncProcess: ############################################################################### -class NmTestBase(unittest.TestCase): +MAX_JOBS = 15 + + +class TestNmcli(unittest.TestCase): def __init__(self, *args, **kwargs): self._calling_num = {} self._skip_test_for_l10n_diff = [] self._async_jobs = [] self._results = [] self.srv = None - return unittest.TestCase.__init__(self, *args, **kwargs) - - -MAX_JOBS = 15 - + unittest.TestCase.__init__(self, *args, **kwargs) -class TestNmcli(NmTestBase): def srv_start(self): self.srv_shutdown() self.srv = NMStubServer(self._testMethodName) -- cgit v1.2.1 From debf78dbedbbe00acf34a2ba0f71a79fd130b407 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 3 Feb 2023 14:07:25 +0100 Subject: test-client: add valgrind support for call_nmcli_pexpect() tests This will allow to find some memory leaks and memory corruptions. The bulk of the nmcli calls are still not hooked up with valgrind. Since we call nmcli a thousand time, we could not just run valgrind with all of them. We would have instead to enable it randomly. This is more work. --- Makefile.am | 2 +- src/tests/client/meson.build | 3 + src/tests/client/test-client.py | 179 +++++++++++++++++++++++++++++++--------- 3 files changed, 146 insertions(+), 38 deletions(-) diff --git a/Makefile.am b/Makefile.am index 43c82a9088..a452cacac4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5456,7 +5456,7 @@ endif ############################################################################### check-local-tests-client: src/nmcli/nmcli src/tests/client/test-client.py - "$(srcdir)/src/tests/client/test-client.sh" "$(builddir)" "$(srcdir)" "$(PYTHON)" -- + LIBTOOL="$(LIBTOOL)" "$(srcdir)/src/tests/client/test-client.sh" "$(builddir)" "$(srcdir)" "$(PYTHON)" -- check_local += check-local-tests-client diff --git a/src/tests/client/meson.build b/src/tests/client/meson.build index 9dd58623a6..6dc0f2a2c8 100644 --- a/src/tests/client/meson.build +++ b/src/tests/client/meson.build @@ -9,5 +9,8 @@ test( python.path(), '--', ], + env: [ + 'LIBTOOL=', + ], timeout: 120, ) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index dc8252ce7c..cb1bef6ae6 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -90,7 +90,12 @@ ENV_NM_TEST_ASAN_OPTIONS = "NM_TEST_ASAN_OPTIONS" ENV_NM_TEST_LSAN_OPTIONS = "NM_TEST_LSAN_OPTIONS" ENV_NM_TEST_UBSAN_OPTIONS = "NM_TEST_UBSAN_OPTIONS" -# +# Run nmcli under valgrind. If unset, we honor NMTST_USE_VALGRIND instead. +# Valgrind is always disabled, if NM_TEST_REGENERATE is enabled. +ENV_NM_TEST_VALGRIND = "NM_TEST_VALGRIND" + +ENV_LIBTOOL = "LIBTOOL" + ############################################################################### import sys @@ -107,8 +112,10 @@ import fcntl import dbus import time import random +import tempfile import dbus.service import dbus.mainloop.glib +import collections import io from signal import SIGINT @@ -474,6 +481,38 @@ class Util: for color in [[], ["--color", "yes"]]: yield mode + fmt + color + @staticmethod + def valgrind_check_log(valgrind_log, logname): + if valgrind_log is None: + return + + fd, name = valgrind_log + + os.close(fd) + + if not os.path.isfile(name): + raise Exception("valgrind log %s unexpectedly does not exist" % (name,)) + + if os.path.getsize(name) != 0: + out = subprocess.run( + [ + "sed", + "-e", + "/^--[0-9]\+-- WARNING: unhandled .* syscall: /,/^--[0-9]\+-- it at http.*\.$/d", + name, + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + if out.returncode != 0: + raise Exception('Calling "sed" to search valgrind log failed') + if out.stdout: + print("valgrind log %s for %s is not empty:" % (name, logname)) + print("\n%s\n" % (out.stdout.decode("utf-8", errors="replace"),)) + raise Exception("valgrind log %s unexpectedly is not empty" % (name,)) + + os.remove(name) + ############################################################################### @@ -520,6 +559,15 @@ class Configuration: v = Util.is_bool(os.environ.get(ENV_NM_TEST_REGENERATE, None)) elif name == ENV_NM_TEST_WITH_LINENO: v = Util.is_bool(os.environ.get(ENV_NM_TEST_WITH_LINENO, None)) + elif name == ENV_NM_TEST_VALGRIND: + if self.get(ENV_NM_TEST_REGENERATE): + v = False + else: + v = os.environ.get(ENV_NM_TEST_VALGRIND, None) + if v: + v = Util.is_bool(v) + else: + v = Util.is_bool(os.environ.get("NMTST_USE_VALGRIND", None)) elif name in [ ENV_NM_TEST_ASAN_OPTIONS, ENV_NM_TEST_LSAN_OPTIONS, @@ -536,6 +584,21 @@ class Configuration: v = "print_stacktrace=1:halt_on_error=1" else: assert False + elif name == ENV_LIBTOOL: + v = os.environ.get(name, None) + if v is None: + v = os.path.abspath( + os.path.dirname(self.get(ENV_NM_TEST_CLIENT_NMCLI_PATH)) + + "/../../libtool" + ) + if not os.path.isfile(v): + v = None + else: + v = [v] + elif not v: + v = None + else: + v = shlex.split(v) else: raise Exception() self._values[name] = v @@ -796,6 +859,39 @@ class TestNmcli(unittest.TestCase): return content_expect, results_expect + def nmcli_construct_argv(self, args, with_valgrind=None): + + if with_valgrind is None: + with_valgrind = conf.get(ENV_NM_TEST_VALGRIND) + + valgrind_log = None + cmd = conf.get(ENV_NM_TEST_CLIENT_NMCLI_PATH) + if with_valgrind: + valgrind_log = tempfile.mkstemp(prefix="nm-test-client-valgrind.") + argv = [ + "valgrind", + "--quiet", + "--error-exitcode=37", + "--leak-check=full", + "--gen-suppressions=all", + ( + "--suppressions=" + + PathConfiguration.top_srcdir() + + "/valgrind.suppressions" + ), + "--num-callers=100", + "--log-file=" + valgrind_log[1], + cmd, + ] + libtool = conf.get(ENV_LIBTOOL) + if libtool: + argv = list(libtool) + ["--mode=execute"] + argv + else: + argv = [cmd] + + argv.extend(args) + return argv, valgrind_log + def call_nmcli_l( self, args, @@ -879,10 +975,14 @@ class TestNmcli(unittest.TestCase): ) def call_nmcli_pexpect(self, args): + env = self._env(extra_env={"NO_COLOR": "1"}) - return pexpect.spawn( - conf.get(ENV_NM_TEST_CLIENT_NMCLI_PATH), args, timeout=10, env=env - ) + argv, valgrind_log = self.nmcli_construct_argv(args) + + pexp = pexpect.spawn(argv[0], argv[1:], timeout=10, env=env) + + typ = collections.namedtuple("CallNmcliPexpect", ["pexp", "valgrind_log"]) + return typ(pexp, valgrind_log) def _env( self, lang="C", calling_num=None, fatal_warnings=_DEFAULT_ARG, extra_env=None @@ -978,7 +1078,10 @@ class TestNmcli(unittest.TestCase): else: self.fail("invalid language %s" % (lang)) - args = [conf.get(ENV_NM_TEST_CLIENT_NMCLI_PATH)] + list(args) + # Running under valgrind is not yet supported for those tests. + args, valgrind_log = self.nmcli_construct_argv(args, with_valgrind=False) + + assert valgrind_log is None if replace_stdout is not None: replace_stdout = list(replace_stdout) @@ -1892,24 +1995,25 @@ class TestNmcli(unittest.TestCase): @nm_test def test_ask_mode(self): nmc = self.call_nmcli_pexpect(["--ask", "c", "add"]) - nmc.expect("Connection type:") - nmc.sendline("ethernet") - nmc.expect("Interface name:") - nmc.sendline("eth0") - nmc.expect("There are 3 optional settings for Wired Ethernet.") - nmc.expect("Do you want to provide them\? \(yes/no\) \[yes]") - nmc.sendline("no") - nmc.expect("There are 2 optional settings for IPv4 protocol.") - nmc.expect("Do you want to provide them\? \(yes/no\) \[yes]") - nmc.sendline("no") - nmc.expect("There are 2 optional settings for IPv6 protocol.") - nmc.expect("Do you want to provide them\? \(yes/no\) \[yes]") - nmc.sendline("no") - nmc.expect("There are 4 optional settings for Proxy.") - nmc.expect("Do you want to provide them\? \(yes/no\) \[yes]") - nmc.sendline("no") - nmc.expect("Connection 'ethernet' \(.*\) successfully added.") - nmc.expect(pexpect.EOF) + nmc.pexp.expect("Connection type:") + nmc.pexp.sendline("ethernet") + nmc.pexp.expect("Interface name:") + nmc.pexp.sendline("eth0") + nmc.pexp.expect("There are 3 optional settings for Wired Ethernet.") + nmc.pexp.expect("Do you want to provide them\? \(yes/no\) \[yes]") + nmc.pexp.sendline("no") + nmc.pexp.expect("There are 2 optional settings for IPv4 protocol.") + nmc.pexp.expect("Do you want to provide them\? \(yes/no\) \[yes]") + nmc.pexp.sendline("no") + nmc.pexp.expect("There are 2 optional settings for IPv6 protocol.") + nmc.pexp.expect("Do you want to provide them\? \(yes/no\) \[yes]") + nmc.pexp.sendline("no") + nmc.pexp.expect("There are 4 optional settings for Proxy.") + nmc.pexp.expect("Do you want to provide them\? \(yes/no\) \[yes]") + nmc.pexp.sendline("no") + nmc.pexp.expect("Connection 'ethernet' \(.*\) successfully added.") + nmc.pexp.expect(pexpect.EOF) + Util.valgrind_check_log(nmc.valgrind_log, "test_ask_mode") @skip_without_pexpect @nm_test @@ -1919,33 +2023,34 @@ class TestNmcli(unittest.TestCase): # https://bugzilla.redhat.com/show_bug.cgi?id=2154288 raise unittest.SkipTest("test is known to randomly fail (rhbz#2154288)") - def start_mon(): + def start_mon(self): nmc = self.call_nmcli_pexpect(["monitor"]) - nmc.expect("NetworkManager is running") + nmc.pexp.expect("NetworkManager is running") return nmc - def end_mon(nmc): - nmc.kill(SIGINT) - nmc.expect(pexpect.EOF) + def end_mon(self, nmc): + nmc.pexp.kill(SIGINT) + nmc.pexp.expect(pexpect.EOF) + Util.valgrind_check_log(nmc.valgrind_log, "test_monitor") - nmc = start_mon() + nmc = start_mon(self) self.srv.op_AddObj("WiredDevice", iface="eth0") - nmc.expect("eth0: device created\r\n") + nmc.pexp.expect("eth0: device created\r\n") self.srv.addConnection( {"connection": {"type": "802-3-ethernet", "id": "con-1"}} ) - nmc.expect("con-1: connection profile created\r\n") + nmc.pexp.expect("con-1: connection profile created\r\n") - end_mon(nmc) + end_mon(self, nmc) - nmc = start_mon() + nmc = start_mon(self) self.srv_shutdown() - nmc.expect("eth0: device removed") - nmc.expect("con-1: connection profile removed") - nmc.expect("NetworkManager is stopped") - end_mon(nmc) + nmc.pexp.expect("eth0: device removed") + nmc.pexp.expect("con-1: connection profile removed") + nmc.pexp.expect("NetworkManager is stopped") + end_mon(self, nmc) ############################################################################### -- cgit v1.2.1 From ee17346cee3c116db5ebebd3f4e4fe81a58944b7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Feb 2023 12:40:50 +0100 Subject: test-client: cleanup imports Sort imports by name. Also avoid "from signal import SIGINT". I find it ugly to import names in the current namespace. "SIGINT" should be refered to by its full name, including the package/namespace. --- src/tests/client/test-client.py | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index cb1bef6ae6..dd90947b76 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -98,26 +98,25 @@ ENV_LIBTOOL = "LIBTOOL" ############################################################################### -import sys - -import os +import collections +import dbus +import dbus.mainloop.glib +import dbus.service import errno -import unittest -import socket -import itertools -import subprocess -import shlex -import re import fcntl -import dbus -import time +import io +import itertools +import os import random +import re +import shlex +import signal +import socket +import subprocess +import sys import tempfile -import dbus.service -import dbus.mainloop.glib -import collections -import io -from signal import SIGINT +import time +import unittest import gi @@ -215,10 +214,10 @@ class Util: } @classmethod - def signal_no_to_str(cls, signal): - s = cls._signal_no_lookup.get(signal, None) + def signal_no_to_str(cls, sig): + s = cls._signal_no_lookup.get(sig, None) if s is None: - return "" % (signal) + return "" % (sig) return s @staticmethod @@ -2029,7 +2028,7 @@ class TestNmcli(unittest.TestCase): return nmc def end_mon(self, nmc): - nmc.pexp.kill(SIGINT) + nmc.pexp.kill(signal.SIGINT) nmc.pexp.expect(pexpect.EOF) Util.valgrind_check_log(nmc.valgrind_log, "test_monitor") -- cgit v1.2.1 From 6dbb215793e5f36a84c39a8edcf327c8df229543 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 12:31:38 +0100 Subject: libnm: support LIBNM_CLIENT_DEBUG_FILE to print debug logging to file With LIBNM_CLIENT_DEBUG we get debug logging for libnm, either to stdout or to stderr. "test-client.py" runs nmcli as a unit test. It thereby catches stdout and stderr. That means, LIBNM_CLIENT_DEBUG would break the tests. Now honor the LIBNM_CLIENT_DEBUG_FILE environment variable to specify a file to which the debug logs get written. The pattern "%p" is replaced by the process id. As before, nm_utils_print(0, ...) also honors this environment variable and uses the same logging destination. --- src/libnm-client-impl/nm-libnm-utils.c | 140 ++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 20 deletions(-) diff --git a/src/libnm-client-impl/nm-libnm-utils.c b/src/libnm-client-impl/nm-libnm-utils.c index 9d51226347..398c6ebcfa 100644 --- a/src/libnm-client-impl/nm-libnm-utils.c +++ b/src/libnm-client-impl/nm-libnm-utils.c @@ -16,7 +16,13 @@ /*****************************************************************************/ -volatile int _nml_dbus_log_level = 0; +#define LOG_FILE_FD_UNSET -3 +#define LOG_FILE_FD_NONE -2 +#define LOG_FILE_FD_DEFUNCT -1 + +volatile int _nml_dbus_log_level = 0; +const char *_nml_dbus_log_file = NULL; +int _nml_dbus_log_file_fd = LOG_FILE_FD_UNSET; int _nml_dbus_log_level_init(void) @@ -40,6 +46,97 @@ _nml_dbus_log_level_init(void) return l; } +static const char * +_nml_dbus_log_file_init(void) +{ + const char *s; + + s = g_getenv("LIBNM_CLIENT_DEBUG_FILE"); + if (nm_str_not_empty(s)) { + if (strstr(s, "%p")) { + gs_strfreev char **tokens = NULL; + char pid_str[100]; + + tokens = g_strsplit(s, "%p", -1); + nm_sprintf_buf(pid_str, "%lld", (long long) getpid()); + s = nm_str_realloc(g_strjoinv(pid_str, tokens)); + } else + s = g_strdup(s); + } else + s = ""; + + if (!g_atomic_pointer_compare_and_exchange(&_nml_dbus_log_file, NULL, s)) { + if (s[0] != '\0') + g_free((gpointer) s); + s = g_atomic_pointer_get(&_nml_dbus_log_file); + } + + return s; +} + +#define nml_dbus_log_file() \ + ({ \ + const char *_l; \ + \ + _l = g_atomic_pointer_get(&_nml_dbus_log_file); \ + if (G_UNLIKELY(!_l)) \ + _l = _nml_dbus_log_file_init(); \ + \ + _l[0] ? _l : NULL; \ + }) + +static int +_nml_dbus_log_file_fd_init(void) +{ + static GMutex mutex; + NM_G_MUTEX_LOCKED(&mutex); + int fd; + + fd = g_atomic_int_get(&_nml_dbus_log_file_fd); + if (fd == LOG_FILE_FD_UNSET) { + const char *name; + + name = nml_dbus_log_file(); + if (!name) + fd = LOG_FILE_FD_NONE; + else { + fd = open(name, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0600); + if (fd < 0) + fd = LOG_FILE_FD_DEFUNCT; + } + g_atomic_int_set(&_nml_dbus_log_file_fd, fd); + } + + return fd; +} + +#define nml_dbus_log_file_fd() \ + ({ \ + int _fd2; \ + \ + _fd2 = g_atomic_int_get(&_nml_dbus_log_file_fd); \ + if (G_UNLIKELY(_fd2 == LOG_FILE_FD_UNSET)) \ + _fd2 = _nml_dbus_log_file_fd_init(); \ + \ + nm_assert(NM_IN_SET(_fd2, LOG_FILE_FD_NONE, LOG_FILE_FD_DEFUNCT) || _fd2 >= 0); \ + _fd2; \ + }) + +#define _log_printf(use_stdout, ...) \ + G_STMT_START \ + { \ + const int _fd = nml_dbus_log_file_fd(); \ + \ + if (_fd != LOG_FILE_FD_NONE) { \ + if (_fd >= 0) \ + dprintf(_fd, __VA_ARGS__); \ + } else if (use_stdout) \ + g_print(__VA_ARGS__); \ + else \ + g_printerr(__VA_ARGS__); \ + } \ + G_STMT_END + void _nml_dbus_log(NMLDBusLogLevel level, gboolean use_stdout, const char *fmt, ...) { @@ -94,21 +191,13 @@ _nml_dbus_log(NMLDBusLogLevel level, gboolean use_stdout, const char *fmt, ...) pid = getpid(); - if (use_stdout) { - g_print("libnm-dbus[%lld]: %s[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s\n", + _log_printf(use_stdout, + "libnm-dbus[%lld]: %s[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s\n", (long long) pid, prefix, ts / NM_UTILS_NSEC_PER_SEC, (ts / (NM_UTILS_NSEC_PER_SEC / 100000)) % 100000, msg); - } else { - g_printerr("libnm-dbus[%lld]: %s[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s\n", - (long long) pid, - prefix, - ts / NM_UTILS_NSEC_PER_SEC, - (ts / (NM_UTILS_NSEC_PER_SEC / 100000)) % 100000, - msg); - } } /*****************************************************************************/ @@ -884,8 +973,10 @@ nm_utils_g_param_spec_is_default(const GParamSpec *pspec) /** * nm_utils_print: * @output_mode: if 1 it uses g_print(). If 2, it uses g_printerr(). - * If 0, it uses either g_print() or g_printerr(), depending - * on LIBNM_CLIENT_DEBUG (and the "stdout" flag). + * If 0, it uses the same output as internal libnm debug logging + * does. That is, depending on LIBNM_CLIENT_DEBUG's "stdout" flag + * it uses g_print() or g_printerr() and if LIBNM_CLIENT_DEBUG_FILE is + * set, it writes the output to file instead * @msg: the message to print. The function does not append * a trailing newline. * @@ -896,6 +987,11 @@ nm_utils_g_param_spec_is_default(const GParamSpec *pspec) * with these functions (it implements additional buffering). By * using nm_utils_print(), the same logging mechanisms can be used. * + * Also, libnm honors LIBNM_CLIENT_DEBUG_FILE environment. If this + * is set to a filename pattern (accepting "%p" for the process ID), + * then the debug log is written to that file instead. With @output_mode + * zero, the same location will be written. Since: 1.44. + * * Since: 1.30 */ void @@ -905,17 +1001,21 @@ nm_utils_print(int output_mode, const char *msg) g_return_if_fail(msg); - if (output_mode == 0) { + switch (output_mode) { + case 0: nml_dbus_log_enabled_full(NML_DBUS_LOG_LEVEL_ANY, &use_stdout); - output_mode = use_stdout ? 1 : 2; - } - - if (output_mode == 1) + _log_printf(use_stdout, "%s", msg); + break; + case 1: g_print("%s", msg); - else if (output_mode == 2) + break; + case 2: g_printerr("%s", msg); - else + break; + default: g_return_if_reached(); + break; + } } /*****************************************************************************/ -- cgit v1.2.1 From 1630009234b3164225671fb485bd75e92d38c69a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 11:25:36 +0100 Subject: test-client: pass LIBNM_CLIENT_DEBUG to nmcli For debugging libnm, LIBNM_CLIENT_DEBUG can be very useful. As the tests compare stdout/stderr from nmcli with expected output, just enabling it will break the tests. However, in combination with LIBNM_CLIENT_DEBUG_FILE this can be very useful. Preserve and pass on the environment variables, if set. --- src/tests/client/test-client.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index dd90947b76..2c8f332706 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -996,7 +996,12 @@ class TestNmcli(unittest.TestCase): self.fail("invalid language %s" % (lang)) env = {} - for k in ["LD_LIBRARY_PATH", "DBUS_SESSION_BUS_ADDRESS"]: + for k in [ + "LD_LIBRARY_PATH", + "DBUS_SESSION_BUS_ADDRESS", + "LIBNM_CLIENT_DEBUG", + "LIBNM_CLIENT_DEBUG_FILE", + ]: val = os.environ.get(k, None) if val is not None: env[k] = val -- cgit v1.2.1 From d3e2e9dc20756aeeaadfd6eec5ee50fa24aaaf50 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 16:36:47 +0100 Subject: nmcli/trivial: rename monitor functions in internal header file Identifiers in our headers should have a "nm" prefix. Rename. --- src/nmcli/connections.c | 2 +- src/nmcli/connections.h | 2 +- src/nmcli/devices.c | 2 +- src/nmcli/devices.h | 2 +- src/nmcli/general.c | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index 610248c865..059bbbf99a 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -10117,7 +10117,7 @@ nmc_command_func_connection(const NMCCommand *cmd, NmCli *nmc, int argc, const c } void -monitor_connections(NmCli *nmc) +nmc_monitor_connections(NmCli *nmc) { do_connection_monitor(NULL, nmc, 0, NULL); } diff --git a/src/nmcli/connections.h b/src/nmcli/connections.h index c610766a62..48c981704d 100644 --- a/src/nmcli/connections.h +++ b/src/nmcli/connections.h @@ -8,7 +8,7 @@ #include "nmcli.h" -void monitor_connections(NmCli *nmc); +void nmc_monitor_connections(NmCli *nmc); const char *nmc_connection_check_deprecated(NMConnection *c); diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index 4a0c3ab8a8..af9aaa93af 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -5331,7 +5331,7 @@ nmc_command_func_device(const NMCCommand *cmd, NmCli *nmc, int argc, const char } void -monitor_devices(NmCli *nmc) +nmc_monitor_devices(NmCli *nmc) { do_devices_monitor(NULL, nmc, 0, NULL); } diff --git a/src/nmcli/devices.h b/src/nmcli/devices.h index 6214ea035a..7ed75909b3 100644 --- a/src/nmcli/devices.h +++ b/src/nmcli/devices.h @@ -12,7 +12,7 @@ void nmc_complete_device(NMClient *client, const char *prefix, gboolean wifi_onl void nmc_complete_bssid(NMClient *client, const char *ifname, const char *bssid_prefix); -void monitor_devices(NmCli *nmc); +void nmc_monitor_devices(NmCli *nmc); NMDevice **nmc_get_devices_sorted(NMClient *client); diff --git a/src/nmcli/general.c b/src/nmcli/general.c index b050d2b740..20471365a8 100644 --- a/src/nmcli/general.c +++ b/src/nmcli/general.c @@ -1632,6 +1632,6 @@ nmc_command_func_monitor(const NMCCommand *cmd, NmCli *nmc, int argc, const char nmc->should_wait++; - monitor_devices(nmc); - monitor_connections(nmc); + nmc_monitor_devices(nmc); + nmc_monitor_connections(nmc); } -- cgit v1.2.1 From 4b2ded7a4aacc00107f216e577d46b8eaa7cf424 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 17:00:00 +0100 Subject: nmcli/trivial: rename nmc_print() to nmc_print_table() nmc_print() will be used for something else. Rename. Also, nmc_print_table() is the better name anyway because the function does a lot of formatting and not simple printf(). --- src/nmcli/common.c | 36 +++++++-------- src/nmcli/connections.c | 45 +++++++++--------- src/nmcli/devices.c | 119 ++++++++++++++++++++++++------------------------ src/nmcli/general.c | 42 ++++++++--------- src/nmcli/settings.c | 2 +- src/nmcli/utils.c | 14 +++--- src/nmcli/utils.h | 14 +++--- 7 files changed, 137 insertions(+), 135 deletions(-) diff --git a/src/nmcli/common.c b/src/nmcli/common.c index 4229f66034..8c89f82dcc 100644 --- a/src/nmcli/common.c +++ b/src/nmcli/common.c @@ -354,15 +354,15 @@ print_ip_config(NMIPConfig *cfg, g_strdup_printf("IP%c.%s", nm_utils_addr_family_to_char(addr_family), one_field); } - if (!nmc_print(nmc_config, - (gpointer[]){cfg, NULL}, - NULL, - NULL, - addr_family == AF_INET - ? NMC_META_GENERIC_GROUP("IP4", metagen_ip4_config, N_("GROUP")) - : NMC_META_GENERIC_GROUP("IP6", metagen_ip6_config, N_("GROUP")), - field_str, - &error)) { + if (!nmc_print_table(nmc_config, + (gpointer[]){cfg, NULL}, + NULL, + NULL, + addr_family == AF_INET + ? NMC_META_GENERIC_GROUP("IP4", metagen_ip4_config, N_("GROUP")) + : NMC_META_GENERIC_GROUP("IP6", metagen_ip6_config, N_("GROUP")), + field_str, + &error)) { return FALSE; } return TRUE; @@ -385,15 +385,15 @@ print_dhcp_config(NMDhcpConfig *dhcp, g_strdup_printf("DHCP%c.%s", nm_utils_addr_family_to_char(addr_family), one_field); } - if (!nmc_print(nmc_config, - (gpointer[]){dhcp, NULL}, - NULL, - NULL, - addr_family == AF_INET - ? NMC_META_GENERIC_GROUP("DHCP4", metagen_dhcp_config, N_("GROUP")) - : NMC_META_GENERIC_GROUP("DHCP6", metagen_dhcp_config, N_("GROUP")), - field_str, - &error)) { + if (!nmc_print_table(nmc_config, + (gpointer[]){dhcp, NULL}, + NULL, + NULL, + addr_family == AF_INET + ? NMC_META_GENERIC_GROUP("DHCP4", metagen_dhcp_config, N_("GROUP")) + : NMC_META_GENERIC_GROUP("DHCP6", metagen_dhcp_config, N_("GROUP")), + field_str, + &error)) { return FALSE; } return TRUE; diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index 059bbbf99a..97cd991e8b 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -1729,13 +1729,14 @@ nmc_active_connection_details(NMActiveConnection *acon, NmCli *nmc) if (group_fld) f = g_strdup_printf("GENERAL.%s", group_fld); - nmc_print(&nmc->nmc_config, - (gpointer[]){acon, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("GENERAL", metagen_con_active_general, N_("GROUP")), - f, - NULL); + nmc_print_table( + &nmc->nmc_config, + (gpointer[]){acon, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("GENERAL", metagen_con_active_general, N_("GROUP")), + f, + NULL); was_output = TRUE; continue; } @@ -1786,13 +1787,13 @@ nmc_active_connection_details(NMActiveConnection *acon, NmCli *nmc) if (nmc_fields_con_active_details_groups[group_idx]->nested == metagen_con_active_vpn) { if (NM_IS_VPN_CONNECTION(acon)) { - nmc_print(&nmc->nmc_config, - (gpointer[]){acon, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("VPN", metagen_con_active_vpn, N_("NAME")), - group_fld, - NULL); + nmc_print_table(&nmc->nmc_config, + (gpointer[]){acon, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("VPN", metagen_con_active_vpn, N_("NAME")), + group_fld, + NULL); was_output = TRUE; } continue; @@ -2367,14 +2368,14 @@ do_connections_show(const NMCCommand *cmd, NmCli *nmc, int argc, const char *con items = con_show_get_items(nmc, active_only, show_active_fields, order); g_ptr_array_add(items, NULL); - if (!nmc_print(&nmc->nmc_config, - items->pdata, - NULL, - active_only ? _("NetworkManager active profiles") - : _("NetworkManager connection profiles"), - (const NMMetaAbstractInfo *const *) metagen_con_show, - fields_str, - &err)) + if (!nmc_print_table(&nmc->nmc_config, + items->pdata, + NULL, + active_only ? _("NetworkManager active profiles") + : _("NetworkManager connection profiles"), + (const NMMetaAbstractInfo *const *) metagen_con_show, + fields_str, + &err)) goto finish; } else { gboolean new_line = FALSE; diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index af9aaa93af..445f12313f 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -1654,13 +1654,14 @@ show_device_info(NMDevice *device, NmCli *nmc) if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_general) { gs_free char *f = section_fld ? g_strdup_printf("GENERAL.%s", section_fld) : NULL; - nmc_print(&nmc->nmc_config, - (gpointer[]){device, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("GENERAL", metagen_device_detail_general, N_("NAME")), - f, - NULL); + nmc_print_table( + &nmc->nmc_config, + (gpointer[]){device, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("GENERAL", metagen_device_detail_general, N_("NAME")), + f, + NULL); was_output = TRUE; continue; } @@ -1669,15 +1670,15 @@ show_device_info(NMDevice *device, NmCli *nmc) == metagen_device_detail_capabilities) { gs_free char *f = section_fld ? g_strdup_printf("CAPABILITIES.%s", section_fld) : NULL; - nmc_print(&nmc->nmc_config, - (gpointer[]){device, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("CAPABILITIES", - metagen_device_detail_capabilities, - N_("NAME")), - f, - NULL); + nmc_print_table(&nmc->nmc_config, + (gpointer[]){device, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("CAPABILITIES", + metagen_device_detail_capabilities, + N_("NAME")), + f, + NULL); was_output = TRUE; continue; } @@ -1687,15 +1688,15 @@ show_device_info(NMDevice *device, NmCli *nmc) gs_free char *f = section_fld ? g_strdup_printf("INTERFACE-FLAGS.%s", section_fld) : NULL; - nmc_print(&nmc->nmc_config, - (gpointer[]){device, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("INTERFACE-FLAGS", - metagen_device_detail_interface_flags, - N_("NAME")), - f, - NULL); + nmc_print_table(&nmc->nmc_config, + (gpointer[]){device, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("INTERFACE-FLAGS", + metagen_device_detail_interface_flags, + N_("NAME")), + f, + NULL); was_output = TRUE; continue; } @@ -1706,15 +1707,15 @@ show_device_info(NMDevice *device, NmCli *nmc) gs_free char *f = section_fld ? g_strdup_printf("WIFI-PROPERTIES.%s", section_fld) : NULL; - nmc_print(&nmc->nmc_config, - (gpointer[]){device, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("WIFI-PROPERTIES", - metagen_device_detail_wifi_properties, - N_("NAME")), - f, - NULL); + nmc_print_table(&nmc->nmc_config, + (gpointer[]){device, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("WIFI-PROPERTIES", + metagen_device_detail_wifi_properties, + N_("NAME")), + f, + NULL); was_output = TRUE; } continue; @@ -1770,15 +1771,15 @@ show_device_info(NMDevice *device, NmCli *nmc) gs_free char *f = section_fld ? g_strdup_printf("WIRED-PROPERTIES.%s", section_fld) : NULL; - nmc_print(&nmc->nmc_config, - (gpointer[]){device, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("WIRED-PROPERTIES", - metagen_device_detail_wired_properties, - N_("NAME")), - f, - NULL); + nmc_print_table(&nmc->nmc_config, + (gpointer[]){device, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("WIRED-PROPERTIES", + metagen_device_detail_wired_properties, + N_("NAME")), + f, + NULL); was_output = TRUE; } continue; @@ -1899,15 +1900,15 @@ show_device_info(NMDevice *device, NmCli *nmc) == metagen_device_detail_connections) { gs_free char *f = section_fld ? g_strdup_printf("CONNECTIONS.%s", section_fld) : NULL; - nmc_print(&nmc->nmc_config, - (gpointer[]){device, NULL}, - NULL, - NULL, - NMC_META_GENERIC_GROUP("CONNECTIONS", - metagen_device_detail_connections, - N_("NAME")), - f, - NULL); + nmc_print_table(&nmc->nmc_config, + (gpointer[]){device, NULL}, + NULL, + NULL, + NMC_META_GENERIC_GROUP("CONNECTIONS", + metagen_device_detail_connections, + N_("NAME")), + f, + NULL); was_output = TRUE; continue; } @@ -1976,13 +1977,13 @@ do_devices_status(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const devices = nmc_get_devices_sorted(nmc->client); - if (!nmc_print(&nmc->nmc_config, - (gpointer *) devices, - NULL, - N_("Status of devices"), - (const NMMetaAbstractInfo *const *) metagen_device_status, - fields_str, - &error)) { + if (!nmc_print_table(&nmc->nmc_config, + (gpointer *) devices, + NULL, + N_("Status of devices"), + (const NMMetaAbstractInfo *const *) metagen_device_status, + fields_str, + &error)) { g_string_printf(nmc->return_text, _("Error: 'device status': %s"), error->message); g_error_free(error); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; diff --git a/src/nmcli/general.c b/src/nmcli/general.c index 20471365a8..4cacc027d1 100644 --- a/src/nmcli/general.c +++ b/src/nmcli/general.c @@ -491,13 +491,13 @@ show_nm_status(NmCli *nmc, const char *pretty_header_name, const char *print_fld else fields_str = nmc->required_fields; - if (!nmc_print(&nmc->nmc_config, - (gpointer[]){nmc, NULL}, - NULL, - pretty_header_name ?: N_("NetworkManager status"), - (const NMMetaAbstractInfo *const *) metagen_general_status, - fields_str, - &error)) { + if (!nmc_print_table(&nmc->nmc_config, + (gpointer[]){nmc, NULL}, + NULL, + pretty_header_name ?: N_("NetworkManager status"), + (const NMMetaAbstractInfo *const *) metagen_general_status, + fields_str, + &error)) { g_string_printf(nmc->return_text, _("Error: only these fields are allowed: %s"), fields_all); @@ -570,13 +570,13 @@ print_permissions(void *user_data) nm_cli_spawn_pager(&nmc->nmc_config, &nmc->pager_data); - if (!nmc_print(&nmc->nmc_config, - permissions, - NULL, - _("NetworkManager permissions"), - (const NMMetaAbstractInfo *const *) metagen_general_permissions, - fields_str, - &error)) { + if (!nmc_print_table(&nmc->nmc_config, + permissions, + NULL, + _("NetworkManager permissions"), + (const NMMetaAbstractInfo *const *) metagen_general_permissions, + fields_str, + &error)) { g_string_printf(nmc->return_text, _("Error: 'general permissions': %s"), error->message); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; } @@ -724,13 +724,13 @@ show_general_logging(NmCli *nmc) } else fields_str = nmc->required_fields; - if (!nmc_print(&nmc->nmc_config, - (gpointer const[]){&d, NULL}, - NULL, - _("NetworkManager logging"), - (const NMMetaAbstractInfo *const *) metagen_general_logging, - fields_str, - &error)) { + if (!nmc_print_table(&nmc->nmc_config, + (gpointer const[]){&d, NULL}, + NULL, + _("NetworkManager logging"), + (const NMMetaAbstractInfo *const *) metagen_general_logging, + fields_str, + &error)) { g_string_printf(nmc->return_text, _("Error: 'general logging': %s"), error->message); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; } diff --git a/src/nmcli/settings.c b/src/nmcli/settings.c index 8cc151ba21..3eebb17f3f 100644 --- a/src/nmcli/settings.c +++ b/src/nmcli/settings.c @@ -759,7 +759,7 @@ setting_details(const NmcConfig *nmc_config, NMSetting *setting, const char *one fields_str = g_strdup_printf("%s.%s", nm_setting_get_name(setting), one_prop); } - if (!nmc_print( + if (!nmc_print_table( nmc_config, (gpointer[]){setting, NULL}, NULL, diff --git a/src/nmcli/utils.c b/src/nmcli/utils.c index 957c0efaff..3e9674ea6a 100644 --- a/src/nmcli/utils.c +++ b/src/nmcli/utils.c @@ -1387,13 +1387,13 @@ _print_do(const NmcConfig *nmc_config, } gboolean -nmc_print(const NmcConfig *nmc_config, - gpointer const *targets, - gpointer targets_data, - const char *header_name_no_l10n, - const NMMetaAbstractInfo *const *fields, - const char *fields_str, - GError **error) +nmc_print_table(const NmcConfig *nmc_config, + gpointer const *targets, + gpointer targets_data, + const char *header_name_no_l10n, + const NMMetaAbstractInfo *const *fields, + const char *fields_str, + GError **error) { gs_unref_ptrarray GPtrArray *gfree_keeper = NULL; gs_free PrintDataCol *cols_data = NULL; diff --git a/src/nmcli/utils.h b/src/nmcli/utils.h index c6ead55b86..3897cd2b87 100644 --- a/src/nmcli/utils.h +++ b/src/nmcli/utils.h @@ -359,13 +359,13 @@ nmc_meta_generic_get_enum_with_detail(NmcMetaGenericGetEnumType get_enum_type, /*****************************************************************************/ -gboolean nmc_print(const NmcConfig *nmc_config, - gpointer const *targets, - gpointer targets_data, - const char *header_name_no_l10n, - const NMMetaAbstractInfo *const *fields, - const char *fields_str, - GError **error); +gboolean nmc_print_table(const NmcConfig *nmc_config, + gpointer const *targets, + gpointer targets_data, + const char *header_name_no_l10n, + const NMMetaAbstractInfo *const *fields, + const char *fields_str, + GError **error); /*****************************************************************************/ -- cgit v1.2.1 From 4cf94f30c72bce47c5079e8534dda7f9b3c49869 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 16:50:50 +0100 Subject: nmcli: add nmc_print()/nmc_printerr() macros These will replace the direct calls to g_print()/g_printerr() in nmcli. There are two purposes. 1) the new macros embody the concept of "printing something from nmcli". It means, we can `git grep` for those functions, and find all the relevant places, without hitting the irrelevant ones (e.g. tests that also use g_print()). 2) by having one place, we can trivially change it. That is useful for printf debugging. For example, "test-client.py" runs nmcli and captures and compares the output. With libnm we can set LIBNM_CLIENT_DEBUG and LIBNM_CLIENT_DEBUG_FILE to print libnm debug messages to a file. But we cannot trivially synchronize the messages from nmcli with that output (also because they are consumed by the test and not immediately accessible). This would be easy, if we temporarily could patch nmc_print*() to also log to nm_utils_print(). The new macros will allow doing that at one place. For example, patch the "#if 0" and run: $ LIBNM_CLIENT_DEBUG=trace \ LIBNM_CLIENT_DEBUG_FILE='xxx.%p' \ NMTST_USE_VALGRIND=1 \ LIBTOOL="/bin/sh ./libtool" ./src/tests/client/test-client.sh -- -k monitor --- src/nmcli/utils.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/nmcli/utils.h b/src/nmcli/utils.h index 3897cd2b87..5d9449f54b 100644 --- a/src/nmcli/utils.h +++ b/src/nmcli/utils.h @@ -369,4 +369,34 @@ gboolean nmc_print_table(const NmcConfig *nmc_config, /*****************************************************************************/ +#if 0 +/* For manual testing to sync output with LIBNM_CLIENT_DEBUG/LIBNM_CLIENT_DEBUG_FILE */ +#define nmc_print(...) \ + G_STMT_START \ + { \ + gs_free char *_ss = g_strdup_printf(__VA_ARGS__); \ + gs_free char *_ss1 = g_strdup_printf("nmcli[out]: %s", _ss); \ + \ + nm_utils_print(0, _ss1); \ + nm_utils_print(1, _ss); \ + } \ + G_STMT_END + +#define nmc_printerr(...) \ + G_STMT_START \ + { \ + gs_free char *_ss = g_strdup_printf(__VA_ARGS__); \ + gs_free char *_ss1 = g_strdup_printf("nmcli[err]: %s", _ss); \ + \ + nm_utils_print(0, _ss1); \ + nm_utils_print(2, _ss); \ + } \ + G_STMT_END +#else +#define nmc_print(...) g_print(__VA_ARGS__) +#define nmc_printerr(...) g_printerr(__VA_ARGS__) +#endif + +/*****************************************************************************/ + #endif /* NMC_UTILS_H */ -- cgit v1.2.1 From b32e4c941a7525881599f6d419ddaafacd85b52c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 6 Feb 2023 16:57:38 +0100 Subject: nmcli: replace all uses of g_print()/g_printerr() with nmc_print()/nmc_printerr() The main purpose is to simplify printf debugging and manual testing. We can now trivially patch the code so that all output from nmcli gets (additionally) written to a file. That is useful when debugging a unit test in "test-client.py". Thereby we can duplicate all messages via nm_utils_print(), which is in sync with the debug messages from libnm and which honors LIBNM_CLIENT_DEBUG_FILE. --- src/nmcli/agent.c | 40 +- src/nmcli/common.c | 20 +- src/nmcli/connections.c | 1054 +++++++++++++++++++++++----------------------- src/nmcli/devices.c | 269 ++++++------ src/nmcli/general.c | 230 +++++----- src/nmcli/nmcli.c | 22 +- src/nmcli/polkit-agent.c | 9 +- src/nmcli/settings.c | 24 +- src/nmcli/utils.c | 76 ++-- 9 files changed, 885 insertions(+), 859 deletions(-) diff --git a/src/nmcli/agent.c b/src/nmcli/agent.c index 6d0fcfb5c9..b16a3c51c9 100644 --- a/src/nmcli/agent.c +++ b/src/nmcli/agent.c @@ -22,36 +22,36 @@ static void usage(void) { - g_printerr(_("Usage: nmcli agent { COMMAND | help }\n\n" - "COMMAND := { secret | polkit | all }\n\n")); + nmc_printerr(_("Usage: nmcli agent { COMMAND | help }\n\n" + "COMMAND := { secret | polkit | all }\n\n")); } static void usage_agent_secret(void) { - g_printerr(_("Usage: nmcli agent secret { help }\n" - "\n" - "Runs nmcli as NetworkManager secret agent. When NetworkManager requires\n" - "a password it asks registered agents for it. This command keeps nmcli running\n" - "and if a password is required asks the user for it.\n\n")); + nmc_printerr(_("Usage: nmcli agent secret { help }\n" + "\n" + "Runs nmcli as NetworkManager secret agent. When NetworkManager requires\n" + "a password it asks registered agents for it. This command keeps nmcli running\n" + "and if a password is required asks the user for it.\n\n")); } static void usage_agent_polkit(void) { - g_printerr(_("Usage: nmcli agent polkit { help }\n" - "\n" - "Registers nmcli as a polkit action for the user session.\n" - "When a polkit daemon requires an authorization, nmcli asks the user and gives\n" - "the response back to polkit.\n\n")); + nmc_printerr(_("Usage: nmcli agent polkit { help }\n" + "\n" + "Registers nmcli as a polkit action for the user session.\n" + "When a polkit daemon requires an authorization, nmcli asks the user and gives\n" + "the response back to polkit.\n\n")); } static void usage_agent_all(void) { - g_printerr(_("Usage: nmcli agent all { help }\n" - "\n" - "Runs nmcli as both NetworkManager secret and a polkit agent.\n\n")); + nmc_printerr(_("Usage: nmcli agent all { help }\n" + "\n" + "Runs nmcli as both NetworkManager secret and a polkit agent.\n\n")); } static char *pre_input_deftext; @@ -82,7 +82,7 @@ get_secrets_from_user(const NmcConfig *nmc_config, /* Ask user for the password */ if (msg) - g_print("%s\n", msg); + nmc_print("%s\n", msg); if (secret->value) { /* Prefill the password if we have it. */ rl_startup_hook = set_deftext; @@ -138,7 +138,7 @@ do_agent_secret(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const * NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS, G_CALLBACK(secrets_requested), nmc); - g_print(_("nmcli successfully registered as a NetworkManager's secret agent.\n")); + nmc_print(_("nmcli successfully registered as a NetworkManager's secret agent.\n")); } else { g_string_printf(nmc->return_text, _("Error: secret agent initialization failed")); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; @@ -148,7 +148,7 @@ do_agent_secret(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const * static void polkit_registered(gpointer instance, gpointer user_data) { - g_print(_("nmcli successfully registered as a polkit agent.\n")); + nmc_print(_("nmcli successfully registered as a polkit agent.\n")); } static void @@ -202,14 +202,14 @@ do_agent_all(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *arg do_agent_secret(cmd, nmc, argc, argv); r = nmc->return_value; if (r != NMC_RESULT_SUCCESS) { - g_printerr("%s\n", nmc->return_text->str); + nmc_printerr("%s\n", nmc->return_text->str); g_string_truncate(nmc->return_text, 0); nmc->return_value = NMC_RESULT_SUCCESS; } do_agent_polkit(cmd, nmc, argc, argv); if (nmc->return_value != NMC_RESULT_SUCCESS) { - g_printerr("%s\n", nmc->return_text->str); + nmc_printerr("%s\n", nmc->return_text->str); g_string_truncate(nmc->return_text, 0); } diff --git a/src/nmcli/common.c b/src/nmcli/common.c index 8c89f82dcc..f31d09872d 100644 --- a/src/nmcli/common.c +++ b/src/nmcli/common.c @@ -660,16 +660,16 @@ vpn_openconnect_get_secrets(NMConnection *connection, GPtrArray *secrets) /* Interactively authenticate to OpenConnect server and get secrets */ ret = nm_vpn_openconnect_authenticate_helper(gw, &cookie, &gateway, &gwcert, &status, &error); if (!ret) { - g_printerr(_("Error: openconnect failed: %s\n"), error->message); + nmc_printerr(_("Error: openconnect failed: %s\n"), error->message); g_clear_error(&error); return FALSE; } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) - g_printerr(_("Error: openconnect failed with status %d\n"), WEXITSTATUS(status)); + nmc_printerr(_("Error: openconnect failed with status %d\n"), WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) - g_printerr(_("Error: openconnect failed with signal %d\n"), WTERMSIG(status)); + nmc_printerr(_("Error: openconnect failed with signal %d\n"), WTERMSIG(status)); /* Append port to the host value */ if (gateway && port) { @@ -743,7 +743,7 @@ get_secrets_from_user(const NmcConfig *nmc_config, } } if (msg) - g_print("%s\n", msg); + nmc_print("%s\n", msg); echo_on = secret->is_secret ? nmc_config->show_secrets : TRUE; @@ -760,10 +760,10 @@ get_secrets_from_user(const NmcConfig *nmc_config, pwd = g_strdup(""); } else { if (msg) - g_print("%s\n", msg); - g_printerr(_("Warning: password for '%s' not given in 'passwd-file' " - "and nmcli cannot ask without '--ask' option.\n"), - secret->entry_id); + nmc_print("%s\n", msg); + nmc_printerr(_("Warning: password for '%s' not given in 'passwd-file' " + "and nmcli cannot ask without '--ask' option.\n"), + secret->entry_id); } } /* No password provided, cancel the secrets. */ @@ -1532,7 +1532,7 @@ nmc_do_cmd(NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, const if (argc == 1 && nmc->complete) { for (c = cmds; c->cmd; ++c) { if (!*cmd || matches(cmd, c->cmd)) - g_print("%s\n", c->cmd); + nmc_print("%s\n", c->cmd); } nmc_complete_help(cmd); g_task_return_boolean(task, TRUE); @@ -1612,7 +1612,7 @@ nmc_complete_strv(const char *prefix, gssize nargs, const char *const *args) if (prefix && !matches(prefix, candidate)) continue; - g_print("%s\n", candidate); + nmc_print("%s\n", candidate); } } diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c index 97cd991e8b..36de6373e9 100644 --- a/src/nmcli/connections.c +++ b/src/nmcli/connections.c @@ -1084,7 +1084,7 @@ static TabCompletionInfo nmc_tab_completion; static void usage(void) { - g_printerr( + nmc_printerr( _("Usage: nmcli connection { COMMAND | help }\n\n" "COMMAND := { show | up | down | add | modify | clone | edit | delete | monitor | reload " "| load | import | export }\n\n" @@ -1110,7 +1110,7 @@ usage(void) static void usage_connection_show(void) { - g_printerr( + nmc_printerr( _("Usage: nmcli connection show { ARGUMENTS | help }\n" "\n" "ARGUMENTS := [--active] [--order ]\n" @@ -1132,171 +1132,173 @@ usage_connection_show(void) static void usage_connection_up(void) { - g_printerr(_("Usage: nmcli connection up { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [id | uuid | path] [ifname ] [ap ] [nsp ] " - "[passwd-file ]\n" - "\n" - "Activate a connection on a device. The profile to activate is identified by its\n" - "name, UUID or D-Bus path.\n" - "\n" - "ARGUMENTS := ifname [ap ] [nsp ] [passwd-file ]\n" - "\n" - "Activate a device with a connection. The connection profile is selected\n" - "automatically by NetworkManager.\n" - "\n" - "ifname - specifies the device to active the connection on\n" - "ap - specifies AP to connect to (only valid for Wi-Fi)\n" - "nsp - specifies NSP to connect to (only valid for WiMAX)\n" - "passwd-file - file with password(s) required to activate the connection\n\n")); + nmc_printerr( + _("Usage: nmcli connection up { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [id | uuid | path] [ifname ] [ap ] [nsp ] " + "[passwd-file ]\n" + "\n" + "Activate a connection on a device. The profile to activate is identified by its\n" + "name, UUID or D-Bus path.\n" + "\n" + "ARGUMENTS := ifname [ap ] [nsp ] [passwd-file ]\n" + "\n" + "Activate a device with a connection. The connection profile is selected\n" + "automatically by NetworkManager.\n" + "\n" + "ifname - specifies the device to active the connection on\n" + "ap - specifies AP to connect to (only valid for Wi-Fi)\n" + "nsp - specifies NSP to connect to (only valid for WiMAX)\n" + "passwd-file - file with password(s) required to activate the connection\n\n")); } static void usage_connection_down(void) { - g_printerr(_("Usage: nmcli connection down { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [id | uuid | path | apath] ...\n" - "\n" - "Deactivate a connection from a device (without preventing the device from\n" - "further auto-activation). The profile to deactivate is identified by its name,\n" - "UUID or D-Bus path.\n\n")); + nmc_printerr( + _("Usage: nmcli connection down { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [id | uuid | path | apath] ...\n" + "\n" + "Deactivate a connection from a device (without preventing the device from\n" + "further auto-activation). The profile to deactivate is identified by its name,\n" + "UUID or D-Bus path.\n\n")); } static void usage_connection_add(void) { - g_printerr(_("Usage: nmcli connection add { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS SLAVE_OPTIONS IP_OPTIONS [-- " - "([+|-]. )+]\n\n" - " COMMON_OPTIONS:\n" - " type \n" - " [ifname | \"*\"]\n" - " [con-name ]\n" - " [autoconnect yes|no]\n" - " [save yes|no]\n" - " [master ]\n" - " [slave-type ]\n\n" - " TYPE_SPECIFIC_OPTIONS:\n" - " ethernet: [mac ]\n" - " [cloned-mac ]\n" - " [mtu ]\n\n" - " wifi: ssid \n" - " [mac ]\n" - " [cloned-mac ]\n" - " [mtu ]\n" - " [mode infrastructure|ap|adhoc]\n\n" - " wimax: [mac ]\n" - " [nsp ]\n\n" - " pppoe: username \n" - " [password ]\n" - " [service ]\n" - " [mtu ]\n" - " [mac ]\n\n" - " gsm: apn \n" - " [user ]\n" - " [password ]\n\n" - " cdma: [user ]\n" - " [password ]\n\n" - " infiniband: [mac ]\n" - " [mtu ]\n" - " [transport-mode datagram | connected]\n" - " [parent ]\n" - " [p-key ]\n\n" - " bluetooth: [addr ]\n" - " [bt-type panu|nap|dun-gsm|dun-cdma]\n\n" - " vlan: dev \n" - " id \n" - " [flags ]\n" - " [ingress ]\n" - " [egress ]\n" - " [mtu ]\n\n" - " bond: [mode balance-rr (0) | active-backup (1) | balance-xor (2) | " - "broadcast (3) |\n" - " 802.3ad (4) | balance-tlb (5) | balance-alb (6)]\n" - " [primary ]\n" - " [miimon ]\n" - " [downdelay ]\n" - " [updelay ]\n" - " [arp-interval ]\n" - " [arp-ip-target ]\n" - " [lacp-rate slow (0) | fast (1)]\n\n" - " bond-slave: master \n" - " [queue-id <0-65535>]\n\n" - " team: [config |]\n\n" - " team-slave: master \n" - " [config |]\n\n" - " bridge: [stp yes|no]\n" - " [priority ]\n" - " [forward-delay <2-30>]\n" - " [hello-time <1-10>]\n" - " [max-age <6-40>]\n" - " [ageing-time <0-1000000>]\n" - " [multicast-snooping yes|no]\n" - " [mac ]\n\n" - " bridge-slave: master \n" - " [priority <0-63>]\n" - " [path-cost <1-65535>]\n" - " [hairpin yes|no]\n\n" - " vpn: vpn-type " - "vpnc|openvpn|pptp|openconnect|openswan|libreswan|ssh|l2tp|iodine|...\n" - " [user ]\n\n" - " olpc-mesh: ssid \n" - " [channel <1-13>]\n" - " [dhcp-anycast ]\n\n" - " adsl: username \n" - " protocol pppoa|pppoe|ipoatm\n" - " [password ]\n" - " [encapsulation vcmux|llc]\n\n" - " tun: mode tun|tap\n" - " [owner ]\n" - " [group ]\n" - " [pi yes|no]\n" - " [vnet-hdr yes|no]\n" - " [multi-queue yes|no]\n\n" - " ip-tunnel: mode ipip|gre|sit|isatap|vti|ip6ip6|ipip6|ip6gre|vti6\n" - " remote \n" - " [local ]\n" - " [dev ]\n\n" - " macsec: dev \n" - " mode \n" - " [cak ckn ]\n" - " [encrypt yes|no]\n" - " [port 1-65534]\n\n\n" - " macvlan: dev \n" - " mode vepa|bridge|private|passthru|source\n" - " [tap yes|no]\n\n" - " vxlan: id \n" - " [remote ]\n" - " [local ]\n" - " [dev ]\n" - " [source-port-min <0-65535>]\n" - " [source-port-max <0-65535>]\n" - " [destination-port <0-65535>]\n\n" - " wpan: [short-addr <0x0000-0xffff>]\n" - " [pan-id <0x0000-0xffff>]\n" - " [page ]\n" - " [channel ]\n" - " [mac ]\n\n" - " 6lowpan: dev \n" - " dummy:\n\n" - " SLAVE_OPTIONS:\n" - " bridge: [priority <0-63>]\n" - " [path-cost <1-65535>]\n" - " [hairpin yes|no]\n\n" - " team: [config |]\n\n" - " bond: [queue-id <0-65535>]\n\n" - " IP_OPTIONS:\n" - " [ip4 ] [gw4 ]\n" - " [ip6 ] [gw6 ]\n\n")); + nmc_printerr(_("Usage: nmcli connection add { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS SLAVE_OPTIONS IP_OPTIONS [-- " + "([+|-]. )+]\n\n" + " COMMON_OPTIONS:\n" + " type \n" + " [ifname | \"*\"]\n" + " [con-name ]\n" + " [autoconnect yes|no]\n" + " [save yes|no]\n" + " [master ]\n" + " [slave-type ]\n\n" + " TYPE_SPECIFIC_OPTIONS:\n" + " ethernet: [mac ]\n" + " [cloned-mac ]\n" + " [mtu ]\n\n" + " wifi: ssid \n" + " [mac ]\n" + " [cloned-mac ]\n" + " [mtu ]\n" + " [mode infrastructure|ap|adhoc]\n\n" + " wimax: [mac ]\n" + " [nsp ]\n\n" + " pppoe: username \n" + " [password ]\n" + " [service ]\n" + " [mtu ]\n" + " [mac ]\n\n" + " gsm: apn \n" + " [user ]\n" + " [password ]\n\n" + " cdma: [user ]\n" + " [password ]\n\n" + " infiniband: [mac ]\n" + " [mtu ]\n" + " [transport-mode datagram | connected]\n" + " [parent ]\n" + " [p-key ]\n\n" + " bluetooth: [addr ]\n" + " [bt-type panu|nap|dun-gsm|dun-cdma]\n\n" + " vlan: dev \n" + " id \n" + " [flags ]\n" + " [ingress ]\n" + " [egress ]\n" + " [mtu ]\n\n" + " bond: [mode balance-rr (0) | active-backup (1) | balance-xor (2) | " + "broadcast (3) |\n" + " 802.3ad (4) | balance-tlb (5) | balance-alb (6)]\n" + " [primary ]\n" + " [miimon ]\n" + " [downdelay ]\n" + " [updelay ]\n" + " [arp-interval ]\n" + " [arp-ip-target ]\n" + " [lacp-rate slow (0) | fast (1)]\n\n" + " bond-slave: master \n" + " [queue-id <0-65535>]\n\n" + " team: [config |]\n\n" + " team-slave: master \n" + " [config |]\n\n" + " bridge: [stp yes|no]\n" + " [priority ]\n" + " [forward-delay <2-30>]\n" + " [hello-time <1-10>]\n" + " [max-age <6-40>]\n" + " [ageing-time <0-1000000>]\n" + " [multicast-snooping yes|no]\n" + " [mac ]\n\n" + " bridge-slave: master \n" + " [priority <0-63>]\n" + " [path-cost <1-65535>]\n" + " [hairpin yes|no]\n\n" + " vpn: vpn-type " + "vpnc|openvpn|pptp|openconnect|openswan|libreswan|ssh|l2tp|iodine|...\n" + " [user ]\n\n" + " olpc-mesh: ssid \n" + " [channel <1-13>]\n" + " [dhcp-anycast ]\n\n" + " adsl: username \n" + " protocol pppoa|pppoe|ipoatm\n" + " [password ]\n" + " [encapsulation vcmux|llc]\n\n" + " tun: mode tun|tap\n" + " [owner ]\n" + " [group ]\n" + " [pi yes|no]\n" + " [vnet-hdr yes|no]\n" + " [multi-queue yes|no]\n\n" + " ip-tunnel: mode ipip|gre|sit|isatap|vti|ip6ip6|ipip6|ip6gre|vti6\n" + " remote \n" + " [local ]\n" + " [dev ]\n\n" + " macsec: dev \n" + " mode \n" + " [cak ckn ]\n" + " [encrypt yes|no]\n" + " [port 1-65534]\n\n\n" + " macvlan: dev \n" + " mode vepa|bridge|private|passthru|source\n" + " [tap yes|no]\n\n" + " vxlan: id \n" + " [remote ]\n" + " [local ]\n" + " [dev ]\n" + " [source-port-min <0-65535>]\n" + " [source-port-max <0-65535>]\n" + " [destination-port <0-65535>]\n\n" + " wpan: [short-addr <0x0000-0xffff>]\n" + " [pan-id <0x0000-0xffff>]\n" + " [page ]\n" + " [channel ]\n" + " [mac ]\n\n" + " 6lowpan: dev \n" + " dummy:\n\n" + " SLAVE_OPTIONS:\n" + " bridge: [priority <0-63>]\n" + " [path-cost <1-65535>]\n" + " [hairpin yes|no]\n\n" + " team: [config |]\n\n" + " bond: [queue-id <0-65535>]\n\n" + " IP_OPTIONS:\n" + " [ip4 ] [gw4 ]\n" + " [ip6 ] [gw6 ]\n\n")); } static void usage_connection_modify(void) { - g_printerr( + nmc_printerr( _("Usage: nmcli connection modify { ARGUMENTS | help }\n" "\n" "ARGUMENTS := [id | uuid | path] ([+|-]. )+\n" @@ -1325,77 +1327,78 @@ usage_connection_modify(void) static void usage_connection_clone(void) { - g_printerr(_("Usage: nmcli connection clone { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [--temporary] [id | uuid | path] \n" - "\n" - "Clone an existing connection profile. The newly created connection will be\n" - "the exact copy of the , except the uuid property (will be generated) and\n" - "id (provided as argument).\n\n")); + nmc_printerr(_("Usage: nmcli connection clone { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [--temporary] [id | uuid | path] \n" + "\n" + "Clone an existing connection profile. The newly created connection will be\n" + "the exact copy of the , except the uuid property (will be generated) and\n" + "id (provided as argument).\n\n")); } static void usage_connection_edit(void) { - g_printerr(_("Usage: nmcli connection edit { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [id | uuid | path] \n" - "\n" - "Edit an existing connection profile in an interactive editor.\n" - "The profile is identified by its name, UUID or D-Bus path\n" - "\n" - "ARGUMENTS := [type ] [con-name ]\n" - "\n" - "Add a new connection profile in an interactive editor.\n\n")); + nmc_printerr(_("Usage: nmcli connection edit { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [id | uuid | path] \n" + "\n" + "Edit an existing connection profile in an interactive editor.\n" + "The profile is identified by its name, UUID or D-Bus path\n" + "\n" + "ARGUMENTS := [type ] [con-name ]\n" + "\n" + "Add a new connection profile in an interactive editor.\n\n")); } static void usage_connection_delete(void) { - g_printerr(_("Usage: nmcli connection delete { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [id | uuid | path] , ...\n" - "\n" - "Delete connection profiles.\n" - "The profiles are identified by their name, UUID or D-Bus path.\n\n")); + nmc_printerr(_("Usage: nmcli connection delete { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [id | uuid | path] , ...\n" + "\n" + "Delete connection profiles.\n" + "The profiles are identified by their name, UUID or D-Bus path.\n\n")); } static void usage_connection_monitor(void) { - g_printerr(_("Usage: nmcli connection monitor { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [id | uuid | path] ...\n" - "\n" - "Monitor connection profile activity.\n" - "This command prints a line whenever the specified connection changes.\n" - "Monitors all connection profiles in case none is specified.\n\n")); + nmc_printerr(_("Usage: nmcli connection monitor { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [id | uuid | path] ...\n" + "\n" + "Monitor connection profile activity.\n" + "This command prints a line whenever the specified connection changes.\n" + "Monitors all connection profiles in case none is specified.\n\n")); } static void usage_connection_reload(void) { - g_printerr(_("Usage: nmcli connection reload { help }\n" - "\n" - "Reload all connection files from disk.\n\n")); + nmc_printerr(_("Usage: nmcli connection reload { help }\n" + "\n" + "Reload all connection files from disk.\n\n")); } static void usage_connection_load(void) { - g_printerr(_("Usage: nmcli connection load { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [...]\n" - "\n" - "Load/reload one or more connection files from disk. Use this after manually\n" - "editing a connection file to ensure that NetworkManager is aware of its latest\n" - "state.\n\n")); + nmc_printerr( + _("Usage: nmcli connection load { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [...]\n" + "\n" + "Load/reload one or more connection files from disk. Use this after manually\n" + "editing a connection file to ensure that NetworkManager is aware of its latest\n" + "state.\n\n")); } static void usage_connection_import(void) { - g_printerr( + nmc_printerr( _("Usage: nmcli connection import { ARGUMENTS | help }\n" "\n" "ARGUMENTS := [--temporary] type file \n" @@ -1409,23 +1412,24 @@ usage_connection_import(void) static void usage_connection_export(void) { - g_printerr(_("Usage: nmcli connection export { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [id | uuid | path] []\n" - "\n" - "Export a connection. Only VPN connections are supported at the moment.\n" - "The data are directed to standard output or to a file if a name is given.\n\n")); + nmc_printerr( + _("Usage: nmcli connection export { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [id | uuid | path] []\n" + "\n" + "Export a connection. Only VPN connections are supported at the moment.\n" + "The data are directed to standard output or to a file if a name is given.\n\n")); } static void usage_connection_migrate(void) { - g_printerr(_("Usage: nmcli connection migrate { ARGUMENTS | help }\n" - "\n" - "ARGUMENTS := [--plugin ] [id | uuid | path] , ...\n" - "\n" - "Migrate connection profiles to a different settings plugin,\n" - "such as \"keyfile\" (default) or \"ifcfg-rh\".\n\n")); + nmc_printerr(_("Usage: nmcli connection migrate { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [--plugin ] [id | uuid | path] , ...\n" + "\n" + "Migrate connection profiles to a different settings plugin,\n" + "such as \"keyfile\" (default) or \"ifcfg-rh\".\n\n")); } static char * @@ -1503,9 +1507,9 @@ got_secrets(GObject *source_object, GAsyncResult *res, gpointer user_data) gs_free_error GError *error = NULL; if (!nm_connection_update_secrets(data->local, NULL, secrets, &error) && error) { - g_printerr(_("Error updating secrets for %s: %s\n"), - data->setting_name, - error->message); + nmc_printerr(_("Error updating secrets for %s: %s\n"), + data->setting_name, + error->message); } } @@ -1613,7 +1617,7 @@ nmc_connection_profile_details(NMConnection *connection, NmCli *nmc) if (NM_IN_SET(nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) && !nmc->nmc_config.multiline_output && was_output) - g_print("\n"); /* Empty line */ + nmc_print("\n"); /* Empty line */ was_output = FALSE; @@ -1719,7 +1723,7 @@ nmc_active_connection_details(NMActiveConnection *acon, NmCli *nmc) if (NM_IN_SET(nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY) && !nmc->nmc_config.multiline_output && was_output) - g_print("\n"); + nmc_print("\n"); was_output = FALSE; @@ -2507,7 +2511,7 @@ do_connections_show(const NMCCommand *cmd, NmCli *nmc, int argc, const char *con nm_assert(explicit_acon || con); if (new_line) - g_print("\n"); + nmc_print("\n"); new_line = TRUE; if (without_fields || profile_flds) { @@ -2532,7 +2536,7 @@ do_connections_show(const NMCCommand *cmd, NmCli *nmc, int argc, const char *con /* if there are multiple active connections, separate them with newline. * that is a bit odd, because we already separate connections with newlines, * and commonly don't separate the connection from the first active connection. */ - g_print("\n"); + nmc_print("\n"); } if (explicit_acon) @@ -2800,12 +2804,12 @@ check_activated(ActivateConnectionInfo *info) if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) nmc_terminal_erase_line(); if (reason) { - g_print(_("Connection successfully activated (%s) (D-Bus active path: %s)\n"), - reason, - nm_object_get_path(NM_OBJECT(info->active))); + nmc_print(_("Connection successfully activated (%s) (D-Bus active path: %s)\n"), + reason, + nm_object_get_path(NM_OBJECT(info->active))); } else { - g_print(_("Connection successfully activated (D-Bus active path: %s)\n"), - nm_object_get_path(NM_OBJECT(info->active))); + nmc_print(_("Connection successfully activated (D-Bus active path: %s)\n"), + nm_object_get_path(NM_OBJECT(info->active))); } activate_connection_info_finish(info); break; @@ -2955,8 +2959,8 @@ activate_connection_cb(GObject *client, GAsyncResult *result, gpointer user_data if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) nmc_terminal_erase_line(); - g_print(_("Connection successfully activated (D-Bus active path: %s)\n"), - nm_object_get_path(NM_OBJECT(active))); + nmc_print(_("Connection successfully activated (D-Bus active path: %s)\n"), + nm_object_get_path(NM_OBJECT(active))); } activate_connection_info_finish(info); } else { @@ -3325,9 +3329,9 @@ connection_removed_cb(NMClient *client, NMConnection *connection, ConnectionCbIn { if (!connection_cb_info_obj_list_has(info, connection)) return; - g_print(_("Connection '%s' (%s) successfully deleted.\n"), - nm_connection_get_id(connection), - nm_connection_get_uuid(connection)); + nmc_print(_("Connection '%s' (%s) successfully deleted.\n"), + nm_connection_get_id(connection), + nm_connection_get_uuid(connection)); connection_cb_info_finish(info, connection); } @@ -3341,9 +3345,9 @@ down_active_connection_state_cb(NMActiveConnection *active, if (info->nmc->nmc_config.print_output == NMC_PRINT_PRETTY) nmc_terminal_erase_line(); - g_print(_("Connection '%s' successfully deactivated (D-Bus active path: %s)\n"), - nm_active_connection_get_id(active), - nm_object_get_path(NM_OBJECT(active))); + nmc_print(_("Connection '%s' successfully deactivated (D-Bus active path: %s)\n"), + nm_active_connection_get_id(active), + nm_object_get_path(NM_OBJECT(active))); g_signal_handlers_disconnect_by_func(G_OBJECT(active), down_active_connection_state_cb, info); connection_cb_info_finish(info, active); @@ -3422,7 +3426,7 @@ do_connection_down(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons arg_num == 1 && nmc->complete); if (!active) { if (!nmc->complete) - g_printerr(_("Error: '%s' is not an active connection.\n"), *arg_ptr); + nmc_printerr(_("Error: '%s' is not an active connection.\n"), *arg_ptr); g_string_printf(nmc->return_text, _("Error: not all active connections found.")); nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; } @@ -3463,9 +3467,9 @@ do_connection_down(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons active = found_active_cons->pdata[i]; if (!nm_client_deactivate_connection(nmc->client, active, NULL, &error)) { - g_print(_("Connection '%s' deactivation failed: %s\n"), - nm_active_connection_get_id(active), - error->message); + nmc_print(_("Connection '%s' deactivation failed: %s\n"), + nm_active_connection_get_id(active), + error->message); g_clear_error(&error); if (info) { @@ -3944,7 +3948,7 @@ normalized_master_for_slave(const GPtrArray *connections, } if (!out_master) { - g_print(_("Warning: master='%s' doesn't refer to any existing profile.\n"), master); + nmc_print(_("Warning: master='%s' doesn't refer to any existing profile.\n"), master); out_master = master; if (out_type) *out_type = type; @@ -4985,7 +4989,7 @@ complete_property_name(NmCli *nmc, prefix, postfix); if (word_list) - g_print("%s", word_list); + nmc_print("%s", word_list); if (modifier != NM_META_ACCESSOR_MODIFIER_SET) return; @@ -5014,7 +5018,7 @@ complete_property_name(NmCli *nmc, if (!bi->base.property_alias || !g_str_has_prefix(bi->base.property_alias, prefix)) continue; - g_print("%s\n", bi->base.property_alias); + nmc_print("%s\n", bi->base.property_alias); } } else { if (!property_info->is_cli_option) @@ -5022,7 +5026,7 @@ complete_property_name(NmCli *nmc, if (!property_info->property_alias || !g_str_has_prefix(property_info->property_alias, prefix)) continue; - g_print("%s\n", property_info->property_alias); + nmc_print("%s\n", property_info->property_alias); } } } @@ -5035,7 +5039,7 @@ run_rl_generator(rl_compentry_func_t *generator_func, const char *prefix) char *str; while ((str = generator_func(prefix, state))) { - g_print("%s\n", str); + nmc_print("%s\n", str); g_free(str); if (state == 0) state = 1; @@ -5069,7 +5073,7 @@ complete_option(NmCli *nmc, } if (values) { for (; values[0]; values++) - g_print("%s\n", values[0]); + nmc_print("%s\n", values[0]); return TRUE; } @@ -5094,11 +5098,11 @@ complete_existing_setting(NmCli *nmc, NMConnection *connection, const char *pref editor = nm_meta_setting_info_editor_find_by_setting(settings[i]); if (!prefix || g_str_has_prefix(editor->general->setting_name, prefix)) - g_print("%s\n", editor->general->setting_name); + nmc_print("%s\n", editor->general->setting_name); if (editor->alias) { if (!prefix || g_str_has_prefix(editor->alias, prefix)) - g_print("%s\n", editor->alias); + nmc_print("%s\n", editor->alias); } } } @@ -5386,7 +5390,7 @@ nmc_process_connection_properties(NmCli *nmc, if (!chosen) { if (*argc == 1 && nmc->complete) { if (allow_setting_removal && g_str_has_prefix("remove", option)) - g_print("remove\n"); + nmc_print("remove\n"); complete_property_name(nmc, connection, modifier, option, NULL); } g_set_error(error, @@ -5426,7 +5430,7 @@ connection_warnings(NmCli *nmc, NMConnection *connection) deprecated = nmc_connection_check_deprecated(NM_CONNECTION(connection)); if (deprecated) - g_printerr(_("Warning: %s.\n"), deprecated); + nmc_printerr(_("Warning: %s.\n"), deprecated); connections = nmc_get_connections(nmc); id = nm_connection_get_id(connection); @@ -5441,15 +5445,15 @@ connection_warnings(NmCli *nmc, NMConnection *connection) } if (found > 0) { - g_printerr(g_dngettext(GETTEXT_PACKAGE, - "Warning: There is another connection with the name '%1$s'. " - "Reference the connection by its uuid '%2$s'\n", - "Warning: There are %3$u other connections with the name " - "'%1$s'. Reference the connection by its uuid '%2$s'\n", - found), - id, - nm_connection_get_uuid(NM_CONNECTION(connection)), - found); + nmc_printerr(g_dngettext(GETTEXT_PACKAGE, + "Warning: There is another connection with the name '%1$s'. " + "Reference the connection by its uuid '%2$s'\n", + "Warning: There are %3$u other connections with the name " + "'%1$s'. Reference the connection by its uuid '%2$s'\n", + found), + id, + nm_connection_get_uuid(NM_CONNECTION(connection)), + found); } } @@ -5481,9 +5485,9 @@ add_connection_cb(GObject *client, GAsyncResult *result, gpointer user_data) * * This is true for many messages that the user might parse. But this one * seems in particular interesting for a user to parse. */ - g_print(_("Connection '%s' (%s) successfully added.\n"), - nm_connection_get_id(NM_CONNECTION(connection)), - nm_connection_get_uuid(NM_CONNECTION(connection))); + nmc_print(_("Connection '%s' (%s) successfully added.\n"), + nm_connection_get_id(NM_CONNECTION(connection)), + nm_connection_get_uuid(NM_CONNECTION(connection))); g_object_unref(connection); } @@ -5629,7 +5633,8 @@ ask_option(NmCli *nmc, NMConnection *connection, const NMMetaAbstractInfo *abstr multi = NM_FLAGS_HAS(inf_flags, NM_META_PROPERTY_INF_FLAG_MULTI); if (multi) - g_print(_("You can specify this option more than once. Press when you're done.\n")); + nmc_print( + _("You can specify this option more than once. Press when you're done.\n")); again: nm_clear_g_free(&value); @@ -5638,7 +5643,7 @@ again: value = nmc_readline(&nmc->nmc_config, "%s", prompt); if (!set_option(nmc, connection, abstract_info, value, FALSE, &error)) { - g_printerr("%s\n", error->message); + nmc_printerr("%s\n", error->message); goto again; } @@ -5740,7 +5745,7 @@ want_provide_opt_args(const NmcConfig *nmc_config, const char *type, guint num) return TRUE; /* Ask for optional arguments. */ - g_print(_("There are %d optional settings for %s.\n"), (int) num, type); + nmc_print(_("There are %d optional settings for %s.\n"), (int) num, type); answer = nmc_readline(nmc_config, _("Do you want to provide them? %s"), prompt_yes_no(TRUE, NULL)); nm_strstrip(answer); @@ -6872,7 +6877,7 @@ load_history_cmds(const char *uuid) kf = g_key_file_new(); if (!g_key_file_load_from_file(kf, filename, G_KEY_FILE_KEEP_COMMENTS, &err)) { if (g_error_matches(err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE)) - g_print("Warning: %s parse error: %s\n", filename, err->message); + nmc_print("Warning: %s parse error: %s\n", filename, err->message); g_key_file_free(kf); g_free(filename); return; @@ -6911,7 +6916,7 @@ save_history_cmds(const char *uuid) if (!g_key_file_load_from_file(kf, filename, G_KEY_FILE_KEEP_COMMENTS, &error)) { if (!g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT) && !g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) { - g_print("Warning: %s parse error: %s\n", filename, error->message); + nmc_print("Warning: %s parse error: %s\n", filename, error->message); return; } g_clear_error(&error); @@ -6947,7 +6952,7 @@ editor_show_connection(NMConnection *connection, NmCli *nmc) static void editor_show_setting(NMSetting *setting, NmCli *nmc) { - g_print(_("['%s' setting values]\n"), nm_setting_get_name(setting)); + nmc_print(_("['%s' setting values]\n"), nm_setting_get_name(setting)); nmc->nmc_config_mutable.print_output = NMC_PRINT_NORMAL; nmc->nmc_config_mutable.multiline_output = TRUE; @@ -7054,24 +7059,24 @@ fail: static void editor_main_usage(void) { - g_print("------------------------------------------------------------------------------\n"); + nmc_print("------------------------------------------------------------------------------\n"); /* TRANSLATORS: do not translate command names and keywords before :: * However, you should translate terms enclosed in <>. */ - g_print(_("---[ Main menu ]---\n" - "goto [ | ] :: go to a setting or property\n" - "remove [.] | :: remove setting or reset property value\n" - "set [. ] :: set property value\n" - "describe [.] :: describe property\n" - "print [all | [.]] :: print the connection\n" - "verify [all | fix] :: verify the connection\n" - "save [persistent|temporary] :: save the connection\n" - "activate [] [/|] :: activate the connection\n" - "back :: go one level up (back)\n" - "help/? [] :: print this help\n" - "nmcli :: nmcli configuration\n" - "quit :: exit nmcli\n")); - g_print("------------------------------------------------------------------------------\n"); + nmc_print(_("---[ Main menu ]---\n" + "goto [ | ] :: go to a setting or property\n" + "remove [.] | :: remove setting or reset property value\n" + "set [. ] :: set property value\n" + "describe [.] :: describe property\n" + "print [all | [.]] :: print the connection\n" + "verify [all | fix] :: verify the connection\n" + "save [persistent|temporary] :: save the connection\n" + "activate [] [/|] :: activate the connection\n" + "back :: go one level up (back)\n" + "help/? [] :: print this help\n" + "nmcli :: nmcli configuration\n" + "quit :: exit nmcli\n")); + nmc_print("------------------------------------------------------------------------------\n"); } static void @@ -7085,14 +7090,15 @@ editor_main_help(const char *command) switch (cmd) { case NMC_EDITOR_MAIN_CMD_GOTO: - g_print(_("goto [.] | :: enter setting/property for editing\n\n" - "This command enters into a setting or property for editing it.\n\n" - "Examples: nmcli> goto connection\n" - " nmcli connection> goto secondaries\n" - " nmcli> goto ipv4.addresses\n")); + nmc_print( + _("goto [.] | :: enter setting/property for editing\n\n" + "This command enters into a setting or property for editing it.\n\n" + "Examples: nmcli> goto connection\n" + " nmcli connection> goto secondaries\n" + " nmcli> goto ipv4.addresses\n")); break; case NMC_EDITOR_MAIN_CMD_REMOVE: - g_print( + nmc_print( _("remove [.] :: remove setting or reset property value\n\n" "This command removes an entire setting from the connection, or if a property\n" "is given, resets that property to the default value.\n\n" @@ -7100,27 +7106,27 @@ editor_main_help(const char *command) " nmcli> remove eth.mtu\n")); break; case NMC_EDITOR_MAIN_CMD_SET: - g_print(_("set [. ] :: set property value\n\n" - "This command sets property value.\n\n" - "Example: nmcli> set con.id My connection\n")); + nmc_print(_("set [. ] :: set property value\n\n" + "This command sets property value.\n\n" + "Example: nmcli> set con.id My connection\n")); break; case NMC_EDITOR_MAIN_CMD_ADD: - g_print(_("add [. ] :: add property value\n\n" - "This command appends property value.\n\n" - "Example: nmcli> add ipv4.addresses 192.168.1.1/24\n")); + nmc_print(_("add [. ] :: add property value\n\n" + "This command appends property value.\n\n" + "Example: nmcli> add ipv4.addresses 192.168.1.1/24\n")); break; case NMC_EDITOR_MAIN_CMD_DESCRIBE: - g_print(_("describe [.] :: describe property\n\n" - "Shows property description. You can consult nm-settings(5) " - "manual page to see all NM settings and properties.\n")); + nmc_print(_("describe [.] :: describe property\n\n" + "Shows property description. You can consult nm-settings(5) " + "manual page to see all NM settings and properties.\n")); break; case NMC_EDITOR_MAIN_CMD_PRINT: - g_print(_("print [all] :: print setting or connection values\n\n" - "Shows current property or the whole connection.\n\n" - "Example: nmcli ipv4> print all\n")); + nmc_print(_("print [all] :: print setting or connection values\n\n" + "Shows current property or the whole connection.\n\n" + "Example: nmcli ipv4> print all\n")); break; case NMC_EDITOR_MAIN_CMD_VERIFY: - g_print( + nmc_print( _("verify [all | fix] :: verify setting or connection validity\n\n" "Verifies whether the setting or connection is valid and can be saved later.\n" "It indicates invalid values on error. Some errors may be fixed automatically\n" @@ -7130,7 +7136,7 @@ editor_main_help(const char *command) " nmcli bond> verify\n")); break; case NMC_EDITOR_MAIN_CMD_SAVE: - g_print( + nmc_print( _("save [persistent|temporary] :: save the connection\n\n" "Sends the connection profile to NetworkManager that either will save it\n" "persistently, or will only keep it in memory. 'save' without an argument\n" @@ -7142,48 +7148,48 @@ editor_main_help(const char *command) "profile must be deleted.\n")); break; case NMC_EDITOR_MAIN_CMD_ACTIVATE: - g_print(_("activate [] [/|] :: activate the connection\n\n" - "Activates the connection.\n\n" - "Available options:\n" - " - device the connection will be activated on\n" - "/| - AP (Wi-Fi) or NSP (WiMAX) (prepend with / when is " - "not specified)\n")); + nmc_print(_("activate [] [/|] :: activate the connection\n\n" + "Activates the connection.\n\n" + "Available options:\n" + " - device the connection will be activated on\n" + "/| - AP (Wi-Fi) or NSP (WiMAX) (prepend with / when is " + "not specified)\n")); break; case NMC_EDITOR_MAIN_CMD_BACK: - g_print(_("back :: go to upper menu level\n\n")); + nmc_print(_("back :: go to upper menu level\n\n")); break; case NMC_EDITOR_MAIN_CMD_HELP: - g_print(_("help/? [] :: help for the nmcli commands\n\n")); + nmc_print(_("help/? [] :: help for the nmcli commands\n\n")); break; case NMC_EDITOR_MAIN_CMD_NMCLI: - g_print(_("nmcli [ ] :: nmcli configuration\n\n" - "Configures nmcli. The following options are available:\n" - "status-line yes | no [default: no]\n" - "save-confirmation yes | no [default: yes]\n" - "show-secrets yes | no [default: no]\n" - "prompt-color | <0-8> [default: 0]\n" - "%s" /* color table description */ - "\n" - "Examples: nmcli> nmcli status-line yes\n" - " nmcli> nmcli save-confirmation no\n" - " nmcli> nmcli prompt-color 3\n"), - " 0 = normal\n" - " 1 = \33[30mblack\33[0m\n" - " 2 = \33[31mred\33[0m\n" - " 3 = \33[32mgreen\33[0m\n" - " 4 = \33[33myellow\33[0m\n" - " 5 = \33[34mblue\33[0m\n" - " 6 = \33[35mmagenta\33[0m\n" - " 7 = \33[36mcyan\33[0m\n" - " 8 = \33[37mwhite\33[0m\n"); + nmc_print(_("nmcli [ ] :: nmcli configuration\n\n" + "Configures nmcli. The following options are available:\n" + "status-line yes | no [default: no]\n" + "save-confirmation yes | no [default: yes]\n" + "show-secrets yes | no [default: no]\n" + "prompt-color | <0-8> [default: 0]\n" + "%s" /* color table description */ + "\n" + "Examples: nmcli> nmcli status-line yes\n" + " nmcli> nmcli save-confirmation no\n" + " nmcli> nmcli prompt-color 3\n"), + " 0 = normal\n" + " 1 = \33[30mblack\33[0m\n" + " 2 = \33[31mred\33[0m\n" + " 3 = \33[32mgreen\33[0m\n" + " 4 = \33[33myellow\33[0m\n" + " 5 = \33[34mblue\33[0m\n" + " 6 = \33[35mmagenta\33[0m\n" + " 7 = \33[36mcyan\33[0m\n" + " 8 = \33[37mwhite\33[0m\n"); break; case NMC_EDITOR_MAIN_CMD_QUIT: - g_print(_("quit :: exit nmcli\n\n" - "This command exits nmcli. When the connection being edited " - "is not saved, the user is asked to confirm the action.\n")); + nmc_print(_("quit :: exit nmcli\n\n" + "This command exits nmcli. When the connection being edited " + "is not saved, the user is asked to confirm the action.\n")); break; default: - g_print(_("Unknown command: '%s'\n"), command); + nmc_print(_("Unknown command: '%s'\n"), command); break; } } @@ -7244,21 +7250,21 @@ fail: static void editor_sub_help(void) { - g_print("------------------------------------------------------------------------------\n"); + nmc_print("------------------------------------------------------------------------------\n"); /* TRANSLATORS: do not translate command names and keywords before :: * However, you should translate terms enclosed in <>. */ - g_print(_("---[ Property menu ]---\n" - "set [] :: set new value\n" - "add [] :: add new option to the property\n" - "change :: change current value\n" - "remove [ | + + reapply + + The connection was reapplied on the device. + + The environment contains more information about the interface and the connection. -- cgit v1.2.1 From 226848ea62ebcb336fceabf8d22d6fa42d2a10c5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 9 Feb 2023 11:59:43 +0100 Subject: logging/trivial: add code comment about logging " [timestamp]" --- src/libnm-log-core/nm-logging.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libnm-log-core/nm-logging.c b/src/libnm-log-core/nm-logging.c index 5cce508daf..f53c27c184 100644 --- a/src/libnm-log-core/nm-logging.c +++ b/src/libnm-log-core/nm-logging.c @@ -707,6 +707,20 @@ _nm_log_impl(const char *file, msg = nm_vsprintf_buf_or_alloc(fmt, fmt, msg_stack, &msg_heap, NULL); + /* We always print the level and the timestamp. + * + * Timestamps are very useful for understanding logfiles. While journalctl + * might record the timestamp, it is not present in plain `journalctl` output. + * Users who report a bug would simply send us the `journalctl` output and + * requesting an output with timestamps (even if it's stored somewhere inside + * journald) is not workable. + * + * We print the level, because this too, it's to quickly identify the severity + * of a message. + * + * We also do this for all messages (for all levels), because then the logging + * lines are formatted and aligned in a consistent way, which aids reading the + * logs. */ #define MESSAGE_FMT "%s%-7s [%ld.%04ld] %s" #define MESSAGE_ARG(prefix, tv, msg) \ prefix, nm_log_level_desc[level].level_str, (tv).tv_sec, ((tv).tv_usec / 100), (msg) -- cgit v1.2.1 From 479e4dbfeeb524b0e64f1be231fe831169514c6a Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 31 Jan 2023 01:50:46 +0100 Subject: NEWS: update https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1521 --- NEWS | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/NEWS b/NEWS index efd5b74c20..eedbee770c 100644 --- a/NEWS +++ b/NEWS @@ -8,39 +8,36 @@ subject to change and not guaranteed to be compatible with the later release. USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! -* bond: add "balance-slb" option which implements source load balancing - with "balance-xor" mode and "vlan-srcmac" xmit_hash_policy. In this - mode, NetworkManager configures nftables to prevent loops in the - switch. -* dns: support specifying DNS-over-TLS server name (SNI) for static - name servers. Only works with systemd-resolved plugin. -* loopback: add support of loopback interface and a new connection type - "loopback". On D-Bus, the loopback interface now has the - "org.freedesktop.NetworkManager.Device.Loopback" interface instead of - "org.freedesktop.NetworkManager.Device.Generic". Loopback handling is special - in that when the NetworkManager profile is deactivated, the interfaces will - still be up and configured with a 127.0.0.1 address. -* Add support of IPv4 ECMP routes. The ECMP routes will get merged +* Added support for source load balancing for Ethernet Bonds. +* Allow specifying vhost name (SNI) for a manually DNS-over-TLS server. + Only works with systemd-resolved plugin. +* Connections can now be activated on a loopback interface. +* Added support of IPv4 ECMP routes. The ECMP routes will get merged automatically but the user need to configure them as single-hop routes specifying a valid weight. -* Add support of VTI and VTI6 ip-tunnels. Add a new property "ip-tunnel.fwmark". -* vlan: add support of "vlan.protocol" property to set 802.1Q (default) or - 802.1ad. -* firewall: pass "--wait 2" to iptables invocations to handle races with concurrent +* Added support of VTI and VTI6 ip-tunnels along with a new property, + "ip-tunnel.fwmark". +* VLAN can now support 802.1ad tagging instead of 802.1Q. +* Invocations of iptables now use "--wait 2" to handle races with concurrent calls. This fixes misbehavior with IPv4 shared mode. -* DHCP: expose used DHCPV4 client-id and DHCPv6 DUID in lease information. -* VPN: support new "ipv[46].auto-route-ext-gw" option to suppress adding direct - route to external VPN gateway. -* ovs: add support of "ovs-dpdk.n-rxq-desc", "ovs-dpdk.n-txq-desc", - "ovs-interface.ofport-request" and "ovs-port.trunks" properties. -* Add support of "other_config" for OVS bridge, port or interface. This +* The DHCP client-id and DHCPv6 DUID are now exposed along with the lease + information. +* Optionally suppress adding direct route to an external VPN gateway + with the new "ipv[46].auto-route-ext-gw" property. +* Open vSwitch support gained new properties: "ovs-dpdk.n-rxq-desc", + "ovs-dpdk.n-txq-desc", "ovs-interface.ofport-request" and + "ovs-port.trunks". +* Added support of "other_config" for OVS bridge, port or interface. This property is not supported by nmcli. * nmtui now supports editing Wi-Fi WPA-Enterprise, Ethernet with 802.1X authentication and MACsec connection profiles. -* nmcli: allow changing "connection.uuid" and "connection.type" - in offline mode and setting the UUID when creating a connection. -* nmcli: accept abbreviations for the UUID with the connection selector +* nmcli now allows changing "connection.uuid" and "connection.type" + properties in offline mode and setting the UUID when creating a + connection. +* nmcli now accepts abbreviations for the UUID with the connection selector in `nmcli connection $operator uuid $uuid`. +* DHCPv6 leases are now declined when addresses fail DAD. +* Documentation improvements. * Many internal improvements and bug fixes. The following changes were backported to 1.40.x releases between 1.40.0 -- cgit v1.2.1 From 46f39829d9bb8dd21b553a833e347efa79cbece3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 9 Feb 2023 19:22:37 +0100 Subject: contrib: accept ssh:// git url for origin in "nm-setup-git.sh" --- contrib/scripts/nm-setup-git.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/scripts/nm-setup-git.sh b/contrib/scripts/nm-setup-git.sh index 392e3f36cc..b735a9fa1c 100755 --- a/contrib/scripts/nm-setup-git.sh +++ b/contrib/scripts/nm-setup-git.sh @@ -96,7 +96,8 @@ done case "$(git config --get-all remote.origin.url)" in "https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git"| \ - "git@gitlab.freedesktop.org:NetworkManager/NetworkManager.git") + "git@gitlab.freedesktop.org:NetworkManager/NetworkManager.git"| \ + "ssh://git@gitlab.freedesktop.org/NetworkManager/NetworkManager") ;; *) die "unexpected git repository. Expected that remote.origin.url is set to \"https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git\"" -- cgit v1.2.1 From c74c16ee21165ca27e982eecfba8d188ff1289cb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 10 Feb 2023 09:37:21 +0100 Subject: NEWS: update --- NEWS | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index eedbee770c..3d692f4668 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ ============================================= -NetworkManager-1.42 -Overview of changes since NetworkManager-1.40 +NetworkManager-1.44 +Overview of changes since NetworkManager-1.42 ============================================= This is a snapshot of NetworkManager development. The API is @@ -8,6 +8,11 @@ subject to change and not guaranteed to be compatible with the later release. USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! +============================================= +NetworkManager-1.42 +Overview of changes since NetworkManager-1.40 +============================================= + * Added support for source load balancing for Ethernet Bonds. * Allow specifying vhost name (SNI) for a manually DNS-over-TLS server. Only works with systemd-resolved plugin. @@ -15,6 +20,7 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! * Added support of IPv4 ECMP routes. The ECMP routes will get merged automatically but the user need to configure them as single-hop routes specifying a valid weight. +* Add new "reapply" dispatcher event. * Added support of VTI and VTI6 ip-tunnels along with a new property, "ip-tunnel.fwmark". * VLAN can now support 802.1ad tagging instead of 802.1Q. -- cgit v1.2.1