mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-11 08:20:38 +01:00
Compare commits
240 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22f4e74942 | ||
|
|
57bc396c12 | ||
|
|
0e2b679afb | ||
|
|
b6bd9cee87 | ||
|
|
2fbaca1cbc | ||
|
|
1252f8dc7e | ||
|
|
7ee50b687a | ||
|
|
d2f98a1669 | ||
|
|
7c8f343f2c | ||
|
|
b9725dab73 | ||
|
|
f346fcf977 | ||
|
|
ec1522fa8c | ||
|
|
0a1503f052 | ||
|
|
47c1b04f9e | ||
|
|
9ff530c322 | ||
|
|
121034d655 | ||
|
|
cdd38f7cdf | ||
|
|
c6b6c7164b | ||
|
|
ff1d435096 | ||
|
|
1a2fec62f0 | ||
|
|
fddda02825 | ||
|
|
2d30b71dd4 | ||
|
|
7651ef0386 | ||
|
|
8236c1c16a | ||
|
|
818cf77cb5 | ||
|
|
98256be220 | ||
|
|
d564a0c3f9 | ||
|
|
a924826e2c | ||
|
|
04f7ca5029 | ||
|
|
de6d9930b9 | ||
|
|
30ca65ab88 | ||
|
|
bf80a9019e | ||
|
|
6b37d612fd | ||
|
|
dbeb7fa0f6 | ||
|
|
b7d9625ae1 | ||
|
|
cb51c4475a | ||
|
|
756e612858 | ||
|
|
03a3a449f6 | ||
|
|
926795f11a | ||
|
|
e4ca177be2 | ||
|
|
20f975abe3 | ||
|
|
024360bffa | ||
|
|
db0825a110 | ||
|
|
eff8330b57 | ||
|
|
128b49fe21 | ||
|
|
2e2b4946ea | ||
|
|
0bfb8fa89d | ||
|
|
2aaf88375e | ||
|
|
29c8bbe21a | ||
|
|
ad78bd8570 | ||
|
|
54a4b42c05 | ||
|
|
8c93d0bdff | ||
|
|
4fcebeaec0 | ||
|
|
40f19ad674 | ||
|
|
f70b37357a | ||
|
|
30a5416a54 | ||
|
|
b5410bb24a | ||
|
|
a4e30ee849 | ||
|
|
112190d09a | ||
|
|
d7edc806b6 | ||
|
|
f9b2083394 | ||
|
|
e2cdd5c4dc | ||
|
|
c86d234516 | ||
|
|
d1598a10ec | ||
|
|
f00030d79a | ||
|
|
72cb5839fc | ||
|
|
5c041cb891 | ||
|
|
6d44237ed3 | ||
|
|
fbfb5afec0 | ||
|
|
aeeb52ab66 | ||
|
|
de42acd3fd | ||
|
|
f2ced1e115 | ||
|
|
cb09291635 | ||
|
|
0aab6ef1c0 | ||
|
|
a01000d811 | ||
|
|
b4fc8550f5 | ||
|
|
746a5902ad | ||
|
|
6dc51ddf01 | ||
|
|
a3267aaf7b | ||
|
|
871da67916 | ||
|
|
f849163e82 | ||
|
|
36275bc51c | ||
|
|
c0fe80ff87 | ||
|
|
9a3462af99 | ||
|
|
5666407f15 | ||
|
|
3a3a8ea59d | ||
|
|
d56cd26aea | ||
|
|
e311df0c75 | ||
|
|
c32f0fb71f | ||
|
|
2c896713b8 | ||
|
|
29eb48d7f9 | ||
|
|
0731d8f3e0 | ||
|
|
2d41711033 | ||
|
|
616e18e61b | ||
|
|
5cbd79a9ba | ||
|
|
3699558106 | ||
|
|
2888d4c800 | ||
|
|
6ac6d4f14e | ||
|
|
6ec321d21b | ||
|
|
bd67cefaaa | ||
|
|
13cf12dd6e | ||
|
|
193e37b410 | ||
|
|
c93ce65467 | ||
|
|
6f29305575 | ||
|
|
8414afd9ae | ||
|
|
8c83367a49 | ||
|
|
183d68dcbe | ||
|
|
173dc154a0 | ||
|
|
e99a6452be | ||
|
|
232da41572 | ||
|
|
213e9e33da | ||
|
|
3af6761655 | ||
|
|
6273f0afba | ||
|
|
d1351f1219 | ||
|
|
ade4de22f3 | ||
|
|
f9cd6e20a5 | ||
|
|
815a795203 | ||
|
|
b5f534d31d | ||
|
|
75c423f4c8 | ||
|
|
f11fb6dafc | ||
|
|
ee1c91bbc8 | ||
|
|
4409c3d99a | ||
|
|
76c18081d6 | ||
|
|
f0e77a4354 | ||
|
|
ebb86ed2dd | ||
|
|
fa9c00b595 | ||
|
|
dd3758dd80 | ||
|
|
83317fed4e | ||
|
|
afae4ddaf4 | ||
|
|
5150a666cd | ||
|
|
c228427ae2 | ||
|
|
87ee398db3 | ||
|
|
7944f80f04 | ||
|
|
5b6776089d | ||
|
|
4567c8e40f | ||
|
|
85ba4d7c53 | ||
|
|
8f9bc6af94 | ||
|
|
63e9b804e9 | ||
|
|
e10fac49bb | ||
|
|
574411b8a5 | ||
|
|
e776f80197 | ||
|
|
a550828f76 | ||
|
|
cd223e6696 | ||
|
|
c254c4df21 | ||
|
|
748be9a3e7 | ||
|
|
9199c56f50 | ||
|
|
42e9cd1856 | ||
|
|
499427a84e | ||
|
|
c39b967a47 | ||
|
|
7879acea8f | ||
|
|
bb0a26e906 | ||
|
|
5763b9b4de | ||
|
|
ccc5f78fc4 | ||
|
|
5838c38b84 | ||
|
|
57b6c1c5b7 | ||
|
|
221da3f8c0 | ||
|
|
4cf6f0f9a8 | ||
|
|
6d952902b9 | ||
|
|
5445ad2287 | ||
|
|
9ebc8aa480 | ||
|
|
7cae64ac02 | ||
|
|
eb784c3f27 | ||
|
|
c4b39914c4 | ||
|
|
99514da050 | ||
|
|
4ce317a261 | ||
|
|
9f4261168d | ||
|
|
d975389bcd | ||
|
|
e422b1c3d9 | ||
|
|
19ac54fbd6 | ||
|
|
6b062dfeb5 | ||
|
|
de8d74aa08 | ||
|
|
90ea2ddb90 | ||
|
|
b416156b10 | ||
|
|
9febe04761 | ||
|
|
71b9d83349 | ||
|
|
664ba417c7 | ||
|
|
a31a644f8b | ||
|
|
a45163b131 | ||
|
|
de1fcdcc72 | ||
|
|
a2d147366c | ||
|
|
427a7cf257 | ||
|
|
3a4e18e302 | ||
|
|
8e0825f9cd | ||
|
|
df8288de7f | ||
|
|
118475d571 | ||
|
|
599cc1ed1d | ||
|
|
1756ec54e3 | ||
|
|
1a52bbe7c9 | ||
|
|
57eb4a5bc6 | ||
|
|
10db4baeb6 | ||
|
|
8d8edda3f4 | ||
|
|
e85cc46d0b | ||
|
|
a1928b4459 | ||
|
|
9703305122 | ||
|
|
932b85f7e7 | ||
|
|
4e26403c4a | ||
|
|
bd2484d1a9 | ||
|
|
41e28b900f | ||
|
|
6c1e04fc61 | ||
|
|
2739850b78 | ||
|
|
d8f143f601 | ||
|
|
39143f8bdd | ||
|
|
0b75d905e5 | ||
|
|
13bfa44ceb | ||
|
|
dad4da06b1 | ||
|
|
0b61924048 | ||
|
|
d40e88fd02 | ||
|
|
8e72e6b4fb | ||
|
|
9e70f31c8c | ||
|
|
ac427b25fb | ||
|
|
754b87e1c4 | ||
|
|
5f6beb0e57 | ||
|
|
487ca30256 | ||
|
|
a07961cfbe | ||
|
|
4e7e159224 | ||
|
|
ae134ca9f4 | ||
|
|
55f96057c6 | ||
|
|
de0a37b248 | ||
|
|
7315e7e0ee | ||
|
|
bcb96a1b19 | ||
|
|
561fff3c8d | ||
|
|
a9f2c15663 | ||
|
|
8a9b17071b | ||
|
|
c1519bd514 | ||
|
|
8b5a61458b | ||
|
|
9e01443b14 | ||
|
|
78519589b9 | ||
|
|
771f86105e | ||
|
|
b3f9f52505 | ||
|
|
b41a5ec2d4 | ||
|
|
636fb5ef24 | ||
|
|
d006d61aa1 | ||
|
|
6e2de1d2b3 | ||
|
|
4afa00874f | ||
|
|
3ce1da1fd2 | ||
|
|
8caa781270 | ||
|
|
2b03057de0 | ||
|
|
3b10b88290 | ||
|
|
d687768c61 | ||
|
|
239b0fbbc9 |
192 changed files with 46869 additions and 18420 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -81,7 +81,6 @@ test-*.trs
|
||||||
/data/org.freedesktop.NetworkManager.service
|
/data/org.freedesktop.NetworkManager.service
|
||||||
/data/server.conf
|
/data/server.conf
|
||||||
/data/org.freedesktop.NetworkManager.policy
|
/data/org.freedesktop.NetworkManager.policy
|
||||||
/data/org.freedesktop.NetworkManager.policy.in
|
|
||||||
/data/nm-sudo.service
|
/data/nm-sudo.service
|
||||||
/data/nm-priv-helper.service
|
/data/nm-priv-helper.service
|
||||||
/data/NetworkManager-config-initrd.service
|
/data/NetworkManager-config-initrd.service
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,11 @@ variables:
|
||||||
#
|
#
|
||||||
# This is done by running `ci-fairy generate-template` and possibly bumping
|
# This is done by running `ci-fairy generate-template` and possibly bumping
|
||||||
# ".default_tag".
|
# ".default_tag".
|
||||||
ALPINE_TAG: 'tag-0c3a6f855fb8'
|
ALPINE_TAG: 'tag-8e4bbc59695b'
|
||||||
CENTOS_TAG: 'tag-c1c23df75dda'
|
CENTOS_TAG: 'tag-caf6673db1a7'
|
||||||
DEBIAN_TAG: 'tag-d4bf5db9e214'
|
DEBIAN_TAG: 'tag-e394e8e726e1'
|
||||||
FEDORA_TAG: 'tag-c1c23df75dda'
|
FEDORA_TAG: 'tag-caf6673db1a7'
|
||||||
UBUNTU_TAG: 'tag-d4bf5db9e214'
|
UBUNTU_TAG: 'tag-e394e8e726e1'
|
||||||
|
|
||||||
ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh'
|
ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh'
|
||||||
CENTOS_EXEC: 'bash .gitlab-ci/fedora-install.sh'
|
CENTOS_EXEC: 'bash .gitlab-ci/fedora-install.sh'
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ Please read
|
||||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/CONTRIBUTING.md
|
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/CONTRIBUTING.md
|
||||||
before opening the merge request. In particular, check that:
|
before opening the merge request. In particular, check that:
|
||||||
|
|
||||||
- [ ] the subject for all commits is concise and explicative
|
- [ ] The subject for all commits is concise, explanatory, and includes a prefix indicating the area of code changed (e.g., "nmcli: ", "core: ")
|
||||||
- [ ] the message for all commits explains the reason for the change
|
- [ ] The message for all commits explains the reason for the change
|
||||||
- [ ] the source is properly formatted
|
- [ ] The source is properly formatted
|
||||||
- [ ] any relevant documentation is up to date
|
- [ ] Any relevant documentation is up to date
|
||||||
- [ ] you have added unit tests if applicable
|
- [ ] You have added unit tests if applicable
|
||||||
- [ ] the NEWS file is updated when the change deserves to be mentioned, for example for new features, behavior changes, API deprecations, etc.
|
- [ ] The NEWS file is updated when the change deserves to be mentioned, for example for new features, behavior changes, API deprecations, etc.
|
||||||
|
|
|
||||||
61
NEWS
61
NEWS
|
|
@ -1,12 +1,64 @@
|
||||||
=============================================
|
=============================================
|
||||||
NetworkManager-1.56
|
NetworkManager-1.58
|
||||||
Overview of changes since NetworkManager-1.54
|
Overview of changes since NetworkManager-1.56
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
|
This is a snapshot of NetworkManager development. The API is
|
||||||
|
subject to change and not guaranteed to be compatible with
|
||||||
|
the later release.
|
||||||
|
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||||
|
|
||||||
* Unify the versioning to use everywhere the scheme with the -rcX or -dev
|
* Unify the versioning to use everywhere the scheme with the -rcX or -dev
|
||||||
suffixes when appropriate. This affects, for example, the URL and filename
|
suffixes when appropriate. This affects, for example, the URL and filename
|
||||||
of the release tarball and the version reported by nmcli and the daemon.
|
of the release tarball and the version reported by nmcli and the daemon.
|
||||||
As an exception, the C API will continue to use the 90+ scheme for RC versions.
|
As an exception, the C API will continue to use the 90+ scheme for RC versions.
|
||||||
|
* Restrict the connectivity check to use the DNS servers defined on the
|
||||||
|
same link. If the link has no DNS servers, the connectivity check will
|
||||||
|
use any servers available in the system.
|
||||||
|
* Install the systemd units in the initramfs using a systemd generator.
|
||||||
|
* A new "check-connectivity" configuration option is available to disable the
|
||||||
|
connectivity check for selected interfaces.
|
||||||
|
* Remove the modify_system build option that allowed setting up the
|
||||||
|
polkit permissions to allow non-admin users to create system-wide
|
||||||
|
connection. That configuration is discouraged because it can be used
|
||||||
|
to bypass filesystem permissions.
|
||||||
|
* For private connections (the ones that specify a user in the
|
||||||
|
"connection.permissions" property), verify that the user can access
|
||||||
|
the 802.1X certificates and keys set in the connection.
|
||||||
|
* Introduce a libnm function that can be used by VPN plugins to check
|
||||||
|
user permissions on certificate and keys.
|
||||||
|
* The support for Wireless Extensions is deprecated and will be
|
||||||
|
removed in a future release. Wireless Extensions are now disabled by
|
||||||
|
default.
|
||||||
|
* Use an internal implementation of the ping functionality when the
|
||||||
|
"connection.gateway-ping-timeout" or "connection.ip-ping-addresses"
|
||||||
|
properties are set, instead of relying on the "ping" tool.
|
||||||
|
* The powersave property now functions with the iwd backend.
|
||||||
|
* The "band" property of Wi-fi connections now accepts the "6GHz"
|
||||||
|
value.
|
||||||
|
* Show the Wi-Fi band of APs in the scan results from nmcli.
|
||||||
|
* New <Select...> button in nmtui that allows users to chose from list of
|
||||||
|
available devices when creating connection profiles for physical interfaces
|
||||||
|
(Ethernet, Wi-Fi, etc.).
|
||||||
|
* Add support for CLAT (464XLAT) using a BPF program.
|
||||||
|
* Change the default value of the ipv4.dhcp-ipv6-only-preferred property
|
||||||
|
to a new value "auto" which automatically enables the option when CLAT
|
||||||
|
is enabled ("yes" or "auto") in the connection profile.
|
||||||
|
* WIFI connections using wpa-psk respect the setting connection.auth-retry
|
||||||
|
and only prompt for new secrets during the last authentication attempt before
|
||||||
|
failing.
|
||||||
|
* Add support for GENEVE interface.
|
||||||
|
* The DHCPv4 internal client now ignores option 3 (Router) if the lease
|
||||||
|
contains option 121 (Classless Static Route), as recommended by RFC 3442.
|
||||||
|
* Allow persisting the managed state across reboots from nmcli and the D-Bus API.
|
||||||
|
* Allow changing the device's administrative state in the kernel at the same
|
||||||
|
time as a change to the managed state from nmcli and the D-Bus API.
|
||||||
|
|
||||||
|
=============================================
|
||||||
|
NetworkManager-1.56
|
||||||
|
Overview of changes since NetworkManager-1.54
|
||||||
|
=============================================
|
||||||
|
|
||||||
* nmcli now supports viewing and managing WireGuard peers.
|
* nmcli now supports viewing and managing WireGuard peers.
|
||||||
* Support reapplying the "sriov.vfs" property as long as
|
* Support reapplying the "sriov.vfs" property as long as
|
||||||
"sriov.total-vfs" is not changed.
|
"sriov.total-vfs" is not changed.
|
||||||
|
|
@ -35,11 +87,6 @@ Overview of changes since NetworkManager-1.54
|
||||||
for eBPF is now detected at run time.
|
for eBPF is now detected at run time.
|
||||||
* Add new MPTCP 'laminar' endpoint type, and set it by default alongside
|
* Add new MPTCP 'laminar' endpoint type, and set it by default alongside
|
||||||
the 'subflow' one.
|
the 'subflow' one.
|
||||||
* For private connections (the ones that specify a user in the
|
|
||||||
"connection.permissions" property), verify that the user can access
|
|
||||||
the 802.1X certificates and keys set in the connection.
|
|
||||||
* Introduce a libnm function that can be used by VPN plugins to check
|
|
||||||
user permissions on certificate and keys.
|
|
||||||
|
|
||||||
=============================================
|
=============================================
|
||||||
NetworkManager-1.54
|
NetworkManager-1.54
|
||||||
|
|
|
||||||
|
|
@ -294,3 +294,6 @@
|
||||||
|
|
||||||
/* Define to 1 if dlvsym() is available */
|
/* Define to 1 if dlvsym() is available */
|
||||||
#mesondefine HAVE_DLVSYM
|
#mesondefine HAVE_DLVSYM
|
||||||
|
|
||||||
|
/* Define to 1 if you want CLAT support. */
|
||||||
|
#mesondefine HAVE_CLAT
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ apk add \
|
||||||
'alpine-sdk' \
|
'alpine-sdk' \
|
||||||
'autoconf' \
|
'autoconf' \
|
||||||
'bash' \
|
'bash' \
|
||||||
|
'bpftool' \
|
||||||
'clang' \
|
'clang' \
|
||||||
'curl-dev' \
|
'curl-dev' \
|
||||||
'dbus' \
|
'dbus' \
|
||||||
|
|
@ -23,6 +24,7 @@ apk add \
|
||||||
'iproute2' \
|
'iproute2' \
|
||||||
'iptables' \
|
'iptables' \
|
||||||
'jansson-dev' \
|
'jansson-dev' \
|
||||||
|
'libbpf-dev' \
|
||||||
'libgudev-dev' \
|
'libgudev-dev' \
|
||||||
'libndp-dev' \
|
'libndp-dev' \
|
||||||
'libnvme-dev' \
|
'libnvme-dev' \
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ install_ignore_missing() {
|
||||||
|
|
||||||
install \
|
install \
|
||||||
\
|
\
|
||||||
|
bpftool \
|
||||||
clang \
|
clang \
|
||||||
dbus \
|
dbus \
|
||||||
dbus-x11 \
|
dbus-x11 \
|
||||||
|
|
@ -43,6 +44,7 @@ install \
|
||||||
iproute2 \
|
iproute2 \
|
||||||
iptables \
|
iptables \
|
||||||
libaudit-dev \
|
libaudit-dev \
|
||||||
|
libbpf-dev \
|
||||||
libcurl4-gnutls-dev \
|
libcurl4-gnutls-dev \
|
||||||
libdbus-1-dev \
|
libdbus-1-dev \
|
||||||
libgirepository1.0-dev \
|
libgirepository1.0-dev \
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ install \
|
||||||
ModemManager-glib-devel \
|
ModemManager-glib-devel \
|
||||||
audit-libs-devel \
|
audit-libs-devel \
|
||||||
bluez-libs-devel \
|
bluez-libs-devel \
|
||||||
|
bpftool \
|
||||||
clang \
|
clang \
|
||||||
dbus-devel \
|
dbus-devel \
|
||||||
dbus-x11 \
|
dbus-x11 \
|
||||||
|
|
@ -64,6 +65,7 @@ install \
|
||||||
iptables \
|
iptables \
|
||||||
jansson-devel \
|
jansson-devel \
|
||||||
jq \
|
jq \
|
||||||
|
libbpf-devel \
|
||||||
libcurl-devel \
|
libcurl-devel \
|
||||||
libndp-devel \
|
libndp-devel \
|
||||||
libnvme-devel \
|
libnvme-devel \
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,17 @@ Release: __RELEASE_VERSION__%{?dist}
|
||||||
%else
|
%else
|
||||||
%bcond_without iwd
|
%bcond_without iwd
|
||||||
%endif
|
%endif
|
||||||
|
%if 0%{?fedora} <= 43 || 0%{?rhel} <= 10
|
||||||
|
%bcond_without polkit_noauth_group
|
||||||
|
%else
|
||||||
|
%bcond_with polkit_noauth_group
|
||||||
|
%endif
|
||||||
|
%ifarch %{ix86}
|
||||||
|
# there is no bpftool in i686
|
||||||
|
%bcond_with clat
|
||||||
|
%else
|
||||||
|
%bcond_without clat
|
||||||
|
%endif
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
%global dbus_version 1.9.18
|
%global dbus_version 1.9.18
|
||||||
|
|
@ -178,7 +188,9 @@ Requires: dbus >= %{dbus_version}
|
||||||
Requires: glib2 >= %{glib2_version}
|
Requires: glib2 >= %{glib2_version}
|
||||||
Requires: %{name}-libnm%{?_isa} = %{epoch}:%{version}-%{release}
|
Requires: %{name}-libnm%{?_isa} = %{epoch}:%{version}-%{release}
|
||||||
|
|
||||||
Recommends: iputils
|
%if %{with clat}
|
||||||
|
Requires: libbpf
|
||||||
|
%endif
|
||||||
|
|
||||||
%if 0%{?rhel} == 8
|
%if 0%{?rhel} == 8
|
||||||
# Older libndp versions use select() (rh#1933041). On well known distros,
|
# Older libndp versions use select() (rh#1933041). On well known distros,
|
||||||
|
|
@ -227,6 +239,7 @@ Conflicts: NetworkManager-dispatcher-routing-rules <= 1:1.47.5-3
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
|
BuildRequires: clang
|
||||||
BuildRequires: pkgconfig
|
BuildRequires: pkgconfig
|
||||||
BuildRequires: meson
|
BuildRequires: meson
|
||||||
BuildRequires: gettext-devel >= 0.19.8
|
BuildRequires: gettext-devel >= 0.19.8
|
||||||
|
|
@ -281,6 +294,10 @@ BuildRequires: firewalld-filesystem
|
||||||
BuildRequires: iproute
|
BuildRequires: iproute
|
||||||
BuildRequires: iproute-tc
|
BuildRequires: iproute-tc
|
||||||
BuildRequires: libnvme-devel >= 1.5
|
BuildRequires: libnvme-devel >= 1.5
|
||||||
|
%if %{with clat}
|
||||||
|
BuildRequires: libbpf-devel
|
||||||
|
BuildRequires: bpftool
|
||||||
|
%endif
|
||||||
|
|
||||||
Provides: %{name}-dispatcher%{?_isa} = %{epoch}:%{version}-%{release}
|
Provides: %{name}-dispatcher%{?_isa} = %{epoch}:%{version}-%{release}
|
||||||
|
|
||||||
|
|
@ -600,19 +617,20 @@ Preferably use nmcli instead.
|
||||||
%endif
|
%endif
|
||||||
%if %{with wifi}
|
%if %{with wifi}
|
||||||
-Dwifi=true \
|
-Dwifi=true \
|
||||||
%if 0%{?fedora}
|
|
||||||
-Dwext=true \
|
|
||||||
%else
|
|
||||||
-Dwext=false \
|
|
||||||
%endif
|
|
||||||
%else
|
%else
|
||||||
-Dwifi=false \
|
-Dwifi=false \
|
||||||
%endif
|
%endif
|
||||||
|
-Dwext=false \
|
||||||
%if %{with iwd}
|
%if %{with iwd}
|
||||||
-Diwd=true \
|
-Diwd=true \
|
||||||
%else
|
%else
|
||||||
-Diwd=false \
|
-Diwd=false \
|
||||||
%endif
|
%endif
|
||||||
|
%if %{with clat}
|
||||||
|
-Dclat=true \
|
||||||
|
%else
|
||||||
|
-Dclat=false \
|
||||||
|
%endif
|
||||||
%if %{with bluetooth}
|
%if %{with bluetooth}
|
||||||
-Dbluez5_dun=true \
|
-Dbluez5_dun=true \
|
||||||
%else
|
%else
|
||||||
|
|
@ -649,7 +667,9 @@ Preferably use nmcli instead.
|
||||||
-Dselinux=true \
|
-Dselinux=true \
|
||||||
-Dpolkit=true \
|
-Dpolkit=true \
|
||||||
-Dconfig_auth_polkit_default=true \
|
-Dconfig_auth_polkit_default=true \
|
||||||
-Dmodify_system=true \
|
%if %{with polkit_noauth_group}
|
||||||
|
-Dpolkit_noauth_group=wheel \
|
||||||
|
%endif
|
||||||
-Dconcheck=true \
|
-Dconcheck=true \
|
||||||
%if 0%{?fedora}
|
%if 0%{?fedora}
|
||||||
-Dlibpsl=true \
|
-Dlibpsl=true \
|
||||||
|
|
@ -659,6 +679,7 @@ Preferably use nmcli instead.
|
||||||
-Dsession_tracking=systemd \
|
-Dsession_tracking=systemd \
|
||||||
-Dsuspend_resume=systemd \
|
-Dsuspend_resume=systemd \
|
||||||
-Dsystemdsystemunitdir=%{_unitdir} \
|
-Dsystemdsystemunitdir=%{_unitdir} \
|
||||||
|
-Dsystemdsystemgeneratordir=%{_systemdgeneratordir} \
|
||||||
-Dsystem_ca_path=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \
|
-Dsystem_ca_path=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \
|
||||||
-Ddbus_conf_dir=%{dbus_sys_dir} \
|
-Ddbus_conf_dir=%{dbus_sys_dir} \
|
||||||
-Dtests=yes \
|
-Dtests=yes \
|
||||||
|
|
@ -731,6 +752,7 @@ rm -f %{buildroot}%{_libdir}/pppd/%{ppp_version}/*.la
|
||||||
rm -f %{buildroot}%{nmplugindir}/*.la
|
rm -f %{buildroot}%{nmplugindir}/*.la
|
||||||
|
|
||||||
# Don't use the *-initrd.service files yet, wait dracut to support them
|
# Don't use the *-initrd.service files yet, wait dracut to support them
|
||||||
|
rm -f %{buildroot}%{_systemdgeneratordir}/nm-initrd-generator.sh
|
||||||
rm -f %{buildroot}%{_unitdir}/NetworkManager-config-initrd.service
|
rm -f %{buildroot}%{_unitdir}/NetworkManager-config-initrd.service
|
||||||
rm -f %{buildroot}%{_unitdir}/NetworkManager-initrd.service
|
rm -f %{buildroot}%{_unitdir}/NetworkManager-initrd.service
|
||||||
rm -f %{buildroot}%{_unitdir}/NetworkManager-wait-online-initrd.service
|
rm -f %{buildroot}%{_unitdir}/NetworkManager-wait-online-initrd.service
|
||||||
|
|
@ -896,6 +918,9 @@ fi
|
||||||
%{_datadir}/dbus-1/system-services/org.freedesktop.nm_dispatcher.service
|
%{_datadir}/dbus-1/system-services/org.freedesktop.nm_dispatcher.service
|
||||||
%{_datadir}/dbus-1/system-services/org.freedesktop.nm_priv_helper.service
|
%{_datadir}/dbus-1/system-services/org.freedesktop.nm_priv_helper.service
|
||||||
%{_datadir}/polkit-1/actions/*.policy
|
%{_datadir}/polkit-1/actions/*.policy
|
||||||
|
%if %{with polkit_noauth_group}
|
||||||
|
%{_datadir}/polkit-1/rules.d/org.freedesktop.NetworkManager.rules
|
||||||
|
%endif
|
||||||
%{_prefix}/lib/udev/rules.d/*.rules
|
%{_prefix}/lib/udev/rules.d/*.rules
|
||||||
%{_prefix}/lib/firewalld/zones/nm-shared.xml
|
%{_prefix}/lib/firewalld/zones/nm-shared.xml
|
||||||
# systemd stuff
|
# systemd stuff
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ P_WIFI="${WIFI-1}"
|
||||||
P_WWAN="${WWAN-1}"
|
P_WWAN="${WWAN-1}"
|
||||||
P_TEAM="${TEAM-1}"
|
P_TEAM="${TEAM-1}"
|
||||||
P_BLUETOOTH="${BLUETOOTH-1}"
|
P_BLUETOOTH="${BLUETOOTH-1}"
|
||||||
|
P_IFCFG_RH="${IFCFG_RH-0}"
|
||||||
P_NMTUI="${NMTUI-1}"
|
P_NMTUI="${NMTUI-1}"
|
||||||
P_NM_CLOUD_SETUP="${NM_CLOUD_SETUP-1}"
|
P_NM_CLOUD_SETUP="${NM_CLOUD_SETUP-1}"
|
||||||
P_OVS="${OVS-1}"
|
P_OVS="${OVS-1}"
|
||||||
|
|
@ -202,7 +203,7 @@ if [ -z "$P_FEDORA" -a -z "$P_RHEL" ] ; then
|
||||||
P_FEDORA="$x"
|
P_FEDORA="$x"
|
||||||
P_RHEL=0
|
P_RHEL=0
|
||||||
else
|
else
|
||||||
x="$(grep -q "ID=fedora" /etc/os-release && sed -n 's/VERSION_ID=//p' /etc/os-release)"
|
x="$(grep -q 'ID="rhel"' /etc/os-release && sed -n 's/^VERSION_ID="*\([0-9]*\).*/\1/p' /etc/os-release)"
|
||||||
if test "$x" -gt 0 ; then
|
if test "$x" -gt 0 ; then
|
||||||
P_FEDORA=0
|
P_FEDORA=0
|
||||||
P_RHEL="$x"
|
P_RHEL="$x"
|
||||||
|
|
@ -293,6 +294,14 @@ if [ -z "$P_MODEM_MANAGER_1" ] ; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$TEAM" ] && [ "${P_RHEL-0}" -ge 10 ] ; then
|
||||||
|
P_TEAM=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$IFCFG_RH" ] && [ -n "$P_RHEL" ] && [ "$P_RHEL" -le 9 ] ; then
|
||||||
|
P_IFCFG_RH=1
|
||||||
|
fi
|
||||||
|
|
||||||
if bool "$P_DEBUG" ; then
|
if bool "$P_DEBUG" ; then
|
||||||
P_CFLAGS="-g -Og -fexceptions${P_CFLAGS:+ }$P_CFLAGS"
|
P_CFLAGS="-g -Og -fexceptions${P_CFLAGS:+ }$P_CFLAGS"
|
||||||
else
|
else
|
||||||
|
|
@ -378,7 +387,7 @@ meson setup\
|
||||||
-Db_lto="$(bool_true "$P_LTO")" \
|
-Db_lto="$(bool_true "$P_LTO")" \
|
||||||
-Dlibaudit=yes-disabled-by-default \
|
-Dlibaudit=yes-disabled-by-default \
|
||||||
-Dmodem_manager="$(bool_true "$P_MODEM_MANAGER_1")" \
|
-Dmodem_manager="$(bool_true "$P_MODEM_MANAGER_1")" \
|
||||||
$(args_enable "$P_WIFI" -Dwifi=true -Dwext="$(bool_true "$P_FEDORA")") \
|
$(args_enable "$P_WIFI" -Dwifi=true -Dwext=false) \
|
||||||
$(args_enable "$(bool_not_true "$P_WIFI")" -Dwifi=false ) \
|
$(args_enable "$(bool_not_true "$P_WIFI")" -Dwifi=false ) \
|
||||||
-Diwd="$(bool_true "$P_IWD")" \
|
-Diwd="$(bool_true "$P_IWD")" \
|
||||||
-Dbluez5_dun="$(bool_true "$P_BLUETOOTH")" \
|
-Dbluez5_dun="$(bool_true "$P_BLUETOOTH")" \
|
||||||
|
|
@ -392,17 +401,17 @@ meson setup\
|
||||||
-Dselinux=true \
|
-Dselinux=true \
|
||||||
-Dpolkit=true \
|
-Dpolkit=true \
|
||||||
-Dconfig_auth_polkit_default=true \
|
-Dconfig_auth_polkit_default=true \
|
||||||
-Dmodify_system=true \
|
|
||||||
-Dconcheck=true \
|
-Dconcheck=true \
|
||||||
-Dlibpsl="$(bool_true "$P_FEDORA")" \
|
-Dlibpsl="$(bool_true "$P_FEDORA")" \
|
||||||
-Dsession_tracking=systemd \
|
-Dsession_tracking=systemd \
|
||||||
-Dsuspend_resume=systemd \
|
-Dsuspend_resume=systemd \
|
||||||
-Dsystemdsystemunitdir=/usr/lib/systemd/system \
|
-Dsystemdsystemunitdir=/usr/lib/systemd/system \
|
||||||
|
-Dsystemdsystemgeneratordir=/usr/lib/systemd/system-generators \
|
||||||
-Dsystem_ca_path=/etc/pki/tls/cert.pem \
|
-Dsystem_ca_path=/etc/pki/tls/cert.pem \
|
||||||
-Ddbus_conf_dir="$P_DBUS_SYS_DIR" \
|
-Ddbus_conf_dir="$P_DBUS_SYS_DIR" \
|
||||||
-Dtests=yes \
|
-Dtests=yes \
|
||||||
-Dvalgrind=no \
|
-Dvalgrind=no \
|
||||||
-Difcfg_rh=true \
|
-Difcfg_rh="$(bool_true "$P_IFCFG_RH")" \
|
||||||
-Difupdown=false \
|
-Difupdown=false \
|
||||||
$(args_enable "$P_PPP" -Dppp=true -Dpppd="$D_SBINDIR/pppd" -Dpppd_plugin_dir="$D_LIBDIR/pppd/$P_PPP_VERSION") \
|
$(args_enable "$P_PPP" -Dppp=true -Dpppd="$D_SBINDIR/pppd" -Dpppd_plugin_dir="$D_LIBDIR/pppd/$P_PPP_VERSION") \
|
||||||
$(args_enable "$(bool_not_true "$P_PPP")" -Dppp=false ) \
|
$(args_enable "$(bool_not_true "$P_PPP")" -Dppp=false ) \
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ meson setup build \
|
||||||
-D ld_gc=false \
|
-D ld_gc=false \
|
||||||
-D session_tracking=no \
|
-D session_tracking=no \
|
||||||
-D systemdsystemunitdir=no \
|
-D systemdsystemunitdir=no \
|
||||||
|
-D systemdsystemgeneratordir=no \
|
||||||
-D systemd_journal=false \
|
-D systemd_journal=false \
|
||||||
-D selinux=false \
|
-D selinux=false \
|
||||||
-D libaudit=no \
|
-D libaudit=no \
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=NetworkManager Configuration (initrd)
|
Description=NetworkManager Configuration (initrd)
|
||||||
|
AssertPathExists=/etc/initrd-release
|
||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
Wants=systemd-journald.socket
|
Wants=systemd-journald.socket
|
||||||
After=systemd-journald.socket
|
After=systemd-journald.socket
|
||||||
Before=systemd-udevd.service systemd-udev-trigger.service
|
Before=systemd-udevd.service systemd-udev-trigger.service
|
||||||
ConditionPathExists=/etc/initrd-release
|
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
|
@ -22,6 +22,3 @@ ExecStartPost=/bin/sh -c ' \
|
||||||
fi \
|
fi \
|
||||||
'
|
'
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=initrd.target
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=NetworkManager (initrd)
|
Description=NetworkManager (initrd)
|
||||||
|
AssertPathExists=/etc/initrd-release
|
||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
Wants=systemd-udev-trigger.service network.target
|
Wants=systemd-udev-trigger.service network.target
|
||||||
After=systemd-udev-trigger.service network-pre.target dbus.service NetworkManager-config-initrd.service
|
After=systemd-udev-trigger.service network-pre.target dbus.service NetworkManager-config-initrd.service
|
||||||
Before=network.target
|
Before=network.target
|
||||||
BindsTo=dbus.service
|
BindsTo=dbus.service
|
||||||
ConditionPathExists=/etc/initrd-release
|
|
||||||
ConditionPathExists=/run/NetworkManager/initrd/neednet
|
ConditionPathExists=/run/NetworkManager/initrd/neednet
|
||||||
ConditionPathExistsGlob=|/usr/lib/NetworkManager/system-connections/*
|
ConditionPathExistsGlob=|/usr/lib/NetworkManager/system-connections/*
|
||||||
ConditionPathExistsGlob=|/run/NetworkManager/system-connections/*
|
ConditionPathExistsGlob=|/run/NetworkManager/system-connections/*
|
||||||
|
|
@ -22,11 +22,3 @@ Environment=NM_CONFIG_ENABLE_TAG=initrd
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
ProtectSystem=true
|
ProtectSystem=true
|
||||||
ProtectHome=read-only
|
ProtectHome=read-only
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=initrd.target
|
|
||||||
# We want to enable NetworkManager-wait-online-initrd.service whenever this
|
|
||||||
# service is enabled. NetworkManager-wait-online-initrd.service has
|
|
||||||
# WantedBy=network-online.target, so enabling it only has an effect if
|
|
||||||
# network-online.target itself is enabled or pulled in by some other unit.
|
|
||||||
Also=NetworkManager-config-initrd.service NetworkManager-wait-online-initrd.service
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=NetworkManager Wait Online (initrd)
|
Description=NetworkManager Wait Online (initrd)
|
||||||
|
AssertPathExists=/etc/initrd-release
|
||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
Requires=NetworkManager-initrd.service
|
Requires=NetworkManager-initrd.service
|
||||||
After=NetworkManager-initrd.service
|
After=NetworkManager-initrd.service
|
||||||
Before=network-online.target
|
Before=network-online.target
|
||||||
ConditionPathExists=/etc/initrd-release
|
|
||||||
ConditionPathExists=/run/NetworkManager/initrd/neednet
|
ConditionPathExists=/run/NetworkManager/initrd/neednet
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
|
@ -21,6 +21,3 @@ Type=oneshot
|
||||||
ExecStart=@bindir@/nm-online -s -q
|
ExecStart=@bindir@/nm-online -s -q
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
Environment=NM_ONLINE_TIMEOUT=3600
|
Environment=NM_ONLINE_TIMEOUT=3600
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=initrd.target network-online.target
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,16 @@ TimeoutStartSec=600
|
||||||
|
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_BPF CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_BPF CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT
|
||||||
|
|
||||||
ProtectSystem=true
|
PrivateTmp=true
|
||||||
|
|
||||||
|
ProtectClock=true
|
||||||
|
ProtectControlGroups=true
|
||||||
ProtectHome=read-only
|
ProtectHome=read-only
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectSystem=true
|
||||||
|
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
|
||||||
# We require file descriptors for DHCP etc. When activating many interfaces,
|
# We require file descriptors for DHCP etc. When activating many interfaces,
|
||||||
# the default limit of 1024 is easily reached.
|
# the default limit of 1024 is easily reached.
|
||||||
|
|
|
||||||
|
|
@ -55,21 +55,22 @@ if install_udevdir
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if enable_polkit
|
if enable_polkit
|
||||||
policy = 'org.freedesktop.NetworkManager.policy'
|
|
||||||
|
|
||||||
policy_in = configure_file(
|
|
||||||
input: policy + '.in.in',
|
|
||||||
output: '@BASENAME@',
|
|
||||||
configuration: data_conf,
|
|
||||||
)
|
|
||||||
|
|
||||||
i18n.merge_file(
|
i18n.merge_file(
|
||||||
input: policy_in,
|
input: 'org.freedesktop.NetworkManager.policy.in',
|
||||||
output: '@BASENAME@',
|
output: '@BASENAME@',
|
||||||
po_dir: po_dir,
|
po_dir: po_dir,
|
||||||
install: true,
|
install: true,
|
||||||
install_dir: polkit_gobject_policydir,
|
install_dir: polkit_policydir,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if polkit_noauth_group != ''
|
||||||
|
configure_file(
|
||||||
|
input: 'org.freedesktop.NetworkManager.rules.in',
|
||||||
|
output: '@BASENAME@',
|
||||||
|
install_dir: polkit_rulesdir,
|
||||||
|
configuration: {'NM_POLKIT_NOAUTH_GROUP': polkit_noauth_group},
|
||||||
|
)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if enable_firewalld_zone
|
if enable_firewalld_zone
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@
|
||||||
<message>System policy prevents modification of network settings for all users</message>
|
<message>System policy prevents modification of network settings for all users</message>
|
||||||
<defaults>
|
<defaults>
|
||||||
<allow_any>auth_admin_keep</allow_any>
|
<allow_any>auth_admin_keep</allow_any>
|
||||||
<allow_inactive>@NM_MODIFY_SYSTEM_POLICY@</allow_inactive>
|
<allow_inactive>auth_admin_keep</allow_inactive>
|
||||||
<allow_active>@NM_MODIFY_SYSTEM_POLICY@</allow_active>
|
<allow_active>auth_admin_keep</allow_active>
|
||||||
</defaults>
|
</defaults>
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
17
data/org.freedesktop.NetworkManager.rules.in
Normal file
17
data/org.freedesktop.NetworkManager.rules.in
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
// NetworkManager authorizations/policy for the @NM_POLKIT_NOAUTH_GROUP@ group.
|
||||||
|
//
|
||||||
|
// DO NOT EDIT THIS FILE, it will be overwritten on update.
|
||||||
|
//
|
||||||
|
// Allow users in the @NM_POLKIT_NOAUTH_GROUP@ group to create system-wide connections without being
|
||||||
|
// prompted for a password if they are in a local console.
|
||||||
|
// This is optional and is only recommended to maintain backwards compatibility
|
||||||
|
// in systems where it was already working in this way. It is discouraged
|
||||||
|
// otherwise.
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (action.id == "org.freedesktop.NetworkManager.settings.modify.system" &&
|
||||||
|
subject.isInGroup("@NM_POLKIT_NOAUTH_GROUP@") &&
|
||||||
|
subject.local) {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -183,6 +183,7 @@
|
||||||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Bridge.xml"/>
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Bridge.xml"/>
|
||||||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Dummy.xml"/>
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Dummy.xml"/>
|
||||||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Generic.xml"/>
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Generic.xml"/>
|
||||||
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Geneve.xml"/>
|
||||||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Hsr.xml"/>
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Hsr.xml"/>
|
||||||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml"/>
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml"/>
|
||||||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml"/>
|
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml"/>
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
|
||||||
<xi:include href="xml/nm-setting-dummy.xml"/>
|
<xi:include href="xml/nm-setting-dummy.xml"/>
|
||||||
<xi:include href="xml/nm-setting-ethtool.xml"/>
|
<xi:include href="xml/nm-setting-ethtool.xml"/>
|
||||||
<xi:include href="xml/nm-setting-generic.xml"/>
|
<xi:include href="xml/nm-setting-generic.xml"/>
|
||||||
|
<xi:include href="xml/nm-setting-geneve.xml"/>
|
||||||
<xi:include href="xml/nm-setting-gsm.xml"/>
|
<xi:include href="xml/nm-setting-gsm.xml"/>
|
||||||
<xi:include href="xml/nm-setting-hostname.xml"/>
|
<xi:include href="xml/nm-setting-hostname.xml"/>
|
||||||
<xi:include href="xml/nm-setting-hsr.xml"/>
|
<xi:include href="xml/nm-setting-hsr.xml"/>
|
||||||
|
|
@ -377,6 +378,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
|
||||||
<xi:include href="xml/nm-device-dummy.xml"/>
|
<xi:include href="xml/nm-device-dummy.xml"/>
|
||||||
<xi:include href="xml/nm-device-ethernet.xml"/>
|
<xi:include href="xml/nm-device-ethernet.xml"/>
|
||||||
<xi:include href="xml/nm-device-generic.xml"/>
|
<xi:include href="xml/nm-device-generic.xml"/>
|
||||||
|
<xi:include href="xml/nm-device-geneve.xml"/>
|
||||||
<xi:include href="xml/nm-device-hsr.xml"/>
|
<xi:include href="xml/nm-device-hsr.xml"/>
|
||||||
<xi:include href="xml/nm-device-infiniband.xml"/>
|
<xi:include href="xml/nm-device-infiniband.xml"/>
|
||||||
<xi:include href="xml/nm-device-ip-tunnel.xml"/>
|
<xi:include href="xml/nm-device-ip-tunnel.xml"/>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ ifaces = [
|
||||||
'org.freedesktop.NetworkManager.Device.Bridge',
|
'org.freedesktop.NetworkManager.Device.Bridge',
|
||||||
'org.freedesktop.NetworkManager.Device.Dummy',
|
'org.freedesktop.NetworkManager.Device.Dummy',
|
||||||
'org.freedesktop.NetworkManager.Device.Generic',
|
'org.freedesktop.NetworkManager.Device.Generic',
|
||||||
|
'org.freedesktop.NetworkManager.Device.Geneve',
|
||||||
'org.freedesktop.NetworkManager.Device.Hsr',
|
'org.freedesktop.NetworkManager.Device.Hsr',
|
||||||
'org.freedesktop.NetworkManager.Device.IPTunnel',
|
'org.freedesktop.NetworkManager.Device.IPTunnel',
|
||||||
'org.freedesktop.NetworkManager.Device.Infiniband',
|
'org.freedesktop.NetworkManager.Device.Infiniband',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<node name="/">
|
||||||
|
<!--
|
||||||
|
org.freedesktop.NetworkManager.Device.Geneve:
|
||||||
|
@short_description: GENEVE Device.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<interface name="org.freedesktop.NetworkManager.Device.Geneve">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Id:
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
The GENEVE Virtual Network Identifier (VNI).
|
||||||
|
-->
|
||||||
|
<property name="Id" type="u" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Remote:
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
The IP (v4 or v6) address of the remote endpoint to which GENEVE packets
|
||||||
|
are sent.
|
||||||
|
-->
|
||||||
|
<property name="Remote" type="s" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Tos:
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
The value to use in the IP ToS field for GENEVE packets sent to the remote
|
||||||
|
endpoint.
|
||||||
|
-->
|
||||||
|
<property name="Tos" type="y" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Ttl:
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
The value to use in the IP TTL field for GENEVE packets sent to the remote
|
||||||
|
endpoint.
|
||||||
|
-->
|
||||||
|
<property name="Ttl" type="i" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Df:
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
The Don't Fragment (DF) flag setting for GENEVE packets. 0 means unset,
|
||||||
|
1 means set, 2 means inherit from the underlying interface.
|
||||||
|
-->
|
||||||
|
<property name="Df" type="y" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
DstPort:
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
Destination port for outgoing GENEVE packets.
|
||||||
|
-->
|
||||||
|
<property name="DstPort" type="q" access="read"/>
|
||||||
|
|
||||||
|
</interface>
|
||||||
|
</node>
|
||||||
|
|
@ -175,6 +175,9 @@
|
||||||
property has a similar effect to configuring the device as unmanaged via
|
property has a similar effect to configuring the device as unmanaged via
|
||||||
the keyfile.unmanaged-devices setting in NetworkManager.conf. Changes to
|
the keyfile.unmanaged-devices setting in NetworkManager.conf. Changes to
|
||||||
this value are not persistent and lost after NetworkManager restart.
|
this value are not persistent and lost after NetworkManager restart.
|
||||||
|
|
||||||
|
DEPRECATED: 1.58: Use the SetManaged method instead, which supports
|
||||||
|
additional features like persisting the state to disk
|
||||||
-->
|
-->
|
||||||
<property name="Managed" type="b" access="readwrite"/>
|
<property name="Managed" type="b" access="readwrite"/>
|
||||||
|
|
||||||
|
|
@ -391,6 +394,20 @@
|
||||||
-->
|
-->
|
||||||
<method name="Delete"/>
|
<method name="Delete"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SetManaged:
|
||||||
|
@managed:(<link linkend="NMDeviceManaged">NMDeviceManaged</link>) Whether the device is managed. Possible values are "no" (0), "yes" (1) and "reset" (2).
|
||||||
|
@flags: (<link linkend="NMDeviceManagedFlags">NMDeviceManagedFlags</link>) flags.
|
||||||
|
@since: 1.58
|
||||||
|
|
||||||
|
Set the managed state of the device. With the flags argument different
|
||||||
|
behaviors can be achieved, like storing the new managed state to disk.
|
||||||
|
-->
|
||||||
|
<method name="SetManaged">
|
||||||
|
<arg name="managed" type="u" direction="in"/>
|
||||||
|
<arg name="flags" type="u" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
StateChanged:
|
StateChanged:
|
||||||
@new_state: (<link linkend="NMDeviceState">NMDeviceState</link>) The new state of the device.
|
@new_state: (<link linkend="NMDeviceState">NMDeviceState</link>) The new state of the device.
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
GetSecrets:
|
GetSecrets:
|
||||||
@setting_name: Name of the setting to return secrets for. If empty, all secrets will be returned.
|
@setting_name: Name of the setting to return secrets for (mandatory).
|
||||||
@secrets: Nested settings maps containing secrets.
|
@secrets: Nested settings maps containing secrets.
|
||||||
|
|
||||||
Get the secrets belonging to this network configuration. Only secrets from
|
Get the secrets belonging to this network configuration. Only secrets from
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,11 @@
|
||||||
note that your distribution or other packages may drop configuration snippets for NetworkManager, such
|
note that your distribution or other packages may drop configuration snippets for NetworkManager, such
|
||||||
that they are part of the factory default.
|
that they are part of the factory default.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
The options that are indicated as boolean can be set to one of these values:
|
||||||
|
<literal>yes</literal>, <literal>true</literal>, <literal>on</literal>, <literal>1</literal>,
|
||||||
|
<literal>no</literal>, <literal>false</literal>, <literal>off</literal>, <literal>0</literal>.
|
||||||
|
</para>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
@ -949,6 +954,10 @@ ipv6.ip6-privacy=0
|
||||||
<term><varname>ipv4.forwarding</varname></term>
|
<term><varname>ipv4.forwarding</varname></term>
|
||||||
<listitem><para>Whether to configure IPv4 sysctl interface-specific forwarding. When enabled, the interface will act as a router to forward the IPv4 packet from one interface to another. If left unspecified, "auto" is used, so NetworkManager sets the IPv4 forwarding if any shared connection is active, or it will use the kernel default value otherwise. The "ipv4.forwarding" property is ignored when "ipv4.method" is set to "shared", because forwarding is always enabled in this case. The accepted values are: 0: disabled, 1: enabled, 2: auto, 3: ignored (leave the forwarding unchanged).</para></listitem>
|
<listitem><para>Whether to configure IPv4 sysctl interface-specific forwarding. When enabled, the interface will act as a router to forward the IPv4 packet from one interface to another. If left unspecified, "auto" is used, so NetworkManager sets the IPv4 forwarding if any shared connection is active, or it will use the kernel default value otherwise. The "ipv4.forwarding" property is ignored when "ipv4.method" is set to "shared", because forwarding is always enabled in this case. The accepted values are: 0: disabled, 1: enabled, 2: auto, 3: ignored (leave the forwarding unchanged).</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>ipv4.clat</varname></term>
|
||||||
|
<listitem><para>If left unspecified, defaults to "no".</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ipv4.routed-dns</varname></term>
|
<term><varname>ipv4.routed-dns</varname></term>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
@ -967,7 +976,7 @@ ipv6.ip6-privacy=0
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ipv4.dhcp-ipv6-only-preferred</varname></term>
|
<term><varname>ipv4.dhcp-ipv6-only-preferred</varname></term>
|
||||||
<listitem><para>If left unspecified, the "IPv6-only preferred" DHCPv4 option is disabled.</para></listitem>
|
<listitem><para>If left unspecified, it defaults to "auto".</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ipv4.dhcp-hostname-flags</varname></term>
|
<term><varname>ipv4.dhcp-hostname-flags</varname></term>
|
||||||
|
|
@ -1249,12 +1258,13 @@ managed=1
|
||||||
<term><varname>managed</varname></term>
|
<term><varname>managed</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Whether the device is managed or not. A device can be
|
A boolean value specifying whether the device is
|
||||||
marked as managed via udev rules (ENV{NM_UNMANAGED}),
|
managed or not. A device can be marked as managed via
|
||||||
or via setting plugins (keyfile.unmanaged-devices).
|
udev rules (ENV{NM_UNMANAGED}), or via setting plugins
|
||||||
This is yet another way. Note that this configuration
|
(keyfile.unmanaged-devices). This is yet another
|
||||||
can be overruled at runtime via D-Bus. Also, it has
|
way. Note that this configuration can be overruled at
|
||||||
higher priority then udev rules.
|
runtime via D-Bus. Also, it has higher priority than
|
||||||
|
udev rules.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
@ -1323,9 +1333,27 @@ managed=1
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry id="keep-configuration">
|
<varlistentry id="check-connectivity">
|
||||||
<term><varname>keep-configuration</varname></term>
|
<term><varname>check-connectivity</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A boolean value specifying whether NetworkManager will perform a connectivity check
|
||||||
|
for this device. Defaults to <literal>yes</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This setting does nothing if the connectivity check has been
|
||||||
|
disabled globally using the
|
||||||
|
<literal>connectivity.enabled</literal> setting.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry id="keep-configuration">
|
||||||
|
<term><varname>keep-configuration</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A boolean value indicating whether the existing device
|
||||||
|
configuration is kept at startup.
|
||||||
|
</para>
|
||||||
<para>
|
<para>
|
||||||
On startup, NetworkManager tries to not interfere with
|
On startup, NetworkManager tries to not interfere with
|
||||||
interfaces that are already configured. It does so by
|
interfaces that are already configured. It does so by
|
||||||
|
|
@ -1422,16 +1450,16 @@ managed=1
|
||||||
<term><varname>wifi.iwd.autoconnect</varname></term>
|
<term><varname>wifi.iwd.autoconnect</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
If <literal>wifi.backend</literal> is <literal>iwd</literal>, setting this to
|
A boolean value. If <literal>wifi.backend</literal> is <literal>iwd</literal>,
|
||||||
<literal>false</literal> forces IWD's autoconnect mechanism to be disabled for
|
setting this to <literal>false</literal> forces IWD's autoconnect mechanism to be
|
||||||
this device and connections will only be initiated by NetworkManager whether
|
disabled for this device and connections will only be initiated by NetworkManager
|
||||||
commanded by a client or automatically. Leaving it <literal>true</literal> (default)
|
whether commanded by a client or automatically. Leaving it <literal>true</literal>
|
||||||
stops NetworkManager from automatically initiating connections and allows
|
(default) stops NetworkManager from automatically initiating connections and allows
|
||||||
IWD to use its network ranking and scanning logic to decide the best networks
|
IWD to use its network ranking and scanning logic to decide the best networks to
|
||||||
to autoconnect to next. Connections' <literal>autoconnect-priority</literal>,
|
autoconnect to next. Connections' <literal>autoconnect-priority</literal>,
|
||||||
<literal>autoconnect-retries</literal> settings will be ignored. Other settings
|
<literal>autoconnect-retries</literal> settings will be ignored. Other settings like
|
||||||
like <literal>permissions</literal> or <literal>multi-connect</literal> may interfere
|
<literal>permissions</literal> or <literal>multi-connect</literal> may interfere with
|
||||||
with IWD connection attempts.
|
IWD connection attempts.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
@ -1490,7 +1518,7 @@ managed=1
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>enabled</varname></term>
|
<term><varname>enabled</varname></term>
|
||||||
<listitem><para>Whether connectivity check is enabled.
|
<listitem><para>A boolean indicating whether connectivity check is enabled.
|
||||||
Note that to enable connectivity check, a valid uri must
|
Note that to enable connectivity check, a valid uri must
|
||||||
also be configured. The value defaults to true, but since
|
also be configured. The value defaults to true, but since
|
||||||
the uri is unset by default, connectivity check may be disabled.
|
the uri is unset by default, connectivity check may be disabled.
|
||||||
|
|
|
||||||
|
|
@ -1436,15 +1436,31 @@
|
||||||
</arg>
|
</arg>
|
||||||
<arg>
|
<arg>
|
||||||
<option>managed</option>
|
<option>managed</option>
|
||||||
|
<group>
|
||||||
|
<arg choice='plain'>--permanent</arg>
|
||||||
|
<arg choice='plain'>--permanent-only</arg>
|
||||||
|
</group>
|
||||||
<group choice='req'>
|
<group choice='req'>
|
||||||
<arg choice='plain'>yes</arg>
|
<arg choice='plain'>yes</arg>
|
||||||
<arg choice='plain'>no</arg>
|
<arg choice='plain'>no</arg>
|
||||||
|
<arg choice='plain'>up</arg>
|
||||||
|
<arg choice='plain'>down</arg>
|
||||||
|
<arg choice='plain'>reset</arg>
|
||||||
</group>
|
</group>
|
||||||
</arg>
|
</arg>
|
||||||
</term>
|
</term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Set device properties.</para>
|
<para>Set device properties.</para>
|
||||||
|
|
||||||
|
<para>The <option>managed</option> property accepts a <option>--permanent</option>
|
||||||
|
option to persist the managed state to disk, and not only in runtime. With
|
||||||
|
<option>--permanent-only</option> only the permanent managed state is set, and not the
|
||||||
|
runtime managed state. The special values <option>up</option> and <option>down</option>
|
||||||
|
can be used to set the administrative state of the device at the same time as the runtime
|
||||||
|
managed state. The <option>reset</option> value clears the explicit managed setting, and
|
||||||
|
with <option>--permanent</option> or <option>--permanent-only</option> it also removes
|
||||||
|
the persisted managed setting.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
@ -1718,6 +1734,7 @@
|
||||||
<group choice='req'>
|
<group choice='req'>
|
||||||
<arg choice='plain'>a</arg>
|
<arg choice='plain'>a</arg>
|
||||||
<arg choice='plain'>bg</arg>
|
<arg choice='plain'>bg</arg>
|
||||||
|
<arg choice='plain'>6GHz</arg>
|
||||||
</group>
|
</group>
|
||||||
</arg>
|
</arg>
|
||||||
<arg><option>channel</option> <replaceable>channel</replaceable></arg>
|
<arg><option>channel</option> <replaceable>channel</replaceable></arg>
|
||||||
|
|
@ -1851,9 +1868,9 @@
|
||||||
connections with an option of restoring the network configuration to a
|
connections with an option of restoring the network configuration to a
|
||||||
known good state in case of an error.</para>
|
known good state in case of an error.</para>
|
||||||
|
|
||||||
<para>If the a list of interface names is specified, the checkpoint is
|
<para>If a list of interface names is specified, the checkpoint is
|
||||||
taken, the checkpoint is takes only on the specified devices. Otherwise
|
taken only on the specified devices. Otherwise a checkpoint is taken for
|
||||||
a checkpoint is taken for all devices.</para>
|
all devices.</para>
|
||||||
|
|
||||||
<para>Currently the timeout defaults to 15 seconds. This may change in
|
<para>Currently the timeout defaults to 15 seconds. This may change in
|
||||||
a future version.</para>
|
a future version.</para>
|
||||||
|
|
|
||||||
50
meson.build
50
meson.build
|
|
@ -5,7 +5,7 @@ project(
|
||||||
# NOTE: When incrementing version also add corresponding
|
# NOTE: When incrementing version also add corresponding
|
||||||
# NM_VERSION_x_y_z macros in
|
# NM_VERSION_x_y_z macros in
|
||||||
# "src/libnm-core-public/nm-version-macros.h.in"
|
# "src/libnm-core-public/nm-version-macros.h.in"
|
||||||
version: '1.56.0',
|
version: '1.57.3-dev',
|
||||||
license: 'GPL2+',
|
license: 'GPL2+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
|
|
@ -358,7 +358,11 @@ enable_iwd = get_option('iwd')
|
||||||
assert((not enable_iwd) or enable_wifi, 'Enabling iwd support requires Wi-Fi support as well')
|
assert((not enable_iwd) or enable_wifi, 'Enabling iwd support requires Wi-Fi support as well')
|
||||||
config_h.set10('WITH_IWD', enable_iwd)
|
config_h.set10('WITH_IWD', enable_iwd)
|
||||||
|
|
||||||
enable_wext = get_option('wext')
|
wext = get_option('wext')
|
||||||
|
if wext == 'true'
|
||||||
|
error('Wireless Extensions support is deprecated and will be removed in the future. Use -Dwext=force to keep using it')
|
||||||
|
endif
|
||||||
|
enable_wext = (wext == 'force')
|
||||||
config_h.set10('HAVE_WEXT', enable_wext)
|
config_h.set10('HAVE_WEXT', enable_wext)
|
||||||
|
|
||||||
# Checks for libdl - on certain platforms its part of libc
|
# Checks for libdl - on certain platforms its part of libc
|
||||||
|
|
@ -408,6 +412,14 @@ if install_systemdunitdir and systemd_systemdsystemunitdir == ''
|
||||||
systemd_systemdsystemunitdir = systemd_dep.get_variable(pkgconfig: 'systemdsystemunitdir', pkgconfig_define: ['rootprefix', nm_prefix])
|
systemd_systemdsystemunitdir = systemd_dep.get_variable(pkgconfig: 'systemdsystemunitdir', pkgconfig_define: ['rootprefix', nm_prefix])
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
systemd_systemdsystemgeneratordir = get_option('systemdsystemgeneratordir')
|
||||||
|
install_systemdgeneratordir = (systemd_systemdsystemgeneratordir != 'no')
|
||||||
|
|
||||||
|
if install_systemdgeneratordir and systemd_systemdsystemgeneratordir == ''
|
||||||
|
assert(systemd_dep.found(), 'systemd required but not found, please provide a valid systemd user generator dir or disable it')
|
||||||
|
systemd_systemdsystemgeneratordir = systemd_dep.get_variable(pkgconfig: 'systemdsystemgeneratordir', pkgconfig_define: ['rootprefix', nm_prefix])
|
||||||
|
endif
|
||||||
|
|
||||||
enable_systemd_journal = get_option('systemd_journal')
|
enable_systemd_journal = get_option('systemd_journal')
|
||||||
if enable_systemd_journal
|
if enable_systemd_journal
|
||||||
assert(libsystemd_dep.found(), 'Missing systemd-journald support')
|
assert(libsystemd_dep.found(), 'Missing systemd-journald support')
|
||||||
|
|
@ -502,6 +514,16 @@ if enable_selinux
|
||||||
endif
|
endif
|
||||||
config_h.set10('HAVE_SELINUX', enable_selinux)
|
config_h.set10('HAVE_SELINUX', enable_selinux)
|
||||||
|
|
||||||
|
# CLAT support
|
||||||
|
enable_clat = get_option('clat')
|
||||||
|
if enable_clat
|
||||||
|
libbpf = dependency('libbpf', version: '>= 0.1.0', required: false)
|
||||||
|
assert(libbpf.found(), 'You must have libbpf installed to build. Use -Dclat=false to disable use of it')
|
||||||
|
libndp_dep = dependency('libndp', version: '>= 1.9', required: false)
|
||||||
|
assert(libndp_dep.found(), 'You must have libndp >= 1.9 installed to build with CLAT support. Use -Dclat=false to disable it')
|
||||||
|
endif
|
||||||
|
config_h.set10('HAVE_CLAT', enable_clat)
|
||||||
|
|
||||||
# libaudit support
|
# libaudit support
|
||||||
libaudit = get_option('libaudit')
|
libaudit = get_option('libaudit')
|
||||||
enable_libaudit = libaudit.contains('yes')
|
enable_libaudit = libaudit.contains('yes')
|
||||||
|
|
@ -526,7 +548,8 @@ config_h.set10('WITH_TEAMDCTL', enable_teamdctl)
|
||||||
enable_polkit = get_option('polkit')
|
enable_polkit = get_option('polkit')
|
||||||
if enable_polkit
|
if enable_polkit
|
||||||
# FIXME: policydir should be relative to `datadir`, not `prefix`. Fixed in https://gitlab.freedesktop.org/polkit/polkit/merge_requests/2
|
# FIXME: policydir should be relative to `datadir`, not `prefix`. Fixed in https://gitlab.freedesktop.org/polkit/polkit/merge_requests/2
|
||||||
polkit_gobject_policydir = dependency('polkit-gobject-1').get_variable(pkgconfig: 'policydir', pkgconfig_define: ['prefix', nm_prefix])
|
polkit_policydir = dependency('polkit-gobject-1').get_variable(pkgconfig: 'policydir', pkgconfig_define: ['prefix', nm_prefix])
|
||||||
|
polkit_rulesdir = join_paths(fs.parent(polkit_policydir), 'rules.d')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config_auth_polkit_default = get_option('config_auth_polkit_default')
|
config_auth_polkit_default = get_option('config_auth_polkit_default')
|
||||||
|
|
@ -536,6 +559,12 @@ endif
|
||||||
config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT', config_auth_polkit_default)
|
config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT', config_auth_polkit_default)
|
||||||
|
|
||||||
enable_modify_system = get_option('modify_system')
|
enable_modify_system = get_option('modify_system')
|
||||||
|
if enable_modify_system
|
||||||
|
# FIXME: remove this after everyone has stopped using modify_system
|
||||||
|
error('modify_system=true is no longer allowed due to security reasons')
|
||||||
|
endif
|
||||||
|
|
||||||
|
polkit_noauth_group = get_option('polkit_noauth_group')
|
||||||
|
|
||||||
polkit_agent_helper_1_path = get_option('polkit_agent_helper_1')
|
polkit_agent_helper_1_path = get_option('polkit_agent_helper_1')
|
||||||
foreach p : [ '/usr/libexec/polkit-agent-helper-1',
|
foreach p : [ '/usr/libexec/polkit-agent-helper-1',
|
||||||
|
|
@ -968,7 +997,6 @@ data_conf.set('NM_DHCP_CLIENTS_ENABLED', ', '.join(config_dhcp_c
|
||||||
data_conf.set('NM_MAJOR_VERSION', nm_major_version)
|
data_conf.set('NM_MAJOR_VERSION', nm_major_version)
|
||||||
data_conf.set('NM_MICRO_VERSION', nm_micro_version)
|
data_conf.set('NM_MICRO_VERSION', nm_micro_version)
|
||||||
data_conf.set('NM_MINOR_VERSION', nm_minor_version)
|
data_conf.set('NM_MINOR_VERSION', nm_minor_version)
|
||||||
data_conf.set('NM_MODIFY_SYSTEM_POLICY', (enable_modify_system ? 'yes' : 'auth_admin_keep'))
|
|
||||||
data_conf.set('NM_VERSION', nm_version)
|
data_conf.set('NM_VERSION', nm_version)
|
||||||
data_conf.set('VERSION', nm_version)
|
data_conf.set('VERSION', nm_version)
|
||||||
data_conf.set('bindir', nm_bindir)
|
data_conf.set('bindir', nm_bindir)
|
||||||
|
|
@ -1084,6 +1112,7 @@ output = '\nSystem paths:\n'
|
||||||
output += ' prefix: ' + nm_prefix + '\n'
|
output += ' prefix: ' + nm_prefix + '\n'
|
||||||
output += ' exec_prefix: ' + nm_prefix + '\n'
|
output += ' exec_prefix: ' + nm_prefix + '\n'
|
||||||
output += ' systemdunitdir: ' + systemd_systemdsystemunitdir + '\n'
|
output += ' systemdunitdir: ' + systemd_systemdsystemunitdir + '\n'
|
||||||
|
output += ' systemdgeneratordir: ' + systemd_systemdsystemgeneratordir + '\n'
|
||||||
output += ' udev_dir: ' + udev_udevdir + '\n'
|
output += ' udev_dir: ' + udev_udevdir + '\n'
|
||||||
output += ' nmbinary: ' + nm_pkgsbindir + '\n'
|
output += ' nmbinary: ' + nm_pkgsbindir + '\n'
|
||||||
output += ' nmconfdir: ' + nm_pkgconfdir + '\n'
|
output += ' nmconfdir: ' + nm_pkgconfdir + '\n'
|
||||||
|
|
@ -1098,17 +1127,7 @@ output += ' dbus_conf_dir: ' + dbus_conf_dir + '\n'
|
||||||
output += '\nPlatform:\n'
|
output += '\nPlatform:\n'
|
||||||
output += ' session tracking: ' + ','.join(session_trackers) + '\n'
|
output += ' session tracking: ' + ','.join(session_trackers) + '\n'
|
||||||
output += ' suspend/resume: ' + suspend_resume + '\n'
|
output += ' suspend/resume: ' + suspend_resume + '\n'
|
||||||
output += ' policykit: ' + enable_polkit.to_string() + ' (default: ' + config_auth_polkit_default + ')'
|
output += ' policykit: ' + enable_polkit.to_string() + ' (default: ' + config_auth_polkit_default + ', noauth_group: "' + polkit_noauth_group + '")\n'
|
||||||
if enable_polkit
|
|
||||||
output += ' ('
|
|
||||||
if enable_modify_system
|
|
||||||
output += 'permissive'
|
|
||||||
else
|
|
||||||
output += 'restrictive'
|
|
||||||
endif
|
|
||||||
output += ' modify.system)'
|
|
||||||
endif
|
|
||||||
output += '\n'
|
|
||||||
output += ' polkit-agent-helper-1: ' + polkit_agent_helper_1_path + '\n'
|
output += ' polkit-agent-helper-1: ' + polkit_agent_helper_1_path + '\n'
|
||||||
output += ' selinux: ' + enable_selinux.to_string() + '\n'
|
output += ' selinux: ' + enable_selinux.to_string() + '\n'
|
||||||
output += ' systemd-journald: ' + enable_systemd_journal.to_string() + ' (default: logging.backend=' + config_logging_backend_default + ')\n'
|
output += ' systemd-journald: ' + enable_systemd_journal.to_string() + ' (default: logging.backend=' + config_logging_backend_default + ')\n'
|
||||||
|
|
@ -1136,6 +1155,7 @@ output += ' ofono: ' + enable_ofono.to_string() + '\n'
|
||||||
output += ' concheck: ' + enable_concheck.to_string() + '\n'
|
output += ' concheck: ' + enable_concheck.to_string() + '\n'
|
||||||
output += ' libteamdctl: ' + enable_teamdctl.to_string() + '\n'
|
output += ' libteamdctl: ' + enable_teamdctl.to_string() + '\n'
|
||||||
output += ' ovs: ' + enable_ovs.to_string() + '\n'
|
output += ' ovs: ' + enable_ovs.to_string() + '\n'
|
||||||
|
output += ' clat: ' + enable_clat.to_string() + '\n'
|
||||||
output += ' nmcli: ' + enable_nmcli.to_string() + '\n'
|
output += ' nmcli: ' + enable_nmcli.to_string() + '\n'
|
||||||
output += ' nmtui: ' + enable_nmtui.to_string() + '\n'
|
output += ' nmtui: ' + enable_nmtui.to_string() + '\n'
|
||||||
output += ' nm-cloud-setup: ' + enable_nm_cloud_setup.to_string() + '\n'
|
output += ' nm-cloud-setup: ' + enable_nm_cloud_setup.to_string() + '\n'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# system paths
|
# system paths
|
||||||
option('systemdsystemunitdir', type: 'string', value: '', description: 'Directory for systemd service files')
|
option('systemdsystemunitdir', type: 'string', value: '', description: 'Directory for systemd service files')
|
||||||
|
option('systemdsystemgeneratordir', type: 'string', value: '', description: 'Directory for systemd generator files')
|
||||||
option('system_ca_path', type: 'string', value: '/etc/ssl/certs', description: 'path to system CA certificates')
|
option('system_ca_path', type: 'string', value: '/etc/ssl/certs', description: 'path to system CA certificates')
|
||||||
option('udev_dir', type: 'string', value: '', description: 'Absolute path of the udev base directory. Set to \'no\' not to install the udev rule')
|
option('udev_dir', type: 'string', value: '', description: 'Absolute path of the udev base directory. Set to \'no\' not to install the udev rule')
|
||||||
option('dbus_conf_dir', type: 'string', value: '', description: 'where D-Bus system.d directory is')
|
option('dbus_conf_dir', type: 'string', value: '', description: 'where D-Bus system.d directory is')
|
||||||
|
|
@ -18,7 +19,8 @@ option('session_tracking', type: 'combo', choices: ['systemd', 'elogind', 'no'],
|
||||||
option('suspend_resume', type: 'combo', choices: ['systemd', 'elogind', 'consolekit', 'auto'], value: 'auto', description: 'Build NetworkManager with specific suspend/resume support')
|
option('suspend_resume', type: 'combo', choices: ['systemd', 'elogind', 'consolekit', 'auto'], value: 'auto', description: 'Build NetworkManager with specific suspend/resume support')
|
||||||
option('polkit', type: 'boolean', value: true, description: 'User auth-polkit configuration option.')
|
option('polkit', type: 'boolean', value: true, description: 'User auth-polkit configuration option.')
|
||||||
option('config_auth_polkit_default', type: 'combo', choices: ['default', 'true', 'false', 'root-only'], value: 'default', description: 'Default value for configuration main.auth-polkit.')
|
option('config_auth_polkit_default', type: 'combo', choices: ['default', 'true', 'false', 'root-only'], value: 'default', description: 'Default value for configuration main.auth-polkit.')
|
||||||
option('modify_system', type: 'boolean', value: false, description: 'Allow users to modify system connections')
|
option('modify_system', type: 'boolean', value: false, description: 'Allow users to modify system connections (option no longer supported, don\'t use)')
|
||||||
|
option('polkit_noauth_group', type: 'string', value: '', description: 'Allow users of the selected group, typically sudo or wheel, to modify system connections without introducing a password (discouraged)')
|
||||||
option('polkit_agent_helper_1', type: 'string', value: '', description: 'Path name to the polkit-agent-helper-1 binary from polkit')
|
option('polkit_agent_helper_1', type: 'string', value: '', description: 'Path name to the polkit-agent-helper-1 binary from polkit')
|
||||||
option('selinux', type: 'boolean', value: true, description: 'Build with SELinux')
|
option('selinux', type: 'boolean', value: true, description: 'Build with SELinux')
|
||||||
option('systemd_journal', type: 'boolean', value: true, description: 'Use systemd journal for logging')
|
option('systemd_journal', type: 'boolean', value: true, description: 'Use systemd journal for logging')
|
||||||
|
|
@ -28,7 +30,7 @@ option('hostname_persist', type: 'combo', choices: ['default', 'suse', 'gentoo',
|
||||||
option('libaudit', type: 'combo', choices: ['yes', 'yes-disabled-by-default', 'no'], value: 'yes', description: 'Build with audit daemon support. yes-disabled-by-default enables support, but disables it unless explicitly configured via NetworkManager.conf')
|
option('libaudit', type: 'combo', choices: ['yes', 'yes-disabled-by-default', 'no'], value: 'yes', description: 'Build with audit daemon support. yes-disabled-by-default enables support, but disables it unless explicitly configured via NetworkManager.conf')
|
||||||
|
|
||||||
# features
|
# features
|
||||||
option('wext', type: 'boolean', value: true, description: 'Enable or disable Linux Wireless Extensions')
|
option('wext', type: 'combo', choices: ['true', 'false', 'force' ], value: 'false', description: 'Enable or disable Linux Wireless Extensions (deprecated). wext support will be removed in a future release, don\'t rely on this.')
|
||||||
option('wifi', type: 'boolean', value: true, description: 'enable Wi-Fi support')
|
option('wifi', type: 'boolean', value: true, description: 'enable Wi-Fi support')
|
||||||
option('iwd', type: 'boolean', value: false, description: 'enable iwd support (experimental)')
|
option('iwd', type: 'boolean', value: false, description: 'enable iwd support (experimental)')
|
||||||
option('ppp', type: 'boolean', value: true, description: 'enable PPP/PPPoE support')
|
option('ppp', type: 'boolean', value: true, description: 'enable PPP/PPPoE support')
|
||||||
|
|
@ -46,6 +48,9 @@ option('nm_cloud_setup', type: 'boolean', value: true, description: 'Build nm-cl
|
||||||
option('bluez5_dun', type: 'boolean', value: false, description: 'enable Bluez5 DUN support')
|
option('bluez5_dun', type: 'boolean', value: false, description: 'enable Bluez5 DUN support')
|
||||||
option('ebpf', type: 'combo', choices: ['auto', 'true', 'false'], description: 'Enable eBPF support (deprecated)')
|
option('ebpf', type: 'combo', choices: ['auto', 'true', 'false'], description: 'Enable eBPF support (deprecated)')
|
||||||
option('nbft', type: 'boolean', value: true, description: 'Enable NBFT support in the initrd generator')
|
option('nbft', type: 'boolean', value: true, description: 'Enable NBFT support in the initrd generator')
|
||||||
|
option('clat', type: 'boolean', value: true, description: 'Build with CLAT support')
|
||||||
|
option('bpf-compiler', type : 'combo', choices : ['auto', 'clang', 'gcc'],
|
||||||
|
description : 'compiler used to build BPF programs')
|
||||||
|
|
||||||
# configuration plugins
|
# configuration plugins
|
||||||
option('config_plugins_default', type: 'string', value: '', description: 'Default configuration option for main.plugins setting, used as fallback if the configuration option is unset')
|
option('config_plugins_default', type: 'string', value: '', description: 'Default configuration option for main.plugins setting, used as fallback if the configuration option is unset')
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ id
|
||||||
it
|
it
|
||||||
ja
|
ja
|
||||||
ka
|
ka
|
||||||
|
kk
|
||||||
kn
|
kn
|
||||||
ko
|
ko
|
||||||
ku
|
ku
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,18 @@
|
||||||
# List of source files containing translatable strings.
|
# List of source files containing translatable strings.
|
||||||
# Please keep this file sorted alphabetically.
|
# Please keep this file sorted alphabetically.
|
||||||
data/org.freedesktop.NetworkManager.policy.in.in
|
data/org.freedesktop.NetworkManager.policy.in
|
||||||
src/core/NetworkManagerUtils.c
|
src/core/NetworkManagerUtils.c
|
||||||
src/core/devices/adsl/nm-device-adsl.c
|
src/core/devices/adsl/nm-device-adsl.c
|
||||||
src/core/devices/bluetooth/nm-bluez-manager.c
|
src/core/devices/bluetooth/nm-bluez-manager.c
|
||||||
src/core/devices/bluetooth/nm-device-bt.c
|
src/core/devices/bluetooth/nm-device-bt.c
|
||||||
|
src/core/devices/nm-device.c
|
||||||
src/core/devices/nm-device-6lowpan.c
|
src/core/devices/nm-device-6lowpan.c
|
||||||
src/core/devices/nm-device-bond.c
|
src/core/devices/nm-device-bond.c
|
||||||
src/core/devices/nm-device-bridge.c
|
src/core/devices/nm-device-bridge.c
|
||||||
src/core/devices/nm-device-dummy.c
|
src/core/devices/nm-device-dummy.c
|
||||||
src/core/devices/nm-device-ethernet-utils.c
|
src/core/devices/nm-device-ethernet-utils.c
|
||||||
src/core/devices/nm-device-ethernet.c
|
src/core/devices/nm-device-ethernet.c
|
||||||
|
src/core/devices/nm-device-geneve.c
|
||||||
src/core/devices/nm-device-infiniband.c
|
src/core/devices/nm-device-infiniband.c
|
||||||
src/core/devices/nm-device-ip-tunnel.c
|
src/core/devices/nm-device-ip-tunnel.c
|
||||||
src/core/devices/nm-device-loopback.c
|
src/core/devices/nm-device-loopback.c
|
||||||
|
|
@ -46,6 +48,7 @@ src/libnm-client-impl/nm-device-bt.c
|
||||||
src/libnm-client-impl/nm-device-dummy.c
|
src/libnm-client-impl/nm-device-dummy.c
|
||||||
src/libnm-client-impl/nm-device-ethernet.c
|
src/libnm-client-impl/nm-device-ethernet.c
|
||||||
src/libnm-client-impl/nm-device-generic.c
|
src/libnm-client-impl/nm-device-generic.c
|
||||||
|
src/libnm-client-impl/nm-device-geneve.c
|
||||||
src/libnm-client-impl/nm-device-hsr.c
|
src/libnm-client-impl/nm-device-hsr.c
|
||||||
src/libnm-client-impl/nm-device-infiniband.c
|
src/libnm-client-impl/nm-device-infiniband.c
|
||||||
src/libnm-client-impl/nm-device-ip-tunnel.c
|
src/libnm-client-impl/nm-device-ip-tunnel.c
|
||||||
|
|
@ -90,6 +93,7 @@ src/libnm-core-impl/nm-setting-connection.c
|
||||||
src/libnm-core-impl/nm-setting-dcb.c
|
src/libnm-core-impl/nm-setting-dcb.c
|
||||||
src/libnm-core-impl/nm-setting-ethtool.c
|
src/libnm-core-impl/nm-setting-ethtool.c
|
||||||
src/libnm-core-impl/nm-setting-generic.c
|
src/libnm-core-impl/nm-setting-generic.c
|
||||||
|
src/libnm-core-impl/nm-setting-geneve.c
|
||||||
src/libnm-core-impl/nm-setting-gsm.c
|
src/libnm-core-impl/nm-setting-gsm.c
|
||||||
src/libnm-core-impl/nm-setting-hsr.c
|
src/libnm-core-impl/nm-setting-hsr.c
|
||||||
src/libnm-core-impl/nm-setting-infiniband.c
|
src/libnm-core-impl/nm-setting-infiniband.c
|
||||||
|
|
|
||||||
9522
po/pt_BR.po
9522
po/pt_BR.po
File diff suppressed because it is too large
Load diff
|
|
@ -1495,11 +1495,10 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
|
||||||
r4->scope_inv = nm_platform_route_scope_inv(scope);
|
r4->scope_inv = nm_platform_route_scope_inv(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that for IPv4 routes in kernel, the onlink flag can be set for
|
/* For IPv4 routes in kernel, the onlink flag is per-nexthop (rtnh_flags).
|
||||||
* each next hop separately (rtnh_flags). Not for NetworkManager. We can
|
* Here we set the flag on r_rtm_flags which represents the first nexthop's
|
||||||
* only merge routes as ECMP routes (when setting a weight) if they all
|
* flags. For ECMP routes, each nexthop carries its own onlink flag, so
|
||||||
* share the same onlink flag. See NM_PLATFORM_IP_ROUTE_CMP_TYPE_ECMP_ID.
|
* routes with different onlink settings per-nexthop can be merged. */
|
||||||
* That simplifies the code. */
|
|
||||||
GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);
|
GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_ONLINK, onlink, BOOLEAN, boolean, FALSE);
|
||||||
r->r_rtm_flags = ((onlink) ? (unsigned) RTNH_F_ONLINK : 0u);
|
r->r_rtm_flags = ((onlink) ? (unsigned) RTNH_F_ONLINK : 0u);
|
||||||
|
|
||||||
|
|
|
||||||
1203
src/core/bpf/clat.bpf.c
Normal file
1203
src/core/bpf/clat.bpf.c
Normal file
File diff suppressed because it is too large
Load diff
30
src/core/bpf/clat.h
Normal file
30
src/core/bpf/clat.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef __NAT64_H__
|
||||||
|
#define __NAT64_H__
|
||||||
|
|
||||||
|
#include <linux/in6.h>
|
||||||
|
|
||||||
|
struct clat_config {
|
||||||
|
struct in6_addr local_v6;
|
||||||
|
struct in6_addr pref64;
|
||||||
|
struct in_addr local_v4;
|
||||||
|
unsigned pref64_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clat_stats {
|
||||||
|
/* egress: v4 to v6 */
|
||||||
|
__u64 egress_tcp;
|
||||||
|
__u64 egress_udp;
|
||||||
|
__u64 egress_icmp;
|
||||||
|
__u64 egress_other;
|
||||||
|
__u64 egress_dropped;
|
||||||
|
/* ingress: v6 to v4 */
|
||||||
|
__u64 ingress_tcp;
|
||||||
|
__u64 ingress_udp;
|
||||||
|
__u64 ingress_icmp;
|
||||||
|
__u64 ingress_other;
|
||||||
|
__u64 ingress_fragment;
|
||||||
|
__u64 ingress_dropped;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
239
src/core/bpf/meson.build
Normal file
239
src/core/bpf/meson.build
Normal file
|
|
@ -0,0 +1,239 @@
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
|
||||||
|
# Ripped from systemd: https://github.com/systemd/systemd/pull/20429
|
||||||
|
|
||||||
|
if not enable_clat
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
bpf_compiler = get_option('bpf-compiler')
|
||||||
|
clang_found = false
|
||||||
|
clang_supports_bpf = false
|
||||||
|
bpf_gcc_found = false
|
||||||
|
bpftool_strip = false
|
||||||
|
|
||||||
|
if bpf_compiler == 'clang' or bpf_compiler == 'auto'
|
||||||
|
# Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
|
||||||
|
# (like clang-10/llvm-strip-10)
|
||||||
|
if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
|
||||||
|
r = find_program('clang',
|
||||||
|
version : '>= 10.0.0')
|
||||||
|
clang_found = r.found()
|
||||||
|
if clang_found
|
||||||
|
if meson.version().version_compare('>= 0.55')
|
||||||
|
clang = r.full_path()
|
||||||
|
else
|
||||||
|
clang = r.path()
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
clang_found = true
|
||||||
|
clang = cc.cmd_array()
|
||||||
|
endif
|
||||||
|
|
||||||
|
if clang_found
|
||||||
|
# Check if 'clang -target bpf' is supported.
|
||||||
|
clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
|
||||||
|
endif
|
||||||
|
elif bpf_compiler == 'gcc' or bpf_compiler == 'auto'
|
||||||
|
bpf_gcc = find_program('bpf-gcc',
|
||||||
|
'bpf-none-gcc',
|
||||||
|
'bpf-unknown-none-gcc',
|
||||||
|
version : '>= 13.1.0')
|
||||||
|
bpf_gcc_found = bpf_gcc.found()
|
||||||
|
endif
|
||||||
|
|
||||||
|
if bpf_compiler == 'auto'
|
||||||
|
if clang_supports_bpf and bpf_gcc_found
|
||||||
|
# Both supported, prefer the one matching our compiler:
|
||||||
|
if cc.get_id() == 'gcc'
|
||||||
|
bpf_compiler = 'gcc'
|
||||||
|
else
|
||||||
|
# Default to clang if we don't know this compiler
|
||||||
|
bpf_compiler = 'clang'
|
||||||
|
endif
|
||||||
|
elif clang_supports_bpf
|
||||||
|
bpf_compiler = 'clang'
|
||||||
|
elif bpf_gcc_found
|
||||||
|
bpf_compiler = 'clang'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if clang_supports_bpf or bpf_gcc_found
|
||||||
|
# Debian installs this in /usr/sbin/ which is not in $PATH.
|
||||||
|
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
|
||||||
|
# We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
|
||||||
|
bpftool = find_program('bpftool',
|
||||||
|
'/usr/sbin/bpftool',
|
||||||
|
required : bpf_compiler == 'gcc',
|
||||||
|
version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
|
||||||
|
|
||||||
|
if bpftool.found()
|
||||||
|
bpftool_strip = true
|
||||||
|
elif bpf_compiler == 'clang'
|
||||||
|
# We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
|
||||||
|
bpftool = find_program('bpftool',
|
||||||
|
'/usr/sbin/bpftool',
|
||||||
|
required : true,
|
||||||
|
version : '>= 5.6.0')
|
||||||
|
endif
|
||||||
|
|
||||||
|
# We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
|
||||||
|
if not bpftool_strip and bpftool.found() and clang_supports_bpf
|
||||||
|
if not meson.is_cross_build()
|
||||||
|
llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
|
||||||
|
check : true).stdout().strip()
|
||||||
|
else
|
||||||
|
llvm_strip_bin = 'llvm-strip'
|
||||||
|
endif
|
||||||
|
llvm_strip = find_program(llvm_strip_bin,
|
||||||
|
required : true,
|
||||||
|
version : '>= 10.0.0')
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
error('clat support was enabled but couldn\'t find a suitable BPF compiler!')
|
||||||
|
endif
|
||||||
|
|
||||||
|
bpf_clang_flags = [
|
||||||
|
'-std=gnu17',
|
||||||
|
'-Wunused',
|
||||||
|
'-Wimplicit-fallthrough',
|
||||||
|
'-Wno-compare-distinct-pointer-types',
|
||||||
|
'-fno-stack-protector',
|
||||||
|
'-O2',
|
||||||
|
'-target',
|
||||||
|
'bpf',
|
||||||
|
'-g',
|
||||||
|
'-c',
|
||||||
|
]
|
||||||
|
|
||||||
|
bpf_gcc_flags = [
|
||||||
|
'-std=gnu17',
|
||||||
|
'-Wunused',
|
||||||
|
'-Wimplicit-fallthrough',
|
||||||
|
'-fno-stack-protector',
|
||||||
|
'-fno-ssa-phiopt',
|
||||||
|
'-O2',
|
||||||
|
'-mcpu=v3',
|
||||||
|
'-mco-re',
|
||||||
|
'-gbtf',
|
||||||
|
'-c',
|
||||||
|
]
|
||||||
|
|
||||||
|
clang_arch_flag = '-D__@0@__'.format(host_machine.cpu_family())
|
||||||
|
|
||||||
|
libbpf_include_dir = dependency('libbpf').get_variable(pkgconfig : 'includedir')
|
||||||
|
|
||||||
|
# Generate defines that are appropriate to tell the compiler what architecture
|
||||||
|
# we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
|
||||||
|
# This dictionary contains the exceptions where this doesn't work.
|
||||||
|
#
|
||||||
|
# C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
|
||||||
|
# and src/basic/missing_syscall_def.h.
|
||||||
|
cpu_arch_defines = {
|
||||||
|
'ppc' : ['-D__powerpc__', '-D__TARGET_ARCH_powerpc'],
|
||||||
|
'ppc64' : ['-D__powerpc64__', '-D__TARGET_ARCH_powerpc', '-D_CALL_ELF=2'],
|
||||||
|
'riscv32' : ['-D__riscv', '-D__riscv_xlen=32', '-D__TARGET_ARCH_riscv'],
|
||||||
|
'riscv64' : ['-D__riscv', '-D__riscv_xlen=64', '-D__TARGET_ARCH_riscv'],
|
||||||
|
'x86' : ['-D__i386__', '-D__TARGET_ARCH_x86'],
|
||||||
|
's390x' : ['-D__s390__', '-D__s390x__', '-D__TARGET_ARCH_s390'],
|
||||||
|
|
||||||
|
# For arm, assume hardware fp is available.
|
||||||
|
'arm' : ['-D__arm__', '-D__ARM_PCS_VFP', '-D__TARGET_ARCH_arm'],
|
||||||
|
'loongarch64' : ['-D__loongarch__', '-D__loongarch_grlen=64', '-D__TARGET_ARCH_loongarch']
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
|
||||||
|
['-D__@0@__'.format(host_machine.cpu_family())])
|
||||||
|
if bpf_compiler == 'gcc'
|
||||||
|
bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
|
||||||
|
endif
|
||||||
|
|
||||||
|
bpf_o_unstripped_cmd = []
|
||||||
|
if bpf_compiler == 'clang'
|
||||||
|
bpf_o_unstripped_cmd += [
|
||||||
|
clang,
|
||||||
|
bpf_clang_flags,
|
||||||
|
bpf_arch_flags,
|
||||||
|
]
|
||||||
|
elif bpf_compiler == 'gcc'
|
||||||
|
bpf_o_unstripped_cmd += [
|
||||||
|
bpf_gcc,
|
||||||
|
bpf_gcc_flags,
|
||||||
|
bpf_arch_flags,
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
bpf_o_unstripped_cmd += ['-I.']
|
||||||
|
|
||||||
|
if cc.get_id() == 'gcc' or meson.is_cross_build()
|
||||||
|
if cc.get_id() != 'gcc'
|
||||||
|
warning('Cross compiler is not gcc. Guessing the target triplet for bpf likely fails.')
|
||||||
|
endif
|
||||||
|
target_triplet_cmd = run_command(cc.cmd_array(), '-print-multiarch', check: false)
|
||||||
|
else
|
||||||
|
# clang does not support -print-multiarch (D133170) and its -dump-machine
|
||||||
|
# does not match multiarch. Query gcc instead.
|
||||||
|
target_triplet_cmd = run_command('gcc', '-print-multiarch', check: false)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if target_triplet_cmd.returncode() == 0
|
||||||
|
target_triplet = target_triplet_cmd.stdout().strip()
|
||||||
|
bpf_o_unstripped_cmd += [
|
||||||
|
'-isystem',
|
||||||
|
'/usr/include/@0@'.format(target_triplet)
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
bpf_o_unstripped_cmd += [
|
||||||
|
'-idirafter',
|
||||||
|
libbpf_include_dir,
|
||||||
|
'@INPUT@',
|
||||||
|
'-o',
|
||||||
|
'@OUTPUT@'
|
||||||
|
]
|
||||||
|
|
||||||
|
if bpftool_strip
|
||||||
|
bpf_o_cmd = [
|
||||||
|
bpftool,
|
||||||
|
'gen',
|
||||||
|
'object',
|
||||||
|
'@OUTPUT@',
|
||||||
|
'@INPUT@'
|
||||||
|
]
|
||||||
|
elif bpf_compiler == 'clang'
|
||||||
|
bpf_o_cmd = [
|
||||||
|
llvm_strip,
|
||||||
|
'-g',
|
||||||
|
'@INPUT@',
|
||||||
|
'-o',
|
||||||
|
'@OUTPUT@'
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
skel_h_cmd = [
|
||||||
|
bpftool,
|
||||||
|
'g',
|
||||||
|
's',
|
||||||
|
'@INPUT@'
|
||||||
|
]
|
||||||
|
|
||||||
|
clat_bpf_o_unstripped = custom_target(
|
||||||
|
'clat.bpf.unstripped.o',
|
||||||
|
input : 'clat.bpf.c',
|
||||||
|
output : 'clat.bpf.unstripped.o',
|
||||||
|
command : bpf_o_unstripped_cmd)
|
||||||
|
|
||||||
|
clat_bpf_o = custom_target(
|
||||||
|
'clat.bpf.o',
|
||||||
|
input : clat_bpf_o_unstripped,
|
||||||
|
output : 'clat.bpf.o',
|
||||||
|
command : bpf_o_cmd)
|
||||||
|
|
||||||
|
clat_skel_h = custom_target(
|
||||||
|
'clat.skel.h',
|
||||||
|
input : clat_bpf_o,
|
||||||
|
output : 'clat.skel.h',
|
||||||
|
command : skel_h_cmd,
|
||||||
|
capture : true)
|
||||||
|
|
||||||
|
|
@ -412,6 +412,7 @@ nm_device_factory_manager_load_factories(NMDeviceFactoryManagerFactoryFunc callb
|
||||||
_ADD_INTERNAL(nm_dummy_device_factory_get_type);
|
_ADD_INTERNAL(nm_dummy_device_factory_get_type);
|
||||||
_ADD_INTERNAL(nm_ethernet_device_factory_get_type);
|
_ADD_INTERNAL(nm_ethernet_device_factory_get_type);
|
||||||
_ADD_INTERNAL(nm_generic_device_factory_get_type);
|
_ADD_INTERNAL(nm_generic_device_factory_get_type);
|
||||||
|
_ADD_INTERNAL(nm_geneve_device_factory_get_type);
|
||||||
_ADD_INTERNAL(nm_hsr_device_factory_get_type);
|
_ADD_INTERNAL(nm_hsr_device_factory_get_type);
|
||||||
_ADD_INTERNAL(nm_infiniband_device_factory_get_type);
|
_ADD_INTERNAL(nm_infiniband_device_factory_get_type);
|
||||||
_ADD_INTERNAL(nm_ip_tunnel_device_factory_get_type);
|
_ADD_INTERNAL(nm_ip_tunnel_device_factory_get_type);
|
||||||
|
|
|
||||||
487
src/core/devices/nm-device-geneve.c
Normal file
487
src/core/devices/nm-device-geneve.c
Normal file
|
|
@ -0,0 +1,487 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "src/core/nm-default-daemon.h"
|
||||||
|
|
||||||
|
#include "nm-manager.h"
|
||||||
|
#include "nm-device-geneve.h"
|
||||||
|
|
||||||
|
#include "libnm-core-intern/nm-core-internal.h"
|
||||||
|
#include "nm-act-request.h"
|
||||||
|
#include "nm-device-private.h"
|
||||||
|
#include "nm-setting-geneve.h"
|
||||||
|
#include "libnm-platform/nm-platform.h"
|
||||||
|
#include "nm-device-factory.h"
|
||||||
|
|
||||||
|
#define _NMLOG_DEVICE_TYPE NMDeviceGeneve
|
||||||
|
#include "nm-device-logging.h"
|
||||||
|
|
||||||
|
NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceGeneve,
|
||||||
|
PROP_ID,
|
||||||
|
PROP_REMOTE,
|
||||||
|
PROP_TOS,
|
||||||
|
PROP_TTL,
|
||||||
|
PROP_DF,
|
||||||
|
PROP_DST_PORT, );
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMPlatformLnkGeneve props;
|
||||||
|
} NMDeviceGenevePrivate;
|
||||||
|
|
||||||
|
struct _NMDeviceGeneve {
|
||||||
|
NMDevice parent;
|
||||||
|
NMDeviceGenevePrivate _priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _NMDeviceGeneveClass {
|
||||||
|
NMDeviceClass parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(NMDeviceGeneve, nm_device_geneve, NM_TYPE_DEVICE)
|
||||||
|
|
||||||
|
#define NM_DEVICE_GENEVE_GET_PRIVATE(self) \
|
||||||
|
_NM_GET_PRIVATE(self, NMDeviceGeneve, NM_IS_DEVICE_GENEVE, NMDevice)
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static NMDeviceCapabilities
|
||||||
|
get_generic_capabilities(NMDevice *dev)
|
||||||
|
{
|
||||||
|
return NM_DEVICE_CAP_IS_SOFTWARE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_properties(NMDevice *device)
|
||||||
|
{
|
||||||
|
NMDeviceGeneve *self;
|
||||||
|
NMDeviceGenevePrivate *priv;
|
||||||
|
const NMPlatformLink *plink;
|
||||||
|
const NMPlatformLnkGeneve *props;
|
||||||
|
int ifindex;
|
||||||
|
|
||||||
|
g_return_if_fail(NM_IS_DEVICE_GENEVE(device));
|
||||||
|
self = NM_DEVICE_GENEVE(device);
|
||||||
|
priv = NM_DEVICE_GENEVE_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
ifindex = nm_device_get_ifindex(device);
|
||||||
|
g_return_if_fail(ifindex > 0);
|
||||||
|
props = nm_platform_link_get_lnk_geneve(nm_device_get_platform(device), ifindex, &plink);
|
||||||
|
|
||||||
|
if (!props) {
|
||||||
|
_LOGW(LOGD_PLATFORM, "could not get GENEVE properties");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_freeze_notify((GObject *) device);
|
||||||
|
|
||||||
|
#define CHECK_PROPERTY_CHANGED(field, prop) \
|
||||||
|
G_STMT_START \
|
||||||
|
{ \
|
||||||
|
if (priv->props.field != props->field) { \
|
||||||
|
priv->props.field = props->field; \
|
||||||
|
_notify(self, prop); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
G_STMT_END
|
||||||
|
|
||||||
|
#define CHECK_PROPERTY_CHANGED_IN6ADDR(field, prop) \
|
||||||
|
G_STMT_START \
|
||||||
|
{ \
|
||||||
|
if (memcmp(&priv->props.field, &props->field, sizeof(props->field)) != 0) { \
|
||||||
|
priv->props.field = props->field; \
|
||||||
|
_notify(self, prop); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
G_STMT_END
|
||||||
|
|
||||||
|
CHECK_PROPERTY_CHANGED(id, PROP_ID);
|
||||||
|
CHECK_PROPERTY_CHANGED(remote, PROP_REMOTE);
|
||||||
|
CHECK_PROPERTY_CHANGED_IN6ADDR(remote6, PROP_REMOTE);
|
||||||
|
CHECK_PROPERTY_CHANGED(tos, PROP_TOS);
|
||||||
|
CHECK_PROPERTY_CHANGED(ttl, PROP_TTL);
|
||||||
|
CHECK_PROPERTY_CHANGED(df, PROP_DF);
|
||||||
|
CHECK_PROPERTY_CHANGED(dst_port, PROP_DST_PORT);
|
||||||
|
|
||||||
|
g_object_thaw_notify((GObject *) device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
link_changed(NMDevice *device, const NMPlatformLink *pllink)
|
||||||
|
{
|
||||||
|
NM_DEVICE_CLASS(nm_device_geneve_parent_class)->link_changed(device, pllink);
|
||||||
|
update_properties(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unrealize_notify(NMDevice *device)
|
||||||
|
{
|
||||||
|
NMDeviceGeneve *self = NM_DEVICE_GENEVE(device);
|
||||||
|
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
NM_DEVICE_CLASS(nm_device_geneve_parent_class)->unrealize_notify(device);
|
||||||
|
|
||||||
|
memset(&priv->props, 0, sizeof(NMPlatformLnkGeneve));
|
||||||
|
|
||||||
|
for (i = 1; i < _PROPERTY_ENUMS_LAST; i++)
|
||||||
|
g_object_notify_by_pspec(G_OBJECT(self), obj_properties[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
create_and_realize(NMDevice *device,
|
||||||
|
NMConnection *connection,
|
||||||
|
NMDevice *parent,
|
||||||
|
const NMPlatformLink **out_plink,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const char *iface = nm_device_get_iface(device);
|
||||||
|
NMPlatformLnkGeneve props = {};
|
||||||
|
NMSettingGeneve *s_geneve;
|
||||||
|
const char *str;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
s_geneve = nm_connection_get_setting_geneve(connection);
|
||||||
|
g_return_val_if_fail(s_geneve, FALSE);
|
||||||
|
|
||||||
|
props.id = nm_setting_geneve_get_id(s_geneve);
|
||||||
|
|
||||||
|
str = nm_setting_geneve_get_remote(s_geneve);
|
||||||
|
if (!nm_inet_parse_bin(AF_INET, str, NULL, &props.remote)
|
||||||
|
&& !nm_inet_parse_bin(AF_INET6, str, NULL, &props.remote6)) {
|
||||||
|
return nm_assert_unreachable_val(FALSE);
|
||||||
|
}
|
||||||
|
props.tos = nm_setting_geneve_get_tos(s_geneve);
|
||||||
|
props.ttl = nm_setting_geneve_get_ttl(s_geneve);
|
||||||
|
props.df = nm_setting_geneve_get_df(s_geneve);
|
||||||
|
props.dst_port = nm_setting_geneve_get_destination_port(s_geneve);
|
||||||
|
|
||||||
|
r = nm_platform_link_geneve_add(nm_device_get_platform(device), iface, &props, out_plink);
|
||||||
|
if (r < 0) {
|
||||||
|
g_set_error(error,
|
||||||
|
NM_DEVICE_ERROR,
|
||||||
|
NM_DEVICE_ERROR_CREATION_FAILED,
|
||||||
|
"Failed to create geneve interface '%s' for '%s': %s",
|
||||||
|
iface,
|
||||||
|
nm_connection_get_id(connection),
|
||||||
|
nm_strerror(r));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
address_matches(const char *candidate, in_addr_t addr4, struct in6_addr *addr6)
|
||||||
|
{
|
||||||
|
NMIPAddr candidate_addr;
|
||||||
|
int addr_family;
|
||||||
|
|
||||||
|
if (!candidate)
|
||||||
|
return addr4 == 0u && IN6_IS_ADDR_UNSPECIFIED(addr6);
|
||||||
|
|
||||||
|
if (!nm_inet_parse_bin(AF_UNSPEC, candidate, &addr_family, &candidate_addr))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!nm_ip_addr_equal(addr_family,
|
||||||
|
&candidate_addr,
|
||||||
|
NM_IS_IPv4(addr_family) ? (gpointer) &addr4 : addr6))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (NM_IS_IPv4(addr_family))
|
||||||
|
return IN6_IS_ADDR_UNSPECIFIED(addr6);
|
||||||
|
else
|
||||||
|
return addr4 == 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_connection_compatible(NMDevice *device,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean check_properties,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(device);
|
||||||
|
NMSettingGeneve *s_geneve;
|
||||||
|
|
||||||
|
if (!NM_DEVICE_CLASS(nm_device_geneve_parent_class)
|
||||||
|
->check_connection_compatible(device, connection, check_properties, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (check_properties && nm_device_is_real(device)) {
|
||||||
|
s_geneve = nm_connection_get_setting_geneve(connection);
|
||||||
|
|
||||||
|
if (priv->props.id != nm_setting_geneve_get_id(s_geneve)) {
|
||||||
|
nm_utils_error_set_literal(error,
|
||||||
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
|
"geneve id mismatches");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!address_matches(nm_setting_geneve_get_remote(s_geneve),
|
||||||
|
priv->props.remote,
|
||||||
|
&priv->props.remote6)) {
|
||||||
|
nm_utils_error_set_literal(error,
|
||||||
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
|
"geneve remote address mismatches");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->props.dst_port != nm_setting_geneve_get_destination_port(s_geneve)) {
|
||||||
|
nm_utils_error_set_literal(error,
|
||||||
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
|
"geneve destination port mismatches");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->props.tos != nm_setting_geneve_get_tos(s_geneve)) {
|
||||||
|
nm_utils_error_set_literal(error,
|
||||||
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
|
"geneve TOS mismatches");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->props.ttl != nm_setting_geneve_get_ttl(s_geneve)) {
|
||||||
|
nm_utils_error_set_literal(error,
|
||||||
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
|
"geneve TTL mismatches");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->props.df != nm_setting_geneve_get_df(s_geneve)) {
|
||||||
|
nm_utils_error_set_literal(error,
|
||||||
|
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
|
||||||
|
"geneve DF mismatches");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
complete_connection(NMDevice *device,
|
||||||
|
NMConnection *connection,
|
||||||
|
const char *specific_object,
|
||||||
|
NMConnection *const *existing_connections,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMSettingGeneve *s_geneve;
|
||||||
|
|
||||||
|
nm_utils_complete_generic(nm_device_get_platform(device),
|
||||||
|
connection,
|
||||||
|
NM_SETTING_GENEVE_SETTING_NAME,
|
||||||
|
existing_connections,
|
||||||
|
NULL,
|
||||||
|
_("Geneve connection"),
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
s_geneve = nm_connection_get_setting_geneve(connection);
|
||||||
|
if (!s_geneve) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
NM_DEVICE_ERROR,
|
||||||
|
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||||
|
"A 'geneve' setting is required.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_connection(NMDevice *device, NMConnection *connection)
|
||||||
|
{
|
||||||
|
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(device);
|
||||||
|
NMSettingGeneve *s_geneve = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_GENEVE);
|
||||||
|
char sbuf[NM_INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (priv->props.id != nm_setting_geneve_get_id(s_geneve))
|
||||||
|
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_ID, priv->props.id, NULL);
|
||||||
|
|
||||||
|
/* Handle remote (IPv4 or IPv6) */
|
||||||
|
if (priv->props.remote) {
|
||||||
|
g_object_set(s_geneve,
|
||||||
|
NM_SETTING_GENEVE_REMOTE,
|
||||||
|
nm_inet4_ntop(priv->props.remote, sbuf),
|
||||||
|
NULL);
|
||||||
|
} else if (memcmp(&priv->props.remote6, &in6addr_any, sizeof(in6addr_any))) {
|
||||||
|
g_object_set(s_geneve,
|
||||||
|
NM_SETTING_GENEVE_REMOTE,
|
||||||
|
nm_inet6_ntop(&priv->props.remote6, sbuf),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->props.dst_port != nm_setting_geneve_get_destination_port(s_geneve))
|
||||||
|
g_object_set(G_OBJECT(s_geneve),
|
||||||
|
NM_SETTING_GENEVE_DESTINATION_PORT,
|
||||||
|
priv->props.dst_port,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (priv->props.tos != nm_setting_geneve_get_tos(s_geneve))
|
||||||
|
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_TOS, priv->props.tos, NULL);
|
||||||
|
|
||||||
|
if (priv->props.ttl != nm_setting_geneve_get_ttl(s_geneve))
|
||||||
|
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_TTL, priv->props.ttl, NULL);
|
||||||
|
|
||||||
|
if (priv->props.df != nm_setting_geneve_get_df(s_geneve))
|
||||||
|
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_DF, priv->props.df, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_ID:
|
||||||
|
g_value_set_uint(value, priv->props.id);
|
||||||
|
break;
|
||||||
|
case PROP_REMOTE:
|
||||||
|
if (priv->props.remote)
|
||||||
|
g_value_take_string(value, nm_inet4_ntop_dup(priv->props.remote));
|
||||||
|
else if (!IN6_IS_ADDR_UNSPECIFIED(&priv->props.remote6))
|
||||||
|
g_value_take_string(value, nm_inet6_ntop_dup(&priv->props.remote6));
|
||||||
|
break;
|
||||||
|
case PROP_TOS:
|
||||||
|
g_value_set_uchar(value, priv->props.tos);
|
||||||
|
break;
|
||||||
|
case PROP_TTL:
|
||||||
|
g_value_set_uchar(value, priv->props.ttl);
|
||||||
|
break;
|
||||||
|
case PROP_DF:
|
||||||
|
g_value_set_uint(value, priv->props.df);
|
||||||
|
break;
|
||||||
|
case PROP_DST_PORT:
|
||||||
|
g_value_set_uint(value, priv->props.dst_port);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
nm_device_geneve_init(NMDeviceGeneve *self)
|
||||||
|
{}
|
||||||
|
|
||||||
|
static const NMDBusInterfaceInfoExtended interface_info_device_geneve = {
|
||||||
|
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
|
||||||
|
NM_DBUS_INTERFACE_DEVICE_GENEVE,
|
||||||
|
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Id", "u", NM_DEVICE_GENEVE_ID),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Remote", "s", NM_DEVICE_GENEVE_REMOTE),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Tos", "y", NM_DEVICE_GENEVE_TOS),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ttl", "y", NM_DEVICE_GENEVE_TTL),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Df", "u", NM_DEVICE_GENEVE_DF),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DstPort",
|
||||||
|
"q",
|
||||||
|
NM_DEVICE_GENEVE_DST_PORT), ), ),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
nm_device_geneve_class_init(NMDeviceGeneveClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
|
||||||
|
NMDeviceClass *device_class = NM_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
object_class->get_property = get_property;
|
||||||
|
|
||||||
|
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_geneve);
|
||||||
|
|
||||||
|
device_class->connection_type_supported = NM_SETTING_GENEVE_SETTING_NAME;
|
||||||
|
device_class->connection_type_check_compatible = NM_SETTING_GENEVE_SETTING_NAME;
|
||||||
|
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_GENEVE);
|
||||||
|
|
||||||
|
device_class->link_changed = link_changed;
|
||||||
|
device_class->unrealize_notify = unrealize_notify;
|
||||||
|
device_class->create_and_realize = create_and_realize;
|
||||||
|
device_class->check_connection_compatible = check_connection_compatible;
|
||||||
|
device_class->complete_connection = complete_connection;
|
||||||
|
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
|
device_class->update_connection = update_connection;
|
||||||
|
|
||||||
|
obj_properties[PROP_ID] = g_param_spec_uint(NM_DEVICE_GENEVE_ID,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
G_MAXUINT32,
|
||||||
|
0,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
obj_properties[PROP_REMOTE] = g_param_spec_string(NM_DEVICE_GENEVE_REMOTE,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
obj_properties[PROP_TOS] = g_param_spec_uchar(NM_DEVICE_GENEVE_TOS,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
obj_properties[PROP_TTL] = g_param_spec_uchar(NM_DEVICE_GENEVE_TTL,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
obj_properties[PROP_DF] = g_param_spec_uint(NM_DEVICE_GENEVE_DF,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
obj_properties[PROP_DST_PORT] = g_param_spec_uint(NM_DEVICE_GENEVE_DST_PORT,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
65535,
|
||||||
|
0,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#define NM_TYPE_GENEVE_DEVICE_FACTORY (nm_geneve_device_factory_get_type())
|
||||||
|
#define NM_GENEVE_DEVICE_FACTORY(obj) \
|
||||||
|
(_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_GENEVE_DEVICE_FACTORY, NMGeneveDeviceFactory))
|
||||||
|
|
||||||
|
static NMDevice *
|
||||||
|
create_device(NMDeviceFactory *factory,
|
||||||
|
const char *iface,
|
||||||
|
const NMPlatformLink *plink,
|
||||||
|
NMConnection *connection,
|
||||||
|
gboolean *out_ignore)
|
||||||
|
{
|
||||||
|
return g_object_new(NM_TYPE_DEVICE_GENEVE,
|
||||||
|
NM_DEVICE_IFACE,
|
||||||
|
iface,
|
||||||
|
NM_DEVICE_TYPE_DESC,
|
||||||
|
"Geneve",
|
||||||
|
NM_DEVICE_DEVICE_TYPE,
|
||||||
|
NM_DEVICE_TYPE_GENEVE,
|
||||||
|
NM_DEVICE_LINK_TYPE,
|
||||||
|
NM_LINK_TYPE_GENEVE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_DEVICE_FACTORY_DEFINE_INTERNAL(
|
||||||
|
GENEVE,
|
||||||
|
Geneve,
|
||||||
|
geneve,
|
||||||
|
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_GENEVE)
|
||||||
|
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_GENEVE_SETTING_NAME),
|
||||||
|
factory_class->create_device = create_device;);
|
||||||
33
src/core/devices/nm-device-geneve.h
Normal file
33
src/core/devices/nm-device-geneve.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NETWORKMANAGER_DEVICE_GENEVE_H__
|
||||||
|
#define __NETWORKMANAGER_DEVICE_GENEVE_H__
|
||||||
|
|
||||||
|
#include "nm-device.h"
|
||||||
|
|
||||||
|
#define NM_TYPE_DEVICE_GENEVE (nm_device_geneve_get_type())
|
||||||
|
#define NM_DEVICE_GENEVE(obj) \
|
||||||
|
(_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneve))
|
||||||
|
#define NM_DEVICE_GENEVE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneveClass))
|
||||||
|
#define NM_IS_DEVICE_GENEVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_GENEVE))
|
||||||
|
#define NM_IS_DEVICE_GENEVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_GENEVE))
|
||||||
|
#define NM_DEVICE_GENEVE_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneveClass))
|
||||||
|
|
||||||
|
#define NM_DEVICE_GENEVE_ID "id"
|
||||||
|
#define NM_DEVICE_GENEVE_REMOTE "remote"
|
||||||
|
#define NM_DEVICE_GENEVE_TOS "tos"
|
||||||
|
#define NM_DEVICE_GENEVE_TTL "ttl"
|
||||||
|
#define NM_DEVICE_GENEVE_DF "df"
|
||||||
|
#define NM_DEVICE_GENEVE_DST_PORT "dst-port"
|
||||||
|
|
||||||
|
typedef struct _NMDeviceGeneve NMDeviceGeneve;
|
||||||
|
typedef struct _NMDeviceGeneveClass NMDeviceGeneveClass;
|
||||||
|
|
||||||
|
GType nm_device_geneve_get_type(void);
|
||||||
|
|
||||||
|
#endif /* __NETWORKMANAGER_DEVICE_GENEVE_H__ */
|
||||||
|
|
@ -176,14 +176,14 @@ create_and_realize(NMDevice *device,
|
||||||
if (str) {
|
if (str) {
|
||||||
if (!nm_inet_parse_bin(AF_INET, str, NULL, &props.local)
|
if (!nm_inet_parse_bin(AF_INET, str, NULL, &props.local)
|
||||||
&& !nm_inet_parse_bin(AF_INET6, str, NULL, &props.local6))
|
&& !nm_inet_parse_bin(AF_INET6, str, NULL, &props.local6))
|
||||||
return FALSE;
|
return nm_assert_unreachable_val(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
str = nm_setting_vxlan_get_remote(s_vxlan);
|
str = nm_setting_vxlan_get_remote(s_vxlan);
|
||||||
if (str) {
|
if (str) {
|
||||||
if (!nm_inet_parse_bin(AF_INET, str, NULL, &props.group)
|
if (!nm_inet_parse_bin(AF_INET, str, NULL, &props.group)
|
||||||
&& !nm_inet_parse_bin(AF_INET6, str, NULL, &props.group6))
|
&& !nm_inet_parse_bin(AF_INET6, str, NULL, &props.group6))
|
||||||
return FALSE;
|
return nm_assert_unreachable_val(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
props.tos = nm_setting_vxlan_get_tos(s_vxlan);
|
props.tos = nm_setting_vxlan_get_tos(s_vxlan);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -791,6 +791,7 @@ void nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_fr
|
||||||
void nm_device_update_dynamic_ip_setup(NMDevice *self, const char *reason);
|
void nm_device_update_dynamic_ip_setup(NMDevice *self, const char *reason);
|
||||||
guint nm_device_get_supplicant_timeout(NMDevice *self);
|
guint nm_device_get_supplicant_timeout(NMDevice *self);
|
||||||
|
|
||||||
|
gboolean nm_device_auth_retries_has_next(NMDevice *self);
|
||||||
gboolean nm_device_auth_retries_try_next(NMDevice *self);
|
gboolean nm_device_auth_retries_try_next(NMDevice *self);
|
||||||
|
|
||||||
gboolean nm_device_hw_addr_get_cloned(NMDevice *self,
|
gboolean nm_device_hw_addr_get_cloned(NMDevice *self,
|
||||||
|
|
|
||||||
|
|
@ -2270,6 +2270,37 @@ add_new:
|
||||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_powersave(NMDevice *device)
|
||||||
|
{
|
||||||
|
NMDeviceIwd *self = NM_DEVICE_IWD(device);
|
||||||
|
NMSettingWireless *s_wireless;
|
||||||
|
NMSettingWirelessPowersave val;
|
||||||
|
|
||||||
|
s_wireless = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS);
|
||||||
|
|
||||||
|
g_return_if_fail(s_wireless);
|
||||||
|
|
||||||
|
val = nm_setting_wireless_get_powersave(s_wireless);
|
||||||
|
if (val == NM_SETTING_WIRELESS_POWERSAVE_DEFAULT) {
|
||||||
|
val = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
|
||||||
|
"wifi.powersave",
|
||||||
|
device,
|
||||||
|
NM_SETTING_WIRELESS_POWERSAVE_IGNORE,
|
||||||
|
NM_SETTING_WIRELESS_POWERSAVE_ENABLE,
|
||||||
|
NM_SETTING_WIRELESS_POWERSAVE_IGNORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGT(LOGD_WIFI, "powersave is set to %u", (unsigned) val);
|
||||||
|
|
||||||
|
if (val == NM_SETTING_WIRELESS_POWERSAVE_IGNORE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nm_platform_wifi_set_powersave(nm_device_get_platform(device),
|
||||||
|
nm_device_get_ifindex(device),
|
||||||
|
val == NM_SETTING_WIRELESS_POWERSAVE_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
static NMActStageReturn
|
static NMActStageReturn
|
||||||
act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
||||||
{
|
{
|
||||||
|
|
@ -2297,6 +2328,8 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_powersave(device);
|
||||||
|
|
||||||
/* With priv->iwd_autoconnect we have to let IWD handle retries for
|
/* With priv->iwd_autoconnect we have to let IWD handle retries for
|
||||||
* infrastructure networks. IWD will not necessarily retry the same
|
* infrastructure networks. IWD will not necessarily retry the same
|
||||||
* network after a failure but it will likely go into an autoconnect
|
* network after a failure but it will likely go into an autoconnect
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,9 @@ static void supplicant_iface_notify_p2p_available(NMSupplicantInterface *iface,
|
||||||
static void supplicant_iface_notify_wpa_psk_mismatch_cb(NMSupplicantInterface *iface,
|
static void supplicant_iface_notify_wpa_psk_mismatch_cb(NMSupplicantInterface *iface,
|
||||||
NMDeviceWifi *self);
|
NMDeviceWifi *self);
|
||||||
|
|
||||||
|
static void supplicant_iface_notify_wpa_sae_mismatch_cb(NMSupplicantInterface *iface,
|
||||||
|
NMDeviceWifi *self);
|
||||||
|
|
||||||
static void periodic_update(NMDeviceWifi *self);
|
static void periodic_update(NMDeviceWifi *self);
|
||||||
|
|
||||||
static void ap_add_remove(NMDeviceWifi *self,
|
static void ap_add_remove(NMDeviceWifi *self,
|
||||||
|
|
@ -631,6 +634,10 @@ supplicant_interface_acquire_cb(NMSupplicantManager *supplicant_manager,
|
||||||
NM_SUPPLICANT_INTERFACE_PSK_MISMATCH,
|
NM_SUPPLICANT_INTERFACE_PSK_MISMATCH,
|
||||||
G_CALLBACK(supplicant_iface_notify_wpa_psk_mismatch_cb),
|
G_CALLBACK(supplicant_iface_notify_wpa_psk_mismatch_cb),
|
||||||
self);
|
self);
|
||||||
|
g_signal_connect(priv->sup_iface,
|
||||||
|
NM_SUPPLICANT_INTERFACE_SAE_MISMATCH,
|
||||||
|
G_CALLBACK(supplicant_iface_notify_wpa_sae_mismatch_cb),
|
||||||
|
self);
|
||||||
|
|
||||||
_scan_notify_is_scanning(self);
|
_scan_notify_is_scanning(self);
|
||||||
|
|
||||||
|
|
@ -2244,6 +2251,26 @@ wps_timeout_cb(gpointer user_data)
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wifi_connection_is_new(NMDeviceWifi *self)
|
||||||
|
{
|
||||||
|
NMDevice *device = NM_DEVICE(self);
|
||||||
|
NMActRequest *req;
|
||||||
|
NMSettingsConnection *connection;
|
||||||
|
guint64 timestamp = 0;
|
||||||
|
|
||||||
|
req = nm_device_get_act_request(device);
|
||||||
|
g_return_val_if_fail(NM_IS_ACT_REQUEST(req), TRUE);
|
||||||
|
|
||||||
|
connection = nm_act_request_get_settings_connection(req);
|
||||||
|
g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(connection), TRUE);
|
||||||
|
|
||||||
|
if (nm_settings_connection_get_timestamp(connection, ×tamp) && timestamp != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wifi_secrets_get_secrets(NMDeviceWifi *self,
|
wifi_secrets_get_secrets(NMDeviceWifi *self,
|
||||||
const char *setting_name,
|
const char *setting_name,
|
||||||
|
|
@ -2398,10 +2425,11 @@ handle_8021x_or_psk_auth_fail(NMDeviceWifi *self,
|
||||||
NMSupplicantInterfaceState old_state,
|
NMSupplicantInterfaceState old_state,
|
||||||
int disconnect_reason)
|
int disconnect_reason)
|
||||||
{
|
{
|
||||||
NMDevice *device = NM_DEVICE(self);
|
NMDevice *device = NM_DEVICE(self);
|
||||||
NMActRequest *req;
|
NMActRequest *req;
|
||||||
const char *setting_name = NULL;
|
const char *setting_name = NULL;
|
||||||
gboolean handled = FALSE;
|
NMSecretAgentGetSecretsFlags secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
|
||||||
|
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW;
|
||||||
|
|
||||||
g_return_val_if_fail(new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE);
|
g_return_val_if_fail(new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE);
|
||||||
|
|
||||||
|
|
@ -2411,8 +2439,7 @@ handle_8021x_or_psk_auth_fail(NMDeviceWifi *self,
|
||||||
req = nm_device_get_act_request(NM_DEVICE(self));
|
req = nm_device_get_act_request(NM_DEVICE(self));
|
||||||
g_return_val_if_fail(req != NULL, FALSE);
|
g_return_val_if_fail(req != NULL, FALSE);
|
||||||
|
|
||||||
if (need_new_8021x_secrets(self, old_state, &setting_name)
|
if (need_new_8021x_secrets(self, old_state, &setting_name)) {
|
||||||
|| need_new_wpa_psk(self, old_state, disconnect_reason, &setting_name)) {
|
|
||||||
nm_act_request_clear_secrets(req);
|
nm_act_request_clear_secrets(req);
|
||||||
|
|
||||||
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
|
@ -2422,14 +2449,54 @@ handle_8021x_or_psk_auth_fail(NMDeviceWifi *self,
|
||||||
nm_device_state_changed(device,
|
nm_device_state_changed(device,
|
||||||
NM_DEVICE_STATE_NEED_AUTH,
|
NM_DEVICE_STATE_NEED_AUTH,
|
||||||
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||||
wifi_secrets_get_secrets(self,
|
wifi_secrets_get_secrets(self, setting_name, secret_flags);
|
||||||
setting_name,
|
return TRUE;
|
||||||
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
|
|
||||||
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW);
|
|
||||||
handled = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
if (need_new_wpa_psk(self, old_state, disconnect_reason, &setting_name)) {
|
||||||
|
nm_act_request_clear_secrets(req);
|
||||||
|
cleanup_association_attempt(self, TRUE);
|
||||||
|
|
||||||
|
if (wifi_connection_is_new(self)) {
|
||||||
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
"Activation: (wifi) new connection disconnected during association, asking for "
|
||||||
|
"new key");
|
||||||
|
nm_device_state_changed(device,
|
||||||
|
NM_DEVICE_STATE_NEED_AUTH,
|
||||||
|
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||||
|
wifi_secrets_get_secrets(self, setting_name, secret_flags);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_device_auth_retries_try_next(device)) {
|
||||||
|
nm_device_state_changed(device,
|
||||||
|
NM_DEVICE_STATE_FAILED,
|
||||||
|
NM_DEVICE_STATE_REASON_NO_SECRETS);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nm_device_auth_retries_has_next(device)) {
|
||||||
|
secret_flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW;
|
||||||
|
_LOGI(
|
||||||
|
LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
"Activation: (wifi) disconnected during association, reauthenticating connection");
|
||||||
|
} else {
|
||||||
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
"Activation: (wifi) disconnected during association, asking for new key");
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_device_state_changed(device,
|
||||||
|
NM_DEVICE_STATE_NEED_AUTH,
|
||||||
|
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||||
|
wifi_secrets_get_secrets(self, setting_name, secret_flags);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
"Activation: (wifi) disconnected during association, retrying connection");
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -2861,6 +2928,12 @@ supplicant_iface_notify_wpa_psk_mismatch_cb(NMSupplicantInterface *iface, NMDevi
|
||||||
if (nm_device_get_state(device) != NM_DEVICE_STATE_CONFIG)
|
if (nm_device_get_state(device) != NM_DEVICE_STATE_CONFIG)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!wifi_connection_is_new(self) && nm_device_auth_retries_has_next(device)) {
|
||||||
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
"Activation: (wifi) psk mismatch reported by supplicant, retrying connection");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
"Activation: (wifi) psk mismatch reported by supplicant, asking for new key");
|
"Activation: (wifi) psk mismatch reported by supplicant, asking for new key");
|
||||||
|
|
||||||
|
|
@ -2879,6 +2952,34 @@ supplicant_iface_notify_wpa_psk_mismatch_cb(NMSupplicantInterface *iface, NMDevi
|
||||||
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW);
|
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supplicant_iface_notify_wpa_sae_mismatch_cb(NMSupplicantInterface *iface, NMDeviceWifi *self)
|
||||||
|
{
|
||||||
|
NMDevice *device = NM_DEVICE(self);
|
||||||
|
NMActRequest *req;
|
||||||
|
const char *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
|
||||||
|
|
||||||
|
if (nm_device_get_state(device) != NM_DEVICE_STATE_CONFIG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_LOGI(LOGD_DEVICE | LOGD_WIFI,
|
||||||
|
"Activation: (wifi) SAE password mismatch reported by supplicant, asking for new key");
|
||||||
|
|
||||||
|
req = nm_device_get_act_request(NM_DEVICE(self));
|
||||||
|
g_return_if_fail(req != NULL);
|
||||||
|
|
||||||
|
nm_act_request_clear_secrets(req);
|
||||||
|
|
||||||
|
cleanup_association_attempt(self, TRUE);
|
||||||
|
nm_device_state_changed(device,
|
||||||
|
NM_DEVICE_STATE_NEED_AUTH,
|
||||||
|
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||||
|
wifi_secrets_get_secrets(self,
|
||||||
|
setting_name,
|
||||||
|
NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION
|
||||||
|
| NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* supplicant_connection_timeout_cb
|
* supplicant_connection_timeout_cb
|
||||||
*
|
*
|
||||||
|
|
@ -3222,8 +3323,19 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
||||||
static void
|
static void
|
||||||
ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP *ap)
|
ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP *ap)
|
||||||
{
|
{
|
||||||
guint32 a_freqs[] = {5180, 5200, 5220, 5745, 5765, 5785, 5805, 0};
|
guint32 freqs_a[] = {5180, /* only U-NII-1 channels: non-DFS and available everywhere */
|
||||||
guint32 bg_freqs[] = {2412, 2437, 2462, 2472, 0};
|
5200,
|
||||||
|
5220,
|
||||||
|
5240,
|
||||||
|
0};
|
||||||
|
guint32 freqs_bg[] = {2412, 2437, 2462, 2472, 0};
|
||||||
|
guint32 freqs_6ghz[] = {5975, /* only U-NII-5 PSC channels, for better compatibility */
|
||||||
|
6055,
|
||||||
|
6135,
|
||||||
|
6215,
|
||||||
|
6295,
|
||||||
|
6375,
|
||||||
|
0};
|
||||||
guint32 *rnd_freqs;
|
guint32 *rnd_freqs;
|
||||||
guint rnd_freqs_len;
|
guint rnd_freqs_len;
|
||||||
NMDevice *device = NM_DEVICE(self);
|
NMDevice *device = NM_DEVICE(self);
|
||||||
|
|
@ -3234,7 +3346,7 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP
|
||||||
guint l;
|
guint l;
|
||||||
|
|
||||||
nm_assert(ap);
|
nm_assert(ap);
|
||||||
nm_assert(NM_IN_STRSET(band, NULL, "a", "bg"));
|
nm_assert(NM_IN_STRSET(band, NULL, "a", "bg", "6GHz"));
|
||||||
|
|
||||||
if (nm_wifi_ap_get_freq(ap))
|
if (nm_wifi_ap_get_freq(ap))
|
||||||
return;
|
return;
|
||||||
|
|
@ -3268,11 +3380,14 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nm_streq0(band, "a")) {
|
if (nm_streq0(band, "a")) {
|
||||||
rnd_freqs = a_freqs;
|
rnd_freqs = freqs_a;
|
||||||
rnd_freqs_len = G_N_ELEMENTS(a_freqs) - 1;
|
rnd_freqs_len = G_N_ELEMENTS(freqs_a) - 1;
|
||||||
|
} else if (nm_streq0(band, "6GHz")) {
|
||||||
|
rnd_freqs = freqs_6ghz;
|
||||||
|
rnd_freqs_len = G_N_ELEMENTS(freqs_6ghz) - 1;
|
||||||
} else {
|
} else {
|
||||||
rnd_freqs = bg_freqs;
|
rnd_freqs = freqs_bg;
|
||||||
rnd_freqs_len = G_N_ELEMENTS(bg_freqs) - 1;
|
rnd_freqs_len = G_N_ELEMENTS(freqs_bg) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shuffle the frequencies (inplace). The idea is to choose
|
/* shuffle the frequencies (inplace). The idea is to choose
|
||||||
|
|
|
||||||
|
|
@ -574,16 +574,6 @@ nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64
|
||||||
return str_buf;
|
return str_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
|
||||||
freq_to_band(guint32 freq)
|
|
||||||
{
|
|
||||||
if (freq >= 4915 && freq <= 5825)
|
|
||||||
return 5;
|
|
||||||
else if (freq >= 2412 && freq <= 2484)
|
|
||||||
return 2;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection)
|
nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection)
|
||||||
{
|
{
|
||||||
|
|
@ -631,12 +621,12 @@ nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection)
|
||||||
|
|
||||||
band = nm_setting_wireless_get_band(s_wireless);
|
band = nm_setting_wireless_get_band(s_wireless);
|
||||||
if (band) {
|
if (band) {
|
||||||
guint ap_band = freq_to_band(priv->freq);
|
const char *ap_band = nm_wifi_freq_to_band_prop(priv->freq);
|
||||||
|
|
||||||
if (!strcmp(band, "a") && ap_band != 5)
|
if (!nm_streq(band, ap_band))
|
||||||
return FALSE;
|
|
||||||
else if (!strcmp(band, "bg") && ap_band != 2)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = nm_setting_wireless_get_channel(s_wireless);
|
channel = nm_setting_wireless_get_channel(s_wireless);
|
||||||
|
|
|
||||||
|
|
@ -639,7 +639,7 @@ nm_wifi_utils_complete_connection(GBytes *ap_ssid,
|
||||||
chan_valid = FALSE;
|
chan_valid = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
band = nm_utils_wifi_freq_to_band(ap_freq);
|
band = nm_wifi_freq_to_band_prop(ap_freq);
|
||||||
if (band) {
|
if (band) {
|
||||||
g_object_set(s_wifi, NM_SETTING_WIRELESS_BAND, band, NULL);
|
g_object_set(s_wifi, NM_SETTING_WIRELESS_BAND, band, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1929,3 +1929,19 @@ nm_wifi_utils_wfd_info_eq(const NMIwdWfdInfo *a, const NMIwdWfdInfo *b)
|
||||||
return a->source == b->source && a->sink == b->sink && a->port == b->port
|
return a->source == b->source && a->sink == b->sink && a->port == b->port
|
||||||
&& a->has_audio == b->has_audio && a->has_uibc == b->has_uibc && a->has_cp == b->has_cp;
|
&& a->has_audio == b->has_audio && a->has_uibc == b->has_uibc && a->has_cp == b->has_cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_wifi_freq_to_band_prop(guint32 freq)
|
||||||
|
{
|
||||||
|
switch (nm_utils_wifi_freq_to_band(freq)) {
|
||||||
|
case NM_WIFI_BAND_2_4_GHZ:
|
||||||
|
return "bg";
|
||||||
|
case NM_WIFI_BAND_5_GHZ:
|
||||||
|
return "a";
|
||||||
|
case NM_WIFI_BAND_6_GHZ:
|
||||||
|
return "6GHz";
|
||||||
|
default:
|
||||||
|
case NM_WIFI_BAND_UNKNOWN:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,4 +56,6 @@ bool nm_wifi_utils_parse_wfd_ies(GBytes *ies, NMIwdWfdInfo *out_wfd);
|
||||||
GBytes *nm_wifi_utils_build_wfd_ies(const NMIwdWfdInfo *wfd);
|
GBytes *nm_wifi_utils_build_wfd_ies(const NMIwdWfdInfo *wfd);
|
||||||
bool nm_wifi_utils_wfd_info_eq(const NMIwdWfdInfo *a, const NMIwdWfdInfo *b);
|
bool nm_wifi_utils_wfd_info_eq(const NMIwdWfdInfo *a, const NMIwdWfdInfo *b);
|
||||||
|
|
||||||
|
const char *nm_wifi_freq_to_band_prop(guint32 freq);
|
||||||
|
|
||||||
#endif /* __NM_WIFI_UTILS_H__ */
|
#endif /* __NM_WIFI_UTILS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -258,16 +258,7 @@ modm_handle_name_owner_changed(MMManager *modem_manager, GParamSpec *pspec, NMMo
|
||||||
/* Available! */
|
/* Available! */
|
||||||
g_free(name_owner);
|
g_free(name_owner);
|
||||||
|
|
||||||
/* Hack alert: GDBusObjectManagerClient won't signal neither 'object-added'
|
modm_manager_available(self);
|
||||||
* nor 'object-removed' if it was created while there was no ModemManager in
|
|
||||||
* the bus. This hack avoids this issue until we get a GIO with the fix
|
|
||||||
* included... */
|
|
||||||
modm_clear_manager(self);
|
|
||||||
modm_ensure_manager(self);
|
|
||||||
|
|
||||||
/* Whenever GDBusObjectManagerClient is fixed, we can just do the following:
|
|
||||||
* modm_manager_available (self);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -1460,7 +1460,9 @@ nm_dhcp_client_schedule_ipv6_only_restart(NMDhcpClient *self, guint timeout)
|
||||||
nm_assert(!priv->is_stopped);
|
nm_assert(!priv->is_stopped);
|
||||||
|
|
||||||
timeout = NM_MAX(priv->v4.ipv6_only_min_wait, timeout);
|
timeout = NM_MAX(priv->v4.ipv6_only_min_wait, timeout);
|
||||||
_LOGI("received option \"ipv6-only-preferred\": stopping DHCPv4 for %u seconds", timeout);
|
_LOGI("received option \"ipv6-only-preferred\": stopping DHCPv4 for %u seconds. Set "
|
||||||
|
"ipv4.dhcp-ipv6-only-preferred=no to force the use of IPv4 on this IPv6-mostly network",
|
||||||
|
timeout);
|
||||||
|
|
||||||
nm_dhcp_client_stop(self, FALSE);
|
nm_dhcp_client_stop(self, FALSE);
|
||||||
nm_clear_g_source_inst(&priv->no_lease_timeout_source);
|
nm_clear_g_source_inst(&priv->no_lease_timeout_source);
|
||||||
|
|
|
||||||
|
|
@ -418,7 +418,6 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
||||||
in_addr_t gateway;
|
in_addr_t gateway;
|
||||||
uint8_t plen;
|
uint8_t plen;
|
||||||
guint32 m;
|
guint32 m;
|
||||||
gboolean has_router_from_classless = FALSE;
|
|
||||||
gboolean has_classless = FALSE;
|
gboolean has_classless = FALSE;
|
||||||
guint32 default_route_metric_offset = 0;
|
guint32 default_route_metric_offset = 0;
|
||||||
const guint8 *l_data;
|
const guint8 *l_data;
|
||||||
|
|
@ -434,7 +433,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
||||||
* We will however also parse one of the options into the "l3cd" for configuring routing.
|
* We will however also parse one of the options into the "l3cd" for configuring routing.
|
||||||
* Thereby we prefer 121 over 249 over 33.
|
* Thereby we prefer 121 over 249 over 33.
|
||||||
*
|
*
|
||||||
* Preferring 121 over 33 is defined by RFC 3443.
|
* Preferring 121 over 33 is defined by RFC 3442.
|
||||||
* Preferring 121 over 249 over 33 is made up as it makes sense (the MS docs are not very clear).
|
* Preferring 121 over 249 over 33 is made up as it makes sense (the MS docs are not very clear).
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
|
|
@ -460,8 +459,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
||||||
if (plen == 0) {
|
if (plen == 0) {
|
||||||
/* if there are multiple default routes, we add them with differing
|
/* if there are multiple default routes, we add them with differing
|
||||||
* metrics. */
|
* metrics. */
|
||||||
m = default_route_metric_offset++;
|
m = default_route_metric_offset++;
|
||||||
has_router_from_classless = TRUE;
|
|
||||||
} else
|
} else
|
||||||
m = 0;
|
m = 0;
|
||||||
|
|
||||||
|
|
@ -495,7 +493,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
||||||
nm_str_buf_append_printf(sbuf, "%s/%d %s", dest_str, (int) plen, gateway_str);
|
nm_str_buf_append_printf(sbuf, "%s/%d %s", dest_str, (int) plen, gateway_str);
|
||||||
|
|
||||||
if (has_classless) {
|
if (has_classless) {
|
||||||
/* RFC 3443: if the DHCP server returns both a Classless Static Routes
|
/* RFC 3442: if the DHCP server returns both a Classless Static Routes
|
||||||
* option and a Static Routes option, the DHCP client MUST ignore the
|
* option and a Static Routes option, the DHCP client MUST ignore the
|
||||||
* Static Routes option. */
|
* Static Routes option. */
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -539,13 +537,10 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_router_from_classless) {
|
if (has_classless) {
|
||||||
/* If the DHCP server returns both a Classless Static Routes option and a
|
/* RFC 3442: if the DHCP server returns both a Classless Static Routes
|
||||||
* Router option, the DHCP client MUST ignore the Router option [RFC 3442].
|
* option and a Router option, the DHCP client MUST ignore the Router
|
||||||
*
|
* option. */
|
||||||
* Be more lenient and ignore the Router option only if Classless Static
|
|
||||||
* Routes contain a default gateway (as other DHCP backends do).
|
|
||||||
*/
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ ip4_process_dhcpcd_rfc3442_routes(const char *iface,
|
||||||
in_addr_t address,
|
in_addr_t address,
|
||||||
guint32 *out_gwaddr)
|
guint32 *out_gwaddr)
|
||||||
{
|
{
|
||||||
gs_free const char **routes = NULL;
|
gs_free char **routes = NULL;
|
||||||
const char **r;
|
char **r;
|
||||||
gboolean have_routes = FALSE;
|
gboolean have_routes = FALSE;
|
||||||
|
|
||||||
routes = nm_strsplit_set(str, " ");
|
routes = (char **) nm_strsplit_set(str, " ");
|
||||||
if (!routes)
|
if (!routes)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1510,8 +1510,8 @@ _domain_track_is_shadowed(GHashTable *ht,
|
||||||
const char **out_parent,
|
const char **out_parent,
|
||||||
int *out_parent_priority)
|
int *out_parent_priority)
|
||||||
{
|
{
|
||||||
char *parent;
|
const char *parent;
|
||||||
int parent_priority;
|
int parent_priority;
|
||||||
|
|
||||||
if (!ht)
|
if (!ht)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
||||||
|
|
@ -298,12 +298,6 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
_nm_utils_is_manager_process = TRUE;
|
_nm_utils_is_manager_process = TRUE;
|
||||||
|
|
||||||
/* Known to cause a possible deadlock upon GDBus initialization:
|
|
||||||
* https://bugzilla.gnome.org/show_bug.cgi?id=674885 */
|
|
||||||
g_type_ensure(G_TYPE_SOCKET);
|
|
||||||
g_type_ensure(G_TYPE_DBUS_CONNECTION);
|
|
||||||
g_type_ensure(NM_TYPE_DBUS_MANAGER);
|
|
||||||
|
|
||||||
/* we determine a first-start (contrary to a restart during the same boot)
|
/* we determine a first-start (contrary to a restart during the same boot)
|
||||||
* based on the existence of NM_CONFIG_DEVICE_STATE_DIR directory. */
|
* based on the existence of NM_CONFIG_DEVICE_STATE_DIR directory. */
|
||||||
config_cli = nm_config_cmd_line_options_new(
|
config_cli = nm_config_cmd_line_options_new(
|
||||||
|
|
@ -328,6 +322,12 @@ main(int argc, char *argv[])
|
||||||
exit(result);
|
exit(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Known to cause a possible deadlock upon GDBus initialization:
|
||||||
|
* https://bugzilla.gnome.org/show_bug.cgi?id=674885 */
|
||||||
|
g_type_ensure(G_TYPE_SOCKET);
|
||||||
|
g_type_ensure(G_TYPE_DBUS_CONNECTION);
|
||||||
|
g_type_ensure(NM_TYPE_DBUS_MANAGER);
|
||||||
|
|
||||||
nm_main_utils_ensure_not_running_pidfile(global_opt.pidfile);
|
nm_main_utils_ensure_not_running_pidfile(global_opt.pidfile);
|
||||||
|
|
||||||
nm_main_utils_ensure_statedir();
|
nm_main_utils_ensure_statedir();
|
||||||
|
|
@ -461,14 +461,8 @@ main(int argc, char *argv[])
|
||||||
/* the first access to State causes the file to be read (and possibly print a warning) */
|
/* the first access to State causes the file to be read (and possibly print a warning) */
|
||||||
nm_config_state_get(config);
|
nm_config_state_get(config);
|
||||||
|
|
||||||
nm_log_dbg(LOGD_CORE,
|
nm_log_dbg(LOGD_CORE, "WEXT support is %s", HAVE_WEXT ? "enabled" : "disabled");
|
||||||
"WEXT support is %s",
|
nm_log_dbg(LOGD_CORE, "CLAT support is %s", HAVE_CLAT ? "enabled" : "disabled");
|
||||||
#if HAVE_WEXT
|
|
||||||
"enabled"
|
|
||||||
#else
|
|
||||||
"disabled"
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!_dbus_manager_init(config))
|
if (!_dbus_manager_init(config))
|
||||||
goto done_no_manager;
|
goto done_no_manager;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,15 @@ install_data(
|
||||||
|
|
||||||
core_plugins = []
|
core_plugins = []
|
||||||
|
|
||||||
|
subdir('bpf')
|
||||||
|
|
||||||
|
base_sources_addon = []
|
||||||
|
base_deps_addon = []
|
||||||
|
if enable_clat
|
||||||
|
base_sources_addon += [clat_skel_h]
|
||||||
|
base_deps_addon += [libbpf]
|
||||||
|
endif
|
||||||
|
|
||||||
libNetworkManagerBase = static_library(
|
libNetworkManagerBase = static_library(
|
||||||
'NetworkManagerBase',
|
'NetworkManagerBase',
|
||||||
sources: files(
|
sources: files(
|
||||||
|
|
@ -55,13 +64,13 @@ libNetworkManagerBase = static_library(
|
||||||
'nm-l3cfg.c',
|
'nm-l3cfg.c',
|
||||||
'nm-bond-manager.c',
|
'nm-bond-manager.c',
|
||||||
'nm-ip-config.c',
|
'nm-ip-config.c',
|
||||||
),
|
) + base_sources_addon,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
core_default_dep,
|
core_default_dep,
|
||||||
libnm_core_public_dep,
|
libnm_core_public_dep,
|
||||||
libsystemd_dep,
|
libsystemd_dep,
|
||||||
libudev_dep,
|
libudev_dep,
|
||||||
],
|
] + base_deps_addon,
|
||||||
)
|
)
|
||||||
|
|
||||||
nm_deps = [
|
nm_deps = [
|
||||||
|
|
@ -102,6 +111,7 @@ libNetworkManager = static_library(
|
||||||
'devices/nm-device-ethernet-utils.c',
|
'devices/nm-device-ethernet-utils.c',
|
||||||
'devices/nm-device-factory.c',
|
'devices/nm-device-factory.c',
|
||||||
'devices/nm-device-generic.c',
|
'devices/nm-device-generic.c',
|
||||||
|
'devices/nm-device-geneve.c',
|
||||||
'devices/nm-device-hsr.c',
|
'devices/nm-device-hsr.c',
|
||||||
'devices/nm-device-infiniband.c',
|
'devices/nm-device-infiniband.c',
|
||||||
'devices/nm-device-ip-tunnel.c',
|
'devices/nm-device-ip-tunnel.c',
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,30 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
/* PREF64 */
|
||||||
|
ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_PREF64) {
|
||||||
|
NMNDiscPref64 pref64;
|
||||||
|
|
||||||
|
pref64 = (NMNDiscPref64) {
|
||||||
|
.prefix = *ndp_msg_opt_pref64_prefix(msg, offset),
|
||||||
|
.plen = ndp_msg_opt_pref64_prefix_length(msg, offset),
|
||||||
|
.gateway = gateway.address,
|
||||||
|
.gateway_preference = gateway.preference,
|
||||||
|
.expiry_msec =
|
||||||
|
_nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_pref64_lifetime(msg, offset)),
|
||||||
|
.gateway_expiry_msec = gateway.expiry_msec,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* libndp should only return lengths defined in RFC 8781 */
|
||||||
|
nm_assert(NM_IN_SET(pref64.plen, 96, 64, 56, 48, 40, 32));
|
||||||
|
|
||||||
|
if (nm_ndisc_add_pref64(ndisc, &pref64, now_msec)) {
|
||||||
|
changed |= NM_NDISC_CONFIG_PREF64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nm_ndisc_ra_received(ndisc, now_msec, changed);
|
nm_ndisc_ra_received(ndisc, now_msec, changed);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ struct _NMNDiscDataInternal {
|
||||||
NMNDiscData public;
|
NMNDiscData public;
|
||||||
GArray *gateways;
|
GArray *gateways;
|
||||||
GArray *addresses;
|
GArray *addresses;
|
||||||
|
GArray *pref64;
|
||||||
GArray *routes;
|
GArray *routes;
|
||||||
GArray *dns_servers;
|
GArray *dns_servers;
|
||||||
GArray *dns_domains;
|
GArray *dns_domains;
|
||||||
|
|
@ -28,6 +29,7 @@ gboolean nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new_item, gi
|
||||||
gboolean
|
gboolean
|
||||||
nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item, gint64 now_msec);
|
nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item, gint64 now_msec);
|
||||||
gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec);
|
gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec);
|
||||||
|
gboolean nm_ndisc_add_pref64(NMNDisc *ndisc, const NMNDiscPref64 *new_item, gint64 now_msec);
|
||||||
gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec);
|
gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec);
|
||||||
gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_item, gint64 now_msec);
|
gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_item, gint64 now_msec);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#define _SIZE_MAX_ROUTES 1000u
|
#define _SIZE_MAX_ROUTES 1000u
|
||||||
#define _SIZE_MAX_DNS_SERVERS 64u
|
#define _SIZE_MAX_DNS_SERVERS 64u
|
||||||
#define _SIZE_MAX_DNS_DOMAINS 64u
|
#define _SIZE_MAX_DNS_DOMAINS 64u
|
||||||
|
#define _SIZE_MAX_PREF64 8u
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -109,7 +110,8 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx,
|
||||||
int ifindex,
|
int ifindex,
|
||||||
const NMNDiscData *rdata,
|
const NMNDiscData *rdata,
|
||||||
NMSettingIP6ConfigPrivacy ip6_privacy,
|
NMSettingIP6ConfigPrivacy ip6_privacy,
|
||||||
NMUtilsIPv6IfaceId *token)
|
NMUtilsIPv6IfaceId *token,
|
||||||
|
const char *network_id)
|
||||||
{
|
{
|
||||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||||
guint32 ifa_flags;
|
guint32 ifa_flags;
|
||||||
|
|
@ -211,13 +213,21 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx,
|
||||||
for (i = 0; i < rdata->dns_domains_n; i++)
|
for (i = 0; i < rdata->dns_domains_n; i++)
|
||||||
nm_l3_config_data_add_search(l3cd, AF_INET6, rdata->dns_domains[i].domain);
|
nm_l3_config_data_add_search(l3cd, AF_INET6, rdata->dns_domains[i].domain);
|
||||||
|
|
||||||
|
if (rdata->pref64_n > 0) {
|
||||||
|
nm_l3_config_data_set_pref64(l3cd, rdata->pref64[0].prefix, rdata->pref64[0].plen);
|
||||||
|
} else {
|
||||||
|
nm_l3_config_data_set_pref64_valid(l3cd, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
nm_l3_config_data_set_ndisc_hop_limit(l3cd, rdata->hop_limit);
|
nm_l3_config_data_set_ndisc_hop_limit(l3cd, rdata->hop_limit);
|
||||||
nm_l3_config_data_set_ndisc_reachable_time_msec(l3cd, rdata->reachable_time_ms);
|
nm_l3_config_data_set_ndisc_reachable_time_msec(l3cd, rdata->reachable_time_ms);
|
||||||
nm_l3_config_data_set_ndisc_retrans_timer_msec(l3cd, rdata->retrans_timer_ms);
|
nm_l3_config_data_set_ndisc_retrans_timer_msec(l3cd, rdata->retrans_timer_ms);
|
||||||
|
|
||||||
nm_l3_config_data_set_ip6_mtu(l3cd, rdata->mtu);
|
nm_l3_config_data_set_ip6_mtu_ra(l3cd, rdata->mtu);
|
||||||
if (token)
|
if (token)
|
||||||
nm_l3_config_data_set_ip6_token(l3cd, *token);
|
nm_l3_config_data_set_ip6_token(l3cd, *token);
|
||||||
|
if (network_id)
|
||||||
|
nm_l3_config_data_set_network_id(l3cd, network_id);
|
||||||
|
|
||||||
return g_steal_pointer(&l3cd);
|
return g_steal_pointer(&l3cd);
|
||||||
}
|
}
|
||||||
|
|
@ -416,6 +426,7 @@ _data_complete(NMNDiscDataInternal *data)
|
||||||
_SET(data, gateways);
|
_SET(data, gateways);
|
||||||
_SET(data, addresses);
|
_SET(data, addresses);
|
||||||
_SET(data, routes);
|
_SET(data, routes);
|
||||||
|
_SET(data, pref64);
|
||||||
_SET(data, dns_servers);
|
_SET(data, dns_servers);
|
||||||
_SET(data, dns_domains);
|
_SET(data, dns_domains);
|
||||||
#undef _SET
|
#undef _SET
|
||||||
|
|
@ -437,7 +448,8 @@ nm_ndisc_emit_config_change(NMNDisc *self, NMNDiscConfigMap changed)
|
||||||
nm_l3cfg_get_ifindex(priv->config.l3cfg),
|
nm_l3cfg_get_ifindex(priv->config.l3cfg),
|
||||||
rdata,
|
rdata,
|
||||||
priv->config.ip6_privacy,
|
priv->config.ip6_privacy,
|
||||||
priv->iid_is_token ? &priv->iid : NULL);
|
priv->iid_is_token ? &priv->iid : NULL,
|
||||||
|
priv->config.network_id);
|
||||||
l3cd = nm_l3_config_data_seal(l3cd);
|
l3cd = nm_l3_config_data_seal(l3cd);
|
||||||
|
|
||||||
if (!nm_l3_config_data_equal(priv->l3cd, l3cd))
|
if (!nm_l3_config_data_equal(priv->l3cd, l3cd))
|
||||||
|
|
@ -760,6 +772,59 @@ nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_ndisc_add_pref64(NMNDisc *ndisc, const NMNDiscPref64 *new_item, gint64 now_msec)
|
||||||
|
{
|
||||||
|
NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata;
|
||||||
|
guint i;
|
||||||
|
guint insert_idx = G_MAXUINT;
|
||||||
|
|
||||||
|
for (i = 0; i < rdata->pref64->len;) {
|
||||||
|
NMNDiscPref64 *item = &nm_g_array_index(rdata->pref64, NMNDiscPref64, i);
|
||||||
|
|
||||||
|
if (item->plen == new_item->plen && IN6_ARE_ADDR_EQUAL(&item->prefix, &new_item->prefix)
|
||||||
|
&& IN6_ARE_ADDR_EQUAL(&item->gateway, &new_item->gateway)) {
|
||||||
|
if (new_item->expiry_msec <= now_msec) {
|
||||||
|
g_array_remove_index(rdata->pref64, i);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->gateway_preference != new_item->gateway_preference) {
|
||||||
|
g_array_remove_index(rdata->pref64, i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->gateway_expiry_msec = new_item->gateway_expiry_msec;
|
||||||
|
|
||||||
|
if (item->expiry_msec == new_item->expiry_msec)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
item->expiry_msec = new_item->expiry_msec;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put before less preferable gateways. */
|
||||||
|
if (_preference_to_priority(item->gateway_preference)
|
||||||
|
< _preference_to_priority(new_item->gateway_preference)
|
||||||
|
&& insert_idx == G_MAXUINT)
|
||||||
|
insert_idx = i;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdata->pref64->len >= _SIZE_MAX_PREF64)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (new_item->expiry_msec <= now_msec)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_array_insert_val(rdata->pref64,
|
||||||
|
insert_idx == G_MAXUINT ? rdata->pref64->len : insert_idx,
|
||||||
|
*new_item);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec)
|
nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec)
|
||||||
{
|
{
|
||||||
|
|
@ -1400,6 +1465,17 @@ _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed)
|
||||||
nm_icmpv6_router_pref_to_string(route->preference, str_pref, sizeof(str_pref)),
|
nm_icmpv6_router_pref_to_string(route->preference, str_pref, sizeof(str_pref)),
|
||||||
get_exp(str_exp, now_msec, route));
|
get_exp(str_exp, now_msec, route));
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < rdata->pref64->len; i++) {
|
||||||
|
const NMNDiscPref64 *pref64 = &nm_g_array_index(rdata->pref64, NMNDiscPref64, i);
|
||||||
|
char addrstr2[NM_INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
_LOGD(" pref64 %s/%u via %s exp %s",
|
||||||
|
nm_inet6_ntop(&pref64->prefix, addrstr),
|
||||||
|
pref64->plen,
|
||||||
|
nm_inet6_ntop(&pref64->gateway, addrstr2),
|
||||||
|
get_exp(str_exp, now_msec, pref64));
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < rdata->dns_servers->len; i++) {
|
for (i = 0; i < rdata->dns_servers->len; i++) {
|
||||||
const NMNDiscDNSServer *dns_server =
|
const NMNDiscDNSServer *dns_server =
|
||||||
&nm_g_array_index(rdata->dns_servers, NMNDiscDNSServer, i);
|
&nm_g_array_index(rdata->dns_servers, NMNDiscDNSServer, i);
|
||||||
|
|
@ -1524,6 +1600,45 @@ clean_routes(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64
|
||||||
*changed |= NM_NDISC_CONFIG_ROUTES;
|
*changed |= NM_NDISC_CONFIG_ROUTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clean_pref64(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec)
|
||||||
|
{
|
||||||
|
NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata;
|
||||||
|
NMNDiscPref64 *arr;
|
||||||
|
guint i;
|
||||||
|
guint j;
|
||||||
|
|
||||||
|
if (rdata->pref64->len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
arr = &nm_g_array_first(rdata->pref64, NMNDiscPref64);
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < rdata->pref64->len; i++) {
|
||||||
|
if (!expiry_next(now_msec, arr[i].expiry_msec, next_msec)
|
||||||
|
|| !expiry_next(now_msec,
|
||||||
|
arr[i].gateway_expiry_msec,
|
||||||
|
next_msec)) { /* no gateway no party */
|
||||||
|
if (i == 0) {
|
||||||
|
/* Emit the changed signal only when the first PREF64 expires,
|
||||||
|
* because only the first item is exported into the l3cd. Changes
|
||||||
|
* in other PREF64s are not relevant. */
|
||||||
|
*changed |= NM_NDISC_CONFIG_PREF64;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != j)
|
||||||
|
arr[j] = arr[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != j) {
|
||||||
|
g_array_set_size(rdata->pref64, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
_array_set_size_max(rdata->pref64, _SIZE_MAX_PREF64);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clean_dns_servers(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec)
|
clean_dns_servers(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec)
|
||||||
{
|
{
|
||||||
|
|
@ -1600,6 +1715,7 @@ check_timestamps(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed)
|
||||||
clean_gateways(ndisc, now_msec, &changed, &next_msec);
|
clean_gateways(ndisc, now_msec, &changed, &next_msec);
|
||||||
clean_addresses(ndisc, now_msec, &changed, &next_msec);
|
clean_addresses(ndisc, now_msec, &changed, &next_msec);
|
||||||
clean_routes(ndisc, now_msec, &changed, &next_msec);
|
clean_routes(ndisc, now_msec, &changed, &next_msec);
|
||||||
|
clean_pref64(ndisc, now_msec, &changed, &next_msec);
|
||||||
clean_dns_servers(ndisc, now_msec, &changed, &next_msec);
|
clean_dns_servers(ndisc, now_msec, &changed, &next_msec);
|
||||||
clean_dns_domains(ndisc, now_msec, &changed, &next_msec);
|
clean_dns_domains(ndisc, now_msec, &changed, &next_msec);
|
||||||
|
|
||||||
|
|
@ -1919,6 +2035,7 @@ nm_ndisc_init(NMNDisc *ndisc)
|
||||||
rdata->gateways = g_array_new(FALSE, FALSE, sizeof(NMNDiscGateway));
|
rdata->gateways = g_array_new(FALSE, FALSE, sizeof(NMNDiscGateway));
|
||||||
rdata->addresses = g_array_new(FALSE, FALSE, sizeof(NMNDiscAddress));
|
rdata->addresses = g_array_new(FALSE, FALSE, sizeof(NMNDiscAddress));
|
||||||
rdata->routes = g_array_new(FALSE, FALSE, sizeof(NMNDiscRoute));
|
rdata->routes = g_array_new(FALSE, FALSE, sizeof(NMNDiscRoute));
|
||||||
|
rdata->pref64 = g_array_new(FALSE, FALSE, sizeof(NMNDiscPref64));
|
||||||
rdata->dns_servers = g_array_new(FALSE, FALSE, sizeof(NMNDiscDNSServer));
|
rdata->dns_servers = g_array_new(FALSE, FALSE, sizeof(NMNDiscDNSServer));
|
||||||
rdata->dns_domains = g_array_new(FALSE, FALSE, sizeof(NMNDiscDNSDomain));
|
rdata->dns_domains = g_array_new(FALSE, FALSE, sizeof(NMNDiscDNSDomain));
|
||||||
g_array_set_clear_func(rdata->dns_domains, dns_domain_free);
|
g_array_set_clear_func(rdata->dns_domains, dns_domain_free);
|
||||||
|
|
@ -1951,6 +2068,7 @@ finalize(GObject *object)
|
||||||
g_array_unref(rdata->gateways);
|
g_array_unref(rdata->gateways);
|
||||||
g_array_unref(rdata->addresses);
|
g_array_unref(rdata->addresses);
|
||||||
g_array_unref(rdata->routes);
|
g_array_unref(rdata->routes);
|
||||||
|
g_array_unref(rdata->pref64);
|
||||||
g_array_unref(rdata->dns_servers);
|
g_array_unref(rdata->dns_servers);
|
||||||
g_array_unref(rdata->dns_domains);
|
g_array_unref(rdata->dns_domains);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,15 @@ typedef struct _NMNDiscRoute {
|
||||||
bool duplicate : 1;
|
bool duplicate : 1;
|
||||||
} NMNDiscRoute;
|
} NMNDiscRoute;
|
||||||
|
|
||||||
|
typedef struct _NMNDiscPref64 {
|
||||||
|
struct in6_addr prefix;
|
||||||
|
struct in6_addr gateway;
|
||||||
|
gint64 expiry_msec;
|
||||||
|
gint64 gateway_expiry_msec;
|
||||||
|
NMIcmpv6RouterPref gateway_preference;
|
||||||
|
guint8 plen;
|
||||||
|
} NMNDiscPref64;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct in6_addr address;
|
struct in6_addr address;
|
||||||
gint64 expiry_msec;
|
gint64 expiry_msec;
|
||||||
|
|
@ -141,6 +150,7 @@ typedef enum {
|
||||||
NM_NDISC_CONFIG_MTU = 1 << 7,
|
NM_NDISC_CONFIG_MTU = 1 << 7,
|
||||||
NM_NDISC_CONFIG_REACHABLE_TIME = 1 << 8,
|
NM_NDISC_CONFIG_REACHABLE_TIME = 1 << 8,
|
||||||
NM_NDISC_CONFIG_RETRANS_TIMER = 1 << 9,
|
NM_NDISC_CONFIG_RETRANS_TIMER = 1 << 9,
|
||||||
|
NM_NDISC_CONFIG_PREF64 = 1 << 10,
|
||||||
} NMNDiscConfigMap;
|
} NMNDiscConfigMap;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -188,12 +198,14 @@ typedef struct {
|
||||||
guint gateways_n;
|
guint gateways_n;
|
||||||
guint addresses_n;
|
guint addresses_n;
|
||||||
guint routes_n;
|
guint routes_n;
|
||||||
|
guint pref64_n;
|
||||||
guint dns_servers_n;
|
guint dns_servers_n;
|
||||||
guint dns_domains_n;
|
guint dns_domains_n;
|
||||||
|
|
||||||
const NMNDiscGateway *gateways;
|
const NMNDiscGateway *gateways;
|
||||||
const NMNDiscAddress *addresses;
|
const NMNDiscAddress *addresses;
|
||||||
const NMNDiscRoute *routes;
|
const NMNDiscRoute *routes;
|
||||||
|
const NMNDiscPref64 *pref64;
|
||||||
const NMNDiscDNSServer *dns_servers;
|
const NMNDiscDNSServer *dns_servers;
|
||||||
const NMNDiscDNSDomain *dns_domains;
|
const NMNDiscDNSDomain *dns_domains;
|
||||||
} NMNDiscData;
|
} NMNDiscData;
|
||||||
|
|
@ -282,6 +294,7 @@ struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_id
|
||||||
int ifindex,
|
int ifindex,
|
||||||
const NMNDiscData *rdata,
|
const NMNDiscData *rdata,
|
||||||
NMSettingIP6ConfigPrivacy ip6_privacy,
|
NMSettingIP6ConfigPrivacy ip6_privacy,
|
||||||
NMUtilsIPv6IfaceId *token);
|
NMUtilsIPv6IfaceId *token,
|
||||||
|
const char *network_id);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_NDISC_H__ */
|
#endif /* __NETWORKMANAGER_NDISC_H__ */
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,9 @@ typedef struct {
|
||||||
bool activation_lifetime_bound_to_profile_visibility : 1;
|
bool activation_lifetime_bound_to_profile_visibility : 1;
|
||||||
bool settings_connection_is_unsaved : 1;
|
bool settings_connection_is_unsaved : 1;
|
||||||
bool settings_connection_is_shadowed_owned : 1;
|
bool settings_connection_is_shadowed_owned : 1;
|
||||||
|
bool permanent_managed_by_mac : 1;
|
||||||
NMUnmanFlagOp unmanaged_explicit;
|
NMUnmanFlagOp unmanaged_explicit;
|
||||||
|
NMTernary permanent_managed;
|
||||||
NMActivationReason activation_reason;
|
NMActivationReason activation_reason;
|
||||||
gulong dev_exported_change_id;
|
gulong dev_exported_change_id;
|
||||||
} DeviceCheckpoint;
|
} DeviceCheckpoint;
|
||||||
|
|
@ -160,7 +162,7 @@ parse_connection_from_shadowed_file(const char *path, GError **error)
|
||||||
{
|
{
|
||||||
nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
|
nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
|
||||||
gs_free char *base_dir = NULL;
|
gs_free char *base_dir = NULL;
|
||||||
char *sep;
|
const char *sep;
|
||||||
|
|
||||||
keyfile = g_key_file_new();
|
keyfile = g_key_file_new();
|
||||||
if (!g_key_file_load_from_file(keyfile, path, G_KEY_FILE_NONE, error))
|
if (!g_key_file_load_from_file(keyfile, path, G_KEY_FILE_NONE, error))
|
||||||
|
|
@ -496,14 +498,19 @@ nm_checkpoint_rollback(NMCheckpoint *self)
|
||||||
/* Start rolling-back each device */
|
/* Start rolling-back each device */
|
||||||
g_hash_table_iter_init(&iter, priv->devices);
|
g_hash_table_iter_init(&iter, priv->devices);
|
||||||
while (g_hash_table_iter_next(&iter, (gpointer *) &device, (gpointer *) &dev_checkpoint)) {
|
while (g_hash_table_iter_next(&iter, (gpointer *) &device, (gpointer *) &dev_checkpoint)) {
|
||||||
guint32 result = NM_ROLLBACK_RESULT_OK;
|
guint32 result = NM_ROLLBACK_RESULT_OK;
|
||||||
|
NMTernary perm_managed = NM_TERNARY_DEFAULT;
|
||||||
|
gboolean perm_managed_by_mac = FALSE;
|
||||||
|
gboolean force_perm_managed;
|
||||||
|
|
||||||
_LOGD("rollback: restoring device %s (state %d, realized %d, explicitly unmanaged %d, "
|
_LOGD("rollback: restoring device %s (state %d, realized %d, explicitly unmanaged %d, "
|
||||||
"connection-unsaved %d, connection-shadowed %d, connection-shadowed-owned %d)",
|
"permanently managed %d, connection-unsaved %d, connection-shadowed %d, "
|
||||||
|
"connection-shadowed-owned %d)",
|
||||||
dev_checkpoint->original_dev_name,
|
dev_checkpoint->original_dev_name,
|
||||||
(int) dev_checkpoint->state,
|
(int) dev_checkpoint->state,
|
||||||
dev_checkpoint->realized,
|
dev_checkpoint->realized,
|
||||||
dev_checkpoint->unmanaged_explicit,
|
dev_checkpoint->unmanaged_explicit,
|
||||||
|
dev_checkpoint->permanent_managed,
|
||||||
dev_checkpoint->settings_connection_is_unsaved,
|
dev_checkpoint->settings_connection_is_unsaved,
|
||||||
!!dev_checkpoint->settings_connection_shadowed,
|
!!dev_checkpoint->settings_connection_shadowed,
|
||||||
dev_checkpoint->settings_connection_is_shadowed_owned);
|
dev_checkpoint->settings_connection_is_shadowed_owned);
|
||||||
|
|
@ -541,6 +548,43 @@ nm_checkpoint_rollback(NMCheckpoint *self)
|
||||||
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
force_perm_managed = !nm_config_get_device_managed(nm_config_get(),
|
||||||
|
device,
|
||||||
|
&perm_managed,
|
||||||
|
&perm_managed_by_mac,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (force_perm_managed || (perm_managed != dev_checkpoint->permanent_managed)
|
||||||
|
|| (dev_checkpoint->permanent_managed != NM_TERNARY_DEFAULT
|
||||||
|
&& perm_managed_by_mac != dev_checkpoint->permanent_managed_by_mac)) {
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
NMUnmanFlagOp set_op;
|
||||||
|
|
||||||
|
_LOGD("rollback: restore permanent managed state");
|
||||||
|
|
||||||
|
if (!nm_config_set_device_managed(nm_config_get(),
|
||||||
|
device,
|
||||||
|
dev_checkpoint->permanent_managed,
|
||||||
|
dev_checkpoint->permanent_managed_by_mac,
|
||||||
|
&error)) {
|
||||||
|
_LOGE("rollback: failed to restore permanent managed state: %s", error->message);
|
||||||
|
result = NM_ROLLBACK_RESULT_ERR_FAILED;
|
||||||
|
/* even if this failed, we try to continue the rollback */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev_checkpoint->permanent_managed == NM_TERNARY_TRUE)
|
||||||
|
set_op = NM_UNMAN_FLAG_OP_SET_MANAGED;
|
||||||
|
else if (dev_checkpoint->permanent_managed == NM_TERNARY_FALSE)
|
||||||
|
set_op = NM_UNMAN_FLAG_OP_SET_UNMANAGED;
|
||||||
|
else
|
||||||
|
set_op = NM_UNMAN_FLAG_OP_FORGET;
|
||||||
|
|
||||||
|
nm_device_set_unmanaged_by_flags_queue(device,
|
||||||
|
NM_UNMANAGED_USER_CONF,
|
||||||
|
set_op,
|
||||||
|
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
||||||
|
}
|
||||||
|
|
||||||
if (dev_checkpoint->state == NM_DEVICE_STATE_UNMANAGED) {
|
if (dev_checkpoint->state == NM_DEVICE_STATE_UNMANAGED) {
|
||||||
if (nm_device_get_state(device) != NM_DEVICE_STATE_UNMANAGED
|
if (nm_device_get_state(device) != NM_DEVICE_STATE_UNMANAGED
|
||||||
|| dev_checkpoint->unmanaged_explicit == NM_UNMAN_FLAG_OP_SET_UNMANAGED) {
|
|| dev_checkpoint->unmanaged_explicit == NM_UNMAN_FLAG_OP_SET_UNMANAGED) {
|
||||||
|
|
@ -703,6 +747,8 @@ device_checkpoint_create(NMCheckpoint *self, NMDevice *device)
|
||||||
NMSettingsConnection *settings_connection;
|
NMSettingsConnection *settings_connection;
|
||||||
const char *path;
|
const char *path;
|
||||||
NMActRequest *act_request;
|
NMActRequest *act_request;
|
||||||
|
gboolean perm_managed_by_mac;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
|
||||||
nm_assert(NM_IS_DEVICE(device));
|
nm_assert(NM_IS_DEVICE(device));
|
||||||
nm_assert(nm_device_is_real(device));
|
nm_assert(nm_device_is_real(device));
|
||||||
|
|
@ -728,12 +774,26 @@ device_checkpoint_create(NMCheckpoint *self, NMDevice *device)
|
||||||
} else
|
} else
|
||||||
dev_checkpoint->unmanaged_explicit = NM_UNMAN_FLAG_OP_FORGET;
|
dev_checkpoint->unmanaged_explicit = NM_UNMAN_FLAG_OP_FORGET;
|
||||||
|
|
||||||
|
if (nm_config_get_device_managed(nm_config_get(),
|
||||||
|
device,
|
||||||
|
&dev_checkpoint->permanent_managed,
|
||||||
|
&perm_managed_by_mac,
|
||||||
|
NULL)) {
|
||||||
|
dev_checkpoint->permanent_managed_by_mac = perm_managed_by_mac;
|
||||||
|
} else {
|
||||||
|
dev_checkpoint->permanent_managed = NM_TERNARY_DEFAULT;
|
||||||
|
dev_checkpoint->permanent_managed_by_mac = FALSE;
|
||||||
|
_LOGW("error getting permanent managed state for %s: %s",
|
||||||
|
nm_device_get_iface(device),
|
||||||
|
error->message);
|
||||||
|
g_clear_error(&error);
|
||||||
|
}
|
||||||
|
|
||||||
act_request = nm_device_get_act_request(device);
|
act_request = nm_device_get_act_request(device);
|
||||||
if (act_request) {
|
if (act_request) {
|
||||||
NMSettingsStorage *storage;
|
NMSettingsStorage *storage;
|
||||||
gboolean shadowed_owned = FALSE;
|
gboolean shadowed_owned = FALSE;
|
||||||
const char *shadowed_file;
|
const char *shadowed_file;
|
||||||
gs_free_error GError *error = NULL;
|
|
||||||
|
|
||||||
settings_connection = nm_act_request_get_settings_connection(act_request);
|
settings_connection = nm_act_request_get_settings_connection(act_request);
|
||||||
applied_connection = nm_act_request_get_applied_connection(act_request);
|
applied_connection = nm_act_request_get_applied_connection(act_request);
|
||||||
|
|
@ -764,6 +824,7 @@ device_checkpoint_create(NMCheckpoint *self, NMDevice *device)
|
||||||
_LOGW("error reading shadowed connection file for %s: %s",
|
_LOGW("error reading shadowed connection file for %s: %s",
|
||||||
nm_device_get_iface(device),
|
nm_device_get_iface(device),
|
||||||
error->message);
|
error->message);
|
||||||
|
g_clear_error(&error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2058,12 +2058,15 @@ _match_section_infos_construct(GKeyFile *keyfile, gboolean is_device)
|
||||||
{
|
{
|
||||||
char **groups;
|
char **groups;
|
||||||
gsize i, j, ngroups;
|
gsize i, j, ngroups;
|
||||||
char *connection_tag = NULL;
|
char *main_group = NULL;
|
||||||
MatchSectionInfo *match_section_infos = NULL;
|
MatchSectionInfo *match_section_infos = NULL;
|
||||||
const char *prefix;
|
const char *prefix, *prefix_intern;
|
||||||
|
|
||||||
prefix =
|
prefix =
|
||||||
is_device ? NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE : NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION;
|
is_device ? NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE : NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION;
|
||||||
|
prefix_intern =
|
||||||
|
is_device ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE
|
||||||
|
: NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION;
|
||||||
|
|
||||||
/* get the list of existing [connection.\+]/[device.\+] sections.
|
/* get the list of existing [connection.\+]/[device.\+] sections.
|
||||||
*
|
*
|
||||||
|
|
@ -2074,27 +2077,36 @@ _match_section_infos_construct(GKeyFile *keyfile, gboolean is_device)
|
||||||
if (!groups)
|
if (!groups)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ngroups > 0) {
|
for (i = 0, j = 0; i < ngroups; i++) {
|
||||||
gsize l = strlen(prefix);
|
if (nm_streq0(groups[i], prefix)) {
|
||||||
|
main_group = groups[i];
|
||||||
for (i = 0, j = 0; i < ngroups; i++) {
|
} else if (nm_streq0(groups[i], prefix_intern)) {
|
||||||
if (g_str_has_prefix(groups[i], prefix)) {
|
/* [.intern.connection] and [.intern.device] should not exist */
|
||||||
if (groups[i][l] == '\0')
|
_nm_log(LOGL_WARN,
|
||||||
connection_tag = groups[i];
|
LOGD_CORE,
|
||||||
else
|
0,
|
||||||
groups[j++] = groups[i];
|
NULL,
|
||||||
} else
|
NULL,
|
||||||
g_free(groups[i]);
|
"Invalid [.intern.*] section 'connection' or 'device' found");
|
||||||
|
g_free(groups[i]);
|
||||||
|
continue;
|
||||||
|
} else if (g_str_has_prefix(groups[i], prefix)) {
|
||||||
|
groups[j++] = groups[i];
|
||||||
|
} else if (g_str_has_prefix(groups[i], prefix_intern)) {
|
||||||
|
/* [.intern.connection-whatever] and [.intern.device-whatever] can exist */
|
||||||
|
groups[j++] = groups[i];
|
||||||
|
} else {
|
||||||
|
g_free(groups[i]);
|
||||||
}
|
}
|
||||||
ngroups = j;
|
|
||||||
}
|
}
|
||||||
|
ngroups = j;
|
||||||
|
|
||||||
if (ngroups == 0 && !connection_tag) {
|
if (ngroups == 0 && !main_group) {
|
||||||
g_free(groups);
|
g_free(groups);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
match_section_infos = g_new0(MatchSectionInfo, ngroups + 1 + (connection_tag ? 1 : 0));
|
match_section_infos = g_new0(MatchSectionInfo, ngroups + 1 + (main_group ? 1 : 0));
|
||||||
match_section_infos->is_device = is_device;
|
match_section_infos->is_device = is_device;
|
||||||
for (i = 0; i < ngroups; i++) {
|
for (i = 0; i < ngroups; i++) {
|
||||||
/* pass ownership of @group on... */
|
/* pass ownership of @group on... */
|
||||||
|
|
@ -2103,9 +2115,9 @@ _match_section_infos_construct(GKeyFile *keyfile, gboolean is_device)
|
||||||
groups[ngroups - i - 1],
|
groups[ngroups - i - 1],
|
||||||
is_device);
|
is_device);
|
||||||
}
|
}
|
||||||
if (connection_tag) {
|
if (main_group) {
|
||||||
/* pass ownership of @connection_tag on... */
|
/* pass ownership of @main_group on... */
|
||||||
_match_section_info_init(&match_section_infos[i], keyfile, connection_tag, is_device);
|
_match_section_info_init(&match_section_infos[i], keyfile, main_group, is_device);
|
||||||
}
|
}
|
||||||
g_free(groups);
|
g_free(groups);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -892,6 +892,7 @@ static const ConfigGroup config_groups[] = {
|
||||||
.is_prefix = TRUE,
|
.is_prefix = TRUE,
|
||||||
.keys = NM_MAKE_STRV(NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT,
|
.keys = NM_MAKE_STRV(NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT,
|
||||||
NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER,
|
NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER,
|
||||||
|
NM_CONFIG_KEYFILE_KEY_DEVICE_CHECK_CONNECTIVITY,
|
||||||
NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED,
|
NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED,
|
||||||
NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS,
|
NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS,
|
||||||
NM_CONFIG_KEYFILE_KEY_DEVICE_KEEP_CONFIGURATION,
|
NM_CONFIG_KEYFILE_KEY_DEVICE_KEEP_CONFIGURATION,
|
||||||
|
|
@ -2075,6 +2076,210 @@ nm_config_set_connectivity_check_enabled(NMConfig *self, gboolean enabled)
|
||||||
g_key_file_unref(keyfile);
|
g_key_file_unref(keyfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
normalize_hwaddr_for_group_name(const char *hwaddr, char *out, GError **error)
|
||||||
|
{
|
||||||
|
guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX];
|
||||||
|
gsize hwaddr_bin_len;
|
||||||
|
|
||||||
|
if (!_nm_utils_hwaddr_aton(hwaddr, hwaddr_bin, sizeof(hwaddr_bin), &hwaddr_bin_len)) {
|
||||||
|
g_set_error(error,
|
||||||
|
NM_DEVICE_ERROR,
|
||||||
|
NM_DEVICE_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Invalid MAC address: %s",
|
||||||
|
hwaddr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
nm_utils_bin2hexstr_full(hwaddr_bin, hwaddr_bin_len, '-', TRUE, out);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_config_get_device_managed:
|
||||||
|
* @self: the NMConfig instance
|
||||||
|
* @device: the interface
|
||||||
|
* @out: (out): the managed state of the device
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Returns: TRUE if there were no errors, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_config_get_device_managed(NMConfig *self,
|
||||||
|
NMDevice *device,
|
||||||
|
NMTernary *out_managed,
|
||||||
|
gboolean *out_by_mac,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMConfigPrivate *priv;
|
||||||
|
const GKeyFile *keyfile = NULL;
|
||||||
|
gs_free char *group_by_name = NULL;
|
||||||
|
gs_free char *group_by_mac = NULL;
|
||||||
|
const char *ifname = nm_device_get_iface(device);
|
||||||
|
const char *hwaddr = nm_device_get_permanent_hw_address(device);
|
||||||
|
char mac_group_name[NM_UTILS_HWADDR_LEN_MAX * 3 + 1];
|
||||||
|
NMTernary val_by_name, val_by_mac = NM_TERNARY_DEFAULT;
|
||||||
|
|
||||||
|
g_return_val_if_fail(NM_IS_CONFIG(self), FALSE);
|
||||||
|
g_return_val_if_fail(NM_CONFIG_GET_PRIVATE(self)->config_data, FALSE);
|
||||||
|
g_return_val_if_fail(out_managed, FALSE);
|
||||||
|
g_return_val_if_fail(ifname, FALSE);
|
||||||
|
|
||||||
|
priv = NM_CONFIG_GET_PRIVATE(self);
|
||||||
|
keyfile = _nm_config_data_get_keyfile_intern(priv->config_data);
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
NM_SET_OUT(out_managed, NM_TERNARY_DEFAULT);
|
||||||
|
NM_SET_OUT(out_by_mac, FALSE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
group_by_name =
|
||||||
|
g_strdup_printf(NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE "-manage-%s", ifname);
|
||||||
|
|
||||||
|
val_by_name = (NMTernary) nm_config_keyfile_get_boolean(keyfile,
|
||||||
|
group_by_name,
|
||||||
|
NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED,
|
||||||
|
NM_TERNARY_DEFAULT);
|
||||||
|
|
||||||
|
/* Devices without a kernel link (i.e. OVS ports) don't have a MAC address */
|
||||||
|
if (hwaddr) {
|
||||||
|
if (!normalize_hwaddr_for_group_name(hwaddr, mac_group_name, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
group_by_mac = g_strdup_printf(NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE "-manage-%s",
|
||||||
|
mac_group_name);
|
||||||
|
|
||||||
|
val_by_mac = (NMTernary) nm_config_keyfile_get_boolean(keyfile,
|
||||||
|
group_by_mac,
|
||||||
|
NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED,
|
||||||
|
NM_TERNARY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val_by_name != NM_TERNARY_DEFAULT && val_by_mac == NM_TERNARY_DEFAULT) {
|
||||||
|
NM_SET_OUT(out_managed, val_by_name);
|
||||||
|
NM_SET_OUT(out_by_mac, FALSE);
|
||||||
|
return TRUE;
|
||||||
|
} else if (val_by_mac != NM_TERNARY_DEFAULT && val_by_name == NM_TERNARY_DEFAULT) {
|
||||||
|
NM_SET_OUT(out_managed, val_by_mac);
|
||||||
|
NM_SET_OUT(out_by_mac, TRUE);
|
||||||
|
return TRUE;
|
||||||
|
} else if (val_by_name == NM_TERNARY_DEFAULT && val_by_mac == NM_TERNARY_DEFAULT) {
|
||||||
|
NM_SET_OUT(out_managed, NM_TERNARY_DEFAULT);
|
||||||
|
NM_SET_OUT(out_by_mac, FALSE);
|
||||||
|
return TRUE;
|
||||||
|
} else if (val_by_name == val_by_mac) {
|
||||||
|
NM_SET_OUT(out_managed, val_by_name);
|
||||||
|
NM_SET_OUT(out_by_mac, FALSE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_set_error(error,
|
||||||
|
NM_DEVICE_ERROR,
|
||||||
|
NM_DEVICE_ERROR_FAILED,
|
||||||
|
"Multiple managed states found for device: %s",
|
||||||
|
nm_device_get_iface(device));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_config_set_device_managed:
|
||||||
|
* @self: the NMConfig instance
|
||||||
|
* @device: the NMDevice instance associated with this config change
|
||||||
|
* @managed: the managed state to set
|
||||||
|
* @by_mac: if %TRUE, match by MAC address, otherwise by interface name. This is
|
||||||
|
* only used when @managed = TRUE.
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Sets the managed state of the device to the intern keyfile. Here we store the
|
||||||
|
* configuration received via the D-Bus API. Configurations from other config
|
||||||
|
* files are still in place and may have higher precedence.
|
||||||
|
*
|
||||||
|
* Prior to setting the new state, the existing configuration is removed. If
|
||||||
|
* @managed is set to %NM_TERNARY_DEFAULT, we only do the removal of the previous
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_config_set_device_managed(NMConfig *self,
|
||||||
|
NMDevice *device,
|
||||||
|
NMTernary managed,
|
||||||
|
gboolean by_mac,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMConfigPrivate *priv;
|
||||||
|
g_autoptr(GKeyFile) keyfile = NULL;
|
||||||
|
char *group;
|
||||||
|
gs_free char *group_by_name = NULL;
|
||||||
|
gs_free char *group_by_mac = NULL;
|
||||||
|
gs_free char *match_value = NULL;
|
||||||
|
gboolean changed = FALSE;
|
||||||
|
const char *ifname = nm_device_get_iface(device);
|
||||||
|
const char *hwaddr = nm_device_get_permanent_hw_address(device);
|
||||||
|
char mac_group_name[NM_UTILS_HWADDR_LEN_MAX * 3 + 1];
|
||||||
|
|
||||||
|
g_return_val_if_fail(NM_IS_CONFIG(self), FALSE);
|
||||||
|
g_return_val_if_fail(NM_CONFIG_GET_PRIVATE(self)->config_data, FALSE);
|
||||||
|
g_return_val_if_fail(ifname, FALSE);
|
||||||
|
|
||||||
|
if (by_mac && !hwaddr) {
|
||||||
|
g_set_error(error,
|
||||||
|
NM_DEVICE_ERROR,
|
||||||
|
NM_DEVICE_ERROR_INVALID_ARGUMENT,
|
||||||
|
"the device has no MAC address, but match by MAC was requested");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hwaddr && !normalize_hwaddr_for_group_name(hwaddr, mac_group_name, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
priv = NM_CONFIG_GET_PRIVATE(self);
|
||||||
|
keyfile = nm_config_data_clone_keyfile_intern(priv->config_data);
|
||||||
|
|
||||||
|
/* Remove existing configs. Search them by group name [.intern.device-manage-*]. In
|
||||||
|
* the intern file, 'device-manage' sections are only used for this purpose, so we
|
||||||
|
* won't remove any other device's config. */
|
||||||
|
group_by_name =
|
||||||
|
g_strdup_printf(NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE "-manage-%s", ifname);
|
||||||
|
|
||||||
|
if (g_key_file_remove_group(keyfile, group_by_name, NULL))
|
||||||
|
changed = TRUE;
|
||||||
|
|
||||||
|
/* Devices without a kernel link (i.e. OVS ports) don't have a MAC address */
|
||||||
|
if (hwaddr) {
|
||||||
|
group_by_mac = g_strdup_printf(NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE "-manage-%s",
|
||||||
|
mac_group_name);
|
||||||
|
|
||||||
|
if (g_key_file_remove_group(keyfile, group_by_mac, NULL))
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the new state is not explicitly TRUE of FALSE, we only remove the configs */
|
||||||
|
if (managed == NM_TERNARY_DEFAULT)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Set new values */
|
||||||
|
if (by_mac) {
|
||||||
|
group = group_by_mac;
|
||||||
|
match_value = g_strdup_printf("mac:%s", hwaddr);
|
||||||
|
} else {
|
||||||
|
group = group_by_name;
|
||||||
|
match_value = g_strdup_printf("interface-name:=%s", ifname);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_key_file_set_value(keyfile, group, NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE, match_value);
|
||||||
|
g_key_file_set_value(keyfile, group, NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED, managed ? "1" : "0");
|
||||||
|
changed = TRUE;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (changed)
|
||||||
|
nm_config_set_values(self, keyfile, TRUE, FALSE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_config_set_values:
|
* nm_config_set_values:
|
||||||
* @self: the NMConfig instance
|
* @self: the NMConfig instance
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,17 @@ gboolean nm_config_set_global_dns(NMConfig *self, NMGlobalDnsConfig *global_dns,
|
||||||
|
|
||||||
void nm_config_set_connectivity_check_enabled(NMConfig *self, gboolean enabled);
|
void nm_config_set_connectivity_check_enabled(NMConfig *self, gboolean enabled);
|
||||||
|
|
||||||
|
gboolean nm_config_get_device_managed(NMConfig *self,
|
||||||
|
NMDevice *device,
|
||||||
|
NMTernary *out_managed,
|
||||||
|
gboolean *out_by_mac,
|
||||||
|
GError **error);
|
||||||
|
gboolean nm_config_set_device_managed(NMConfig *self,
|
||||||
|
NMDevice *device,
|
||||||
|
NMTernary managed,
|
||||||
|
gboolean by_mac,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
/* internal defines ... */
|
/* internal defines ... */
|
||||||
extern guint _nm_config_match_nm_version;
|
extern guint _nm_config_match_nm_version;
|
||||||
extern char *_nm_config_match_env;
|
extern char *_nm_config_match_env;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@
|
||||||
#include <linux/if_infiniband.h>
|
#include <linux/if_infiniband.h>
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
|
#include <netinet/ip_icmp.h>
|
||||||
|
#include <netinet/icmp6.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
|
||||||
#include "libnm-glib-aux/nm-uuid.h"
|
#include "libnm-glib-aux/nm-uuid.h"
|
||||||
#include "libnm-platform/nmp-base.h"
|
#include "libnm-platform/nmp-base.h"
|
||||||
|
|
@ -5002,6 +5006,469 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_activation_type_to_string,
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMIPAddrTyped address;
|
||||||
|
char *addr_str;
|
||||||
|
GTask *task;
|
||||||
|
GSource *timeout_source;
|
||||||
|
GSource *retry_source;
|
||||||
|
GSource *input_source;
|
||||||
|
gulong cancellable_id;
|
||||||
|
int ifindex;
|
||||||
|
int socket;
|
||||||
|
guint16 seq;
|
||||||
|
} PingInfo;
|
||||||
|
|
||||||
|
#define _NMLOG2_PREFIX_NAME "ping"
|
||||||
|
#define _NMLOG2_DOMAIN LOGD_CORE
|
||||||
|
#define _NMLOG2(level, info, ...) \
|
||||||
|
G_STMT_START \
|
||||||
|
{ \
|
||||||
|
if (nm_logging_enabled((level), (_NMLOG2_DOMAIN))) { \
|
||||||
|
PingInfo *_info = (info); \
|
||||||
|
\
|
||||||
|
_nm_log((level), \
|
||||||
|
(_NMLOG2_DOMAIN), \
|
||||||
|
0, \
|
||||||
|
NULL, \
|
||||||
|
NULL, \
|
||||||
|
_NMLOG2_PREFIX_NAME "[" NM_HASH_OBFUSCATE_PTR_FMT \
|
||||||
|
",if=%d,%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||||
|
NM_HASH_OBFUSCATE_PTR(_info), \
|
||||||
|
_info->ifindex, \
|
||||||
|
_info->addr_str _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
G_STMT_END
|
||||||
|
|
||||||
|
static void
|
||||||
|
ping_complete(PingInfo *info, GError *error)
|
||||||
|
{
|
||||||
|
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task), &info->cancellable_id);
|
||||||
|
|
||||||
|
if (error && !nm_utils_error_is_cancelled(error)) {
|
||||||
|
_LOG2T(info, "terminated with error: %s", error->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
g_task_return_error(info->task, error);
|
||||||
|
else
|
||||||
|
g_task_return_boolean(info->task, TRUE);
|
||||||
|
|
||||||
|
nm_clear_g_source_inst(&info->timeout_source);
|
||||||
|
nm_clear_g_source_inst(&info->retry_source);
|
||||||
|
nm_clear_g_source_inst(&info->input_source);
|
||||||
|
nm_clear_g_free(&info->addr_str);
|
||||||
|
nm_clear_fd(&info->socket);
|
||||||
|
g_object_unref(info->task);
|
||||||
|
|
||||||
|
g_free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
ping_socket_data_cb(int fd, GIOCondition condition, gpointer user_data)
|
||||||
|
{
|
||||||
|
PingInfo *info = user_data;
|
||||||
|
ssize_t len;
|
||||||
|
union {
|
||||||
|
struct icmphdr icmph;
|
||||||
|
struct icmp6_hdr icmp6h;
|
||||||
|
} pkt;
|
||||||
|
|
||||||
|
len = recv(fd, &pkt, sizeof(pkt), 0);
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
|
if (info->address.addr_family == AF_INET) {
|
||||||
|
if (len >= sizeof(struct icmphdr) && pkt.icmph.type == ICMP_ECHOREPLY) {
|
||||||
|
_LOG2T(info, "received echo-reply with seq %hu", ntohs(pkt.icmph.un.echo.sequence));
|
||||||
|
ping_complete(info, NULL);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (len >= sizeof(struct icmp6_hdr) && pkt.icmp6h.icmp6_type == ICMP6_ECHO_REPLY) {
|
||||||
|
_LOG2T(info, "received echo-reply with seq %hu", ntohs(pkt.icmp6h.icmp6_seq));
|
||||||
|
ping_complete(info, NULL);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ping_send(PingInfo *info)
|
||||||
|
{
|
||||||
|
const bool IS_IPv4 = NM_IS_IPv4(info->address.addr_family);
|
||||||
|
union {
|
||||||
|
struct sockaddr_in6 sa6;
|
||||||
|
struct sockaddr_in sa4;
|
||||||
|
} sa;
|
||||||
|
union {
|
||||||
|
struct icmphdr icmph;
|
||||||
|
struct icmp6_hdr icmp6h;
|
||||||
|
} pkt;
|
||||||
|
socklen_t sa_len;
|
||||||
|
size_t pkt_len;
|
||||||
|
nm_be32_t ifindex_be;
|
||||||
|
int errsv;
|
||||||
|
|
||||||
|
info->seq++;
|
||||||
|
|
||||||
|
if (info->socket < 0) {
|
||||||
|
info->socket = socket(info->address.addr_family,
|
||||||
|
SOCK_DGRAM | SOCK_CLOEXEC,
|
||||||
|
IS_IPv4 ? IPPROTO_ICMP : IPPROTO_ICMPV6);
|
||||||
|
if (info->socket < 0) {
|
||||||
|
errsv = errno;
|
||||||
|
_LOG2T(info, "socket creation failed: %s", nm_strerror_native(errsv));
|
||||||
|
/* Try again at the next iteration */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
if (IS_IPv4) {
|
||||||
|
sa.sa4.sin_family = AF_INET;
|
||||||
|
sa.sa4.sin_addr.s_addr = info->address.addr.addr4;
|
||||||
|
sa_len = sizeof(struct sockaddr_in);
|
||||||
|
} else {
|
||||||
|
sa.sa6.sin6_family = AF_INET6;
|
||||||
|
sa.sa6.sin6_addr = info->address.addr.addr6;
|
||||||
|
if (IN6_IS_ADDR_LINKLOCAL(&info->address.addr.addr6))
|
||||||
|
sa.sa6.sin6_scope_id = info->ifindex;
|
||||||
|
sa_len = sizeof(struct sockaddr_in6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setsockopt(IP*_UNICAST_IF) must be called *before* connecting
|
||||||
|
* the socket, otherwise it doesn't have any effect */
|
||||||
|
ifindex_be = htonl(info->ifindex);
|
||||||
|
if (setsockopt(info->socket,
|
||||||
|
IS_IPv4 ? IPPROTO_IP : IPPROTO_IPV6,
|
||||||
|
IS_IPv4 ? IP_UNICAST_IF : IPV6_UNICAST_IF,
|
||||||
|
&ifindex_be,
|
||||||
|
sizeof(ifindex_be))) {
|
||||||
|
errsv = errno;
|
||||||
|
_LOG2T(info,
|
||||||
|
"failed to bind the socket to the interface: %s",
|
||||||
|
nm_strerror_native(errsv));
|
||||||
|
/* Try again at the next iteration */
|
||||||
|
nm_clear_fd(&info->socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect the socket so that the kernel only delivers us packets
|
||||||
|
* coming from the given remote address */
|
||||||
|
if (connect(info->socket, (struct sockaddr *) &sa, sa_len) < 0) {
|
||||||
|
errsv = errno;
|
||||||
|
_LOG2T(info, "failed to connect the socket: %s", nm_strerror_native(errsv));
|
||||||
|
/* try again at the next iteration */
|
||||||
|
nm_clear_fd(&info->socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->input_source = nm_g_unix_fd_source_new(info->socket,
|
||||||
|
G_IO_IN,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
ping_socket_data_cb,
|
||||||
|
info,
|
||||||
|
NULL);
|
||||||
|
g_source_attach(info->input_source, g_task_get_context(info->task));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_IPv4) {
|
||||||
|
memset(&pkt.icmph, 0, sizeof(struct icmphdr));
|
||||||
|
pkt.icmph.type = ICMP_ECHO;
|
||||||
|
pkt.icmph.un.echo.sequence = htons(info->seq);
|
||||||
|
pkt_len = sizeof(struct icmphdr);
|
||||||
|
} else {
|
||||||
|
memset(&pkt.icmp6h, 0, sizeof(struct icmp6_hdr));
|
||||||
|
pkt.icmp6h.icmp6_type = ICMP6_ECHO_REQUEST;
|
||||||
|
pkt.icmp6h.icmp6_seq = htons(info->seq);
|
||||||
|
pkt_len = sizeof(struct icmp6_hdr);
|
||||||
|
}
|
||||||
|
/* The kernel will automatically set the ID ICMP field and filter
|
||||||
|
* incoming packets by the same ID */
|
||||||
|
|
||||||
|
if (send(info->socket, &pkt, pkt_len, 0) < 0) {
|
||||||
|
errsv = errno;
|
||||||
|
_LOG2T(info, "error sending echo-request #%u: %s", info->seq, nm_strerror_native(errsv));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOG2T(info, "sent echo-request #%u", info->seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
ping_timeout_cb(gpointer user_data)
|
||||||
|
{
|
||||||
|
PingInfo *info = user_data;
|
||||||
|
|
||||||
|
_LOG2T(info, "timeout");
|
||||||
|
|
||||||
|
nm_clear_g_source_inst(&info->timeout_source);
|
||||||
|
ping_complete(info, g_error_new_literal(NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "timeout"));
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
ping_retry_cb(gpointer user_data)
|
||||||
|
{
|
||||||
|
PingInfo *info = user_data;
|
||||||
|
|
||||||
|
ping_send(info);
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ping_cancelled(GObject *object, gpointer user_data)
|
||||||
|
{
|
||||||
|
PingInfo *info = user_data;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
nm_clear_g_signal_handler(g_task_get_cancellable(info->task), &info->cancellable_id);
|
||||||
|
nm_utils_error_set_cancelled(&error, FALSE, NULL);
|
||||||
|
ping_complete(info, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_utils_ping_host(NMIPAddrTyped address,
|
||||||
|
int ifindex,
|
||||||
|
guint timeout_sec,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer cb_data)
|
||||||
|
{
|
||||||
|
PingInfo *info;
|
||||||
|
char buf[NM_INET_ADDRSTRLEN];
|
||||||
|
gulong signal_id;
|
||||||
|
|
||||||
|
nm_assert(ifindex > 0);
|
||||||
|
nm_assert(G_IS_CANCELLABLE(cancellable));
|
||||||
|
nm_assert(callback);
|
||||||
|
nm_assert(cb_data);
|
||||||
|
|
||||||
|
info = g_new0(PingInfo, 1);
|
||||||
|
info->address = address;
|
||||||
|
info->ifindex = ifindex;
|
||||||
|
info->task = nm_g_task_new(NULL, cancellable, nm_utils_ping_host, callback, cb_data);
|
||||||
|
info->socket = -1;
|
||||||
|
|
||||||
|
nm_inet_ntop(address.addr_family, address.addr.addr_ptr, buf);
|
||||||
|
info->addr_str = g_strdup(buf);
|
||||||
|
|
||||||
|
_LOG2T(info, "started");
|
||||||
|
|
||||||
|
if (timeout_sec > 0) {
|
||||||
|
info->timeout_source = nm_g_timeout_source_new_seconds(timeout_sec,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
ping_timeout_cb,
|
||||||
|
info,
|
||||||
|
NULL);
|
||||||
|
g_source_attach(info->timeout_source, g_task_get_context(info->task));
|
||||||
|
}
|
||||||
|
|
||||||
|
info->retry_source =
|
||||||
|
nm_g_timeout_source_new_seconds(1, G_PRIORITY_DEFAULT, ping_retry_cb, info, NULL);
|
||||||
|
g_source_attach(info->retry_source, g_task_get_context(info->task));
|
||||||
|
|
||||||
|
signal_id = g_cancellable_connect(cancellable, G_CALLBACK(ping_cancelled), info, NULL);
|
||||||
|
if (signal_id == 0) {
|
||||||
|
/* the callback was invoked synchronously, which destroyed @info.
|
||||||
|
* We must not touch it anymore. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info->cancellable_id = signal_id;
|
||||||
|
|
||||||
|
ping_send(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_utils_ping_host_finish(GAsyncResult *result, GError **error)
|
||||||
|
{
|
||||||
|
GTask *task = G_TASK(result);
|
||||||
|
|
||||||
|
nm_assert(nm_g_task_is_valid(result, NULL, nm_utils_ping_host));
|
||||||
|
|
||||||
|
return g_task_propagate_boolean(task, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nm_utils_icmp6_checksum:
|
||||||
|
* @ip6_src: pointer to the IPv6 source address
|
||||||
|
* @data_len: length of the data
|
||||||
|
* @data: the data on which to compute the checksum
|
||||||
|
*
|
||||||
|
* Computes the ICMP6 checksum over @data (with length @data_len) and the IPv6
|
||||||
|
* pseudo-header. @ip6_src points to the source address in the IPv6 header.
|
||||||
|
*/
|
||||||
|
uint16_t
|
||||||
|
nm_utils_icmp6_checksum(const void *ip6_src, size_t data_len, const void *data)
|
||||||
|
{
|
||||||
|
uint32_t sum = 0;
|
||||||
|
const uint16_t *ptr;
|
||||||
|
const uint8_t *ptr8;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* Pseudo-header: source address */
|
||||||
|
ptr = (const uint16_t *) ip6_src;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
sum += *ptr++;
|
||||||
|
|
||||||
|
/* Pseudo-header: destination address */
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
sum += *ptr++;
|
||||||
|
|
||||||
|
/* Pseudo-header: payload length */
|
||||||
|
sum += htons(data_len);
|
||||||
|
|
||||||
|
/* Pseudo-header: next header */
|
||||||
|
sum += htons(IPPROTO_ICMPV6);
|
||||||
|
|
||||||
|
/* ICMPv6 data */
|
||||||
|
ptr = (const uint16_t *) data;
|
||||||
|
for (i = 0; i < data_len / 2; i++)
|
||||||
|
sum += ptr[i];
|
||||||
|
|
||||||
|
/* Handle odd byte */
|
||||||
|
if (data_len % 2) {
|
||||||
|
ptr8 = &((const uint8_t *) data)[data_len - 1];
|
||||||
|
sum += htons((guint16) (*ptr8) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fold 32-bit sum to 16 bits */
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
|
||||||
|
return (uint16_t) ~sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nm_utils_ipv6_dad_send:
|
||||||
|
* @addr: the target IPv6 address
|
||||||
|
* @ifindex: the interface index
|
||||||
|
* @arptype: the ARP hardware type of the interface (e.g. ARPHRD_ETHER, ARPHRD_NONE)
|
||||||
|
*
|
||||||
|
* Send an IPv6 Duplicate Address Detection (DAD) Neighbor Solicitation
|
||||||
|
* for the given address.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the packet was sent successfully, %FALSE on error
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_utils_ipv6_dad_send(const struct in6_addr *addr, int ifindex, int arptype)
|
||||||
|
{
|
||||||
|
/* DAD packet: IPv6 header + ICMPv6 NS + nonce option (RFC 3971) */
|
||||||
|
struct _nm_packed {
|
||||||
|
struct ip6_hdr ip6h;
|
||||||
|
struct nd_neighbor_solicit ns;
|
||||||
|
guint8 ns_opt_nr;
|
||||||
|
guint8 ns_opt_len;
|
||||||
|
guint8 ns_opt_nonce[6];
|
||||||
|
} dad_pkt;
|
||||||
|
nm_auto_close int fd = -1;
|
||||||
|
int errsv;
|
||||||
|
char sbuf[NM_INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
nm_assert(addr);
|
||||||
|
nm_assert(ifindex > 0);
|
||||||
|
|
||||||
|
/* IPv6 header */
|
||||||
|
dad_pkt.ip6h = (struct ip6_hdr) {
|
||||||
|
.ip6_flow = htonl(6 << 28), /* version 6, tclass 0, flowlabel 0 */
|
||||||
|
.ip6_plen = htons(sizeof(dad_pkt) - sizeof(struct ip6_hdr)),
|
||||||
|
.ip6_nxt = IPPROTO_ICMPV6,
|
||||||
|
.ip6_hlim = 255,
|
||||||
|
.ip6_src = IN6ADDR_ANY_INIT,
|
||||||
|
.ip6_dst.s6_addr = {0xff,
|
||||||
|
0x02,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0x01,
|
||||||
|
0xff,
|
||||||
|
addr->s6_addr[13],
|
||||||
|
addr->s6_addr[14],
|
||||||
|
addr->s6_addr[15]},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICMPv6 Neighbor Solicitation */
|
||||||
|
dad_pkt.ns = (struct nd_neighbor_solicit) {
|
||||||
|
.nd_ns_type = ND_NEIGHBOR_SOLICIT,
|
||||||
|
.nd_ns_target = *addr,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Nonce option (RFC 3971) */
|
||||||
|
dad_pkt.ns_opt_nr = 14;
|
||||||
|
dad_pkt.ns_opt_len = 1; /* in units of 8 bytes */
|
||||||
|
nm_random_get_bytes(dad_pkt.ns_opt_nonce, sizeof(dad_pkt.ns_opt_nonce));
|
||||||
|
|
||||||
|
/* Compute the ICMPv6 checksum */
|
||||||
|
dad_pkt.ns.nd_ns_cksum = nm_utils_icmp6_checksum(&dad_pkt.ip6h.ip6_src,
|
||||||
|
sizeof(dad_pkt) - sizeof(struct ip6_hdr),
|
||||||
|
&dad_pkt.ns);
|
||||||
|
|
||||||
|
/* We need a ETH_P_IPV6 socket because we need to use a zero IPv6 source address */
|
||||||
|
fd = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_IPV6));
|
||||||
|
if (fd < 0) {
|
||||||
|
errsv = errno;
|
||||||
|
nm_log_warn(LOGD_CORE,
|
||||||
|
"ipv6-dad: failed to create socket for %s: %s",
|
||||||
|
nm_inet6_ntop(addr, sbuf),
|
||||||
|
nm_strerror_native(errsv));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build link-layer destination address. For Ethernet, use the solicited-node
|
||||||
|
* multicast MAC address. For L3-only devices (ARPHRD_NONE, ARPHRD_RAWIP, etc.)
|
||||||
|
* there is no L2 header, so set sll_halen to 0. */
|
||||||
|
{
|
||||||
|
struct sockaddr_ll dst_ll = {
|
||||||
|
.sll_family = AF_PACKET,
|
||||||
|
.sll_protocol = htons(ETH_P_IPV6),
|
||||||
|
.sll_ifindex = ifindex,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (arptype == ARPHRD_ETHER) {
|
||||||
|
dst_ll.sll_halen = ETH_ALEN;
|
||||||
|
dst_ll.sll_addr[0] = 0x33;
|
||||||
|
dst_ll.sll_addr[1] = 0x33;
|
||||||
|
dst_ll.sll_addr[2] = 0xff;
|
||||||
|
dst_ll.sll_addr[3] = addr->s6_addr[13];
|
||||||
|
dst_ll.sll_addr[4] = addr->s6_addr[14];
|
||||||
|
dst_ll.sll_addr[5] = addr->s6_addr[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendto(fd, &dad_pkt, sizeof(dad_pkt), 0, (struct sockaddr *) &dst_ll, sizeof(dst_ll))
|
||||||
|
< 0) {
|
||||||
|
errsv = errno;
|
||||||
|
nm_log_warn(LOGD_CORE,
|
||||||
|
"ipv6-dad: failed to send DAD NS for %s: %s",
|
||||||
|
nm_inet6_ntop(addr, sbuf),
|
||||||
|
nm_strerror_native(errsv));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_log_dbg(LOGD_CORE,
|
||||||
|
"ipv6-dad: sent DAD NS for %s on ifindex %d",
|
||||||
|
nm_inet6_ntop(addr, sbuf),
|
||||||
|
ifindex);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GPid pid;
|
GPid pid;
|
||||||
GTask *task;
|
GTask *task;
|
||||||
|
|
@ -5023,6 +5490,9 @@ typedef struct {
|
||||||
gsize out_buffer_offset;
|
gsize out_buffer_offset;
|
||||||
} HelperInfo;
|
} HelperInfo;
|
||||||
|
|
||||||
|
#undef _NMLOG2_PREFIX_NAME
|
||||||
|
#undef _NMLOG2_DOMAIN
|
||||||
|
#undef _NMLOG2
|
||||||
#define _NMLOG2_PREFIX_NAME "nm-daemon-helper"
|
#define _NMLOG2_PREFIX_NAME "nm-daemon-helper"
|
||||||
#define _NMLOG2_DOMAIN LOGD_CORE
|
#define _NMLOG2_DOMAIN LOGD_CORE
|
||||||
#define _NMLOG2(level, info, ...) \
|
#define _NMLOG2(level, info, ...) \
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,7 @@ typedef enum {
|
||||||
NM_UTILS_STABLE_TYPE_STABLE_ID = 1,
|
NM_UTILS_STABLE_TYPE_STABLE_ID = 1,
|
||||||
NM_UTILS_STABLE_TYPE_GENERATED = 2,
|
NM_UTILS_STABLE_TYPE_GENERATED = 2,
|
||||||
NM_UTILS_STABLE_TYPE_RANDOM = 3,
|
NM_UTILS_STABLE_TYPE_RANDOM = 3,
|
||||||
|
NM_UTILS_STABLE_TYPE_CLAT = 4,
|
||||||
} NMUtilsStableType;
|
} NMUtilsStableType;
|
||||||
|
|
||||||
#define NM_UTILS_STABLE_TYPE_NONE ((NMUtilsStableType) - 1)
|
#define NM_UTILS_STABLE_TYPE_NONE ((NMUtilsStableType) - 1)
|
||||||
|
|
@ -520,4 +521,19 @@ void nm_utils_read_private_files(const char *const *paths,
|
||||||
gpointer cb_data);
|
gpointer cb_data);
|
||||||
GHashTable *nm_utils_read_private_files_finish(GAsyncResult *result, GError **error);
|
GHashTable *nm_utils_read_private_files_finish(GAsyncResult *result, GError **error);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void nm_utils_ping_host(NMIPAddrTyped address,
|
||||||
|
int ifindex,
|
||||||
|
guint timeout_sec,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer cb_data);
|
||||||
|
|
||||||
|
gboolean nm_utils_ping_host_finish(GAsyncResult *result, GError **error);
|
||||||
|
|
||||||
|
uint16_t nm_utils_icmp6_checksum(const void *ip6_src, size_t data_len, const void *data);
|
||||||
|
|
||||||
|
gboolean nm_utils_ipv6_dad_send(const struct in6_addr *addr, int ifindex, int arptype);
|
||||||
|
|
||||||
#endif /* __NM_CORE_UTILS_H__ */
|
#endif /* __NM_CORE_UTILS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ GType nm_ip6_config_get_type(void);
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define NM_IP_CONFIG_ADDRESS_DATA "address-data"
|
#define NM_IP_CONFIG_ADDRESS_DATA "address-data"
|
||||||
|
#define NM_IP_CONFIG_CLAT_ADDRESS "clat-address"
|
||||||
#define NM_IP_CONFIG_DNS_OPTIONS "dns-options"
|
#define NM_IP_CONFIG_DNS_OPTIONS "dns-options"
|
||||||
#define NM_IP_CONFIG_DNS_PRIORITY "dns-priority"
|
#define NM_IP_CONFIG_DNS_PRIORITY "dns-priority"
|
||||||
#define NM_IP_CONFIG_DOMAINS "domains"
|
#define NM_IP_CONFIG_DOMAINS "domains"
|
||||||
|
|
@ -41,6 +42,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip,
|
||||||
NMIPConfig,
|
NMIPConfig,
|
||||||
PROP_IP_L3CFG,
|
PROP_IP_L3CFG,
|
||||||
PROP_IP_ADDRESS_DATA,
|
PROP_IP_ADDRESS_DATA,
|
||||||
|
PROP_IP_CLAT_ADDRESS,
|
||||||
PROP_IP_GATEWAY,
|
PROP_IP_GATEWAY,
|
||||||
PROP_IP_ROUTE_DATA,
|
PROP_IP_ROUTE_DATA,
|
||||||
PROP_IP_DOMAINS,
|
PROP_IP_DOMAINS,
|
||||||
|
|
@ -54,7 +56,7 @@ G_DEFINE_ABSTRACT_TYPE(NMIPConfig, nm_ip_config, NM_TYPE_DBUS_OBJECT)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void _handle_platform_change(NMIPConfig *self, guint32 obj_type_flags, gboolean is_init);
|
static void _handle_platform_change(NMIPConfig *self, guint64 obj_type_flags, gboolean is_init);
|
||||||
static void _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd);
|
static void _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -75,7 +77,7 @@ static void
|
||||||
_notify_platform_handle(NMIPConfig *self, gint64 now_msec)
|
_notify_platform_handle(NMIPConfig *self, gint64 now_msec)
|
||||||
{
|
{
|
||||||
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
|
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
|
||||||
guint32 obj_type_flags;
|
guint64 obj_type_flags;
|
||||||
|
|
||||||
nm_clear_g_source_inst(&priv->notify_platform_timeout_source);
|
nm_clear_g_source_inst(&priv->notify_platform_timeout_source);
|
||||||
|
|
||||||
|
|
@ -96,7 +98,7 @@ _notify_platform_cb(gpointer user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_notify_platform(NMIPConfig *self, guint32 obj_type_flags)
|
_notify_platform(NMIPConfig *self, guint64 obj_type_flags)
|
||||||
{
|
{
|
||||||
const int addr_family = nm_ip_config_get_addr_family(self);
|
const int addr_family = nm_ip_config_get_addr_family(self);
|
||||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||||
|
|
@ -164,6 +166,8 @@ get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec
|
||||||
const int addr_family = nm_ip_config_get_addr_family(self);
|
const int addr_family = nm_ip_config_get_addr_family(self);
|
||||||
char **to_free = NULL;
|
char **to_free = NULL;
|
||||||
char sbuf_addr[NM_INET_ADDRSTRLEN];
|
char sbuf_addr[NM_INET_ADDRSTRLEN];
|
||||||
|
in_addr_t addr4;
|
||||||
|
struct in6_addr addr6;
|
||||||
const char *const *strv;
|
const char *const *strv;
|
||||||
guint len;
|
guint len;
|
||||||
int v_i;
|
int v_i;
|
||||||
|
|
@ -218,6 +222,20 @@ get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec
|
||||||
strv = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
|
strv = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
|
||||||
_value_set_variant_as(value, strv, len);
|
_value_set_variant_as(value, strv, len);
|
||||||
break;
|
break;
|
||||||
|
case PROP_IP_CLAT_ADDRESS:
|
||||||
|
if (nm_l3_config_data_get_clat_state(priv->l3cd, &addr6, NULL, NULL, &addr4)) {
|
||||||
|
if (addr_family == AF_INET) {
|
||||||
|
g_value_set_variant(value,
|
||||||
|
g_variant_new_string(nm_inet_ntop(AF_INET, &addr4, sbuf_addr)));
|
||||||
|
} else {
|
||||||
|
g_value_set_variant(
|
||||||
|
value,
|
||||||
|
g_variant_new_string(nm_inet_ntop(AF_INET6, &addr6, sbuf_addr)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_value_set_variant(value, nm_g_variant_singleton_s_empty());
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
@ -336,6 +354,13 @@ nm_ip_config_class_init(NMIPConfigClass *klass)
|
||||||
G_VARIANT_TYPE("aa{sv}"),
|
G_VARIANT_TYPE("aa{sv}"),
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
obj_properties_ip[PROP_IP_CLAT_ADDRESS] =
|
||||||
|
g_param_spec_variant(NM_IP_CONFIG_CLAT_ADDRESS,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
G_VARIANT_TYPE("s"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
obj_properties_ip[PROP_IP_GATEWAY] =
|
obj_properties_ip[PROP_IP_GATEWAY] =
|
||||||
g_param_spec_variant(NM_IP_CONFIG_GATEWAY,
|
g_param_spec_variant(NM_IP_CONFIG_GATEWAY,
|
||||||
"",
|
"",
|
||||||
|
|
@ -512,6 +537,9 @@ static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
|
||||||
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
|
||||||
"aa{sv}",
|
"aa{sv}",
|
||||||
NM_IP_CONFIG_ADDRESS_DATA),
|
NM_IP_CONFIG_ADDRESS_DATA),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ClatAddress",
|
||||||
|
"s",
|
||||||
|
NM_IP_CONFIG_CLAT_ADDRESS),
|
||||||
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
|
||||||
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(
|
||||||
"Routes",
|
"Routes",
|
||||||
|
|
@ -614,6 +642,7 @@ nm_ip4_config_class_init(NMIP4ConfigClass *klass)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/* public */
|
/* public */
|
||||||
|
#define NM_IP6_CONFIG_CLAT_PREF64 "clat-pref64"
|
||||||
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
|
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
|
||||||
|
|
||||||
/* deprecated */
|
/* deprecated */
|
||||||
|
|
@ -625,6 +654,7 @@ typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
|
||||||
|
|
||||||
NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip6,
|
NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip6,
|
||||||
NMIP6Config,
|
NMIP6Config,
|
||||||
|
PROP_IP6_CLAT_PREF64,
|
||||||
PROP_IP6_NAMESERVERS,
|
PROP_IP6_NAMESERVERS,
|
||||||
PROP_IP6_ADDRESSES,
|
PROP_IP6_ADDRESSES,
|
||||||
PROP_IP6_ROUTES, );
|
PROP_IP6_ROUTES, );
|
||||||
|
|
@ -651,6 +681,12 @@ static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
|
||||||
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
|
||||||
"aa{sv}",
|
"aa{sv}",
|
||||||
NM_IP_CONFIG_ADDRESS_DATA),
|
NM_IP_CONFIG_ADDRESS_DATA),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ClatAddress",
|
||||||
|
"s",
|
||||||
|
NM_IP_CONFIG_CLAT_ADDRESS),
|
||||||
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ClatPref64",
|
||||||
|
"s",
|
||||||
|
NM_IP6_CONFIG_CLAT_PREF64),
|
||||||
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
|
||||||
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(
|
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(
|
||||||
"Routes",
|
"Routes",
|
||||||
|
|
@ -682,11 +718,24 @@ get_property_ip6(GObject *object, guint prop_id, GValue *value, GParamSpec *pspe
|
||||||
guint len;
|
guint len;
|
||||||
guint i;
|
guint i;
|
||||||
const char *const *strarr;
|
const char *const *strarr;
|
||||||
|
guint8 plen;
|
||||||
|
struct in6_addr addr6;
|
||||||
|
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_IP6_ADDRESSES:
|
case PROP_IP6_ADDRESSES:
|
||||||
g_value_set_variant(value, priv->v_addresses);
|
g_value_set_variant(value, priv->v_addresses);
|
||||||
break;
|
break;
|
||||||
|
case PROP_IP6_CLAT_PREF64:
|
||||||
|
if (nm_l3_config_data_get_clat_state(priv->l3cd, NULL, &addr6, &plen, NULL)) {
|
||||||
|
nm_inet6_ntop(&addr6, sbuf);
|
||||||
|
g_value_set_variant(value,
|
||||||
|
g_variant_new_string(
|
||||||
|
nm_sprintf_bufa(NM_INET_ADDRSTRLEN + 32, "%s/%u", sbuf, plen)));
|
||||||
|
} else {
|
||||||
|
g_value_set_variant(value, nm_g_variant_singleton_s_empty());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PROP_IP6_ROUTES:
|
case PROP_IP6_ROUTES:
|
||||||
g_value_set_variant(value, priv->v_routes);
|
g_value_set_variant(value, priv->v_routes);
|
||||||
break;
|
break;
|
||||||
|
|
@ -740,6 +789,13 @@ nm_ip6_config_class_init(NMIP6ConfigClass *klass)
|
||||||
G_VARIANT_TYPE("a(ayuay)"),
|
G_VARIANT_TYPE("a(ayuay)"),
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
obj_properties_ip6[PROP_IP6_CLAT_PREF64] =
|
||||||
|
g_param_spec_variant(NM_IP6_CONFIG_CLAT_PREF64,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
G_VARIANT_TYPE("s"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
obj_properties_ip6[PROP_IP6_ROUTES] =
|
obj_properties_ip6[PROP_IP6_ROUTES] =
|
||||||
g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
|
g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
|
||||||
"",
|
"",
|
||||||
|
|
@ -787,7 +843,7 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
|
||||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||||
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
|
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
|
||||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
|
nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
|
||||||
GParamSpec *changed_params[8];
|
GParamSpec *changed_params[10];
|
||||||
guint n_changed_params = 0;
|
guint n_changed_params = 0;
|
||||||
const char *const *strarr;
|
const char *const *strarr;
|
||||||
const char *const *strarr_old;
|
const char *const *strarr_old;
|
||||||
|
|
@ -840,11 +896,64 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CLAT state */
|
||||||
|
{
|
||||||
|
struct in6_addr clat_ip6;
|
||||||
|
struct in6_addr clat_pref64;
|
||||||
|
guint8 clat_pref64_plen;
|
||||||
|
in_addr_t clat_ip4;
|
||||||
|
gboolean clat_enabled;
|
||||||
|
struct in6_addr clat_ip6_old;
|
||||||
|
struct in6_addr clat_pref64_old;
|
||||||
|
guint8 clat_pref64_plen_old;
|
||||||
|
in_addr_t clat_ip4_old;
|
||||||
|
gboolean clat_enabled_old;
|
||||||
|
gboolean changed;
|
||||||
|
|
||||||
|
clat_enabled_old = nm_l3_config_data_get_clat_state(l3cd_old,
|
||||||
|
&clat_ip6_old,
|
||||||
|
&clat_pref64_old,
|
||||||
|
&clat_pref64_plen_old,
|
||||||
|
&clat_ip4_old);
|
||||||
|
clat_enabled = nm_l3_config_data_get_clat_state(priv->l3cd,
|
||||||
|
&clat_ip6,
|
||||||
|
&clat_pref64,
|
||||||
|
&clat_pref64_plen,
|
||||||
|
&clat_ip4);
|
||||||
|
|
||||||
|
/* CLAT address */
|
||||||
|
if (clat_enabled != clat_enabled_old) {
|
||||||
|
changed = TRUE;
|
||||||
|
} else if (!clat_enabled) {
|
||||||
|
changed = FALSE;
|
||||||
|
} else if (IS_IPv4) {
|
||||||
|
changed = (clat_ip4 != clat_ip4_old);
|
||||||
|
} else {
|
||||||
|
changed = !IN6_ARE_ADDR_EQUAL(&clat_ip6, &clat_ip6_old);
|
||||||
|
}
|
||||||
|
if (changed)
|
||||||
|
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_CLAT_ADDRESS];
|
||||||
|
|
||||||
|
/* PREF64 */
|
||||||
|
if (!IS_IPv4) {
|
||||||
|
if (clat_enabled != clat_enabled_old) {
|
||||||
|
changed = TRUE;
|
||||||
|
} else if (!clat_enabled) {
|
||||||
|
changed = FALSE;
|
||||||
|
} else {
|
||||||
|
changed = (clat_pref64_plen != clat_pref64_plen_old)
|
||||||
|
|| (!IN6_ARE_ADDR_EQUAL(&clat_pref64, &clat_pref64_old));
|
||||||
|
}
|
||||||
|
if (changed)
|
||||||
|
changed_params[n_changed_params++] = obj_properties_ip6[PROP_IP6_CLAT_PREF64];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_notify_all(self, changed_params, n_changed_params);
|
_notify_all(self, changed_params, n_changed_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_handle_platform_change(NMIPConfig *self, guint32 obj_type_flags, gboolean is_init)
|
_handle_platform_change(NMIPConfig *self, guint64 obj_type_flags, gboolean is_init)
|
||||||
{
|
{
|
||||||
const int addr_family = nm_ip_config_get_addr_family(self);
|
const int addr_family = nm_ip_config_get_addr_family(self);
|
||||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct _NMIPConfigPrivate {
|
||||||
GSource *notify_platform_timeout_source;
|
GSource *notify_platform_timeout_source;
|
||||||
gint64 notify_platform_rlimited_until_msec;
|
gint64 notify_platform_rlimited_until_msec;
|
||||||
gulong l3cfg_notify_id;
|
gulong l3cfg_notify_id;
|
||||||
guint32 notify_platform_obj_type_flags;
|
guint64 notify_platform_obj_type_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _NMIPConfig {
|
struct _NMIPConfig {
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ struct _NML3ConfigData {
|
||||||
const NMPObject *best_default_route_x[2];
|
const NMPObject *best_default_route_x[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct in6_addr pref64_prefix;
|
||||||
|
guint32 pref64_plen;
|
||||||
|
|
||||||
GArray *wins;
|
GArray *wins;
|
||||||
GArray *nis_servers;
|
GArray *nis_servers;
|
||||||
|
|
||||||
|
|
@ -122,6 +125,19 @@ struct _NML3ConfigData {
|
||||||
NMSettingConnectionDnsOverTls dns_over_tls;
|
NMSettingConnectionDnsOverTls dns_over_tls;
|
||||||
NMSettingConnectionDnssec dnssec;
|
NMSettingConnectionDnssec dnssec;
|
||||||
NMUtilsIPv6IfaceId ip6_token;
|
NMUtilsIPv6IfaceId ip6_token;
|
||||||
|
NMRefString *network_id;
|
||||||
|
NMSettingIp4ConfigClat clat_config; /* this indicates the 'administrative' CLAT
|
||||||
|
* state, i.e. whether CLAT will be started
|
||||||
|
* once we receive a PREF64 */
|
||||||
|
|
||||||
|
/* The runtime CLAT state */
|
||||||
|
struct {
|
||||||
|
struct in6_addr ip6;
|
||||||
|
struct in6_addr pref64;
|
||||||
|
in_addr_t ip4;
|
||||||
|
guint8 pref64_plen;
|
||||||
|
bool enabled;
|
||||||
|
} clat_state;
|
||||||
|
|
||||||
NML3ConfigDatFlags flags;
|
NML3ConfigDatFlags flags;
|
||||||
|
|
||||||
|
|
@ -130,7 +146,8 @@ struct _NML3ConfigData {
|
||||||
int ndisc_hop_limit_val;
|
int ndisc_hop_limit_val;
|
||||||
|
|
||||||
guint32 mtu;
|
guint32 mtu;
|
||||||
guint32 ip6_mtu;
|
guint32 ip6_mtu_static; /* IPv6 MTU from the connection profile */
|
||||||
|
guint32 ip6_mtu_ra; /* IPv6 MTU from Router Advertisement */
|
||||||
guint32 ndisc_reachable_time_msec_val;
|
guint32 ndisc_reachable_time_msec_val;
|
||||||
guint32 ndisc_retrans_timer_msec_val;
|
guint32 ndisc_retrans_timer_msec_val;
|
||||||
|
|
||||||
|
|
@ -167,6 +184,8 @@ struct _NML3ConfigData {
|
||||||
|
|
||||||
bool routed_dns_4 : 1;
|
bool routed_dns_4 : 1;
|
||||||
bool routed_dns_6 : 1;
|
bool routed_dns_6 : 1;
|
||||||
|
|
||||||
|
bool pref64_valid : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -390,8 +409,11 @@ nm_l3_config_data_log(const NML3ConfigData *self,
|
||||||
: "",
|
: "",
|
||||||
!self->is_sealed ? ", not-sealed" : "");
|
!self->is_sealed ? ", not-sealed" : "");
|
||||||
|
|
||||||
if (self->mtu != 0 || self->ip6_mtu != 0) {
|
if (self->mtu != 0 || self->ip6_mtu_static != 0 || self->ip6_mtu_ra != 0) {
|
||||||
_L("mtu: %u, ip6-mtu: %u", self->mtu, self->ip6_mtu);
|
_L("mtu: %u, ip6-mtu-static: %u, ip6-mtu-ra %u",
|
||||||
|
self->mtu,
|
||||||
|
self->ip6_mtu_static,
|
||||||
|
self->ip6_mtu_ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||||
|
|
@ -519,6 +541,27 @@ nm_l3_config_data_log(const NML3ConfigData *self,
|
||||||
_L("nis-domain: %s", self->nis_domain->str);
|
_L("nis-domain: %s", self->nis_domain->str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IS_IPv4) {
|
||||||
|
if (self->clat_config == NM_SETTING_IP4_CONFIG_CLAT_AUTO)
|
||||||
|
_L("clat-config: auto");
|
||||||
|
else if (self->clat_config == NM_SETTING_IP4_CONFIG_CLAT_FORCE)
|
||||||
|
_L("clat-config: force");
|
||||||
|
|
||||||
|
if (self->clat_state.enabled) {
|
||||||
|
_L("clat-state: ip4=%s/32, pref64=%s/%u, ip6=%s/64",
|
||||||
|
nm_inet4_ntop(self->clat_state.ip4, sbuf + NM_INET_ADDRSTRLEN),
|
||||||
|
nm_inet6_ntop(&self->clat_state.pref64, sbuf),
|
||||||
|
self->clat_state.pref64_plen,
|
||||||
|
nm_inet6_ntop(&self->clat_state.ip6, sbuf_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_IPv4 && self->pref64_valid) {
|
||||||
|
_L("pref64_prefix: %s/%d",
|
||||||
|
nm_utils_inet6_ntop(&self->pref64_prefix, sbuf_addr),
|
||||||
|
self->pref64_plen);
|
||||||
|
}
|
||||||
|
|
||||||
if (self->dhcp_lease_x[IS_IPv4]) {
|
if (self->dhcp_lease_x[IS_IPv4]) {
|
||||||
gs_free NMUtilsNamedValue *options_free = NULL;
|
gs_free NMUtilsNamedValue *options_free = NULL;
|
||||||
NMUtilsNamedValue options_buffer[30];
|
NMUtilsNamedValue options_buffer[30];
|
||||||
|
|
@ -603,6 +646,10 @@ nm_l3_config_data_log(const NML3ConfigData *self,
|
||||||
nm_utils_inet6_interface_identifier_to_token(&self->ip6_token, sbuf_addr));
|
nm_utils_inet6_interface_identifier_to_token(&self->ip6_token, sbuf_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->network_id) {
|
||||||
|
_L("network-id: %s", self->network_id->str);
|
||||||
|
}
|
||||||
|
|
||||||
if (self->metered != NM_TERNARY_DEFAULT)
|
if (self->metered != NM_TERNARY_DEFAULT)
|
||||||
_L("metered: %s", self->metered ? "yes" : "no");
|
_L("metered: %s", self->metered ? "yes" : "no");
|
||||||
|
|
||||||
|
|
@ -709,6 +756,7 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSourc
|
||||||
.flags = NM_L3_CONFIG_DAT_FLAGS_NONE,
|
.flags = NM_L3_CONFIG_DAT_FLAGS_NONE,
|
||||||
.metered = NM_TERNARY_DEFAULT,
|
.metered = NM_TERNARY_DEFAULT,
|
||||||
.proxy_browser_only = NM_TERNARY_DEFAULT,
|
.proxy_browser_only = NM_TERNARY_DEFAULT,
|
||||||
|
.clat_config = NM_SETTING_IP4_CONFIG_CLAT_NO,
|
||||||
.proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN,
|
.proxy_method = NM_PROXY_CONFIG_METHOD_UNKNOWN,
|
||||||
.route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
.route_table_sync_4 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||||
.route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
.route_table_sync_6 = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||||
|
|
@ -722,6 +770,7 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSourc
|
||||||
.ndisc_retrans_timer_msec_set = FALSE,
|
.ndisc_retrans_timer_msec_set = FALSE,
|
||||||
.allow_routes_without_address_4 = TRUE,
|
.allow_routes_without_address_4 = TRUE,
|
||||||
.allow_routes_without_address_6 = TRUE,
|
.allow_routes_without_address_6 = TRUE,
|
||||||
|
.pref64_valid = FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
_idx_type_init(&self->idx_addresses_4, NMP_OBJECT_TYPE_IP4_ADDRESS);
|
_idx_type_init(&self->idx_addresses_4, NMP_OBJECT_TYPE_IP4_ADDRESS);
|
||||||
|
|
@ -822,6 +871,7 @@ nm_l3_config_data_unref(const NML3ConfigData *self)
|
||||||
nm_ref_string_unref(mutable->nis_domain);
|
nm_ref_string_unref(mutable->nis_domain);
|
||||||
nm_ref_string_unref(mutable->proxy_pac_url);
|
nm_ref_string_unref(mutable->proxy_pac_url);
|
||||||
nm_ref_string_unref(mutable->proxy_pac_script);
|
nm_ref_string_unref(mutable->proxy_pac_script);
|
||||||
|
nm_ref_string_unref(mutable->network_id);
|
||||||
|
|
||||||
nm_g_slice_free(mutable);
|
nm_g_slice_free(mutable);
|
||||||
}
|
}
|
||||||
|
|
@ -1890,22 +1940,42 @@ nm_l3_config_data_set_mtu(NML3ConfigData *self, guint32 mtu)
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32
|
guint32
|
||||||
nm_l3_config_data_get_ip6_mtu(const NML3ConfigData *self)
|
nm_l3_config_data_get_ip6_mtu_static(const NML3ConfigData *self)
|
||||||
{
|
{
|
||||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||||
|
|
||||||
return self->ip6_mtu;
|
return self->ip6_mtu_static;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_l3_config_data_set_ip6_mtu(NML3ConfigData *self, guint32 ip6_mtu)
|
nm_l3_config_data_set_ip6_mtu_static(NML3ConfigData *self, guint32 ip6_mtu)
|
||||||
{
|
{
|
||||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||||
|
|
||||||
if (self->ip6_mtu == ip6_mtu)
|
if (self->ip6_mtu_static == ip6_mtu)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
self->ip6_mtu = ip6_mtu;
|
self->ip6_mtu_static = ip6_mtu;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint32
|
||||||
|
nm_l3_config_data_get_ip6_mtu_ra(const NML3ConfigData *self)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||||
|
|
||||||
|
return self->ip6_mtu_ra;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_set_ip6_mtu_ra(NML3ConfigData *self, guint32 ip6_mtu)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||||
|
|
||||||
|
if (self->ip6_mtu_ra == ip6_mtu)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
self->ip6_mtu_ra = ip6_mtu;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1957,6 +2027,132 @@ nm_l3_config_data_set_ip6_token(NML3ConfigData *self, NMUtilsIPv6IfaceId ipv6_to
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_l3_config_data_get_network_id(const NML3ConfigData *self)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||||
|
|
||||||
|
return nm_ref_string_get_str(self->network_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_set_network_id(NML3ConfigData *self, const char *value)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||||
|
|
||||||
|
return nm_ref_string_reset_str(&self->network_id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_set_clat_config(NML3ConfigData *self, NMSettingIp4ConfigClat val)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||||
|
nm_assert(NM_IN_SET(val,
|
||||||
|
NM_SETTING_IP4_CONFIG_CLAT_NO,
|
||||||
|
NM_SETTING_IP4_CONFIG_CLAT_FORCE,
|
||||||
|
NM_SETTING_IP4_CONFIG_CLAT_AUTO));
|
||||||
|
|
||||||
|
if (self->clat_config == val)
|
||||||
|
return FALSE;
|
||||||
|
self->clat_config = val;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NMSettingIp4ConfigClat
|
||||||
|
nm_l3_config_data_get_clat_config(const NML3ConfigData *self)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||||
|
|
||||||
|
return self->clat_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_get_clat_state(const NML3ConfigData *self,
|
||||||
|
struct in6_addr *out_ip6,
|
||||||
|
struct in6_addr *out_pref64,
|
||||||
|
guint8 *out_pref64_plen,
|
||||||
|
in_addr_t *out_ip4)
|
||||||
|
{
|
||||||
|
if (!self || !self->clat_state.enabled)
|
||||||
|
return FALSE;
|
||||||
|
NM_SET_OUT(out_ip6, self->clat_state.ip6);
|
||||||
|
NM_SET_OUT(out_pref64, self->clat_state.pref64);
|
||||||
|
NM_SET_OUT(out_pref64_plen, self->clat_state.pref64_plen);
|
||||||
|
NM_SET_OUT(out_ip4, self->clat_state.ip4);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_l3_config_data_set_clat_state(NML3ConfigData *self,
|
||||||
|
gboolean enabled,
|
||||||
|
const struct in6_addr *ip6,
|
||||||
|
const struct in6_addr *pref64,
|
||||||
|
guint8 pref64_plen,
|
||||||
|
in_addr_t ip4)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||||
|
|
||||||
|
self->clat_state.enabled = enabled;
|
||||||
|
if (enabled) {
|
||||||
|
self->clat_state.ip6 = *ip6;
|
||||||
|
self->clat_state.pref64 = *pref64;
|
||||||
|
self->clat_state.pref64_plen = pref64_plen;
|
||||||
|
self->clat_state.ip4 = ip4;
|
||||||
|
} else {
|
||||||
|
self->clat_state.ip6 = in6addr_any;
|
||||||
|
self->clat_state.pref64 = in6addr_any;
|
||||||
|
self->clat_state.pref64_plen = 0;
|
||||||
|
self->clat_state.ip4 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_set_pref64_valid(NML3ConfigData *self, gboolean val)
|
||||||
|
{
|
||||||
|
if (self->pref64_valid == val)
|
||||||
|
return FALSE;
|
||||||
|
self->pref64_valid = val;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_get_pref64_valid(const NML3ConfigData *self)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||||
|
|
||||||
|
return self->pref64_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_get_pref64(const NML3ConfigData *self,
|
||||||
|
struct in6_addr *out_prefix,
|
||||||
|
guint32 *out_plen)
|
||||||
|
{
|
||||||
|
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||||
|
|
||||||
|
if (!self->pref64_valid)
|
||||||
|
return FALSE;
|
||||||
|
NM_SET_OUT(out_prefix, self->pref64_prefix);
|
||||||
|
NM_SET_OUT(out_plen, self->pref64_plen);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_l3_config_data_set_pref64(NML3ConfigData *self, struct in6_addr prefix, guint32 plen)
|
||||||
|
{
|
||||||
|
if (self->pref64_valid) {
|
||||||
|
if (self->pref64_plen == plen
|
||||||
|
&& nm_ip6_addr_same_prefix(&self->pref64_prefix, &prefix, plen)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self->pref64_valid = TRUE;
|
||||||
|
}
|
||||||
|
self->pref64_prefix = prefix;
|
||||||
|
self->pref64_plen = plen;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
NMMptcpFlags
|
NMMptcpFlags
|
||||||
nm_l3_config_data_get_mptcp_flags(const NML3ConfigData *self)
|
nm_l3_config_data_get_mptcp_flags(const NML3ConfigData *self)
|
||||||
{
|
{
|
||||||
|
|
@ -2484,8 +2680,10 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a,
|
||||||
if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_OTHER)) {
|
if (NM_FLAGS_HAS(flags, NM_L3_CONFIG_CMP_FLAGS_OTHER)) {
|
||||||
NM_CMP_DIRECT(a->flags, b->flags);
|
NM_CMP_DIRECT(a->flags, b->flags);
|
||||||
NM_CMP_DIRECT(a->ip6_token.id, b->ip6_token.id);
|
NM_CMP_DIRECT(a->ip6_token.id, b->ip6_token.id);
|
||||||
|
NM_CMP_DIRECT_REF_STRING(a->network_id, b->network_id);
|
||||||
NM_CMP_DIRECT(a->mtu, b->mtu);
|
NM_CMP_DIRECT(a->mtu, b->mtu);
|
||||||
NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu);
|
NM_CMP_DIRECT(a->ip6_mtu_static, b->ip6_mtu_static);
|
||||||
|
NM_CMP_DIRECT(a->ip6_mtu_ra, b->ip6_mtu_ra);
|
||||||
NM_CMP_DIRECT_UNSAFE(a->metered, b->metered);
|
NM_CMP_DIRECT_UNSAFE(a->metered, b->metered);
|
||||||
NM_CMP_DIRECT_UNSAFE(a->proxy_browser_only, b->proxy_browser_only);
|
NM_CMP_DIRECT_UNSAFE(a->proxy_browser_only, b->proxy_browser_only);
|
||||||
NM_CMP_DIRECT_UNSAFE(a->proxy_method, b->proxy_method);
|
NM_CMP_DIRECT_UNSAFE(a->proxy_method, b->proxy_method);
|
||||||
|
|
@ -2509,6 +2707,23 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a,
|
||||||
NM_CMP_DIRECT_UNSAFE(a->routed_dns_4, b->routed_dns_4);
|
NM_CMP_DIRECT_UNSAFE(a->routed_dns_4, b->routed_dns_4);
|
||||||
NM_CMP_DIRECT_UNSAFE(a->routed_dns_6, b->routed_dns_6);
|
NM_CMP_DIRECT_UNSAFE(a->routed_dns_6, b->routed_dns_6);
|
||||||
|
|
||||||
|
NM_CMP_DIRECT_UNSAFE(a->clat_config, b->clat_config);
|
||||||
|
|
||||||
|
NM_CMP_DIRECT(!!a->clat_state.enabled, !!b->clat_state.enabled);
|
||||||
|
if (a->clat_state.enabled) {
|
||||||
|
NM_CMP_DIRECT_IN6ADDR(&a->clat_state.ip6, &b->clat_state.ip6);
|
||||||
|
NM_CMP_DIRECT_IN6ADDR(&a->clat_state.pref64, &b->clat_state.pref64);
|
||||||
|
NM_CMP_DIRECT(a->clat_state.pref64_plen, b->clat_state.pref64_plen);
|
||||||
|
NM_CMP_DIRECT(a->clat_state.ip4, b->clat_state.ip4);
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_CMP_DIRECT(!!a->pref64_valid, !!b->pref64_valid);
|
||||||
|
if (a->pref64_valid) {
|
||||||
|
NM_CMP_DIRECT(a->pref64_plen, b->pref64_plen);
|
||||||
|
NM_CMP_RETURN_DIRECT(
|
||||||
|
nm_ip6_addr_same_prefix_cmp(&a->pref64_prefix, &b->pref64_prefix, a->pref64_plen));
|
||||||
|
}
|
||||||
|
|
||||||
NM_CMP_FIELD(a, b, source);
|
NM_CMP_FIELD(a, b, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2524,8 +2739,10 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a,
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static const NMPObject *
|
const NMPObject *
|
||||||
_data_get_direct_route_for_host(const NML3ConfigData *self, int addr_family, gconstpointer host)
|
nm_l3_config_data_get_direct_route_for_host(const NML3ConfigData *self,
|
||||||
|
int addr_family,
|
||||||
|
gconstpointer host)
|
||||||
{
|
{
|
||||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||||
const NMPObject *best_route_obj = NULL;
|
const NMPObject *best_route_obj = NULL;
|
||||||
|
|
@ -2683,7 +2900,7 @@ nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_fam
|
||||||
if (NM_FLAGS_HAS(route_src->rx.r_rtm_flags, (unsigned) RTNH_F_ONLINK))
|
if (NM_FLAGS_HAS(route_src->rx.r_rtm_flags, (unsigned) RTNH_F_ONLINK))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_data_get_direct_route_for_host(self, addr_family, p_gateway))
|
if (nm_l3_config_data_get_direct_route_for_host(self, addr_family, p_gateway))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new_route = nmp_object_clone(obj_src, FALSE);
|
new_route = nmp_object_clone(obj_src, FALSE);
|
||||||
|
|
@ -2991,12 +3208,9 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co
|
||||||
* the one we create here (because the "onlink" flag is part of the
|
* the one we create here (because the "onlink" flag is part of the
|
||||||
* identifier of a route, see nm_platform_ip4_route_cmp()).
|
* identifier of a route, see nm_platform_ip4_route_cmp()).
|
||||||
*
|
*
|
||||||
* Note however that for ECMP routes we currently can only merge routes
|
* The onlink flag is tracked per-nexthop (in NMPlatformIP4RtNextHop.rtnh_flags
|
||||||
* that agree in their onlink flag. So a route without gateway cannot
|
* for extra nexthops, and in r_rtm_flags for the first nexthop). ECMP routes
|
||||||
* merge with an onlink route that has a gateway. That needs fixing,
|
* can be merged regardless of per-nexthop onlink flags. */
|
||||||
* 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);
|
r.r4.r_rtm_flags &= ~((unsigned) RTNH_F_ONLINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3030,6 +3244,9 @@ _init_from_connection_ip(NML3ConfigData *self, int addr_family, NMConnection *co
|
||||||
nm_l3_config_data_set_ip6_privacy(
|
nm_l3_config_data_set_ip6_privacy(
|
||||||
self,
|
self,
|
||||||
nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip)));
|
nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip)));
|
||||||
|
nm_l3_config_data_set_ip6_mtu_static(
|
||||||
|
self,
|
||||||
|
nm_setting_ip6_config_get_mtu(NM_SETTING_IP6_CONFIG(s_ip)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3506,6 +3723,9 @@ nm_l3_config_data_merge(NML3ConfigData *self,
|
||||||
if (self->ip6_token.id == 0)
|
if (self->ip6_token.id == 0)
|
||||||
self->ip6_token.id = src->ip6_token.id;
|
self->ip6_token.id = src->ip6_token.id;
|
||||||
|
|
||||||
|
if (!self->network_id)
|
||||||
|
self->network_id = nm_ref_string_ref(src->network_id);
|
||||||
|
|
||||||
self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered);
|
self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered);
|
||||||
|
|
||||||
if (self->proxy_method == NM_PROXY_CONFIG_METHOD_UNKNOWN)
|
if (self->proxy_method == NM_PROXY_CONFIG_METHOD_UNKNOWN)
|
||||||
|
|
@ -3544,8 +3764,11 @@ nm_l3_config_data_merge(NML3ConfigData *self,
|
||||||
if (self->mtu == 0u)
|
if (self->mtu == 0u)
|
||||||
self->mtu = src->mtu;
|
self->mtu = src->mtu;
|
||||||
|
|
||||||
if (self->ip6_mtu == 0u)
|
if (self->ip6_mtu_static == 0u)
|
||||||
self->ip6_mtu = src->ip6_mtu;
|
self->ip6_mtu_static = src->ip6_mtu_static;
|
||||||
|
|
||||||
|
if (self->ip6_mtu_ra == 0u)
|
||||||
|
self->ip6_mtu_ra = src->ip6_mtu_ra;
|
||||||
|
|
||||||
if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) {
|
if (NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) {
|
||||||
_nm_unused nm_auto_unref_dhcplease NMDhcpLease *dhcp_lease_6 =
|
_nm_unused nm_auto_unref_dhcplease NMDhcpLease *dhcp_lease_6 =
|
||||||
|
|
@ -3567,6 +3790,24 @@ nm_l3_config_data_merge(NML3ConfigData *self,
|
||||||
self->routed_dns_4 = TRUE;
|
self->routed_dns_4 = TRUE;
|
||||||
if (src->routed_dns_6)
|
if (src->routed_dns_6)
|
||||||
self->routed_dns_6 = TRUE;
|
self->routed_dns_6 = TRUE;
|
||||||
|
|
||||||
|
if (self->clat_config == NM_SETTING_IP4_CONFIG_CLAT_NO) {
|
||||||
|
/* 'no' always loses to 'force' and 'auto' */
|
||||||
|
self->clat_config = src->clat_config;
|
||||||
|
} else if (src->clat_config == NM_SETTING_IP4_CONFIG_CLAT_FORCE) {
|
||||||
|
/* 'force' always takes precedence */
|
||||||
|
self->clat_config = src->clat_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self->clat_state.enabled && src->clat_state.enabled) {
|
||||||
|
self->clat_state = src->clat_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->pref64_valid) {
|
||||||
|
self->pref64_prefix = src->pref64_prefix;
|
||||||
|
self->pref64_plen = src->pref64_plen;
|
||||||
|
self->pref64_valid = src->pref64_valid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NML3ConfigData *
|
NML3ConfigData *
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "libnm-glib-aux/nm-dedup-multi.h"
|
#include "libnm-glib-aux/nm-dedup-multi.h"
|
||||||
#include "nm-setting-connection.h"
|
#include "nm-setting-connection.h"
|
||||||
|
#include "nm-setting-ip4-config.h"
|
||||||
#include "nm-setting-ip6-config.h"
|
#include "nm-setting-ip6-config.h"
|
||||||
#include "libnm-platform/nm-platform.h"
|
#include "libnm-platform/nm-platform.h"
|
||||||
#include "libnm-platform/nmp-object.h"
|
#include "libnm-platform/nmp-object.h"
|
||||||
|
|
@ -225,6 +226,10 @@ nm_l3_config_data_equal(const NML3ConfigData *a, const NML3ConfigData *b)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const NMPObject *nm_l3_config_data_get_direct_route_for_host(const NML3ConfigData *self,
|
||||||
|
int addr_family,
|
||||||
|
gconstpointer host);
|
||||||
|
|
||||||
const NMDedupMultiIdxType *nm_l3_config_data_lookup_index(const NML3ConfigData *self,
|
const NMDedupMultiIdxType *nm_l3_config_data_lookup_index(const NML3ConfigData *self,
|
||||||
NMPObjectType obj_type);
|
NMPObjectType obj_type);
|
||||||
|
|
||||||
|
|
@ -482,14 +487,49 @@ guint32 nm_l3_config_data_get_mtu(const NML3ConfigData *self);
|
||||||
|
|
||||||
gboolean nm_l3_config_data_set_mtu(NML3ConfigData *self, guint32 mtu);
|
gboolean nm_l3_config_data_set_mtu(NML3ConfigData *self, guint32 mtu);
|
||||||
|
|
||||||
guint32 nm_l3_config_data_get_ip6_mtu(const NML3ConfigData *self);
|
guint32 nm_l3_config_data_get_ip6_mtu_static(const NML3ConfigData *self);
|
||||||
|
|
||||||
gboolean nm_l3_config_data_set_ip6_mtu(NML3ConfigData *self, guint32 ip6_mtu);
|
gboolean nm_l3_config_data_set_ip6_mtu_static(NML3ConfigData *self, guint32 ip6_mtu);
|
||||||
|
|
||||||
|
guint32 nm_l3_config_data_get_ip6_mtu_ra(const NML3ConfigData *self);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_set_ip6_mtu_ra(NML3ConfigData *self, guint32 ip6_mtu);
|
||||||
|
|
||||||
NMUtilsIPv6IfaceId nm_l3_config_data_get_ip6_token(const NML3ConfigData *self);
|
NMUtilsIPv6IfaceId nm_l3_config_data_get_ip6_token(const NML3ConfigData *self);
|
||||||
|
|
||||||
gboolean nm_l3_config_data_set_ip6_token(NML3ConfigData *self, NMUtilsIPv6IfaceId ipv6_token);
|
gboolean nm_l3_config_data_set_ip6_token(NML3ConfigData *self, NMUtilsIPv6IfaceId ipv6_token);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_set_network_id(NML3ConfigData *self, const char *network_id);
|
||||||
|
|
||||||
|
const char *nm_l3_config_data_get_network_id(const NML3ConfigData *self);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_set_clat_config(NML3ConfigData *self, NMSettingIp4ConfigClat val);
|
||||||
|
|
||||||
|
NMSettingIp4ConfigClat nm_l3_config_data_get_clat_config(const NML3ConfigData *self);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_get_clat_state(const NML3ConfigData *self,
|
||||||
|
struct in6_addr *out_ip6,
|
||||||
|
struct in6_addr *out_pref64,
|
||||||
|
guint8 *out_pref64_plen,
|
||||||
|
in_addr_t *out_ip4);
|
||||||
|
|
||||||
|
void nm_l3_config_data_set_clat_state(NML3ConfigData *self,
|
||||||
|
gboolean enabled,
|
||||||
|
const struct in6_addr *ip6,
|
||||||
|
const struct in6_addr *pref64,
|
||||||
|
guint8 pref64_plen,
|
||||||
|
in_addr_t ip4);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_set_pref64_valid(NML3ConfigData *self, gboolean val);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_get_pref64_valid(const NML3ConfigData *self);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_get_pref64(const NML3ConfigData *self,
|
||||||
|
struct in6_addr *out_prefix,
|
||||||
|
guint32 *out_plen);
|
||||||
|
|
||||||
|
gboolean nm_l3_config_data_set_pref64(NML3ConfigData *self, struct in6_addr prefix, guint32 plen);
|
||||||
|
|
||||||
NMMptcpFlags nm_l3_config_data_get_mptcp_flags(const NML3ConfigData *self);
|
NMMptcpFlags nm_l3_config_data_get_mptcp_flags(const NML3ConfigData *self);
|
||||||
|
|
||||||
gboolean nm_l3_config_data_set_mptcp_flags(NML3ConfigData *self, NMMptcpFlags mptcp_flags);
|
gboolean nm_l3_config_data_set_mptcp_flags(NML3ConfigData *self, NMMptcpFlags mptcp_flags);
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,15 @@
|
||||||
#include "libnm-std-aux/nm-linux-compat.h"
|
#include "libnm-std-aux/nm-linux-compat.h"
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <net/if_arp.h>
|
||||||
#include "nm-compat-headers/linux/if_addr.h"
|
#include "nm-compat-headers/linux/if_addr.h"
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/fib_rules.h>
|
#include <linux/fib_rules.h>
|
||||||
|
#if HAVE_CLAT
|
||||||
|
#include <bpf/libbpf.h>
|
||||||
|
#include <bpf/bpf.h>
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
||||||
#include "libnm-glib-aux/nm-prioq.h"
|
#include "libnm-glib-aux/nm-prioq.h"
|
||||||
|
|
@ -22,6 +27,13 @@
|
||||||
#include "n-acd/src/n-acd.h"
|
#include "n-acd/src/n-acd.h"
|
||||||
#include "nm-l3-ipv4ll.h"
|
#include "nm-l3-ipv4ll.h"
|
||||||
#include "nm-ip-config.h"
|
#include "nm-ip-config.h"
|
||||||
|
#include "nm-core-utils.h"
|
||||||
|
#if HAVE_CLAT
|
||||||
|
#include "bpf/clat.h"
|
||||||
|
NM_PRAGMA_WARNING_DISABLE("-Wcast-align")
|
||||||
|
#include "bpf/clat.skel.h"
|
||||||
|
NM_PRAGMA_WARNING_REENABLE
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -289,6 +301,24 @@ typedef struct _NML3CfgPrivate {
|
||||||
NMIPConfig *ipconfig_x[2];
|
NMIPConfig *ipconfig_x[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
/* The reserved IPv4 address for CLAT in the 192.0.0.0/28 range */
|
||||||
|
NMNetnsIPReservation *clat_address_4;
|
||||||
|
/* The IPv6 address for sending and receiving translated packets */
|
||||||
|
NMPlatformIP6Address clat_address_6;
|
||||||
|
|
||||||
|
/* The same addresses as above, but already committed previously */
|
||||||
|
NMNetnsIPReservation *clat_address_4_committed;
|
||||||
|
NMPlatformIP6Address clat_address_6_committed;
|
||||||
|
|
||||||
|
/* If NULL, the BPF program hasn't been loaded or attached */
|
||||||
|
struct clat_bpf *clat_bpf;
|
||||||
|
struct bpf_link *clat_ingress_link;
|
||||||
|
struct bpf_link *clat_egress_link;
|
||||||
|
|
||||||
|
int clat_socket;
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
/* Whether we earlier configured MPTCP endpoints for the interface. */
|
/* Whether we earlier configured MPTCP endpoints for the interface. */
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -353,6 +383,9 @@ typedef struct _NML3CfgPrivate {
|
||||||
|
|
||||||
bool rp_filter_handled : 1;
|
bool rp_filter_handled : 1;
|
||||||
bool rp_filter_set : 1;
|
bool rp_filter_set : 1;
|
||||||
|
|
||||||
|
bool clat_address_6_valid : 1;
|
||||||
|
bool clat_address_6_committed_valid : 1;
|
||||||
} NML3CfgPrivate;
|
} NML3CfgPrivate;
|
||||||
|
|
||||||
struct _NML3CfgClass {
|
struct _NML3CfgClass {
|
||||||
|
|
@ -624,7 +657,7 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data,
|
||||||
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
|
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
|
||||||
nm_strbuf_append(&s,
|
nm_strbuf_append(&s,
|
||||||
&l,
|
&l,
|
||||||
", obj-type-flags=0x%x",
|
", obj-type-flags=0x%" G_GINT64_MODIFIER "x",
|
||||||
notify_data->platform_change_on_idle.obj_type_flags);
|
notify_data->platform_change_on_idle.obj_type_flags);
|
||||||
break;
|
break;
|
||||||
case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT:
|
case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT:
|
||||||
|
|
@ -1571,7 +1604,7 @@ _load_link(NML3Cfg *self, gboolean initial)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
_nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags)
|
_nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint64 obj_type_flags)
|
||||||
{
|
{
|
||||||
NML3ConfigNotifyData notify_data;
|
NML3ConfigNotifyData notify_data;
|
||||||
|
|
||||||
|
|
@ -4107,6 +4140,233 @@ update_routes:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_l3cfg_update_clat_config(NML3Cfg *self,
|
||||||
|
NML3ConfigData *l3cd,
|
||||||
|
const L3ConfigData **l3_config_datas_arr,
|
||||||
|
guint l3_config_datas_len)
|
||||||
|
{
|
||||||
|
#if !HAVE_CLAT
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
struct in6_addr pref64;
|
||||||
|
guint32 pref64_plen;
|
||||||
|
gboolean clat_enabled = FALSE;
|
||||||
|
const NMPlatformIP4Route *ip4_route;
|
||||||
|
NMDedupMultiIter iter;
|
||||||
|
|
||||||
|
switch (nm_l3_config_data_get_clat_config(l3cd)) {
|
||||||
|
case NM_SETTING_IP4_CONFIG_CLAT_FORCE:
|
||||||
|
clat_enabled = TRUE;
|
||||||
|
break;
|
||||||
|
case NM_SETTING_IP4_CONFIG_CLAT_NO:
|
||||||
|
clat_enabled = FALSE;
|
||||||
|
break;
|
||||||
|
case NM_SETTING_IP4_CONFIG_CLAT_AUTO:
|
||||||
|
clat_enabled = TRUE;
|
||||||
|
/* disable if there is a native IPv4 gateway */
|
||||||
|
nm_l3_config_data_iter_ip4_route_for_each (&iter, l3cd, &ip4_route) {
|
||||||
|
if (ip4_route->network == INADDR_ANY && ip4_route->plen == 0
|
||||||
|
&& ip4_route->gateway != INADDR_ANY)
|
||||||
|
clat_enabled = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NM_SETTING_IP4_CONFIG_CLAT_DEFAULT:
|
||||||
|
nm_assert_not_reached();
|
||||||
|
clat_enabled = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clat_enabled && nm_l3_config_data_get_pref64_valid(l3cd)) {
|
||||||
|
NMPlatformIPXRoute rx;
|
||||||
|
NMIPAddrTyped best_v6_gateway;
|
||||||
|
const NMPlatformIP6Route *best_v6_route;
|
||||||
|
const NMPlatformIP6Address *ip6_entry;
|
||||||
|
struct in6_addr ip6;
|
||||||
|
const char *network_id;
|
||||||
|
char buf[512];
|
||||||
|
guint32 route4_metric = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
/* If we have a valid NAT64 prefix, configure in kernel:
|
||||||
|
*
|
||||||
|
* - a CLAT IPv4 address (192.0.0.x)
|
||||||
|
* - a IPv4 default route via the best IPv6 gateway
|
||||||
|
*
|
||||||
|
* We also set clat_address_6 as an additional /64 IPv6 address
|
||||||
|
* determined according to https://www.rfc-editor.org/rfc/rfc6877#section-6.3 .
|
||||||
|
* This address is used for sending and receiving translated packets,
|
||||||
|
* but is not configured in kernel to avoid that it gets used by applications.
|
||||||
|
* Later in _l3_commit_pref64() we use IPV6_JOIN_ANYCAST to let the kernel
|
||||||
|
* handle ND for the address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nm_l3_config_data_get_pref64(l3cd, &pref64, &pref64_plen);
|
||||||
|
network_id = nm_l3_config_data_get_network_id(l3cd);
|
||||||
|
|
||||||
|
if (!self->priv.p->clat_address_6_valid && network_id) {
|
||||||
|
nm_l3_config_data_iter_ip6_address_for_each (&iter, l3cd, &ip6_entry) {
|
||||||
|
if (ip6_entry->addr_source == NM_IP_CONFIG_SOURCE_NDISC && ip6_entry->plen == 64) {
|
||||||
|
ip6 = ip6_entry->address;
|
||||||
|
|
||||||
|
nm_utils_ipv6_addr_set_stable_privacy(NM_UTILS_STABLE_TYPE_CLAT,
|
||||||
|
&ip6,
|
||||||
|
nm_l3cfg_get_ifname(self, TRUE),
|
||||||
|
network_id,
|
||||||
|
0);
|
||||||
|
self->priv.p->clat_address_6 = (NMPlatformIP6Address) {
|
||||||
|
.ifindex = self->priv.ifindex,
|
||||||
|
.address = ip6,
|
||||||
|
.peer_address = ip6,
|
||||||
|
.addr_source = NM_IP_CONFIG_SOURCE_CLAT,
|
||||||
|
.plen = ip6_entry->plen,
|
||||||
|
};
|
||||||
|
|
||||||
|
_LOGT("clat: using IPv6 address %s", nm_inet6_ntop(&ip6, buf));
|
||||||
|
|
||||||
|
self->priv.p->clat_address_6_valid = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't get a v4 address if we have no v6 address (otherwise, we could
|
||||||
|
* potentially create broken v4 connectivity) */
|
||||||
|
if (!self->priv.p->clat_address_6_valid) {
|
||||||
|
_LOGW("CLAT is currently only supported when SLAAC is in use.");
|
||||||
|
/* Deallocate the v4 address unless it's the committed one */
|
||||||
|
if (self->priv.p->clat_address_4 != self->priv.p->clat_address_4_committed) {
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_address_4, nm_netns_ip_reservation_release);
|
||||||
|
} else {
|
||||||
|
self->priv.p->clat_address_4 = NULL;
|
||||||
|
}
|
||||||
|
} else if (!self->priv.p->clat_address_4) {
|
||||||
|
/* We need a v4 /32 */
|
||||||
|
self->priv.p->clat_address_4 =
|
||||||
|
nm_netns_ip_reservation_get(self->priv.netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const NMPlatformIP4Route *r4;
|
||||||
|
guint32 metric = 0;
|
||||||
|
guint32 penalty = 0;
|
||||||
|
|
||||||
|
/* Find the IPv4 metric for the CLAT default route.
|
||||||
|
* If there is another non-CLAT default route on the device, use the
|
||||||
|
* same metric + 1, so that native connectivity is always preferred.
|
||||||
|
* Otherwise, use the metric from the connection profile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
r4 = NMP_OBJECT_CAST_IP4_ROUTE(nm_l3_config_data_get_best_default_route(l3cd, AF_INET));
|
||||||
|
|
||||||
|
if (r4) {
|
||||||
|
route4_metric = nm_add_clamped_u32(r4->metric, 1u);
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < l3_config_datas_len; i++) {
|
||||||
|
const L3ConfigData *l3cd_data = l3_config_datas_arr[i];
|
||||||
|
|
||||||
|
if (l3cd_data->default_route_metric_4 != NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4) {
|
||||||
|
metric = l3cd_data->default_route_metric_4;
|
||||||
|
}
|
||||||
|
if (l3cd_data->default_route_penalty_4 != 0) {
|
||||||
|
penalty = l3cd_data->default_route_penalty_4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route4_metric = nm_add_clamped_u32(metric, penalty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv.p->clat_address_4) {
|
||||||
|
best_v6_route = NMP_OBJECT_CAST_IP6_ROUTE(
|
||||||
|
nm_l3_config_data_get_direct_route_for_host(l3cd, AF_INET6, &pref64));
|
||||||
|
if (!best_v6_route) {
|
||||||
|
best_v6_route = NMP_OBJECT_CAST_IP6_ROUTE(
|
||||||
|
nm_l3_config_data_get_best_default_route(l3cd, AF_INET6));
|
||||||
|
}
|
||||||
|
if (best_v6_route) {
|
||||||
|
NMPlatformIP4Address addr = {
|
||||||
|
.ifindex = self->priv.ifindex,
|
||||||
|
.address = self->priv.p->clat_address_4->addr,
|
||||||
|
.peer_address = self->priv.p->clat_address_4->addr,
|
||||||
|
.addr_source = NM_IP_CONFIG_SOURCE_CLAT,
|
||||||
|
.plen = 32,
|
||||||
|
};
|
||||||
|
const NMPlatformLink *pllink;
|
||||||
|
guint mtu = 0;
|
||||||
|
guint val = 0;
|
||||||
|
|
||||||
|
best_v6_gateway.addr_family = AF_INET6;
|
||||||
|
best_v6_gateway.addr.addr6 = best_v6_route->gateway;
|
||||||
|
|
||||||
|
/* Determine the IPv6 MTU of the interface. Unfortunately,
|
||||||
|
* the logic to set the MTU is in NMDevice and here we need
|
||||||
|
* some duplication to find the actual value.
|
||||||
|
* TODO: move the MTU handling into l3cfg. */
|
||||||
|
|
||||||
|
/* Get the link MTU */
|
||||||
|
pllink = nm_l3cfg_get_pllink(self, TRUE);
|
||||||
|
if (pllink)
|
||||||
|
mtu = pllink->mtu;
|
||||||
|
if (mtu == 0)
|
||||||
|
mtu = 1500;
|
||||||
|
|
||||||
|
/* Update it with the IPv6 MTU value from the connection
|
||||||
|
* or from RA */
|
||||||
|
val = nm_l3_config_data_get_ip6_mtu_static(l3cd);
|
||||||
|
if (val == 0) {
|
||||||
|
val = nm_l3_config_data_get_ip6_mtu_ra(l3cd);
|
||||||
|
}
|
||||||
|
if (val != 0 && val < mtu) {
|
||||||
|
mtu = val;
|
||||||
|
}
|
||||||
|
if (mtu < 1280)
|
||||||
|
mtu = 1280;
|
||||||
|
|
||||||
|
/* Leave 20 additional bytes for the ipv4 -> ipv6 header translation,
|
||||||
|
* plus 8 for a potential fragmentation extension header */
|
||||||
|
mtu -= 28;
|
||||||
|
|
||||||
|
rx.r4 = (NMPlatformIP4Route) {
|
||||||
|
.ifindex = self->priv.ifindex,
|
||||||
|
.rt_source = NM_IP_CONFIG_SOURCE_CLAT,
|
||||||
|
.network = 0, /* default route */
|
||||||
|
.plen = 0,
|
||||||
|
.table_coerced = nm_platform_route_table_coerce(RT_TABLE_MAIN),
|
||||||
|
.scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE),
|
||||||
|
.type_coerced = nm_platform_route_type_coerce(RTN_UNICAST),
|
||||||
|
.pref_src = self->priv.p->clat_address_4->addr,
|
||||||
|
.via = best_v6_gateway,
|
||||||
|
.metric = route4_metric,
|
||||||
|
.mtu = mtu,
|
||||||
|
};
|
||||||
|
nm_platform_ip_route_normalize(AF_INET, &rx.rx);
|
||||||
|
if (!nm_l3_config_data_lookup_route(l3cd, AF_INET, &rx.rx)) {
|
||||||
|
nm_l3_config_data_add_route_4(l3cd, &rx.r4);
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGT("clat: route %s", nm_platform_ip4_route_to_string(&rx.r4, buf, sizeof(buf)));
|
||||||
|
|
||||||
|
nm_l3_config_data_add_address_4(l3cd, &addr);
|
||||||
|
} else {
|
||||||
|
_LOGW("Couldn't find a good ipv6 route! Unable to set up CLAT!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv.p->clat_address_4 && self->priv.p->clat_address_6_valid) {
|
||||||
|
nm_l3_config_data_set_clat_state(l3cd,
|
||||||
|
TRUE,
|
||||||
|
&self->priv.p->clat_address_6.address,
|
||||||
|
&pref64,
|
||||||
|
pref64_plen,
|
||||||
|
self->priv.p->clat_address_4->addr);
|
||||||
|
} else {
|
||||||
|
nm_l3_config_data_set_clat_state(l3cd, FALSE, NULL, NULL, 0, INADDR_ANY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_l3cfg_update_combined_config(NML3Cfg *self,
|
_l3cfg_update_combined_config(NML3Cfg *self,
|
||||||
gboolean to_commit,
|
gboolean to_commit,
|
||||||
|
|
@ -4220,6 +4480,8 @@ _l3cfg_update_combined_config(NML3Cfg *self,
|
||||||
&hook_data);
|
&hook_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_l3cfg_update_clat_config(self, l3cd, l3_config_datas_arr, l3_config_datas_len);
|
||||||
|
|
||||||
if (self->priv.ifindex == NM_LOOPBACK_IFINDEX) {
|
if (self->priv.ifindex == NM_LOOPBACK_IFINDEX) {
|
||||||
NMPlatformIPXAddress ax;
|
NMPlatformIPXAddress ax;
|
||||||
NMPlatformIPXRoute rx;
|
NMPlatformIPXRoute rx;
|
||||||
|
|
@ -4280,6 +4542,18 @@ _l3cfg_update_combined_config(NML3Cfg *self,
|
||||||
if (nm_l3_config_data_equal(l3cd, self->priv.p->combined_l3cd_merged))
|
if (nm_l3_config_data_equal(l3cd, self->priv.p->combined_l3cd_merged))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
if (!l3cd) {
|
||||||
|
self->priv.p->clat_address_6_valid = FALSE;
|
||||||
|
/* Deallocate the v4 address unless it's the commited one */
|
||||||
|
if (self->priv.p->clat_address_4 != self->priv.p->clat_address_4_committed) {
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_address_4, nm_netns_ip_reservation_release);
|
||||||
|
} else {
|
||||||
|
self->priv.p->clat_address_4 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
l3cd_old = g_steal_pointer(&self->priv.p->combined_l3cd_merged);
|
l3cd_old = g_steal_pointer(&self->priv.p->combined_l3cd_merged);
|
||||||
self->priv.p->combined_l3cd_merged = nm_l3_config_data_seal(g_steal_pointer(&l3cd));
|
self->priv.p->combined_l3cd_merged = nm_l3_config_data_seal(g_steal_pointer(&l3cd));
|
||||||
merged_changed = TRUE;
|
merged_changed = TRUE;
|
||||||
|
|
@ -5379,6 +5653,251 @@ _l3_commit_one(NML3Cfg *self,
|
||||||
_failedobj_handle_routes(self, addr_family, routes_failed);
|
_failedobj_handle_routes(self, addr_family, routes_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
static void
|
||||||
|
_l3_clat_destroy(NML3Cfg *self)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (self->priv.p->clat_bpf) {
|
||||||
|
const struct clat_stats *s = &self->priv.p->clat_bpf->bss->stats;
|
||||||
|
|
||||||
|
_LOGT("clat: stats:"
|
||||||
|
" egress (v4 to v6): tcp %" G_GUINT64_FORMAT ", udp %" G_GUINT64_FORMAT
|
||||||
|
", icmp %" G_GUINT64_FORMAT ", other %" G_GUINT64_FORMAT
|
||||||
|
", dropped %" G_GUINT64_FORMAT "; ingress (v6 to v4): tcp %" G_GUINT64_FORMAT
|
||||||
|
", udp %" G_GUINT64_FORMAT ", icmp %" G_GUINT64_FORMAT ", other %" G_GUINT64_FORMAT
|
||||||
|
", fragment %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT,
|
||||||
|
(guint64) s->egress_tcp,
|
||||||
|
(guint64) s->egress_udp,
|
||||||
|
(guint64) s->egress_icmp,
|
||||||
|
(guint64) s->egress_other,
|
||||||
|
(guint64) s->egress_dropped,
|
||||||
|
(guint64) s->ingress_tcp,
|
||||||
|
(guint64) s->ingress_udp,
|
||||||
|
(guint64) s->ingress_icmp,
|
||||||
|
(guint64) s->ingress_other,
|
||||||
|
(guint64) s->ingress_fragment,
|
||||||
|
(guint64) s->ingress_dropped);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv.p->clat_ingress_link) {
|
||||||
|
err = bpf_link__destroy(self->priv.p->clat_ingress_link);
|
||||||
|
if (err != 0) {
|
||||||
|
libbpf_strerror(err, buf, sizeof(buf));
|
||||||
|
_LOGD("clat: failed to destroy the ingress link");
|
||||||
|
}
|
||||||
|
self->priv.p->clat_ingress_link = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv.p->clat_egress_link) {
|
||||||
|
err = bpf_link__destroy(self->priv.p->clat_egress_link);
|
||||||
|
if (err != 0) {
|
||||||
|
libbpf_strerror(err, buf, sizeof(buf));
|
||||||
|
_LOGD("clat: failed to destroy the egress link");
|
||||||
|
}
|
||||||
|
self->priv.p->clat_egress_link = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_bpf, clat_bpf__destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_l3_commit_pref64(NML3Cfg *self, NML3CfgCommitType commit_type)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
const NML3ConfigData *l3cd = self->priv.p->combined_l3cd_commited;
|
||||||
|
struct in6_addr _l3cd_pref64_inner;
|
||||||
|
const struct in6_addr *l3cd_pref64 = NULL;
|
||||||
|
guint32 l3cd_pref64_plen;
|
||||||
|
char buf[100];
|
||||||
|
struct clat_config clat_config;
|
||||||
|
gboolean v6_changed;
|
||||||
|
const NMPlatformLink *pllink;
|
||||||
|
gboolean has_ethernet_header = FALSE;
|
||||||
|
|
||||||
|
if (l3cd && nm_l3_config_data_get_pref64(l3cd, &_l3cd_pref64_inner, &l3cd_pref64_plen)) {
|
||||||
|
l3cd_pref64 = &_l3cd_pref64_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l3cd_pref64 && self->priv.p->clat_address_4 && self->priv.p->clat_address_6_valid) {
|
||||||
|
pllink = nm_l3cfg_get_pllink(self, TRUE);
|
||||||
|
if (!pllink) {
|
||||||
|
has_ethernet_header = TRUE;
|
||||||
|
} else {
|
||||||
|
switch (pllink->arptype) {
|
||||||
|
case ARPHRD_ETHER:
|
||||||
|
has_ethernet_header = TRUE;
|
||||||
|
break;
|
||||||
|
case ARPHRD_NONE:
|
||||||
|
case ARPHRD_PPP:
|
||||||
|
case ARPHRD_RAWIP:
|
||||||
|
has_ethernet_header = FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_LOGD("clat: unknown ARP type %u, assuming the interface uses no L2 header",
|
||||||
|
pllink->arptype);
|
||||||
|
has_ethernet_header = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self->priv.p->clat_bpf) {
|
||||||
|
_LOGT("clat: attaching the BPF program");
|
||||||
|
|
||||||
|
self->priv.p->clat_bpf = clat_bpf__open();
|
||||||
|
if (!self->priv.p->clat_bpf) {
|
||||||
|
libbpf_strerror(errno, buf, sizeof(buf));
|
||||||
|
_LOGW("clat: failed to open the BPF program: %s", buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only load the programs for the right L2 type */
|
||||||
|
bpf_program__set_autoload(self->priv.p->clat_bpf->progs.nm_clat_ingress_eth,
|
||||||
|
has_ethernet_header);
|
||||||
|
bpf_program__set_autoload(self->priv.p->clat_bpf->progs.nm_clat_egress_eth,
|
||||||
|
has_ethernet_header);
|
||||||
|
bpf_program__set_autoload(self->priv.p->clat_bpf->progs.nm_clat_ingress_rawip,
|
||||||
|
!has_ethernet_header);
|
||||||
|
bpf_program__set_autoload(self->priv.p->clat_bpf->progs.nm_clat_egress_rawip,
|
||||||
|
!has_ethernet_header);
|
||||||
|
|
||||||
|
if (clat_bpf__load(self->priv.p->clat_bpf)) {
|
||||||
|
libbpf_strerror(errno, buf, sizeof(buf));
|
||||||
|
_LOGW("clat: failed to load the BPF program: %s", buf);
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_bpf, clat_bpf__destroy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv.p->clat_ingress_link = bpf_program__attach_tcx(
|
||||||
|
has_ethernet_header ? self->priv.p->clat_bpf->progs.nm_clat_ingress_eth
|
||||||
|
: self->priv.p->clat_bpf->progs.nm_clat_ingress_rawip,
|
||||||
|
self->priv.ifindex,
|
||||||
|
NULL);
|
||||||
|
if (!self->priv.p->clat_ingress_link) {
|
||||||
|
libbpf_strerror(errno, buf, sizeof(buf));
|
||||||
|
_LOGW("clat: failed to attach the ingress program: %s", buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv.p->clat_egress_link = bpf_program__attach_tcx(
|
||||||
|
has_ethernet_header ? self->priv.p->clat_bpf->progs.nm_clat_egress_eth
|
||||||
|
: self->priv.p->clat_bpf->progs.nm_clat_egress_rawip,
|
||||||
|
self->priv.ifindex,
|
||||||
|
NULL);
|
||||||
|
if (!self->priv.p->clat_egress_link) {
|
||||||
|
libbpf_strerror(errno, buf, sizeof(buf));
|
||||||
|
_LOGW("clat: failed to attach the egress program: %s", buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGT("clat: program attached successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pass configuration to the BPF program */
|
||||||
|
memset(&clat_config, 0, sizeof(clat_config));
|
||||||
|
clat_config.local_v4.s_addr = self->priv.p->clat_address_4->addr;
|
||||||
|
clat_config.local_v6 = self->priv.p->clat_address_6.address;
|
||||||
|
clat_config.pref64 = *l3cd_pref64;
|
||||||
|
clat_config.pref64_len = l3cd_pref64_plen;
|
||||||
|
self->priv.p->clat_bpf->bss->config = clat_config;
|
||||||
|
|
||||||
|
if (self->priv.p->clat_socket < 0) {
|
||||||
|
self->priv.p->clat_socket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||||
|
if (self->priv.p->clat_socket < 0) {
|
||||||
|
_LOGW("clat: couldn't create the socket: %s", nm_strerror_native(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self->priv.p->clat_socket >= 0) {
|
||||||
|
err = setsockopt(self->priv.p->clat_socket,
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_BINDTOIFINDEX,
|
||||||
|
&self->priv.ifindex,
|
||||||
|
sizeof(self->priv.ifindex));
|
||||||
|
if (err < 0) {
|
||||||
|
_LOGW("clat: couldn't bind the socket: %s", nm_strerror_native(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v6_changed =
|
||||||
|
(self->priv.p->clat_address_6_valid != self->priv.p->clat_address_6_committed_valid)
|
||||||
|
|| (self->priv.p->clat_address_6_valid && self->priv.p->clat_address_6_committed_valid
|
||||||
|
&& memcmp(&self->priv.p->clat_address_6.address,
|
||||||
|
&self->priv.p->clat_address_6_committed.address,
|
||||||
|
sizeof(self->priv.p->clat_address_6_committed.address)));
|
||||||
|
|
||||||
|
if (self->priv.p->clat_socket > 0 && v6_changed) {
|
||||||
|
struct ipv6_mreq mreq = {.ipv6mr_interface = self->priv.ifindex};
|
||||||
|
|
||||||
|
if (self->priv.p->clat_address_6_committed_valid) {
|
||||||
|
mreq.ipv6mr_multiaddr = self->priv.p->clat_address_6_committed.address;
|
||||||
|
|
||||||
|
err = setsockopt(self->priv.p->clat_socket,
|
||||||
|
SOL_IPV6,
|
||||||
|
IPV6_LEAVE_ANYCAST,
|
||||||
|
&mreq,
|
||||||
|
sizeof(mreq));
|
||||||
|
if (err < 0) {
|
||||||
|
_LOGW("clat: couldn't leave the anycast group: %s", nm_strerror_native(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv.p->clat_address_6_valid) {
|
||||||
|
/* As per draft-ietf-v6ops-claton-14, hosts must perform duplicate
|
||||||
|
* addresses detection (DAD) on the generated CLAT IPv6 address. This is
|
||||||
|
* necessary not only to avoid address collisions but also because some
|
||||||
|
* networks drop traffic from addresses that have not done DAD.
|
||||||
|
* Since doing true DAD adds complexity, adopt the same approach as
|
||||||
|
* Android: start DAD by sending a neighbor solicitation and don't wait
|
||||||
|
* for any reply. This avoids the problem with dropped traffic; it
|
||||||
|
* doesn't help with collisions, but collisions are anyway very unlikely
|
||||||
|
* because the interface identifier is a random 64-bit value.
|
||||||
|
*/
|
||||||
|
nm_utils_ipv6_dad_send(&self->priv.p->clat_address_6.address,
|
||||||
|
self->priv.ifindex,
|
||||||
|
pllink ? pllink->arptype : ARPHRD_ETHER);
|
||||||
|
|
||||||
|
mreq.ipv6mr_multiaddr = self->priv.p->clat_address_6.address;
|
||||||
|
|
||||||
|
err = setsockopt(self->priv.p->clat_socket,
|
||||||
|
SOL_IPV6,
|
||||||
|
IPV6_JOIN_ANYCAST,
|
||||||
|
&mreq,
|
||||||
|
sizeof(mreq));
|
||||||
|
if (err < 0) {
|
||||||
|
_LOGW("clat: couldn't join the anycast group: %s", nm_strerror_native(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (self->priv.p->clat_bpf) {
|
||||||
|
_l3_clat_destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Committed will get cleaned up below */
|
||||||
|
self->priv.p->clat_address_6_valid = FALSE;
|
||||||
|
|
||||||
|
nm_clear_fd(&self->priv.p->clat_socket);
|
||||||
|
|
||||||
|
/* Deallocate the v4 address. Committed address will get cleaned up below,
|
||||||
|
but we need to make sure there's no double-free */
|
||||||
|
if (self->priv.p->clat_address_4 != self->priv.p->clat_address_4_committed) {
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_address_4, nm_netns_ip_reservation_release);
|
||||||
|
} else {
|
||||||
|
self->priv.p->clat_address_4 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record the new state */
|
||||||
|
if (self->priv.p->clat_address_4_committed != self->priv.p->clat_address_4) {
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_address_4_committed, nm_netns_ip_reservation_release);
|
||||||
|
self->priv.p->clat_address_4_committed = self->priv.p->clat_address_4;
|
||||||
|
}
|
||||||
|
self->priv.p->clat_address_6_committed = self->priv.p->clat_address_6;
|
||||||
|
self->priv.p->clat_address_6_committed_valid = self->priv.p->clat_address_6_valid;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle)
|
_l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle)
|
||||||
{
|
{
|
||||||
|
|
@ -5461,6 +5980,10 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle)
|
||||||
|
|
||||||
_l3_acd_data_process_changes(self);
|
_l3_acd_data_process_changes(self);
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
_l3_commit_pref64(self, commit_type);
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
nm_assert(self->priv.p->commit_reentrant_count == 1);
|
nm_assert(self->priv.p->commit_reentrant_count == 1);
|
||||||
self->priv.p->commit_reentrant_count--;
|
self->priv.p->commit_reentrant_count--;
|
||||||
|
|
||||||
|
|
@ -5842,6 +6365,10 @@ nm_l3cfg_init(NML3Cfg *self)
|
||||||
{
|
{
|
||||||
self->priv.p = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_L3CFG, NML3CfgPrivate);
|
self->priv.p = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_L3CFG, NML3CfgPrivate);
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
self->priv.p->clat_socket = -1;
|
||||||
|
#endif /* HAVE_CLAT */
|
||||||
|
|
||||||
c_list_init(&self->priv.p->acd_lst_head);
|
c_list_init(&self->priv.p->acd_lst_head);
|
||||||
c_list_init(&self->priv.p->acd_event_notify_lst_head);
|
c_list_init(&self->priv.p->acd_event_notify_lst_head);
|
||||||
c_list_init(&self->priv.p->commit_type_lst_head);
|
c_list_init(&self->priv.p->commit_type_lst_head);
|
||||||
|
|
@ -5950,6 +6477,14 @@ finalize(GObject *object)
|
||||||
if (changed)
|
if (changed)
|
||||||
nmp_global_tracker_sync_mptcp_addrs(self->priv.global_tracker, FALSE);
|
nmp_global_tracker_sync_mptcp_addrs(self->priv.global_tracker, FALSE);
|
||||||
|
|
||||||
|
#if HAVE_CLAT
|
||||||
|
self->priv.p->clat_address_4_committed = NULL;
|
||||||
|
nm_clear_pointer(&self->priv.p->clat_address_4, nm_netns_ip_reservation_release);
|
||||||
|
nm_clear_fd(&self->priv.p->clat_socket);
|
||||||
|
if (self->priv.p->clat_bpf) {
|
||||||
|
_l3_clat_destroy(self);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
g_clear_object(&self->priv.netns);
|
g_clear_object(&self->priv.netns);
|
||||||
g_clear_object(&self->priv.platform);
|
g_clear_object(&self->priv.platform);
|
||||||
nm_clear_pointer(&self->priv.global_tracker, nmp_global_tracker_unref);
|
nm_clear_pointer(&self->priv.global_tracker, nmp_global_tracker_unref);
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ typedef struct {
|
||||||
} platform_change;
|
} platform_change;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
guint32 obj_type_flags;
|
guint64 obj_type_flags;
|
||||||
} platform_change_on_idle;
|
} platform_change_on_idle;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -207,7 +207,7 @@ struct _NML3Cfg {
|
||||||
* NML3Cfg instance. We track some per-l3cfg-data that is only
|
* NML3Cfg instance. We track some per-l3cfg-data that is only
|
||||||
* relevant to NMNetns here. */
|
* relevant to NMNetns here. */
|
||||||
struct {
|
struct {
|
||||||
guint32 signal_pending_obj_type_flags;
|
guint64 signal_pending_obj_type_flags;
|
||||||
CList signal_pending_lst;
|
CList signal_pending_lst;
|
||||||
CList ecmp_track_ifindex_lst_head;
|
CList ecmp_track_ifindex_lst_head;
|
||||||
} internal_netns;
|
} internal_netns;
|
||||||
|
|
@ -223,7 +223,7 @@ NML3Cfg *nm_l3cfg_new(NMNetns *netns, int ifindex);
|
||||||
|
|
||||||
gboolean nm_l3cfg_is_ready(NML3Cfg *self);
|
gboolean nm_l3cfg_is_ready(NML3Cfg *self);
|
||||||
|
|
||||||
void _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags);
|
void _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint64 obj_type_flags);
|
||||||
|
|
||||||
void _nm_l3cfg_notify_platform_change(NML3Cfg *self,
|
void _nm_l3cfg_notify_platform_change(NML3Cfg *self,
|
||||||
NMPlatformSignalChangeType change_type,
|
NMPlatformSignalChangeType change_type,
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ _ecmp_track_sort_lst_cmp(const CList *a, const CList *b, const void *user_data)
|
||||||
NM_CMP_FIELD(route_a, route_b, ifindex);
|
NM_CMP_FIELD(route_a, route_b, ifindex);
|
||||||
NM_CMP_FIELD(route_b, route_a, weight);
|
NM_CMP_FIELD(route_b, route_a, weight);
|
||||||
NM_CMP_DIRECT(htonl(route_a->gateway), htonl(route_b->gateway));
|
NM_CMP_DIRECT(htonl(route_a->gateway), htonl(route_b->gateway));
|
||||||
|
NM_CMP_DIRECT(route_a->r_rtm_flags & RTNH_F_ONLINK, route_b->r_rtm_flags & RTNH_F_ONLINK);
|
||||||
|
|
||||||
return nm_assert_unreachable_val(
|
return nm_assert_unreachable_val(
|
||||||
nm_platform_ip4_route_cmp(route_a, route_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID));
|
nm_platform_ip4_route_cmp(route_a, route_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID));
|
||||||
|
|
@ -275,9 +276,10 @@ _ecmp_track_init_merged_obj(EcmpTrackEcmpid *track_ecmpid, const NMPObject **out
|
||||||
NMPlatformIP4RtNextHop *nh = (gpointer) &obj_new->_ip4_route.extra_nexthops[i - 1];
|
NMPlatformIP4RtNextHop *nh = (gpointer) &obj_new->_ip4_route.extra_nexthops[i - 1];
|
||||||
|
|
||||||
*nh = (NMPlatformIP4RtNextHop) {
|
*nh = (NMPlatformIP4RtNextHop) {
|
||||||
.ifindex = r->ifindex,
|
.ifindex = r->ifindex,
|
||||||
.gateway = r->gateway,
|
.gateway = r->gateway,
|
||||||
.weight = r->weight,
|
.weight = r->weight,
|
||||||
|
.rtnh_flags = r->r_rtm_flags & RTNH_F_ONLINK,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -574,8 +576,8 @@ notify_watcher:
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
guint32 start_addr; /* host byte order */
|
guint32 start_addr; /* host byte order */
|
||||||
guint prefix_len;
|
guint range_plen;
|
||||||
guint num_addrs;
|
guint addr_plen;
|
||||||
gboolean allow_reuse;
|
gboolean allow_reuse;
|
||||||
} IPReservationTypeDesc;
|
} IPReservationTypeDesc;
|
||||||
|
|
||||||
|
|
@ -583,11 +585,19 @@ static const IPReservationTypeDesc ip_reservation_types[_NM_NETNS_IP_RESERVATION
|
||||||
[NM_NETNS_IP_RESERVATION_TYPE_SHARED4] =
|
[NM_NETNS_IP_RESERVATION_TYPE_SHARED4] =
|
||||||
{
|
{
|
||||||
.name = "shared-ip4",
|
.name = "shared-ip4",
|
||||||
.start_addr = 0x0a2a0001, /* 10.42.0.1 */
|
.start_addr = 0x0a2a0001, /* 10.42.{0-255}.1/24 */
|
||||||
.prefix_len = 24,
|
.range_plen = 16,
|
||||||
.num_addrs = 256,
|
.addr_plen = 24,
|
||||||
.allow_reuse = TRUE,
|
.allow_reuse = TRUE,
|
||||||
},
|
},
|
||||||
|
[NM_NETNS_IP_RESERVATION_TYPE_CLAT] =
|
||||||
|
{
|
||||||
|
.name = "clat",
|
||||||
|
.start_addr = 0xc0000005, /* 192.0.0.{5-7,0-4}/32 */
|
||||||
|
.range_plen = 29,
|
||||||
|
.addr_plen = 32,
|
||||||
|
.allow_reuse = FALSE,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
NMNetnsIPReservation *
|
NMNetnsIPReservation *
|
||||||
|
|
@ -613,13 +623,23 @@ nm_netns_ip_reservation_get(NMNetns *self, NMNetnsIPReservationType type)
|
||||||
g_object_ref(self);
|
g_object_ref(self);
|
||||||
} else {
|
} else {
|
||||||
guint32 count;
|
guint32 count;
|
||||||
|
guint32 base_network;
|
||||||
|
guint32 host_mask;
|
||||||
|
guint32 increment;
|
||||||
|
|
||||||
nm_assert(g_hash_table_size(*table) > 0);
|
nm_assert(g_hash_table_size(*table) > 0);
|
||||||
nm_assert(desc->prefix_len > 0 && desc->prefix_len <= 32);
|
nm_assert(desc->range_plen < 32);
|
||||||
|
nm_assert(desc->addr_plen > 0 && desc->addr_plen <= 32);
|
||||||
|
nm_assert(desc->addr_plen > desc->range_plen);
|
||||||
|
|
||||||
|
base_network = desc->start_addr & ~(0xFFFFFFFFu >> desc->range_plen);
|
||||||
|
host_mask = 0xFFFFFFFFu >> desc->range_plen;
|
||||||
|
increment = 1 << (32 - desc->addr_plen);
|
||||||
|
|
||||||
count = 0u;
|
count = 0u;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
addr = htonl(desc->start_addr + (count << (32 - desc->prefix_len)));
|
addr = htonl(base_network
|
||||||
|
+ ((base_network + (desc->start_addr + count * increment)) & host_mask));
|
||||||
|
|
||||||
res = g_hash_table_lookup(*table, &addr);
|
res = g_hash_table_lookup(*table, &addr);
|
||||||
if (!res)
|
if (!res)
|
||||||
|
|
@ -627,7 +647,7 @@ nm_netns_ip_reservation_get(NMNetns *self, NMNetnsIPReservationType type)
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count >= desc->num_addrs) {
|
if (count >= 1 << (desc->addr_plen - desc->range_plen)) {
|
||||||
if (!desc->allow_reuse) {
|
if (!desc->allow_reuse) {
|
||||||
_LOGE("%s: ran out of IP addresses", desc->name);
|
_LOGE("%s: ran out of IP addresses", desc->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -637,12 +657,12 @@ nm_netns_ip_reservation_get(NMNetns *self, NMNetnsIPReservationType type)
|
||||||
_LOGE("%s: ran out of IP addresses. Reuse %s/%u",
|
_LOGE("%s: ran out of IP addresses. Reuse %s/%u",
|
||||||
desc->name,
|
desc->name,
|
||||||
nm_inet4_ntop(res->addr, buf),
|
nm_inet4_ntop(res->addr, buf),
|
||||||
desc->prefix_len);
|
desc->addr_plen);
|
||||||
} else {
|
} else {
|
||||||
_LOGD("%s: reserved IP address %s/%u (duplicate)",
|
_LOGD("%s: reserved IP address %s/%u (duplicate)",
|
||||||
desc->name,
|
desc->name,
|
||||||
nm_inet4_ntop(res->addr, buf),
|
nm_inet4_ntop(res->addr, buf),
|
||||||
desc->prefix_len);
|
desc->addr_plen);
|
||||||
}
|
}
|
||||||
res->_ref_count++;
|
res->_ref_count++;
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -663,7 +683,7 @@ nm_netns_ip_reservation_get(NMNetns *self, NMNetnsIPReservationType type)
|
||||||
_LOGD("%s: reserved IP address %s/%u",
|
_LOGD("%s: reserved IP address %s/%u",
|
||||||
desc->name,
|
desc->name,
|
||||||
nm_inet4_ntop(res->addr, buf),
|
nm_inet4_ntop(res->addr, buf),
|
||||||
desc->prefix_len);
|
desc->addr_plen);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -695,7 +715,7 @@ nm_netns_ip_reservation_release(NMNetnsIPReservation *res)
|
||||||
_LOGD("%s: release IP address reservation %s/%u (%d more references held)",
|
_LOGD("%s: release IP address reservation %s/%u (%d more references held)",
|
||||||
desc->name,
|
desc->name,
|
||||||
nm_inet4_ntop(res->addr, buf),
|
nm_inet4_ntop(res->addr, buf),
|
||||||
desc->prefix_len,
|
desc->addr_plen,
|
||||||
res->_ref_count);
|
res->_ref_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -706,7 +726,7 @@ nm_netns_ip_reservation_release(NMNetnsIPReservation *res)
|
||||||
_LOGD("%s: release IP address reservation %s/%u",
|
_LOGD("%s: release IP address reservation %s/%u",
|
||||||
desc->name,
|
desc->name,
|
||||||
nm_inet4_ntop(res->addr, buf),
|
nm_inet4_ntop(res->addr, buf),
|
||||||
desc->prefix_len);
|
desc->addr_plen);
|
||||||
|
|
||||||
if (g_hash_table_size(*table) == 0) {
|
if (g_hash_table_size(*table) == 0) {
|
||||||
nm_clear_pointer(table, g_hash_table_unref);
|
nm_clear_pointer(table, g_hash_table_unref);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ NML3Cfg *nm_netns_l3cfg_acquire(NMNetns *netns, int ifindex);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NM_NETNS_IP_RESERVATION_TYPE_SHARED4,
|
NM_NETNS_IP_RESERVATION_TYPE_SHARED4,
|
||||||
|
NM_NETNS_IP_RESERVATION_TYPE_CLAT,
|
||||||
|
|
||||||
_NM_NETNS_IP_RESERVATION_TYPE_NUM,
|
_NM_NETNS_IP_RESERVATION_TYPE_NUM,
|
||||||
} NMNetnsIPReservationType;
|
} NMNetnsIPReservationType;
|
||||||
|
|
|
||||||
|
|
@ -1230,7 +1230,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolean do_assert)
|
nmtstp_check_platform_full(NMPlatform *platform, guint64 obj_type_flags, gboolean do_assert)
|
||||||
{
|
{
|
||||||
static const NMPObjectType obj_types[] = {
|
static const NMPObjectType obj_types[] = {
|
||||||
NMP_OBJECT_TYPE_IP4_ADDRESS,
|
NMP_OBJECT_TYPE_IP4_ADDRESS,
|
||||||
|
|
@ -1265,7 +1265,7 @@ nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolea
|
||||||
|
|
||||||
for (i_obj_types = 0; i_obj_types < (int) G_N_ELEMENTS(obj_types); i_obj_types++) {
|
for (i_obj_types = 0; i_obj_types < (int) G_N_ELEMENTS(obj_types); i_obj_types++) {
|
||||||
const NMPObjectType obj_type = obj_types[i_obj_types];
|
const NMPObjectType obj_type = obj_types[i_obj_types];
|
||||||
const guint32 i_obj_type_flags = nmp_object_type_to_flags(obj_type);
|
const guint64 i_obj_type_flags = nmp_object_type_to_flags(obj_type);
|
||||||
gs_unref_ptrarray GPtrArray *arr1 = NULL;
|
gs_unref_ptrarray GPtrArray *arr1 = NULL;
|
||||||
gs_unref_ptrarray GPtrArray *arr2 = NULL;
|
gs_unref_ptrarray GPtrArray *arr2 = NULL;
|
||||||
NMPLookup lookup;
|
NMPLookup lookup;
|
||||||
|
|
@ -1408,7 +1408,7 @@ nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolea
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nmtstp_check_platform(NMPlatform *platform, guint32 obj_type_flags)
|
nmtstp_check_platform(NMPlatform *platform, guint64 obj_type_flags)
|
||||||
{
|
{
|
||||||
if (!nmtstp_check_platform_full(platform, obj_type_flags, FALSE)) {
|
if (!nmtstp_check_platform_full(platform, obj_type_flags, FALSE)) {
|
||||||
/* It's unclear why this failure sometimes happens. It happens
|
/* It's unclear why this failure sometimes happens. It happens
|
||||||
|
|
@ -2393,6 +2393,61 @@ nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *na
|
||||||
return pllink;
|
return pllink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NMPlatformLink *
|
||||||
|
nmtstp_link_geneve_add(NMPlatform *platform,
|
||||||
|
int external_command,
|
||||||
|
const char *name,
|
||||||
|
const NMPlatformLnkGeneve *lnk)
|
||||||
|
{
|
||||||
|
const NMPlatformLink *pllink = NULL;
|
||||||
|
int success;
|
||||||
|
|
||||||
|
g_assert(nm_utils_ifname_valid_kernel(name, NULL));
|
||||||
|
g_assert(lnk->remote || !IN6_IS_ADDR_UNSPECIFIED(&lnk->remote6));
|
||||||
|
|
||||||
|
external_command = nmtstp_run_command_check_external(external_command);
|
||||||
|
|
||||||
|
_init_platform(&platform, external_command);
|
||||||
|
|
||||||
|
if (external_command) {
|
||||||
|
char remote[NM_INET_ADDRSTRLEN];
|
||||||
|
char remote6[NM_INET_ADDRSTRLEN];
|
||||||
|
char str_ttl[30];
|
||||||
|
|
||||||
|
if (lnk->remote)
|
||||||
|
nm_inet4_ntop(lnk->remote, remote);
|
||||||
|
else
|
||||||
|
remote[0] = '\0';
|
||||||
|
|
||||||
|
if (memcmp(&lnk->remote6, &in6addr_any, sizeof(in6addr_any)))
|
||||||
|
nm_inet6_ntop(&lnk->remote6, remote6);
|
||||||
|
else
|
||||||
|
remote6[0] = '\0';
|
||||||
|
|
||||||
|
success = !nmtstp_run_command(
|
||||||
|
"ip link add %s type geneve id %u remote %s %s tos %02x dstport %u%s",
|
||||||
|
name,
|
||||||
|
lnk->id,
|
||||||
|
remote[0] ? remote : remote6,
|
||||||
|
lnk->ttl > 0 ? nm_sprintf_buf(str_ttl, "ttl %u", lnk->ttl & 0xff)
|
||||||
|
: lnk->ttl == 0 ? "ttl auto"
|
||||||
|
: "ttl inherit",
|
||||||
|
lnk->tos,
|
||||||
|
lnk->dst_port,
|
||||||
|
lnk->df == 1 ? " df set "
|
||||||
|
: lnk->df == 2 ? " df inherit "
|
||||||
|
: "");
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_GENEVE, 100);
|
||||||
|
} else
|
||||||
|
success = NMTST_NM_ERR_SUCCESS(nm_platform_link_geneve_add(platform, name, lnk, &pllink));
|
||||||
|
|
||||||
|
_assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_GENEVE);
|
||||||
|
|
||||||
|
return pllink;
|
||||||
|
}
|
||||||
|
|
||||||
const NMPlatformLink *
|
const NMPlatformLink *
|
||||||
nmtstp_link_gre_add(NMPlatform *platform,
|
nmtstp_link_gre_add(NMPlatform *platform,
|
||||||
int external_command,
|
int external_command,
|
||||||
|
|
@ -3024,8 +3079,6 @@ nmtstp_link_vxlan_add(NMPlatform *platform,
|
||||||
return pllink;
|
return pllink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
const NMPlatformLink *
|
const NMPlatformLink *
|
||||||
nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type)
|
nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -140,9 +140,9 @@ int nmtstp_run_command(const char *format, ...) _nm_printf(1, 2);
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolean do_assert);
|
nmtstp_check_platform_full(NMPlatform *platform, guint64 obj_type_flags, gboolean do_assert);
|
||||||
|
|
||||||
void nmtstp_check_platform(NMPlatform *platform, guint32 obj_type_flags);
|
void nmtstp_check_platform(NMPlatform *platform, guint64 obj_type_flags);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -474,6 +474,10 @@ const NMPlatformLink *nmtstp_link_veth_add(NMPlatform *platform,
|
||||||
const char *peer);
|
const char *peer);
|
||||||
const NMPlatformLink *
|
const NMPlatformLink *
|
||||||
nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *name);
|
nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *name);
|
||||||
|
const NMPlatformLink *nmtstp_link_geneve_add(NMPlatform *platform,
|
||||||
|
int external_command,
|
||||||
|
const char *name,
|
||||||
|
const NMPlatformLnkGeneve *lnk);
|
||||||
const NMPlatformLink *nmtstp_link_gre_add(NMPlatform *platform,
|
const NMPlatformLink *nmtstp_link_gre_add(NMPlatform *platform,
|
||||||
int external_command,
|
int external_command,
|
||||||
const char *name,
|
const char *name,
|
||||||
|
|
|
||||||
|
|
@ -1388,10 +1388,11 @@ test_software_detect(gconstpointer user_data)
|
||||||
const gboolean ext = test_data->external_command;
|
const gboolean ext = test_data->external_command;
|
||||||
NMPlatformLnkBridge lnk_bridge = {};
|
NMPlatformLnkBridge lnk_bridge = {};
|
||||||
NMPlatformLnkTun lnk_tun;
|
NMPlatformLnkTun lnk_tun;
|
||||||
NMPlatformLnkGre lnk_gre = {};
|
NMPlatformLnkGeneve lnk_geneve = {};
|
||||||
NMPlatformLnkVti lnk_vti = {};
|
NMPlatformLnkGre lnk_gre = {};
|
||||||
NMPlatformLnkVti6 lnk_vti6 = {};
|
NMPlatformLnkVti lnk_vti = {};
|
||||||
nm_auto_close int tun_fd = -1;
|
NMPlatformLnkVti6 lnk_vti6 = {};
|
||||||
|
nm_auto_close int tun_fd = -1;
|
||||||
gboolean module_loaded;
|
gboolean module_loaded;
|
||||||
|
|
||||||
nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME);
|
nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME);
|
||||||
|
|
@ -1434,6 +1435,31 @@ test_software_detect(gconstpointer user_data)
|
||||||
g_error("Failed adding Bridge interface");
|
g_error("Failed adding Bridge interface");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NM_LINK_TYPE_GENEVE:
|
||||||
|
{
|
||||||
|
switch (test_data->test_mode) {
|
||||||
|
case 0:
|
||||||
|
lnk_geneve.id = 42;
|
||||||
|
lnk_geneve.remote = nmtst_inet4_from_string("192.168.1.100");
|
||||||
|
lnk_geneve.ttl = 64;
|
||||||
|
lnk_geneve.tos = 0;
|
||||||
|
lnk_geneve.dst_port = 6081;
|
||||||
|
lnk_geneve.df = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
lnk_geneve.id = 12345;
|
||||||
|
lnk_geneve.remote6 = nmtst_inet6_from_string("2001:db8::1");
|
||||||
|
lnk_geneve.ttl = 128;
|
||||||
|
lnk_geneve.tos = 16;
|
||||||
|
lnk_geneve.dst_port = 6082;
|
||||||
|
lnk_geneve.df = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert(nmtstp_link_geneve_add(NULL, ext, DEVICE_NAME, &lnk_geneve));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NM_LINK_TYPE_GRE:
|
case NM_LINK_TYPE_GRE:
|
||||||
module_loaded = nmtstp_ensure_module("ip_gre");
|
module_loaded = nmtstp_ensure_module("ip_gre");
|
||||||
|
|
||||||
|
|
@ -2208,6 +2234,34 @@ test_software_detect(gconstpointer user_data)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NM_LINK_TYPE_GENEVE:
|
||||||
|
{
|
||||||
|
const NMPlatformLnkGeneve *plnk = &lnk->lnk_geneve;
|
||||||
|
|
||||||
|
g_assert(plnk == nm_platform_link_get_lnk_geneve(NM_PLATFORM_GET, ifindex, NULL));
|
||||||
|
|
||||||
|
switch (test_data->test_mode) {
|
||||||
|
case 0:
|
||||||
|
g_assert_cmpint(plnk->id, ==, 42);
|
||||||
|
nmtst_assert_ip4_address(plnk->remote, "192.168.1.100");
|
||||||
|
nmtst_assert_ip6_address(&plnk->remote6, "::");
|
||||||
|
g_assert_cmpint(plnk->ttl, ==, 64);
|
||||||
|
g_assert_cmpint(plnk->tos, ==, 0);
|
||||||
|
g_assert_cmpint(plnk->dst_port, ==, 6081);
|
||||||
|
g_assert_cmpint(plnk->df, ==, 0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
g_assert_cmpint(plnk->id, ==, 12345);
|
||||||
|
nmtst_assert_ip4_address(plnk->remote, "0.0.0.0");
|
||||||
|
nmtst_assert_ip6_address(&plnk->remote6, "2001:db8::1");
|
||||||
|
g_assert_cmpint(plnk->ttl, ==, 128);
|
||||||
|
g_assert_cmpint(plnk->tos, ==, 16);
|
||||||
|
g_assert_cmpint(plnk->dst_port, ==, 6082);
|
||||||
|
g_assert_cmpint(plnk->df, ==, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NM_LINK_TYPE_WIREGUARD:
|
case NM_LINK_TYPE_WIREGUARD:
|
||||||
{
|
{
|
||||||
const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard;
|
const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard;
|
||||||
|
|
@ -4143,6 +4197,8 @@ _nmtstp_setup_tests(void)
|
||||||
g_test_add_func("/link/external", test_external);
|
g_test_add_func("/link/external", test_external);
|
||||||
|
|
||||||
test_software_detect_add("/link/software/detect/bridge", NM_LINK_TYPE_BRIDGE, 0);
|
test_software_detect_add("/link/software/detect/bridge", NM_LINK_TYPE_BRIDGE, 0);
|
||||||
|
test_software_detect_add("/link/software/detect/geneve/0", NM_LINK_TYPE_GENEVE, 0);
|
||||||
|
test_software_detect_add("/link/software/detect/geneve/1", NM_LINK_TYPE_GENEVE, 1);
|
||||||
test_software_detect_add("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0);
|
test_software_detect_add("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0);
|
||||||
test_software_detect_add("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0);
|
test_software_detect_add("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0);
|
||||||
test_software_detect_add("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);
|
test_software_detect_add("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);
|
||||||
|
|
|
||||||
|
|
@ -2460,6 +2460,78 @@ done:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static void
|
||||||
|
test_ip4_rtnh_onlink(void)
|
||||||
|
{
|
||||||
|
/* Extra nexthops that differ only in rtnh_flags ONLINK should
|
||||||
|
* compare as different. */
|
||||||
|
NMPlatformIP4RtNextHop nh_a = {
|
||||||
|
.ifindex = 2,
|
||||||
|
.gateway = nmtst_inet4_from_string("10.10.10.10"),
|
||||||
|
.weight = 1,
|
||||||
|
.rtnh_flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
NMPlatformIP4RtNextHop nh_b = nh_a;
|
||||||
|
nh_b.rtnh_flags = RTNH_F_ONLINK;
|
||||||
|
|
||||||
|
g_assert_cmpint(nm_platform_ip4_rt_nexthop_cmp(&nh_a, &nh_b, TRUE), !=, 0);
|
||||||
|
g_assert_cmpint(nm_platform_ip4_rt_nexthop_cmp(&nh_a, &nh_b, FALSE), !=, 0);
|
||||||
|
|
||||||
|
nh_b.rtnh_flags = 0;
|
||||||
|
g_assert_cmpint(nm_platform_ip4_rt_nexthop_cmp(&nh_a, &nh_b, TRUE), ==, 0);
|
||||||
|
g_assert_cmpint(nm_platform_ip4_rt_nexthop_cmp(&nh_a, &nh_b, FALSE), ==, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_ip4_route_onlink_per_nexthop(void)
|
||||||
|
{
|
||||||
|
NMPlatformIP4Route r_a = {};
|
||||||
|
NMPlatformIP4Route r_b;
|
||||||
|
|
||||||
|
/* Two single-hop routes that are identical, except for the onlink flag. */
|
||||||
|
r_a.ifindex = 1;
|
||||||
|
r_a.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||||
|
r_a.network = nmtst_inet4_from_string("10.10.10.10");
|
||||||
|
r_a.plen = 24;
|
||||||
|
r_a.gateway = nmtst_inet4_from_string("10.10.10.1");
|
||||||
|
r_a.metric = 100;
|
||||||
|
r_a.n_nexthops = 1;
|
||||||
|
r_a.type_coerced = nm_platform_route_type_coerce(RTN_UNICAST);
|
||||||
|
r_a.scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
|
||||||
|
|
||||||
|
r_b = r_a;
|
||||||
|
r_b.r_rtm_flags = RTNH_F_ONLINK;
|
||||||
|
|
||||||
|
/* Onlink flag should result in the same ECMP_ID but different IDs. */
|
||||||
|
g_assert_cmpint(nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ECMP_ID),
|
||||||
|
==,
|
||||||
|
0);
|
||||||
|
|
||||||
|
g_assert_cmpint(nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID), !=, 0);
|
||||||
|
g_assert_cmpint(
|
||||||
|
nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY),
|
||||||
|
!=,
|
||||||
|
0);
|
||||||
|
g_assert_cmpint(nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL),
|
||||||
|
!=,
|
||||||
|
0);
|
||||||
|
|
||||||
|
r_b.r_rtm_flags = 0;
|
||||||
|
g_assert_cmpint(nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID), ==, 0);
|
||||||
|
g_assert_cmpint(nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ECMP_ID),
|
||||||
|
==,
|
||||||
|
0);
|
||||||
|
g_assert_cmpint(
|
||||||
|
nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY),
|
||||||
|
==,
|
||||||
|
0);
|
||||||
|
g_assert_cmpint(nm_platform_ip4_route_cmp(&r_a, &r_b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL),
|
||||||
|
==,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
|
NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
|
||||||
|
|
@ -2480,6 +2552,8 @@ _nmtstp_setup_tests(void)
|
||||||
nmtstp_env1_add_test_func_data(testpath, test_func, arg, 2, TRUE)
|
nmtstp_env1_add_test_func_data(testpath, test_func, arg, 2, TRUE)
|
||||||
|
|
||||||
add_test_func("/route/ip4", test_ip4_route);
|
add_test_func("/route/ip4", test_ip4_route);
|
||||||
|
add_test_func("/route/ip4_onlink_per_nexthop", test_ip4_route_onlink_per_nexthop);
|
||||||
|
add_test_func("/route/ip4_rtnh_onlink", test_ip4_rtnh_onlink);
|
||||||
add_test_func("/route/ip6", test_ip6_route);
|
add_test_func("/route/ip6", test_ip6_route);
|
||||||
add_test_func("/route/ip4_metric0", test_ip4_route_metric0);
|
add_test_func("/route/ip4_metric0", test_ip4_route_metric0);
|
||||||
add_test_func_data("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER(1));
|
add_test_func_data("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER(1));
|
||||||
|
|
|
||||||
|
|
@ -1083,6 +1083,39 @@ _con_get_request_start_validated(NMAuthChain *chain,
|
||||||
_con_get_request_start_proceed(req, req->con.current_has_modify);
|
_con_get_request_start_proceed(req, req->con.current_has_modify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_req_has_existing_secrets(Request *req)
|
||||||
|
{
|
||||||
|
GVariantIter iter;
|
||||||
|
const char *setting_name;
|
||||||
|
GVariant *setting_dict;
|
||||||
|
gboolean has;
|
||||||
|
|
||||||
|
if (!req->con.get.existing_secrets)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
nm_assert(g_variant_is_of_type(req->con.get.existing_secrets, NM_VARIANT_TYPE_CONNECTION));
|
||||||
|
|
||||||
|
g_variant_iter_init(&iter, req->con.get.existing_secrets);
|
||||||
|
while (g_variant_iter_next(&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) {
|
||||||
|
GVariantIter setting_iter;
|
||||||
|
GVariant *val;
|
||||||
|
|
||||||
|
g_variant_iter_init(&setting_iter, setting_dict);
|
||||||
|
while (g_variant_iter_next(&setting_iter, "{&sv}", NULL, &val)) {
|
||||||
|
has = !g_variant_is_container(val) || g_variant_n_children(val) > 0;
|
||||||
|
g_variant_unref(val);
|
||||||
|
if (has) {
|
||||||
|
g_variant_unref(setting_dict);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_variant_unref(setting_dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_con_get_request_start(Request *req)
|
_con_get_request_start(Request *req)
|
||||||
{
|
{
|
||||||
|
|
@ -1103,7 +1136,7 @@ _con_get_request_start(Request *req)
|
||||||
* unprivileged users.
|
* unprivileged users.
|
||||||
*/
|
*/
|
||||||
if ((req->con.get.flags != NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE)
|
if ((req->con.get.flags != NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE)
|
||||||
&& (req->con.get.existing_secrets
|
&& (_req_has_existing_secrets(req)
|
||||||
|| _nm_connection_aggregate(req->con.connection,
|
|| _nm_connection_aggregate(req->con.connection,
|
||||||
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS,
|
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS,
|
||||||
NULL))) {
|
NULL))) {
|
||||||
|
|
|
||||||
|
|
@ -781,7 +781,8 @@ validate_secret_flags(NMConnection *connection, GVariant *secrets, ForEachSecret
|
||||||
static gboolean
|
static gboolean
|
||||||
secret_is_system_owned(NMSettingSecretFlags flags, gpointer user_data)
|
secret_is_system_owned(NMSettingSecretFlags flags, gpointer user_data)
|
||||||
{
|
{
|
||||||
return !NM_FLAGS_HAS(flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
|
return !NM_FLAGS_ANY(flags,
|
||||||
|
NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ get_full_file_path(const char *ifcfg_path, const char *file_path)
|
||||||
{
|
{
|
||||||
const char *base = file_path;
|
const char *base = file_path;
|
||||||
gs_free char *dirname = NULL;
|
gs_free char *dirname = NULL;
|
||||||
char *p;
|
const char *p;
|
||||||
|
|
||||||
g_return_val_if_fail(ifcfg_path != NULL, NULL);
|
g_return_val_if_fail(ifcfg_path != NULL, NULL);
|
||||||
g_return_val_if_fail(file_path != NULL, NULL);
|
g_return_val_if_fail(file_path != NULL, NULL);
|
||||||
|
|
@ -4401,7 +4401,7 @@ make_wireless_setting(shvarFile *ifcfg, GError **error)
|
||||||
NMSettingWireless *s_wireless;
|
NMSettingWireless *s_wireless;
|
||||||
const char *cvalue;
|
const char *cvalue;
|
||||||
char *value = NULL;
|
char *value = NULL;
|
||||||
gint64 chan = 0;
|
guint64 chan = 0;
|
||||||
NMSettingMacRandomization mac_randomization;
|
NMSettingMacRandomization mac_randomization;
|
||||||
NMSettingWirelessPowersave powersave = NM_SETTING_WIRELESS_POWERSAVE_DEFAULT;
|
NMSettingWirelessPowersave powersave = NM_SETTING_WIRELESS_POWERSAVE_DEFAULT;
|
||||||
NMTernary ternary;
|
NMTernary ternary;
|
||||||
|
|
@ -4502,7 +4502,7 @@ make_wireless_setting(shvarFile *ifcfg, GError **error)
|
||||||
|
|
||||||
value = svGetValueStr_cp(ifcfg, "CHANNEL");
|
value = svGetValueStr_cp(ifcfg, "CHANNEL");
|
||||||
if (value) {
|
if (value) {
|
||||||
chan = _nm_utils_ascii_str_to_int64(value, 10, 1, 196, 0);
|
chan = _nm_utils_ascii_str_to_int64(value, 10, 1, _NM_WIFI_CHANNEL_MAX, 0);
|
||||||
if (chan == 0) {
|
if (chan == 0) {
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
NM_SETTINGS_ERROR,
|
NM_SETTINGS_ERROR,
|
||||||
|
|
@ -4518,44 +4518,47 @@ make_wireless_setting(shvarFile *ifcfg, GError **error)
|
||||||
|
|
||||||
value = svGetValueStr_cp(ifcfg, "BAND");
|
value = svGetValueStr_cp(ifcfg, "BAND");
|
||||||
if (value) {
|
if (value) {
|
||||||
if (!strcmp(value, "a")) {
|
if (!NM_IN_STRSET(value, "a", "bg", "6GHz")) {
|
||||||
if (chan && chan <= 14) {
|
|
||||||
g_set_error(error,
|
|
||||||
NM_SETTINGS_ERROR,
|
|
||||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
|
||||||
"Band '%s' invalid for channel %u",
|
|
||||||
value,
|
|
||||||
(guint32) chan);
|
|
||||||
g_free(value);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else if (!strcmp(value, "bg")) {
|
|
||||||
if (chan && chan > 14) {
|
|
||||||
g_set_error(error,
|
|
||||||
NM_SETTINGS_ERROR,
|
|
||||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
|
||||||
"Band '%s' invalid for channel %u",
|
|
||||||
value,
|
|
||||||
(guint32) chan);
|
|
||||||
g_free(value);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
NM_SETTINGS_ERROR,
|
NM_SETTINGS_ERROR,
|
||||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||||
"Invalid wireless band '%s'",
|
"Band '%s' invalid",
|
||||||
value);
|
value);
|
||||||
g_free(value);
|
g_free(value);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chan) {
|
||||||
|
if (!nm_utils_wifi_is_channel_valid(chan, value)) {
|
||||||
|
g_set_error(error,
|
||||||
|
NM_SETTINGS_ERROR,
|
||||||
|
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||||
|
"Band '%s' invalid for channel %u",
|
||||||
|
value,
|
||||||
|
(guint32) chan);
|
||||||
|
g_free(value);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, value, NULL);
|
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, value, NULL);
|
||||||
g_free(value);
|
g_free(value);
|
||||||
} else if (chan > 0) {
|
} else if (chan > 0) {
|
||||||
if (chan > 14)
|
if (chan > _NM_WIFI_CHANNEL_MAX_5GHZ) {
|
||||||
|
g_set_error(error,
|
||||||
|
NM_SETTINGS_ERROR,
|
||||||
|
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||||
|
"Setting channel without band is ambiguous and deprecated. Not supported "
|
||||||
|
"for 6GHz.");
|
||||||
|
g_free(value);
|
||||||
|
goto error;
|
||||||
|
} else if (chan > _NM_WIFI_CHANNEL_MAX_2GHZ) {
|
||||||
|
PARSE_WARNING(
|
||||||
|
"Setting channel without band is ambiguous and deprecated. Assuming band 'a'.");
|
||||||
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, "a", NULL);
|
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, "a", NULL);
|
||||||
else
|
} else {
|
||||||
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, "bg", NULL);
|
g_object_set(s_wireless, NM_SETTING_WIRELESS_BAND, "bg", NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = svGetValueStr_cp(ifcfg, "MTU");
|
value = svGetValueStr_cp(ifcfg, "MTU");
|
||||||
|
|
|
||||||
|
|
@ -849,7 +849,7 @@ write_wireless_setting(NMConnection *connection,
|
||||||
GBytes *ssid;
|
GBytes *ssid;
|
||||||
const guint8 *ssid_data;
|
const guint8 *ssid_data;
|
||||||
gsize ssid_len;
|
gsize ssid_len;
|
||||||
const char *mode, *bssid;
|
const char *mode, *bssid, *band;
|
||||||
const char *device_mac, *cloned_mac;
|
const char *device_mac, *cloned_mac;
|
||||||
guint32 mtu, chan, i;
|
guint32 mtu, chan, i;
|
||||||
gboolean adhoc = FALSE, hex_ssid = FALSE;
|
gboolean adhoc = FALSE, hex_ssid = FALSE;
|
||||||
|
|
@ -968,9 +968,11 @@ write_wireless_setting(NMConnection *connection,
|
||||||
chan = nm_setting_wireless_get_channel(s_wireless);
|
chan = nm_setting_wireless_get_channel(s_wireless);
|
||||||
if (chan) {
|
if (chan) {
|
||||||
svSetValueInt64(ifcfg, "CHANNEL", chan);
|
svSetValueInt64(ifcfg, "CHANNEL", chan);
|
||||||
} else {
|
}
|
||||||
/* Band only set if channel is not, since channel implies band */
|
|
||||||
svSetValueStr(ifcfg, "BAND", nm_setting_wireless_get_band(s_wireless));
|
band = nm_setting_wireless_get_band(s_wireless);
|
||||||
|
if (band) {
|
||||||
|
svSetValueStr(ifcfg, "BAND", band);
|
||||||
}
|
}
|
||||||
|
|
||||||
bssid = nm_setting_wireless_get_bssid(s_wireless);
|
bssid = nm_setting_wireless_get_bssid(s_wireless);
|
||||||
|
|
@ -3598,6 +3600,7 @@ do_write_construct(NMConnection *connection,
|
||||||
} else
|
} else
|
||||||
route_ignore = FALSE;
|
route_ignore = FALSE;
|
||||||
|
|
||||||
|
/* Unsupported properties */
|
||||||
if ((s_ip4 = nm_connection_get_setting_ip4_config(connection))) {
|
if ((s_ip4 = nm_connection_get_setting_ip4_config(connection))) {
|
||||||
if (nm_setting_ip_config_get_dhcp_dscp(s_ip4)) {
|
if (nm_setting_ip_config_get_dhcp_dscp(s_ip4)) {
|
||||||
set_error_unsupported(error,
|
set_error_unsupported(error,
|
||||||
|
|
@ -3616,6 +3619,14 @@ do_write_construct(NMConnection *connection,
|
||||||
FALSE);
|
FALSE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (nm_setting_ip4_config_get_clat(NM_SETTING_IP4_CONFIG(s_ip4))
|
||||||
|
!= NM_SETTING_IP4_CONFIG_CLAT_DEFAULT) {
|
||||||
|
set_error_unsupported(error,
|
||||||
|
connection,
|
||||||
|
NM_SETTING_IP4_CONFIG_SETTING_NAME "." NM_SETTING_IP4_CONFIG_CLAT,
|
||||||
|
FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write_ip4_setting(connection,
|
write_ip4_setting(connection,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
ESSID=MySSID
|
ESSID=MySSID
|
||||||
MODE=Ap
|
MODE=Ap
|
||||||
CHANNEL=196
|
CHANNEL=52
|
||||||
|
BAND=a
|
||||||
MAC_ADDRESS_RANDOMIZATION=default
|
MAC_ADDRESS_RANDOMIZATION=default
|
||||||
AP_ISOLATION=yes
|
AP_ISOLATION=yes
|
||||||
TYPE=Wireless
|
TYPE=Wireless
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
ESSID="Test SSID"
|
||||||
|
MODE=Managed
|
||||||
|
BAND=6GHz
|
||||||
|
MAC_ADDRESS_RANDOMIZATION=default
|
||||||
|
TYPE=Wireless
|
||||||
|
PROXY_METHOD=none
|
||||||
|
BROWSER_ONLY=no
|
||||||
|
BOOTPROTO=dhcp
|
||||||
|
DEFROUTE=yes
|
||||||
|
IPV4_FAILURE_FATAL=no
|
||||||
|
IPV6INIT=yes
|
||||||
|
IPV6_AUTOCONF=yes
|
||||||
|
IPV6_DEFROUTE=yes
|
||||||
|
IPV6_FAILURE_FATAL=no
|
||||||
|
IPV6_ADDR_GEN_MODE=default
|
||||||
|
NAME="Test Write Wi-Fi Band 6GHz"
|
||||||
|
UUID=${UUID}
|
||||||
|
ONBOOT=yes
|
||||||
|
|
@ -13,6 +13,6 @@ IPV6_AUTOCONF=yes
|
||||||
IPV6_DEFROUTE=yes
|
IPV6_DEFROUTE=yes
|
||||||
IPV6_FAILURE_FATAL=no
|
IPV6_FAILURE_FATAL=no
|
||||||
IPV6_ADDR_GEN_MODE=default
|
IPV6_ADDR_GEN_MODE=default
|
||||||
NAME="Test Write Wi-Fi Band A"
|
NAME="Test Write Wi-Fi Band A - 5GHz"
|
||||||
UUID=${UUID}
|
UUID=${UUID}
|
||||||
ONBOOT=yes
|
ONBOOT=yes
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
TYPE=Wireless
|
||||||
|
DEVICE=eth2
|
||||||
|
HWADDR=00:16:41:11:22:33
|
||||||
|
NM_CONTROLLED=yes
|
||||||
|
BOOTPROTO=dhcp
|
||||||
|
ESSID=blahblah
|
||||||
|
BAND=6GHz
|
||||||
|
MODE=Managed
|
||||||
|
RATE=auto
|
||||||
|
ONBOOT=yes
|
||||||
|
USERCTL=yes
|
||||||
|
PEERDNS=yes
|
||||||
|
IPV6INIT=no
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
TYPE=Wireless
|
||||||
|
DEVICE=eth2
|
||||||
|
HWADDR=00:16:41:11:22:33
|
||||||
|
BOOTPROTO=dhcp
|
||||||
|
ESSID=blahblah
|
||||||
|
CHANNEL=14
|
||||||
|
BAND=6GHz
|
||||||
|
MODE=Managed
|
||||||
|
|
||||||
|
|
@ -3991,7 +3991,7 @@ test_write_wifi_band_a(void)
|
||||||
s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION);
|
s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION);
|
||||||
g_object_set(s_con,
|
g_object_set(s_con,
|
||||||
NM_SETTING_CONNECTION_ID,
|
NM_SETTING_CONNECTION_ID,
|
||||||
"Test Write Wi-Fi Band A",
|
"Test Write Wi-Fi Band A - 5GHz",
|
||||||
NM_SETTING_CONNECTION_UUID,
|
NM_SETTING_CONNECTION_UUID,
|
||||||
nm_uuid_generate_random_str_a(),
|
nm_uuid_generate_random_str_a(),
|
||||||
NM_SETTING_CONNECTION_TYPE,
|
NM_SETTING_CONNECTION_TYPE,
|
||||||
|
|
@ -4012,7 +4012,7 @@ test_write_wifi_band_a(void)
|
||||||
|
|
||||||
_writer_new_connec_exp(connection,
|
_writer_new_connec_exp(connection,
|
||||||
TEST_SCRATCH_DIR,
|
TEST_SCRATCH_DIR,
|
||||||
TEST_IFCFG_DIR "/ifcfg-Test_Write_WiFi_Band_A.cexpected",
|
TEST_IFCFG_DIR "/ifcfg-Test_Write_WiFi_Band_a.cexpected",
|
||||||
&testfile);
|
&testfile);
|
||||||
|
|
||||||
f = _svOpenFile(testfile);
|
f = _svOpenFile(testfile);
|
||||||
|
|
@ -4024,6 +4024,77 @@ test_write_wifi_band_a(void)
|
||||||
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
|
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_read_wifi_band_6ghz(void)
|
||||||
|
{
|
||||||
|
gs_unref_object NMConnection *connection = NULL;
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
NMSettingWireless *s_wifi;
|
||||||
|
|
||||||
|
connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-band-6ghz",
|
||||||
|
NULL,
|
||||||
|
TYPE_WIRELESS,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
s_con = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_CONNECTION);
|
||||||
|
g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con),
|
||||||
|
==,
|
||||||
|
NM_SETTING_WIRELESS_SETTING_NAME);
|
||||||
|
|
||||||
|
s_wifi = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRELESS);
|
||||||
|
g_assert_cmpstr(nm_setting_wireless_get_band(s_wifi), ==, "6GHz");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_write_wifi_band_6ghz(void)
|
||||||
|
{
|
||||||
|
nmtst_auto_unlinkfile char *testfile = NULL;
|
||||||
|
gs_unref_object NMConnection *connection = NULL;
|
||||||
|
gs_unref_object NMConnection *reread = NULL;
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
NMSettingWireless *s_wifi;
|
||||||
|
shvarFile *f;
|
||||||
|
gs_unref_bytes GBytes *ssid =
|
||||||
|
nmtst_gbytes_from_arr(0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44);
|
||||||
|
|
||||||
|
connection = nm_simple_connection_new();
|
||||||
|
|
||||||
|
s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION);
|
||||||
|
g_object_set(s_con,
|
||||||
|
NM_SETTING_CONNECTION_ID,
|
||||||
|
"Test Write Wi-Fi Band 6GHz",
|
||||||
|
NM_SETTING_CONNECTION_UUID,
|
||||||
|
nm_uuid_generate_random_str_a(),
|
||||||
|
NM_SETTING_CONNECTION_TYPE,
|
||||||
|
NM_SETTING_WIRELESS_SETTING_NAME,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
s_wifi = _nm_connection_new_setting(connection, NM_TYPE_SETTING_WIRELESS);
|
||||||
|
g_object_set(s_wifi,
|
||||||
|
NM_SETTING_WIRELESS_SSID,
|
||||||
|
ssid,
|
||||||
|
NM_SETTING_WIRELESS_MODE,
|
||||||
|
"infrastructure",
|
||||||
|
NM_SETTING_WIRELESS_BAND,
|
||||||
|
"6GHz",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
nmtst_assert_connection_verifies(connection);
|
||||||
|
|
||||||
|
_writer_new_connec_exp(connection,
|
||||||
|
TEST_SCRATCH_DIR,
|
||||||
|
TEST_IFCFG_DIR "/ifcfg-Test_Write_WiFi_Band_6ghz.cexpected",
|
||||||
|
&testfile);
|
||||||
|
|
||||||
|
f = _svOpenFile(testfile);
|
||||||
|
_svGetValue_check(f, "BAND", "6GHz");
|
||||||
|
svCloseFile(f);
|
||||||
|
|
||||||
|
reread = _connection_from_file(testfile, NULL, TYPE_WIRELESS, NULL);
|
||||||
|
|
||||||
|
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_write_wifi_ap_mode(void)
|
test_write_wifi_ap_mode(void)
|
||||||
{
|
{
|
||||||
|
|
@ -4055,7 +4126,7 @@ test_write_wifi_ap_mode(void)
|
||||||
NM_SETTING_WIRELESS_BAND,
|
NM_SETTING_WIRELESS_BAND,
|
||||||
"a",
|
"a",
|
||||||
NM_SETTING_WIRELESS_CHANNEL,
|
NM_SETTING_WIRELESS_CHANNEL,
|
||||||
(guint) 196,
|
(guint) 52,
|
||||||
NM_SETTING_WIRELESS_AP_ISOLATION,
|
NM_SETTING_WIRELESS_AP_ISOLATION,
|
||||||
NM_TERNARY_TRUE,
|
NM_TERNARY_TRUE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
@ -4072,6 +4143,18 @@ test_write_wifi_ap_mode(void)
|
||||||
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
|
nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_read_wifi_band_6ghz_channel_mismatch(void)
|
||||||
|
{
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
|
||||||
|
_connection_from_file_fail(TEST_IFCFG_DIR "/ifcfg-test-wifi-band-6ghz-channel-mismatch",
|
||||||
|
NULL,
|
||||||
|
TYPE_WIRELESS,
|
||||||
|
&error);
|
||||||
|
g_assert_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_read_wifi_band_a_channel_mismatch(void)
|
test_read_wifi_band_a_channel_mismatch(void)
|
||||||
{
|
{
|
||||||
|
|
@ -10680,6 +10763,9 @@ main(int argc, char **argv)
|
||||||
test_read_wifi_band_a_channel_mismatch);
|
test_read_wifi_band_a_channel_mismatch);
|
||||||
g_test_add_func(TPATH "wifi/read-band-bg-channel-mismatch",
|
g_test_add_func(TPATH "wifi/read-band-bg-channel-mismatch",
|
||||||
test_read_wifi_band_bg_channel_mismatch);
|
test_read_wifi_band_bg_channel_mismatch);
|
||||||
|
g_test_add_func(TPATH "wifi/read-band-6ghz", test_read_wifi_band_6ghz);
|
||||||
|
g_test_add_func(TPATH "wifi/read-band-6ghz-channel-mismatch",
|
||||||
|
test_read_wifi_band_6ghz_channel_mismatch);
|
||||||
g_test_add_func(TPATH "wifi/read-hidden", test_read_wifi_hidden);
|
g_test_add_func(TPATH "wifi/read-hidden", test_read_wifi_hidden);
|
||||||
|
|
||||||
nmtst_add_test_func(TPATH "wifi/read-mac-random-always",
|
nmtst_add_test_func(TPATH "wifi/read-mac-random-always",
|
||||||
|
|
@ -10852,6 +10938,7 @@ main(int argc, char **argv)
|
||||||
test_write_wifi_wpa_then_wep_with_perms);
|
test_write_wifi_wpa_then_wep_with_perms);
|
||||||
g_test_add_func(TPATH "wifi/write-hidden", test_write_wifi_hidden);
|
g_test_add_func(TPATH "wifi/write-hidden", test_write_wifi_hidden);
|
||||||
g_test_add_func(TPATH "wifi/write-band-a", test_write_wifi_band_a);
|
g_test_add_func(TPATH "wifi/write-band-a", test_write_wifi_band_a);
|
||||||
|
g_test_add_func(TPATH "wifi/write-band-6ghz", test_write_wifi_band_6ghz);
|
||||||
g_test_add_func(TPATH "wifi/write-ap-mode", test_write_wifi_ap_mode);
|
g_test_add_func(TPATH "wifi/write-ap-mode", test_write_wifi_ap_mode);
|
||||||
|
|
||||||
g_test_add_func(TPATH "s390/read-qeth-static", test_read_wired_qeth_static);
|
g_test_add_func(TPATH "s390/read-qeth-static", test_read_wired_qeth_static);
|
||||||
|
|
|
||||||
|
|
@ -373,14 +373,24 @@ nm_supplicant_config_get_blobs(NMSupplicantConfig *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
wifi_freqs_to_string(gboolean bg_band)
|
wifi_freqs_to_string(const char *band)
|
||||||
{
|
{
|
||||||
static const char *str_2ghz = NULL;
|
static const char *str_2ghz = NULL;
|
||||||
static const char *str_5ghz = NULL;
|
static const char *str_5ghz = NULL;
|
||||||
|
static const char *str_6ghz = NULL;
|
||||||
const char **f_p;
|
const char **f_p;
|
||||||
const char *f;
|
const char *f;
|
||||||
|
|
||||||
f_p = bg_band ? &str_2ghz : &str_5ghz;
|
if (nm_streq0(band, "a"))
|
||||||
|
f_p = &str_5ghz;
|
||||||
|
else if (nm_streq0(band, "bg"))
|
||||||
|
f_p = &str_2ghz;
|
||||||
|
else if (nm_streq0(band, "6GHz"))
|
||||||
|
f_p = &str_6ghz;
|
||||||
|
else {
|
||||||
|
nm_assert_not_reached();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
again:
|
again:
|
||||||
f = g_atomic_pointer_get(f_p);
|
f = g_atomic_pointer_get(f_p);
|
||||||
|
|
@ -390,7 +400,13 @@ again:
|
||||||
const guint *freqs;
|
const guint *freqs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
freqs = bg_band ? nm_utils_wifi_2ghz_freqs() : nm_utils_wifi_5ghz_freqs();
|
if (f_p == &str_2ghz)
|
||||||
|
freqs = nm_utils_wifi_2ghz_freqs();
|
||||||
|
else if (f_p == &str_5ghz)
|
||||||
|
freqs = nm_utils_wifi_5ghz_freqs();
|
||||||
|
else
|
||||||
|
freqs = nm_utils_wifi_6ghz_freqs();
|
||||||
|
|
||||||
for (i = 0; freqs[i]; i++) {
|
for (i = 0; freqs[i]; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
nm_str_buf_append_c(&strbuf, ' ');
|
nm_str_buf_append_c(&strbuf, ' ');
|
||||||
|
|
@ -533,38 +549,47 @@ get_ap_params(guint freq,
|
||||||
guint channel;
|
guint channel;
|
||||||
guint center_channel = 0;
|
guint center_channel = 0;
|
||||||
|
|
||||||
if (freq < 5000) {
|
|
||||||
/* the setting is not valid */
|
|
||||||
nm_assert_not_reached();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine the center channel according to the table at
|
/* Determine the center channel according to the table at
|
||||||
* https://en.wikipedia.org/wiki/List_of_WLAN_channels */
|
* https://en.wikipedia.org/wiki/List_of_WLAN_channels */
|
||||||
|
|
||||||
channel = (freq - 5000) / 5;
|
if (freq > 5950) {
|
||||||
|
/* 6 GHz */
|
||||||
|
channel = (freq - 5950) / 5;
|
||||||
|
channel = ((channel - 1) / 16) * 16 + 7;
|
||||||
|
|
||||||
if (channel >= 36 && channel <= 48)
|
|
||||||
center_channel = 42;
|
|
||||||
else if (channel >= 52 && channel <= 64)
|
|
||||||
center_channel = 58;
|
|
||||||
else if (channel >= 100 && channel <= 112)
|
|
||||||
center_channel = 106;
|
|
||||||
else if (channel >= 116 && channel <= 128)
|
|
||||||
center_channel = 122;
|
|
||||||
else if (channel >= 132 && channel <= 144)
|
|
||||||
center_channel = 138;
|
|
||||||
else if (channel >= 149 && channel <= 161)
|
|
||||||
center_channel = 155;
|
|
||||||
else if (channel >= 165 && channel <= 177)
|
|
||||||
center_channel = 171;
|
|
||||||
|
|
||||||
if (center_channel) {
|
|
||||||
*out_ht40 = 1;
|
*out_ht40 = 1;
|
||||||
*out_max_oper_chwidth = 1;
|
*out_max_oper_chwidth = 1;
|
||||||
*out_center_freq = 5000 + 5 * center_channel;
|
*out_center_freq = 5950 + 5 * channel;
|
||||||
}
|
} else {
|
||||||
|
/* 5 GHz */
|
||||||
|
if (freq < 5000) {
|
||||||
|
/* the setting is not valid */
|
||||||
|
nm_assert_not_reached();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
channel = (freq - 5000) / 5;
|
||||||
|
|
||||||
|
if (channel >= 36 && channel <= 48)
|
||||||
|
center_channel = 42;
|
||||||
|
else if (channel >= 52 && channel <= 64)
|
||||||
|
center_channel = 58;
|
||||||
|
else if (channel >= 100 && channel <= 112)
|
||||||
|
center_channel = 106;
|
||||||
|
else if (channel >= 116 && channel <= 128)
|
||||||
|
center_channel = 122;
|
||||||
|
else if (channel >= 132 && channel <= 144)
|
||||||
|
center_channel = 138;
|
||||||
|
else if (channel >= 149 && channel <= 161)
|
||||||
|
center_channel = 155;
|
||||||
|
else if (channel >= 165 && channel <= 177)
|
||||||
|
center_channel = 171;
|
||||||
|
|
||||||
|
if (center_channel) {
|
||||||
|
*out_ht40 = 1;
|
||||||
|
*out_max_oper_chwidth = 1;
|
||||||
|
*out_center_freq = 5000 + 5 * center_channel;
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -711,10 +736,7 @@ nm_supplicant_config_add_setting_wireless(NMSupplicantConfig *self,
|
||||||
} else {
|
} else {
|
||||||
const char *freqs = NULL;
|
const char *freqs = NULL;
|
||||||
|
|
||||||
if (nm_streq(band, "a"))
|
freqs = wifi_freqs_to_string(band);
|
||||||
freqs = wifi_freqs_to_string(FALSE);
|
|
||||||
else if (nm_streq(band, "bg"))
|
|
||||||
freqs = wifi_freqs_to_string(TRUE);
|
|
||||||
|
|
||||||
if (freqs
|
if (freqs
|
||||||
&& !nm_supplicant_config_add_option(self,
|
&& !nm_supplicant_config_add_option(self,
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ enum {
|
||||||
GROUP_STARTED, /* a new Group (interface) was created */
|
GROUP_STARTED, /* a new Group (interface) was created */
|
||||||
GROUP_FINISHED, /* a Group (interface) has been finished */
|
GROUP_FINISHED, /* a Group (interface) has been finished */
|
||||||
PSK_MISMATCH, /* supplicant reported incorrect PSK */
|
PSK_MISMATCH, /* supplicant reported incorrect PSK */
|
||||||
|
SAE_MISMATCH, /* supplicant reported incorrect SAE Password */
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -3237,6 +3238,11 @@ _signal_handle(NMSupplicantInterface *self,
|
||||||
g_signal_emit(self, signals[PSK_MISMATCH], 0);
|
g_signal_emit(self, signals[PSK_MISMATCH], 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nm_streq(signal_name, "SaePasswordMismatch")) {
|
||||||
|
g_signal_emit(self, signals[SAE_MISMATCH], 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3879,4 +3885,13 @@ nm_supplicant_interface_class_init(NMSupplicantInterfaceClass *klass)
|
||||||
NULL,
|
NULL,
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
0);
|
0);
|
||||||
|
signals[SAE_MISMATCH] = g_signal_new(NM_SUPPLICANT_INTERFACE_SAE_MISMATCH,
|
||||||
|
G_OBJECT_CLASS_TYPE(object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ typedef enum {
|
||||||
#define NM_SUPPLICANT_INTERFACE_GROUP_STARTED "group-started"
|
#define NM_SUPPLICANT_INTERFACE_GROUP_STARTED "group-started"
|
||||||
#define NM_SUPPLICANT_INTERFACE_GROUP_FINISHED "group-finished"
|
#define NM_SUPPLICANT_INTERFACE_GROUP_FINISHED "group-finished"
|
||||||
#define NM_SUPPLICANT_INTERFACE_PSK_MISMATCH "wpa-psk-mismatch"
|
#define NM_SUPPLICANT_INTERFACE_PSK_MISMATCH "wpa-psk-mismatch"
|
||||||
|
#define NM_SUPPLICANT_INTERFACE_SAE_MISMATCH "wpa-sae-password-mismatch"
|
||||||
|
|
||||||
typedef struct _NMSupplicantInterfaceClass NMSupplicantInterfaceClass;
|
typedef struct _NMSupplicantInterfaceClass NMSupplicantInterfaceClass;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "src/core/nm-default-daemon.h"
|
#include "src/core/nm-default-daemon.h"
|
||||||
|
|
||||||
#include "nm-supplicant-settings-verify.h"
|
#include "nm-supplicant-settings-verify.h"
|
||||||
|
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -71,7 +72,7 @@ static const struct Opt opt_table[] = {
|
||||||
OPT_BYTES("engine_id", 0),
|
OPT_BYTES("engine_id", 0),
|
||||||
OPT_INT("fragment_size", 1, 2000),
|
OPT_INT("fragment_size", 1, 2000),
|
||||||
OPT_KEYWORD("freq_list", NULL),
|
OPT_KEYWORD("freq_list", NULL),
|
||||||
OPT_INT("frequency", 2412, 5825),
|
OPT_INT("frequency", _NM_WIFI_FREQ_MIN, _NM_WIFI_FREQ_MAX),
|
||||||
OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )),
|
OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )),
|
||||||
OPT_INT("ht40", 0, 1),
|
OPT_INT("ht40", 0, 1),
|
||||||
OPT_BYTES("identity", 0),
|
OPT_BYTES("identity", 0),
|
||||||
|
|
@ -212,18 +213,19 @@ validate_type_utf8(const struct Opt *opt, const char *value, const guint32 len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
validate_type_keyword(const struct Opt *opt, const char *value, const guint32 len)
|
validate_type_keyword(const struct Opt *opt, const char *value_in, const guint32 len)
|
||||||
{
|
{
|
||||||
gs_free char *value_free = NULL;
|
gs_free char *value_free = NULL;
|
||||||
|
char *value;
|
||||||
|
|
||||||
nm_assert(opt);
|
nm_assert(opt);
|
||||||
nm_assert(value);
|
nm_assert(value_in);
|
||||||
|
|
||||||
/* Allow everything */
|
/* Allow everything */
|
||||||
if (!opt->str_allowed)
|
if (!opt->str_allowed)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
value = nm_strndup_a(300, value, len, &value_free);
|
value = nm_strndup_a(300, value_in, len, &value_free);
|
||||||
|
|
||||||
/* validate each space-separated word in 'value' */
|
/* validate each space-separated word in 'value' */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,108 @@ test_config_override(void)
|
||||||
g_assert_cmpstr(plugins[3], ==, "delta");
|
g_assert_cmpstr(plugins[3], ==, "delta");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_config_managed(void)
|
||||||
|
{
|
||||||
|
NMConfig *config;
|
||||||
|
const char *CONFIG_USER = BUILD_DIR "/test-config-managed.conf";
|
||||||
|
const char *CONFIG_INTERN = BUILD_DIR "/test-config-managed-intern.conf";
|
||||||
|
NMDevice *dev;
|
||||||
|
gs_free char *group_by_name = NULL;
|
||||||
|
const char *ifname, *group_by_mac;
|
||||||
|
NMTernary managed;
|
||||||
|
gboolean by_mac;
|
||||||
|
GKeyFile *kf = nm_config_create_keyfile();
|
||||||
|
|
||||||
|
dev = nm_test_device_new("11:11:11:11:11:11");
|
||||||
|
ifname = nm_device_get_iface(dev);
|
||||||
|
group_by_name =
|
||||||
|
g_strdup_printf(NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE "-manage-%s", ifname);
|
||||||
|
group_by_mac = NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE "-manage-11-11-11-11-11-11";
|
||||||
|
|
||||||
|
g_assert(g_file_set_contents(CONFIG_USER, "", 0, NULL));
|
||||||
|
g_assert(g_file_set_contents(CONFIG_INTERN, "", 0, NULL));
|
||||||
|
|
||||||
|
config = setup_config(NULL, CONFIG_USER, CONFIG_INTERN, NULL, "/no/such/dir", "", NULL);
|
||||||
|
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, NULL, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_DEFAULT);
|
||||||
|
|
||||||
|
/* Matching by name */
|
||||||
|
NMTST_EXPECT_NM_INFO("config: signal: *");
|
||||||
|
g_assert(nm_config_set_device_managed(config, dev, NM_TERNARY_TRUE, FALSE, NULL));
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, &by_mac, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_TRUE);
|
||||||
|
g_assert_false(by_mac);
|
||||||
|
g_key_file_load_from_file(kf, CONFIG_INTERN, G_KEY_FILE_NONE, NULL);
|
||||||
|
g_assert_false(g_key_file_has_key(kf, group_by_mac, "managed", NULL));
|
||||||
|
g_assert_true(g_key_file_has_key(kf, group_by_name, "managed", NULL));
|
||||||
|
g_assert_cmpint(g_key_file_get_integer(kf, group_by_name, "managed", NULL), ==, 1);
|
||||||
|
|
||||||
|
NMTST_EXPECT_NM_INFO("config: signal: *");
|
||||||
|
g_assert(nm_config_set_device_managed(config, dev, NM_TERNARY_FALSE, FALSE, NULL));
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, &by_mac, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_FALSE);
|
||||||
|
g_assert_false(by_mac);
|
||||||
|
g_key_file_load_from_file(kf, CONFIG_INTERN, G_KEY_FILE_NONE, NULL);
|
||||||
|
g_assert_false(g_key_file_has_key(kf, group_by_mac, "managed", NULL));
|
||||||
|
g_assert_true(g_key_file_has_key(kf, group_by_name, "managed", NULL));
|
||||||
|
g_assert_cmpint(g_key_file_get_integer(kf, group_by_name, "managed", NULL), ==, 0);
|
||||||
|
|
||||||
|
/* Matching by MAC address */
|
||||||
|
NMTST_EXPECT_NM_INFO("config: signal: *");
|
||||||
|
g_assert(nm_config_set_device_managed(config, dev, NM_TERNARY_TRUE, TRUE, NULL));
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, &by_mac, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_TRUE);
|
||||||
|
g_assert_true(by_mac);
|
||||||
|
g_key_file_load_from_file(kf, CONFIG_INTERN, G_KEY_FILE_NONE, NULL);
|
||||||
|
g_assert_false(g_key_file_has_key(kf, group_by_name, "managed", NULL));
|
||||||
|
g_assert_true(g_key_file_has_key(kf, group_by_mac, "managed", NULL));
|
||||||
|
g_assert_cmpint(g_key_file_get_integer(kf, group_by_mac, "managed", NULL), ==, 1);
|
||||||
|
|
||||||
|
NMTST_EXPECT_NM_INFO("config: signal: *");
|
||||||
|
g_assert(nm_config_set_device_managed(config, dev, NM_TERNARY_FALSE, TRUE, NULL));
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, &by_mac, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_FALSE);
|
||||||
|
g_assert_true(by_mac);
|
||||||
|
g_key_file_load_from_file(kf, CONFIG_INTERN, G_KEY_FILE_NONE, NULL);
|
||||||
|
g_assert_false(g_key_file_has_key(kf, group_by_name, "managed", NULL));
|
||||||
|
g_assert_true(g_key_file_has_key(kf, group_by_mac, "managed", NULL));
|
||||||
|
g_assert_cmpint(g_key_file_get_integer(kf, group_by_mac, "managed", NULL), ==, 0);
|
||||||
|
|
||||||
|
/* Resetting the managed state */
|
||||||
|
NMTST_EXPECT_NM_INFO("config: signal: *");
|
||||||
|
g_assert(nm_config_set_device_managed(config, dev, NM_TERNARY_DEFAULT, FALSE, NULL));
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, NULL, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_DEFAULT);
|
||||||
|
g_key_file_load_from_file(kf, CONFIG_INTERN, G_KEY_FILE_NONE, NULL);
|
||||||
|
g_assert_false(g_key_file_has_key(kf, group_by_name, "managed", NULL));
|
||||||
|
g_assert_false(g_key_file_has_key(kf, group_by_mac, "managed", NULL));
|
||||||
|
|
||||||
|
g_object_unref(config);
|
||||||
|
|
||||||
|
/* Both values set in the intern config file, different values */
|
||||||
|
g_key_file_set_string(kf, group_by_name, "managed", "1");
|
||||||
|
g_key_file_set_string(kf, group_by_mac, "managed", "0");
|
||||||
|
g_assert(g_key_file_save_to_file(kf, CONFIG_INTERN, NULL));
|
||||||
|
config = setup_config(NULL, CONFIG_USER, CONFIG_INTERN, NULL, "/no/such/dir", "", NULL);
|
||||||
|
g_assert(!nm_config_get_device_managed(config, dev, &managed, NULL, NULL));
|
||||||
|
|
||||||
|
g_object_unref(config);
|
||||||
|
|
||||||
|
/* Both values set in the intern config file, same values */
|
||||||
|
g_key_file_set_string(kf, group_by_name, "managed", "1");
|
||||||
|
g_key_file_set_string(kf, group_by_mac, "managed", "1");
|
||||||
|
g_assert(g_key_file_save_to_file(kf, CONFIG_INTERN, NULL));
|
||||||
|
config = setup_config(NULL, CONFIG_USER, CONFIG_INTERN, NULL, "/no/such/dir", "", NULL);
|
||||||
|
g_assert(nm_config_get_device_managed(config, dev, &managed, NULL, NULL));
|
||||||
|
g_assert_cmpint(managed, ==, NM_TERNARY_TRUE);
|
||||||
|
|
||||||
|
g_key_file_unref(kf);
|
||||||
|
g_object_unref(dev);
|
||||||
|
g_object_unref(config);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_config_global_dns(void)
|
test_config_global_dns(void)
|
||||||
{
|
{
|
||||||
|
|
@ -1412,6 +1514,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
g_test_add_func("/config/set-values", test_config_set_values);
|
g_test_add_func("/config/set-values", test_config_set_values);
|
||||||
g_test_add_func("/config/global-dns", test_config_global_dns);
|
g_test_add_func("/config/global-dns", test_config_global_dns);
|
||||||
|
g_test_add_func("/config/managed", test_config_managed);
|
||||||
g_test_add_func("/config/connectivity-check", test_config_connectivity_check);
|
g_test_add_func("/config/connectivity-check", test_config_connectivity_check);
|
||||||
|
|
||||||
g_test_add_func("/config/signal", test_config_signal);
|
g_test_add_func("/config/signal", test_config_signal);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
|
||||||
/* need math.h for isinf() and INFINITY. No need to link with -lm */
|
/* need math.h for isinf() and INFINITY. No need to link with -lm */
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
@ -2770,6 +2771,56 @@ test_nm_firewall_nft_stdio_mlag(void)
|
||||||
"nm-mlag-bond0\012delete table netdev nm-mlag-bond0\012");
|
"nm-mlag-bond0\012delete table netdev nm-mlag-bond0\012");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_icmp6_checksum(void)
|
||||||
|
{
|
||||||
|
struct ip6_hdr ip6h = {};
|
||||||
|
guint8 *data;
|
||||||
|
guint16 c;
|
||||||
|
|
||||||
|
ip6h.ip6_src = NM_IN6ADDR_INIT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
ip6h.ip6_dst = NM_IN6ADDR_INIT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
data = (guint8[]) {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
c = nm_utils_icmp6_checksum(&ip6h.ip6_src, 12, data);
|
||||||
|
g_assert_cmpint(c, ==, htons(0xffb9));
|
||||||
|
|
||||||
|
ip6h.ip6_src = NM_IN6ADDR_INIT(0xfe,
|
||||||
|
0x80,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0xc0,
|
||||||
|
0x60,
|
||||||
|
0x8c,
|
||||||
|
0xaf,
|
||||||
|
0xf6,
|
||||||
|
0x9b,
|
||||||
|
0xe4,
|
||||||
|
0x1a);
|
||||||
|
ip6h.ip6_dst = NM_IN6ADDR_INIT(0x20,
|
||||||
|
0x02,
|
||||||
|
0xaa,
|
||||||
|
0xaa,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x64,
|
||||||
|
0xd4,
|
||||||
|
0x29,
|
||||||
|
0x32,
|
||||||
|
0x35,
|
||||||
|
0x85,
|
||||||
|
0x7c,
|
||||||
|
0x89);
|
||||||
|
data = (guint8[]) {0xdc, 0x74, 0x1a, 0xcc, 0xd3, 0x8e, 0xca, 0x34};
|
||||||
|
c = nm_utils_icmp6_checksum(&ip6h.ip6_src, 8, data);
|
||||||
|
g_assert_cmpint(c, ==, htons(0x39af));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
NMTST_DEFINE();
|
NMTST_DEFINE();
|
||||||
|
|
@ -2848,5 +2899,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
g_test_add_func("/core/test_nm_firewall_nft_stdio_mlag", test_nm_firewall_nft_stdio_mlag);
|
g_test_add_func("/core/test_nm_firewall_nft_stdio_mlag", test_nm_firewall_nft_stdio_mlag);
|
||||||
|
|
||||||
|
g_test_add_func("/core/general/test_icmp6_checksum", test_icmp6_checksum);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,44 @@ test_ip_reservation_shared4(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_ip_reservation_clat(void)
|
||||||
|
{
|
||||||
|
gs_unref_object NMPlatform *platform = NULL;
|
||||||
|
gs_unref_object NMNetns *netns = NULL;
|
||||||
|
NMNetnsIPReservation *res[8];
|
||||||
|
NMNetnsIPReservation *res1;
|
||||||
|
char buf[NM_INET_ADDRSTRLEN];
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
platform = g_object_ref(NM_PLATFORM_GET);
|
||||||
|
netns = nm_netns_new(platform);
|
||||||
|
|
||||||
|
/* Allocate addresses 192.0.0.{5,6,7,0,1,2,3,4} */
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
res[i] = nm_netns_ip_reservation_get(netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT);
|
||||||
|
g_snprintf(buf, sizeof(buf), "192.0.0.%u", (i + 5) % 8);
|
||||||
|
nmtst_assert_ip4_address(res[i]->addr, buf);
|
||||||
|
g_assert_cmpint(res[i]->_ref_count, ==, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release an address and get it back */
|
||||||
|
nm_netns_ip_reservation_release(res[2]);
|
||||||
|
res[2] = nm_netns_ip_reservation_get(netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT);
|
||||||
|
nmtst_assert_ip4_address(res[2]->addr, "192.0.0.7");
|
||||||
|
|
||||||
|
/* No reuse */
|
||||||
|
NMTST_EXPECT_NM_ERROR("netns[*]: clat: ran out of IP addresses");
|
||||||
|
res1 = nm_netns_ip_reservation_get(netns, NM_NETNS_IP_RESERVATION_TYPE_CLAT);
|
||||||
|
g_test_assert_expected_messages();
|
||||||
|
g_assert_null(res1);
|
||||||
|
|
||||||
|
/* Release all */
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
nm_netns_ip_reservation_release(res[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
NMTST_DEFINE();
|
NMTST_DEFINE();
|
||||||
|
|
@ -64,6 +102,7 @@ main(int argc, char **argv)
|
||||||
nm_linux_platform_setup();
|
nm_linux_platform_setup();
|
||||||
|
|
||||||
g_test_add_func("/netns/ip_reservation/shared4", test_ip_reservation_shared4);
|
g_test_add_func("/netns/ip_reservation/shared4", test_ip_reservation_shared4);
|
||||||
|
g_test_add_func("/netns/ip_reservation/clat", test_ip_reservation_clat);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2135,16 +2135,20 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
|
||||||
IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN
|
IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN
|
||||||
: NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN,
|
: NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN,
|
||||||
"&s",
|
"&s",
|
||||||
&v_str))
|
&v_str)) {
|
||||||
nm_l3_config_data_add_domain(l3cd, addr_family, v_str);
|
nm_l3_config_data_add_domain(l3cd, addr_family, v_str);
|
||||||
|
nm_l3_config_data_add_search(l3cd, addr_family, v_str);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_variant_lookup(dict,
|
if (g_variant_lookup(dict,
|
||||||
IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS
|
IS_IPv4 ? NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS
|
||||||
: NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS,
|
: NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS,
|
||||||
"as",
|
"as",
|
||||||
&var_iter)) {
|
&var_iter)) {
|
||||||
while (g_variant_iter_next(var_iter, "&s", &v_str))
|
while (g_variant_iter_next(var_iter, "&s", &v_str)) {
|
||||||
nm_l3_config_data_add_domain(l3cd, addr_family, v_str);
|
nm_l3_config_data_add_domain(l3cd, addr_family, v_str);
|
||||||
|
nm_l3_config_data_add_search(l3cd, addr_family, v_str);
|
||||||
|
}
|
||||||
g_variant_iter_free(var_iter);
|
g_variant_iter_free(var_iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,16 +60,21 @@ nm_vpn_manager_activate_connection(NMVpnManager *manager, NMVpnConnection *vpn,
|
||||||
{
|
{
|
||||||
NMVpnManagerPrivate *priv;
|
NMVpnManagerPrivate *priv;
|
||||||
NMVpnPluginInfo *plugin_info;
|
NMVpnPluginInfo *plugin_info;
|
||||||
|
NMConnection *applied;
|
||||||
const char *service_name;
|
const char *service_name;
|
||||||
NMDevice *device;
|
NMDevice *device;
|
||||||
|
const char *user;
|
||||||
|
|
||||||
g_return_val_if_fail(NM_IS_VPN_MANAGER(manager), FALSE);
|
g_return_val_if_fail(NM_IS_VPN_MANAGER(manager), FALSE);
|
||||||
g_return_val_if_fail(NM_IS_VPN_CONNECTION(vpn), FALSE);
|
g_return_val_if_fail(NM_IS_VPN_CONNECTION(vpn), FALSE);
|
||||||
g_return_val_if_fail(!error || !*error, FALSE);
|
g_return_val_if_fail(!error || !*error, FALSE);
|
||||||
|
|
||||||
priv = NM_VPN_MANAGER_GET_PRIVATE(manager);
|
priv = NM_VPN_MANAGER_GET_PRIVATE(manager);
|
||||||
device = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(vpn));
|
device = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(vpn));
|
||||||
g_assert(device);
|
applied = nm_active_connection_get_applied_connection(NM_ACTIVE_CONNECTION(vpn));
|
||||||
|
nm_assert(device);
|
||||||
|
nm_assert(applied);
|
||||||
|
|
||||||
if (nm_device_get_state(device) != NM_DEVICE_STATE_ACTIVATED
|
if (nm_device_get_state(device) != NM_DEVICE_STATE_ACTIVATED
|
||||||
&& nm_device_get_state(device) != NM_DEVICE_STATE_SECONDARIES) {
|
&& nm_device_get_state(device) != NM_DEVICE_STATE_SECONDARIES) {
|
||||||
g_set_error_literal(error,
|
g_set_error_literal(error,
|
||||||
|
|
@ -101,6 +106,30 @@ nm_vpn_manager_activate_connection(NMVpnManager *manager, NMVpnConnection *vpn,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user = nm_utils_get_connection_first_permissions_user(applied);
|
||||||
|
if (user) {
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
|
||||||
|
s_con = nm_connection_get_setting_connection(applied);
|
||||||
|
nm_assert(s_con);
|
||||||
|
if (_nm_setting_connection_get_num_permissions_users(s_con) > 1) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE,
|
||||||
|
"private VPN connections with multiple users are not allowed.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_vpn_plugin_info_supports_safe_private_file_access(plugin_info)) {
|
||||||
|
g_set_error(error,
|
||||||
|
NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE,
|
||||||
|
"The '%s' plugin doesn't support private connections.",
|
||||||
|
nm_vpn_plugin_info_get_name(plugin_info));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nm_vpn_connection_activate(vpn, plugin_info);
|
nm_vpn_connection_activate(vpn, plugin_info);
|
||||||
|
|
||||||
if (!nm_vpn_plugin_info_supports_multiple(plugin_info)) {
|
if (!nm_vpn_plugin_info_supports_multiple(plugin_info)) {
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,7 @@ typedef enum {
|
||||||
NM_IP_CONFIG_SOURCE_VPN,
|
NM_IP_CONFIG_SOURCE_VPN,
|
||||||
NM_IP_CONFIG_SOURCE_DHCP,
|
NM_IP_CONFIG_SOURCE_DHCP,
|
||||||
NM_IP_CONFIG_SOURCE_NDISC,
|
NM_IP_CONFIG_SOURCE_NDISC,
|
||||||
|
NM_IP_CONFIG_SOURCE_CLAT,
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
NM_IP_CONFIG_SOURCE_USER,
|
||||||
} NMIPConfigSource;
|
} NMIPConfigSource;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@
|
||||||
|
|
||||||
#define NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED "managed"
|
#define NM_CONFIG_KEYFILE_KEY_DEVICE_MANAGED "managed"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER "ignore-carrier"
|
#define NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER "ignore-carrier"
|
||||||
|
#define NM_CONFIG_KEYFILE_KEY_DEVICE_CHECK_CONNECTIVITY "check-connectivity"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS "sriov-num-vfs"
|
#define NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS "sriov-num-vfs"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_DEVICE_KEEP_CONFIGURATION "keep-configuration"
|
#define NM_CONFIG_KEYFILE_KEY_DEVICE_KEEP_CONFIGURATION "keep-configuration"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_DEVICE_ALLOWED_CONNECTIONS "allowed-connections"
|
#define NM_CONFIG_KEYFILE_KEY_DEVICE_ALLOWED_CONNECTIONS "allowed-connections"
|
||||||
|
|
@ -89,4 +90,7 @@
|
||||||
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN \
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN \
|
||||||
NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN
|
NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN
|
||||||
|
|
||||||
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_DEVICE \
|
||||||
|
NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE
|
||||||
|
|
||||||
#endif /* __NM_CONFIG_BASE_H__ */
|
#endif /* __NM_CONFIG_BASE_H__ */
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue