mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 11:40:14 +01:00
Compare commits
82 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57a409441b | ||
|
|
22d3b80a77 | ||
|
|
45835b5128 | ||
|
|
376210ec37 | ||
|
|
bb0d29a8f1 | ||
|
|
29d190ef95 | ||
|
|
425fd0d031 | ||
|
|
b5c19e47ba | ||
|
|
598e266179 | ||
|
|
3e096c087d | ||
|
|
46b8bc0f1c | ||
|
|
7252fb5d8f | ||
|
|
70efbbd5a5 | ||
|
|
5c3b7e029b | ||
|
|
5ad3a752b9 | ||
|
|
4074f9e2c6 | ||
|
|
d1a1db43b8 | ||
|
|
554e3a3e83 | ||
|
|
737000860e | ||
|
|
8676995903 | ||
|
|
daf43f3732 | ||
|
|
0a9bc10076 | ||
|
|
a2cad8cb10 | ||
|
|
4e240c493d | ||
|
|
db2f88bc73 | ||
|
|
1877c8b464 | ||
|
|
2f6597a673 | ||
|
|
bd9886963e | ||
|
|
507c0d625c | ||
|
|
95d2da5da9 | ||
|
|
0135379ac4 | ||
|
|
1489f9d0e3 | ||
|
|
826e37b175 | ||
|
|
2ee4ba9034 | ||
|
|
7106daf1a3 | ||
|
|
3dfd364502 | ||
|
|
35f11cd6e1 | ||
|
|
ff9032ff9d | ||
|
|
37e72927d7 | ||
|
|
e059388f05 | ||
|
|
399b08aab6 | ||
|
|
693e1e9742 | ||
|
|
6d3ff1c30b | ||
|
|
b83f847b4d | ||
|
|
2172c5ff5a | ||
|
|
59be16b91a | ||
|
|
051a4a27a2 | ||
|
|
a1e1dd2978 | ||
|
|
d19068c9e3 | ||
|
|
ca39902cee | ||
|
|
e766920e0b | ||
|
|
9e640cb751 | ||
|
|
75bb71fddf | ||
|
|
c3ed106d63 | ||
|
|
9c74fa8e36 | ||
|
|
2fe69da6fd | ||
|
|
9ec498f321 | ||
|
|
15a68c6a9b | ||
|
|
ae420a8dd6 | ||
|
|
3f2c0869dc | ||
|
|
4d0223f8a4 | ||
|
|
2afcebe0c7 | ||
|
|
57321f78c9 | ||
|
|
ff853203d9 | ||
|
|
e77a1df6e7 | ||
|
|
6f480d9494 | ||
|
|
e568648717 | ||
|
|
0c5e37f34d | ||
|
|
4321cca3e8 | ||
|
|
629d85e4da | ||
|
|
a212c9452e | ||
|
|
8371b4733e | ||
|
|
06e35f165f | ||
|
|
e933dfaf72 | ||
|
|
22f3cdd8ab | ||
|
|
07d549eb5a | ||
|
|
3dee98acdc | ||
|
|
094a542546 | ||
|
|
b7e34f225a | ||
|
|
1ace58c0c2 | ||
|
|
873adc4dc0 | ||
|
|
de4f4e870d |
95 changed files with 4515 additions and 2560 deletions
354
.gitlab-ci.yml
354
.gitlab-ci.yml
|
|
@ -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-77ec3d923fd6'
|
ALPINE_TAG: 'tag-672dcdb2e2bf'
|
||||||
CENTOS_TAG: 'tag-7a677f4838e1'
|
CENTOS_TAG: 'tag-d7d348d344cf'
|
||||||
DEBIAN_TAG: 'tag-ecad19904683'
|
DEBIAN_TAG: 'tag-217545cfdeb1'
|
||||||
FEDORA_TAG: 'tag-7a677f4838e1'
|
FEDORA_TAG: 'tag-d7d348d344cf'
|
||||||
UBUNTU_TAG: 'tag-ecad19904683'
|
UBUNTU_TAG: 'tag-217545cfdeb1'
|
||||||
|
|
||||||
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'
|
||||||
|
|
@ -102,7 +102,61 @@ variables:
|
||||||
# Build a container for each distribution + version. The ci-templates
|
# Build a container for each distribution + version. The ci-templates
|
||||||
# will re-use the containers if the tag doesn't change.
|
# will re-use the containers if the tag doesn't change.
|
||||||
|
|
||||||
tier1:fedora:41@prep:
|
tier1:fedora:42@prep:
|
||||||
|
extends:
|
||||||
|
- .fdo.container-build@fedora
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
FDO_DISTRIBUTION_VERSION: '42'
|
||||||
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
|
FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE != 'schedule' || $SCHEDULED_PIPELINE_NAME == "weekly"
|
||||||
|
|
||||||
|
tier2:ubuntu:25.04@prep:
|
||||||
|
extends:
|
||||||
|
- .fdo.container-build@ubuntu
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
FDO_DISTRIBUTION_VERSION: '25.04'
|
||||||
|
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
||||||
|
FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
when: manual
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
tier2:debian:13@prep:
|
||||||
|
extends:
|
||||||
|
- .fdo.container-build@debian
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
FDO_DISTRIBUTION_VERSION: '13'
|
||||||
|
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
||||||
|
FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
when: manual
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
tier2:alpine:3.22@prep:
|
||||||
|
extends:
|
||||||
|
- .fdo.container-build@alpine
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
FDO_DISTRIBUTION_VERSION: '3.22'
|
||||||
|
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
||||||
|
FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
when: manual
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
tier3:fedora:41@prep:
|
||||||
extends:
|
extends:
|
||||||
- .fdo.container-build@fedora
|
- .fdo.container-build@fedora
|
||||||
stage: prep
|
stage: prep
|
||||||
|
|
@ -111,116 +165,6 @@ tier1:fedora:41@prep:
|
||||||
FDO_DISTRIBUTION_VERSION: '41'
|
FDO_DISTRIBUTION_VERSION: '41'
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
|
FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule' || $SCHEDULED_PIPELINE_NAME == "weekly"
|
|
||||||
|
|
||||||
tier2:fedora:rawhide@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@fedora
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'rawhide'
|
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier2:centos:stream9@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@centos
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'stream9'
|
|
||||||
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $CENTOS_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier2:ubuntu:devel@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@ubuntu
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'devel'
|
|
||||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier2:debian:testing@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'testing'
|
|
||||||
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier2:debian:sid@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@debian
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'sid'
|
|
||||||
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier2:alpine:edge@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@alpine
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'edge'
|
|
||||||
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier3:fedora:40@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@fedora
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: '40'
|
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier3:ubuntu:24.10@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@ubuntu
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: '24.10'
|
|
||||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
|
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
when: manual
|
when: manual
|
||||||
|
|
@ -254,20 +198,6 @@ tier3:ubuntu:22.04@prep:
|
||||||
when: manual
|
when: manual
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
|
||||||
tier3:ubuntu:20.04@prep:
|
|
||||||
extends:
|
|
||||||
- .fdo.container-build@ubuntu
|
|
||||||
stage: prep
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
FDO_DISTRIBUTION_VERSION: '20.04'
|
|
||||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
|
||||||
FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
tier3:debian:12@prep:
|
tier3:debian:12@prep:
|
||||||
extends:
|
extends:
|
||||||
- .fdo.container-build@debian
|
- .fdo.container-build@debian
|
||||||
|
|
@ -324,15 +254,29 @@ tier3:alpine:3.19@prep:
|
||||||
when: manual
|
when: manual
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
|
||||||
tier3:alpine:3.18@prep:
|
tier3:centos:stream10@prep:
|
||||||
extends:
|
extends:
|
||||||
- .fdo.container-build@alpine
|
- .fdo.container-build@centos
|
||||||
stage: prep
|
stage: prep
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: none
|
GIT_STRATEGY: none
|
||||||
FDO_DISTRIBUTION_VERSION: '3.18'
|
FDO_DISTRIBUTION_VERSION: 'stream10'
|
||||||
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
||||||
FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
|
FDO_DISTRIBUTION_EXEC: $CENTOS_EXEC
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
when: manual
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
tier3:centos:stream9@prep:
|
||||||
|
extends:
|
||||||
|
- .fdo.container-build@centos
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
FDO_DISTRIBUTION_VERSION: 'stream9'
|
||||||
|
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
||||||
|
FDO_DISTRIBUTION_EXEC: $CENTOS_EXEC
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
when: manual
|
when: manual
|
||||||
|
|
@ -354,7 +298,7 @@ tier3:alpine:3.18@prep:
|
||||||
dependencies: []
|
dependencies: []
|
||||||
|
|
||||||
|
|
||||||
t_fedora:41:
|
t_fedora:42:
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
- .fdo.distribution-image@fedora
|
- .fdo.distribution-image@fedora
|
||||||
|
|
@ -370,122 +314,66 @@ t_fedora:41:
|
||||||
- tarball
|
- tarball
|
||||||
- subtree
|
- subtree
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: '41'
|
FDO_DISTRIBUTION_VERSION: '42'
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier1:fedora:41@prep"
|
- "tier1:fedora:42@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
t_fedora:rawhide:
|
t_ubuntu:25.04:
|
||||||
extends:
|
|
||||||
- .build@template
|
|
||||||
- .fdo.distribution-image@fedora
|
|
||||||
- .nm_artifacts_debug
|
|
||||||
stage: tier2
|
|
||||||
variables:
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'rawhide'
|
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
|
||||||
needs:
|
|
||||||
- "tier2:fedora:rawhide@prep"
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
|
|
||||||
t_centos:stream9:
|
|
||||||
extends:
|
|
||||||
- .build@template
|
|
||||||
- .fdo.distribution-image@centos
|
|
||||||
- .nm_artifacts_debug
|
|
||||||
stage: tier2
|
|
||||||
variables:
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'stream9'
|
|
||||||
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
|
||||||
needs:
|
|
||||||
- "tier2:centos:stream9@prep"
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
|
|
||||||
t_ubuntu:devel:
|
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
- .fdo.distribution-image@ubuntu
|
- .fdo.distribution-image@ubuntu
|
||||||
- .nm_artifacts_debug
|
- .nm_artifacts_debug
|
||||||
stage: tier2
|
stage: tier2
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: 'devel'
|
FDO_DISTRIBUTION_VERSION: '25.04'
|
||||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier2:ubuntu:devel@prep"
|
- "tier2:ubuntu:25.04@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
t_debian:testing:
|
t_debian:13:
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
- .fdo.distribution-image@debian
|
- .fdo.distribution-image@debian
|
||||||
- .nm_artifacts_debug
|
- .nm_artifacts_debug
|
||||||
stage: tier2
|
stage: tier2
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: 'testing'
|
FDO_DISTRIBUTION_VERSION: '13'
|
||||||
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier2:debian:testing@prep"
|
- "tier2:debian:13@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
t_debian:sid:
|
t_alpine:3.22:
|
||||||
extends:
|
|
||||||
- .build@template
|
|
||||||
- .fdo.distribution-image@debian
|
|
||||||
- .nm_artifacts_debug
|
|
||||||
stage: tier2
|
|
||||||
variables:
|
|
||||||
FDO_DISTRIBUTION_VERSION: 'sid'
|
|
||||||
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
|
||||||
needs:
|
|
||||||
- "tier2:debian:sid@prep"
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
|
|
||||||
t_alpine:edge:
|
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
- .fdo.distribution-image@alpine
|
- .fdo.distribution-image@alpine
|
||||||
- .nm_artifacts_debug
|
- .nm_artifacts_debug
|
||||||
stage: tier2
|
stage: tier2
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: 'edge'
|
FDO_DISTRIBUTION_VERSION: '3.22'
|
||||||
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier2:alpine:edge@prep"
|
- "tier2:alpine:3.22@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
t_fedora:40:
|
t_fedora:41:
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
- .fdo.distribution-image@fedora
|
- .fdo.distribution-image@fedora
|
||||||
- .nm_artifacts_debug
|
- .nm_artifacts_debug
|
||||||
stage: tier3
|
stage: tier3
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: '40'
|
FDO_DISTRIBUTION_VERSION: '41'
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier3:fedora:40@prep"
|
- "tier3:fedora:41@prep"
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
|
|
||||||
t_ubuntu:24.10:
|
|
||||||
extends:
|
|
||||||
- .build@template
|
|
||||||
- .fdo.distribution-image@ubuntu
|
|
||||||
- .nm_artifacts_debug
|
|
||||||
stage: tier3
|
|
||||||
variables:
|
|
||||||
FDO_DISTRIBUTION_VERSION: '24.10'
|
|
||||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
|
||||||
needs:
|
|
||||||
- "tier3:ubuntu:24.10@prep"
|
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
|
|
@ -517,20 +405,6 @@ t_ubuntu:22.04:
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
t_ubuntu:20.04:
|
|
||||||
extends:
|
|
||||||
- .build@template
|
|
||||||
- .fdo.distribution-image@ubuntu
|
|
||||||
- .nm_artifacts_debug
|
|
||||||
stage: tier3
|
|
||||||
variables:
|
|
||||||
FDO_DISTRIBUTION_VERSION: '20.04'
|
|
||||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
|
||||||
needs:
|
|
||||||
- "tier3:ubuntu:20.04@prep"
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
|
||||||
|
|
||||||
t_debian:12:
|
t_debian:12:
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
|
|
@ -587,17 +461,31 @@ t_alpine:3.19:
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
t_alpine:3.18:
|
t_centos:stream10:
|
||||||
extends:
|
extends:
|
||||||
- .build@template
|
- .build@template
|
||||||
- .fdo.distribution-image@alpine
|
- .fdo.distribution-image@centos
|
||||||
- .nm_artifacts_debug
|
- .nm_artifacts_debug
|
||||||
stage: tier3
|
stage: tier3
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: '3.18'
|
FDO_DISTRIBUTION_VERSION: 'stream10'
|
||||||
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier3:alpine:3.18@prep"
|
- "tier3:centos:stream10@prep"
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
|
t_centos:stream9:
|
||||||
|
extends:
|
||||||
|
- .build@template
|
||||||
|
- .fdo.distribution-image@centos
|
||||||
|
- .nm_artifacts_debug
|
||||||
|
stage: tier3
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_VERSION: 'stream9'
|
||||||
|
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
||||||
|
needs:
|
||||||
|
- "tier3:centos:stream9@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
|
|
||||||
|
|
@ -611,10 +499,10 @@ check-patch:
|
||||||
extends:
|
extends:
|
||||||
- .fdo.distribution-image@fedora
|
- .fdo.distribution-image@fedora
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: '41'
|
FDO_DISTRIBUTION_VERSION: '42'
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier1:fedora:41@prep"
|
- "tier1:fedora:42@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||||
stage: tier1
|
stage: tier1
|
||||||
|
|
@ -626,10 +514,10 @@ check-tree:
|
||||||
extends:
|
extends:
|
||||||
- .fdo.distribution-image@fedora
|
- .fdo.distribution-image@fedora
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: '41'
|
FDO_DISTRIBUTION_VERSION: '42'
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
needs:
|
needs:
|
||||||
- "tier1:fedora:41@prep"
|
- "tier1:fedora:42@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
|
@ -659,9 +547,9 @@ pages:
|
||||||
when: never
|
when: never
|
||||||
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'main'
|
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'main'
|
||||||
dependencies:
|
dependencies:
|
||||||
- "t_fedora:41: [meson+gcc+docs+valgrind]"
|
- "t_fedora:42: [meson+gcc+docs+valgrind]"
|
||||||
needs:
|
needs:
|
||||||
- "t_fedora:41: [meson+gcc+docs+valgrind]"
|
- "t_fedora:42: [meson+gcc+docs+valgrind]"
|
||||||
|
|
||||||
triage:issues:
|
triage:issues:
|
||||||
stage: triage
|
stage: triage
|
||||||
|
|
@ -678,11 +566,11 @@ coverity:
|
||||||
extends:
|
extends:
|
||||||
- .fdo.distribution-image@fedora
|
- .fdo.distribution-image@fedora
|
||||||
variables:
|
variables:
|
||||||
FDO_DISTRIBUTION_VERSION: '41'
|
FDO_DISTRIBUTION_VERSION: '42'
|
||||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||||
stage: coverity
|
stage: coverity
|
||||||
needs:
|
needs:
|
||||||
- "tier1:fedora:41@prep"
|
- "tier1:fedora:42@prep"
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_PIPELINE_NAME == "weekly"
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_PIPELINE_NAME == "weekly"
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -23,45 +23,34 @@ distributions:
|
||||||
- name: fedora
|
- name: fedora
|
||||||
tier: 1
|
tier: 1
|
||||||
versions:
|
versions:
|
||||||
- '41'
|
- '42'
|
||||||
|
|
||||||
# TIER 2: distribution versions that will or might use the current NM version.
|
# TIER 2: distribution versions that will or might use the current NM version.
|
||||||
# Run when doing a release.
|
# Run when doing a release.
|
||||||
- name: fedora
|
|
||||||
tier: 2
|
|
||||||
versions:
|
|
||||||
- 'rawhide'
|
|
||||||
- name: centos
|
|
||||||
tier: 2
|
|
||||||
versions:
|
|
||||||
- 'stream9'
|
|
||||||
- name: ubuntu
|
- name: ubuntu
|
||||||
tier: 2
|
tier: 2
|
||||||
versions:
|
versions:
|
||||||
- 'devel'
|
- '25.04'
|
||||||
- name: debian
|
- name: debian
|
||||||
tier: 2
|
tier: 2
|
||||||
versions:
|
versions:
|
||||||
- 'testing'
|
- '13'
|
||||||
- 'sid'
|
|
||||||
- name: alpine
|
- name: alpine
|
||||||
tier: 2
|
tier: 2
|
||||||
versions:
|
versions:
|
||||||
- 'edge'
|
- '3.22'
|
||||||
|
|
||||||
# TIER 3: distribution versions not in EOL but don't use the current NM version.
|
# TIER 3: distribution versions not in EOL but don't use the current NM version.
|
||||||
# Run when doing a release, but a failure won't be blocking for the release.
|
# Run when doing a release, but a failure won't be blocking for the release.
|
||||||
- name: fedora
|
- name: fedora
|
||||||
tier: 3
|
tier: 3
|
||||||
versions:
|
versions:
|
||||||
- '40'
|
- '41'
|
||||||
- name: ubuntu
|
- name: ubuntu
|
||||||
tier: 3
|
tier: 3
|
||||||
versions:
|
versions:
|
||||||
- '24.10'
|
|
||||||
- '24.04'
|
- '24.04'
|
||||||
- '22.04'
|
- '22.04'
|
||||||
- '20.04'
|
|
||||||
- name: debian
|
- name: debian
|
||||||
tier: 3
|
tier: 3
|
||||||
versions:
|
versions:
|
||||||
|
|
@ -72,4 +61,8 @@ distributions:
|
||||||
- '3.21'
|
- '3.21'
|
||||||
- '3.20'
|
- '3.20'
|
||||||
- '3.19'
|
- '3.19'
|
||||||
- '3.18'
|
- name: centos
|
||||||
|
tier: 3
|
||||||
|
versions:
|
||||||
|
- 'stream10'
|
||||||
|
- 'stream9'
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ if [ $IS_CENTOS = 1 ]; then
|
||||||
CENTOS_VERSION=8
|
CENTOS_VERSION=8
|
||||||
elif grep -q '^VERSION_ID=.*\<9\>' /etc/os-release ; then
|
elif grep -q '^VERSION_ID=.*\<9\>' /etc/os-release ; then
|
||||||
CENTOS_VERSION=9
|
CENTOS_VERSION=9
|
||||||
|
elif grep -q '^VERSION_ID=.*\<10\>' /etc/os-release ; then
|
||||||
|
CENTOS_VERSION=10
|
||||||
else
|
else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -33,6 +35,11 @@ fi
|
||||||
dnf install -y 'dnf-command(config-manager)'
|
dnf install -y 'dnf-command(config-manager)'
|
||||||
dnf config-manager --set-enabled crb
|
dnf config-manager --set-enabled crb
|
||||||
curl https://copr.fedorainfracloud.org/coprs/nmstate/nm-build-deps/repo/epel-9/nmstate-nm-build-deps-epel-9.repo > /etc/yum.repos.d/nmstate-nm-build-deps-epel-9.repo
|
curl https://copr.fedorainfracloud.org/coprs/nmstate/nm-build-deps/repo/epel-9/nmstate-nm-build-deps-epel-9.repo > /etc/yum.repos.d/nmstate-nm-build-deps-epel-9.repo
|
||||||
|
elif [ "$CENTOS_VERSION" = stream10 ]; then
|
||||||
|
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
|
||||||
|
dnf install -y 'dnf-command(config-manager)'
|
||||||
|
dnf config-manager --set-enabled crb
|
||||||
|
curl https://copr.fedorainfracloud.org/coprs/nmstate/nm-build-deps/repo/epel-10/nmstate-nm-build-deps-epel-10.repo > /etc/yum.repos.d/nmstate-nm-build-deps-epel-10.repo
|
||||||
else
|
else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,17 @@ grep -q '^NAME=.*\(CentOS\)' /etc/os-release && IS_CENTOS=1
|
||||||
grep -q '^NAME=.*\(Fedora\)' /etc/os-release && IS_FEDORA=1
|
grep -q '^NAME=.*\(Fedora\)' /etc/os-release && IS_FEDORA=1
|
||||||
grep -q '^NAME=.*\(Alpine\)' /etc/os-release && IS_ALPINE=1
|
grep -q '^NAME=.*\(Alpine\)' /etc/os-release && IS_ALPINE=1
|
||||||
|
|
||||||
IS_CENTOS_7=0
|
|
||||||
if [ $IS_CENTOS = 1 ]; then
|
if [ $IS_CENTOS = 1 ]; then
|
||||||
if grep -q '^VERSION_ID=.*\<7\>' /etc/os-release ; then
|
CENTOS_VER_LINE="$(grep '^VERSION_ID=' /etc/os-release)"
|
||||||
IS_CENTOS_7=1
|
if [[ $CENTOS_VER_LINE =~ ^VERSION_ID=\"?([0-9]+)\"?$ ]]; then
|
||||||
|
CENTOS_VER="${BASH_REMATCH[1]}"
|
||||||
|
else
|
||||||
|
echo "Error detecting CentOS Stream version" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( $CENTOS_VER >= 10 )); then
|
||||||
|
export WITH_LIBTEAM=0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
25
NEWS
25
NEWS
|
|
@ -1,3 +1,28 @@
|
||||||
|
===============================================
|
||||||
|
NetworkManager-1.52.2
|
||||||
|
Overview of changes since NetworkManager-1.52.1
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
* Support reapplying the "sriov.vfs" property as long as
|
||||||
|
"sriov.total-vfs" is not changed.
|
||||||
|
* 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.52.1
|
||||||
|
Overview of changes since NetworkManager-1.52
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
* Fail early if we cannot get current FEC
|
||||||
|
(Forward Error Correction) value.
|
||||||
|
* Allow reapplying ovs-bridge and ovs-port properties.
|
||||||
|
* When activating a WireGuard connection to an IPv6 endpoint, now
|
||||||
|
NetworkManager creates firewall rules to ensure that the incoming
|
||||||
|
packets are not dropped by kernel reverse path filtering.
|
||||||
|
|
||||||
=============================================
|
=============================================
|
||||||
NetworkManager-1.52
|
NetworkManager-1.52
|
||||||
Overview of changes since NetworkManager-1.50
|
Overview of changes since NetworkManager-1.50
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,9 @@
|
||||||
/* Define to path of iptables binary */
|
/* Define to path of iptables binary */
|
||||||
#mesondefine IPTABLES_PATH
|
#mesondefine IPTABLES_PATH
|
||||||
|
|
||||||
|
/* Define to path of ip6tables binary */
|
||||||
|
#mesondefine IP6TABLES_PATH
|
||||||
|
|
||||||
/* Define to path of nft binary */
|
/* Define to path of nft binary */
|
||||||
#mesondefine NFT_PATH
|
#mesondefine NFT_PATH
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ apk add \
|
||||||
'clang' \
|
'clang' \
|
||||||
'curl-dev' \
|
'curl-dev' \
|
||||||
'dbus' \
|
'dbus' \
|
||||||
|
'dbus-dev' \
|
||||||
'elogind-dev' \
|
'elogind-dev' \
|
||||||
'eudev-dev' \
|
'eudev-dev' \
|
||||||
'gcc' \
|
'gcc' \
|
||||||
|
|
|
||||||
|
|
@ -597,6 +597,7 @@ Preferably use nmcli instead.
|
||||||
%endif
|
%endif
|
||||||
-Dnft=%{_sbindir}/nft \
|
-Dnft=%{_sbindir}/nft \
|
||||||
-Diptables=%{_sbindir}/iptables \
|
-Diptables=%{_sbindir}/iptables \
|
||||||
|
-Dip6tables=%{_sbindir}/ip6tables \
|
||||||
%if %{with dhclient}
|
%if %{with dhclient}
|
||||||
-Ddhclient=%{_sbindir}/dhclient \
|
-Ddhclient=%{_sbindir}/dhclient \
|
||||||
%else
|
%else
|
||||||
|
|
@ -889,6 +890,7 @@ fi
|
||||||
%{_libexecdir}/nm-dispatcher
|
%{_libexecdir}/nm-dispatcher
|
||||||
%{_libexecdir}/nm-initrd-generator
|
%{_libexecdir}/nm-initrd-generator
|
||||||
%{_libexecdir}/nm-daemon-helper
|
%{_libexecdir}/nm-daemon-helper
|
||||||
|
%{_libexecdir}/nm-libnm-helper
|
||||||
%{_libexecdir}/nm-priv-helper
|
%{_libexecdir}/nm-priv-helper
|
||||||
%dir %{_libdir}/%{name}
|
%dir %{_libdir}/%{name}
|
||||||
%dir %{nmplugindir}
|
%dir %{nmplugindir}
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,7 @@ if [[ $NO_DIST != 1 ]]; then
|
||||||
-Dconfig_dhcp_default=internal \
|
-Dconfig_dhcp_default=internal \
|
||||||
-Dconfig_dns_rc_manager_default=auto \
|
-Dconfig_dns_rc_manager_default=auto \
|
||||||
-Diptables=/usr/sbin/iptables \
|
-Diptables=/usr/sbin/iptables \
|
||||||
|
-Dip6tables=/usr/sbin/ip6tables \
|
||||||
-Dnft=/usr/bin/nft \
|
-Dnft=/usr/bin/nft \
|
||||||
|| die "Error meson setup"
|
|| die "Error meson setup"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,7 @@ meson setup\
|
||||||
$(args_enable "$P_TEST" --werror) \
|
$(args_enable "$P_TEST" --werror) \
|
||||||
-Dnft="${D_SBINDIR}/nft" \
|
-Dnft="${D_SBINDIR}/nft" \
|
||||||
-Diptables="${D_SBINDIR}/iptables" \
|
-Diptables="${D_SBINDIR}/iptables" \
|
||||||
|
-Dip6tables="${D_SBINDIR}/ip6tables" \
|
||||||
-Ddhclient="${D_SBINDIR}/dhclient" \
|
-Ddhclient="${D_SBINDIR}/dhclient" \
|
||||||
-Ddhcpcd=no \
|
-Ddhcpcd=no \
|
||||||
-Dconfig_dhcp_default="$P_DHCP_DEFAULT" \
|
-Dconfig_dhcp_default="$P_DHCP_DEFAULT" \
|
||||||
|
|
|
||||||
|
|
@ -559,9 +559,11 @@ if [[ $GITLAB_TOKEN == "" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# This step is not necessary for authentication, we use it only to provide a meaningful error message.
|
# This step is not necessary for authentication, we use it only to provide a meaningful error message.
|
||||||
curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
GITLAB_USER_ID=$(curl --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||||
"https://gitlab.freedesktop.org/api/v4/personal_access_tokens/self" &>/dev/null \
|
"https://gitlab.freedesktop.org/api/v4/personal_access_tokens/self" 2>/dev/null | jq ".user_id" || true)
|
||||||
|| die "failed to authenticate at gitlab.freedesktop.org with the private token"
|
if [ -z "$GITLAB_USER_ID" ] || [ "$GITLAB_USER_ID" = "null" ]; then
|
||||||
|
die "failed to authenticate to gitlab.freedesktop.org with the private token"
|
||||||
|
fi
|
||||||
|
|
||||||
do_command git push "$ORIGIN" "${BRANCHES[@]}" || die "failed to to push branches ${BRANCHES[@]} to $ORIGIN"
|
do_command git push "$ORIGIN" "${BRANCHES[@]}" || die "failed to to push branches ${BRANCHES[@]} to $ORIGIN"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,14 @@ if [ "$CC" != gcc ]; then
|
||||||
_WITH_CRYPTO=nss
|
_WITH_CRYPTO=nss
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$WITH_LIBTEAM" != "" ]; then
|
||||||
|
if _is_true "$WITH_LIBTEAM"; then
|
||||||
|
_WITH_LIBTEAM="true"
|
||||||
|
else
|
||||||
|
_WITH_LIBTEAM="false"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$WITH_DOCS" != "" ]; then
|
if [ "$WITH_DOCS" != "" ]; then
|
||||||
if _is_true "$WITH_DOCS"; then
|
if _is_true "$WITH_DOCS"; then
|
||||||
_WITH_DOCS="true"
|
_WITH_DOCS="true"
|
||||||
|
|
|
||||||
|
|
@ -1933,7 +1933,7 @@ interface-name:vboxnet*,except:interface-name:vboxnet2
|
||||||
<literal>"uuid:83037490-1d17-4986-a397-01f1db3a7fc2"</literal></para></listitem>
|
<literal>"uuid:83037490-1d17-4986-a397-01f1db3a7fc2"</literal></para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>id=ID</term>
|
<term>id:ID</term>
|
||||||
<listitem><para>Match the connection by name.</para></listitem>
|
<listitem><para>Match the connection by name.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,10 @@
|
||||||
NetworkManager inserts the records for Bridges into OVSDB when a Port is
|
NetworkManager inserts the records for Bridges into OVSDB when a Port is
|
||||||
attached.
|
attached.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>Known limitation: when the last NetworkManager's owned port is removed,
|
||||||
|
the bridge is removed too, even if there are other externally attached ports.
|
||||||
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2>
|
||||||
|
|
@ -102,6 +106,10 @@
|
||||||
exist. Ports can also be configured to do VLAN tagging or Bonding.
|
exist. Ports can also be configured to do VLAN tagging or Bonding.
|
||||||
NetworkManager inserts the records for Ports into OVSDB when an Interface is
|
NetworkManager inserts the records for Ports into OVSDB when an Interface is
|
||||||
attached. Ports must be attached to a Bridge.</para>
|
attached. Ports must be attached to a Bridge.</para>
|
||||||
|
|
||||||
|
<para>Known limitation: when the last NetworkManager's owned interface is removed,
|
||||||
|
the port is removed too, even if there are other externally attached interfaces.
|
||||||
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2>
|
||||||
|
|
|
||||||
|
|
@ -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.52.0',
|
version: '1.52.2',
|
||||||
license: 'GPL2+',
|
license: 'GPL2+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
|
|
@ -723,6 +723,7 @@ default_paths = ['/sbin', '/usr/sbin']
|
||||||
|
|
||||||
# 0: cmdline option, 1: paths, 2: fallback
|
# 0: cmdline option, 1: paths, 2: fallback
|
||||||
progs = [['iptables', default_paths, '/usr/sbin/iptables'],
|
progs = [['iptables', default_paths, '/usr/sbin/iptables'],
|
||||||
|
['ip6tables', default_paths, '/usr/sbin/ip6tables'],
|
||||||
['nft', default_paths, '/usr/sbin/nft'],
|
['nft', default_paths, '/usr/sbin/nft'],
|
||||||
['dnsmasq', default_paths, ''],
|
['dnsmasq', default_paths, ''],
|
||||||
['modprobe', default_paths, '/sbin/modprobe']
|
['modprobe', default_paths, '/sbin/modprobe']
|
||||||
|
|
@ -1125,6 +1126,7 @@ endif
|
||||||
output += '\n'
|
output += '\n'
|
||||||
output += ' jansson: ' + jansson_msg + '\n'
|
output += ' jansson: ' + jansson_msg + '\n'
|
||||||
output += ' iptables: ' + config_h.get('IPTABLES_PATH') + '\n'
|
output += ' iptables: ' + config_h.get('IPTABLES_PATH') + '\n'
|
||||||
|
output += ' ip6tables: ' + config_h.get('IP6TABLES_PATH') + '\n'
|
||||||
output += ' nft: ' + config_h.get('NFT_PATH') + '\n'
|
output += ' nft: ' + config_h.get('NFT_PATH') + '\n'
|
||||||
output += ' modprobe: ' + config_h.get('MODPROBE_PATH') + '\n'
|
output += ' modprobe: ' + config_h.get('MODPROBE_PATH') + '\n'
|
||||||
output += ' modemmanager-1: ' + enable_modem_manager.to_string() + '\n'
|
output += ' modemmanager-1: ' + enable_modem_manager.to_string() + '\n'
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ option('dbus_conf_dir', type: 'string', value: '', description: 'where D-Bus sys
|
||||||
option('kernel_firmware_dir', type: 'string', value: '/lib/firmware', description: 'where kernel firmware directory is (default is /lib/firmware)')
|
option('kernel_firmware_dir', type: 'string', value: '/lib/firmware', description: 'where kernel firmware directory is (default is /lib/firmware)')
|
||||||
option('runtime_dir', type: 'string', value: '', description: 'Directory for transient runtime state [default: LOCALSTATEDIR/run or /run]')
|
option('runtime_dir', type: 'string', value: '', description: 'Directory for transient runtime state [default: LOCALSTATEDIR/run or /run]')
|
||||||
option('iptables', type: 'string', value: '', description: 'path to iptables')
|
option('iptables', type: 'string', value: '', description: 'path to iptables')
|
||||||
|
option('ip6tables', type: 'string', value: '', description: 'path to ip6tables')
|
||||||
option('nft', type: 'string', value: '', description: 'path to nft')
|
option('nft', type: 'string', value: '', description: 'path to nft')
|
||||||
option('dnsmasq', type: 'string', value: '', description: 'path to dnsmasq')
|
option('dnsmasq', type: 'string', value: '', description: 'path to dnsmasq')
|
||||||
option('modprobe', type: 'string', value: '', description: 'path to modprobe')
|
option('modprobe', type: 'string', value: '', description: 'path to modprobe')
|
||||||
|
|
|
||||||
|
|
@ -137,14 +137,6 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink)
|
||||||
nm_device_parent_set_ifindex(device, parent);
|
nm_device_parent_set_ifindex(device, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
|
||||||
{
|
|
||||||
if (!nm_device_parent_get_device(device))
|
|
||||||
return FALSE;
|
|
||||||
return NM_DEVICE_CLASS(nm_device_6lowpan_parent_class)->is_available(device, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
complete_connection(NMDevice *device,
|
complete_connection(NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
@ -237,7 +229,6 @@ nm_device_6lowpan_class_init(NMDevice6LowpanClass *klass)
|
||||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
||||||
device_class->link_changed = link_changed;
|
device_class->link_changed = link_changed;
|
||||||
device_class->is_available = is_available;
|
|
||||||
device_class->parent_changed_notify = parent_changed_notify;
|
device_class->parent_changed_notify = parent_changed_notify;
|
||||||
device_class->update_connection = update_connection;
|
device_class->update_connection = update_connection;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -735,6 +735,11 @@ merge_bridge_vlan_default_pvid(NMPlatformBridgeVlan *vlans, guint *num_vlans, gu
|
||||||
gboolean has_pvid = FALSE;
|
gboolean has_pvid = FALSE;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
|
if (default_pvid == 0) {
|
||||||
|
/* default_pvid=0 means that the default PVID is disabled. No need to merge it. */
|
||||||
|
return vlans;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < *num_vlans; i++) {
|
for (i = 0; i < *num_vlans; i++) {
|
||||||
if (vlans[i].pvid) {
|
if (vlans[i].pvid) {
|
||||||
has_pvid = TRUE;
|
has_pvid = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -630,10 +630,17 @@ build_supplicant_config(NMDeviceEthernet *self, GError **error)
|
||||||
mtu = nm_platform_link_get_mtu(nm_device_get_platform(NM_DEVICE(self)),
|
mtu = nm_platform_link_get_mtu(nm_device_get_platform(NM_DEVICE(self)),
|
||||||
nm_device_get_ifindex(NM_DEVICE(self)));
|
nm_device_get_ifindex(NM_DEVICE(self)));
|
||||||
|
|
||||||
config = nm_supplicant_config_new(NM_SUPPL_CAP_MASK_NONE);
|
config = nm_supplicant_config_new(NM_SUPPL_CAP_MASK_NONE,
|
||||||
|
nm_utils_get_connection_first_permissions_user(connection));
|
||||||
|
|
||||||
security = nm_connection_get_setting_802_1x(connection);
|
security = nm_connection_get_setting_802_1x(connection);
|
||||||
if (!nm_supplicant_config_add_setting_8021x(config, security, con_uuid, mtu, TRUE, error)) {
|
if (!nm_supplicant_config_add_setting_8021x(config,
|
||||||
|
security,
|
||||||
|
con_uuid,
|
||||||
|
mtu,
|
||||||
|
TRUE,
|
||||||
|
nm_device_get_private_files(NM_DEVICE(self)),
|
||||||
|
error)) {
|
||||||
g_prefix_error(error, "802-1x-setting: ");
|
g_prefix_error(error, "802-1x-setting: ");
|
||||||
g_clear_object(&config);
|
g_clear_object(&config);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,16 +221,6 @@ get_generic_capabilities(NMDevice *device)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
|
||||||
{
|
|
||||||
if (!nm_device_parent_get_device(device))
|
|
||||||
return FALSE;
|
|
||||||
return NM_DEVICE_CLASS(nm_device_ipvlan_parent_class)->is_available(device, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_connection_compatible(NMDevice *device,
|
check_connection_compatible(NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
@ -376,7 +366,6 @@ nm_device_ipvlan_class_init(NMDeviceIpvlanClass *klass)
|
||||||
device_class->check_connection_compatible = check_connection_compatible;
|
device_class->check_connection_compatible = check_connection_compatible;
|
||||||
device_class->create_and_realize = create_and_realize;
|
device_class->create_and_realize = create_and_realize;
|
||||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
device_class->is_available = is_available;
|
|
||||||
device_class->link_changed = link_changed;
|
device_class->link_changed = link_changed;
|
||||||
device_class->update_connection = update_connection;
|
device_class->update_connection = update_connection;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,8 @@ build_supplicant_config(NMDeviceMacsec *self, GError **error)
|
||||||
mtu = nm_platform_link_get_mtu(nm_device_get_platform(NM_DEVICE(self)),
|
mtu = nm_platform_link_get_mtu(nm_device_get_platform(NM_DEVICE(self)),
|
||||||
nm_device_get_ifindex(NM_DEVICE(self)));
|
nm_device_get_ifindex(NM_DEVICE(self)));
|
||||||
|
|
||||||
config = nm_supplicant_config_new(NM_SUPPL_CAP_MASK_NONE);
|
config = nm_supplicant_config_new(NM_SUPPL_CAP_MASK_NONE,
|
||||||
|
nm_utils_get_connection_first_permissions_user(connection));
|
||||||
|
|
||||||
s_macsec = nm_device_get_applied_setting(NM_DEVICE(self), NM_TYPE_SETTING_MACSEC);
|
s_macsec = nm_device_get_applied_setting(NM_DEVICE(self), NM_TYPE_SETTING_MACSEC);
|
||||||
|
|
||||||
|
|
@ -227,7 +228,13 @@ build_supplicant_config(NMDeviceMacsec *self, GError **error)
|
||||||
|
|
||||||
if (nm_setting_macsec_get_mode(s_macsec) == NM_SETTING_MACSEC_MODE_EAP) {
|
if (nm_setting_macsec_get_mode(s_macsec) == NM_SETTING_MACSEC_MODE_EAP) {
|
||||||
s_8021x = nm_connection_get_setting_802_1x(connection);
|
s_8021x = nm_connection_get_setting_802_1x(connection);
|
||||||
if (!nm_supplicant_config_add_setting_8021x(config, s_8021x, con_uuid, mtu, TRUE, error)) {
|
if (!nm_supplicant_config_add_setting_8021x(config,
|
||||||
|
s_8021x,
|
||||||
|
con_uuid,
|
||||||
|
mtu,
|
||||||
|
TRUE,
|
||||||
|
nm_device_get_private_files(NM_DEVICE(self)),
|
||||||
|
error)) {
|
||||||
g_prefix_error(error, "802-1x-setting: ");
|
g_prefix_error(error, "802-1x-setting: ");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -683,14 +690,6 @@ get_generic_capabilities(NMDevice *dev)
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
|
||||||
{
|
|
||||||
if (!nm_device_parent_get_device(device))
|
|
||||||
return FALSE;
|
|
||||||
return NM_DEVICE_CLASS(nm_device_macsec_parent_class)->is_available(device, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
create_and_realize(NMDevice *device,
|
create_and_realize(NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
@ -903,7 +902,6 @@ nm_device_macsec_class_init(NMDeviceMacsecClass *klass)
|
||||||
device_class->deactivate = deactivate;
|
device_class->deactivate = deactivate;
|
||||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
device_class->link_changed = link_changed;
|
device_class->link_changed = link_changed;
|
||||||
device_class->is_available = is_available;
|
|
||||||
device_class->parent_changed_notify = parent_changed_notify;
|
device_class->parent_changed_notify = parent_changed_notify;
|
||||||
device_class->state_changed = device_state_changed;
|
device_class->state_changed = device_state_changed;
|
||||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
|
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
|
||||||
|
|
|
||||||
|
|
@ -270,16 +270,6 @@ get_generic_capabilities(NMDevice *device)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
|
||||||
{
|
|
||||||
if (!nm_device_parent_get_device(device))
|
|
||||||
return FALSE;
|
|
||||||
return NM_DEVICE_CLASS(nm_device_macvlan_parent_class)->is_available(device, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_connection_compatible(NMDevice *device,
|
check_connection_compatible(NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
@ -508,7 +498,6 @@ nm_device_macvlan_class_init(NMDeviceMacvlanClass *klass)
|
||||||
device_class->create_and_realize = create_and_realize;
|
device_class->create_and_realize = create_and_realize;
|
||||||
device_class->get_generic_capabilities = get_generic_capabilities;
|
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
|
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
|
||||||
device_class->is_available = is_available;
|
|
||||||
device_class->link_changed = link_changed;
|
device_class->link_changed = link_changed;
|
||||||
device_class->parent_changed_notify = parent_changed_notify;
|
device_class->parent_changed_notify = parent_changed_notify;
|
||||||
device_class->update_connection = update_connection;
|
device_class->update_connection = update_connection;
|
||||||
|
|
|
||||||
|
|
@ -179,4 +179,6 @@ void nm_device_auth_request(NMDevice *self,
|
||||||
|
|
||||||
void nm_device_link_properties_set(NMDevice *self, gboolean reapply);
|
void nm_device_link_properties_set(NMDevice *self, gboolean reapply);
|
||||||
|
|
||||||
|
GHashTable *nm_device_get_private_files(NMDevice *self);
|
||||||
|
|
||||||
#endif /* NM_DEVICE_PRIVATE_H */
|
#endif /* NM_DEVICE_PRIVATE_H */
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ resolve_addr_helper_cb(GObject *source, GAsyncResult *result, gpointer user_data
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
gs_free char *output = NULL;
|
gs_free char *output = NULL;
|
||||||
|
|
||||||
output = nm_utils_spawn_helper_finish(result, &error);
|
output = nm_utils_spawn_helper_finish_string(result, &error);
|
||||||
if (nm_utils_error_is_cancelled(error))
|
if (nm_utils_error_is_cancelled(error))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -274,6 +274,7 @@ resolve_addr_spawn_helper(ResolveAddrInfo *info, ResolveAddrService services)
|
||||||
nm_inet_ntop(info->addr_family, &info->address, addr_str);
|
nm_inet_ntop(info->addr_family, &info->address, addr_str);
|
||||||
_LOG2D(info, "start lookup via nm-daemon-helper using services: %s", str);
|
_LOG2D(info, "start lookup via nm-daemon-helper using services: %s", str);
|
||||||
nm_utils_spawn_helper(NM_MAKE_STRV("resolve-address", addr_str, str),
|
nm_utils_spawn_helper(NM_MAKE_STRV("resolve-address", addr_str, str),
|
||||||
|
FALSE,
|
||||||
g_task_get_cancellable(info->task),
|
g_task_get_cancellable(info->task),
|
||||||
resolve_addr_helper_cb,
|
resolve_addr_helper_cb,
|
||||||
info);
|
info);
|
||||||
|
|
|
||||||
|
|
@ -292,16 +292,6 @@ get_generic_capabilities(NMDevice *device)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
|
||||||
{
|
|
||||||
if (!nm_device_parent_get_device(device))
|
|
||||||
return FALSE;
|
|
||||||
return NM_DEVICE_CLASS(nm_device_vlan_parent_class)->is_available(device, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_connection_compatible(NMDevice *device,
|
check_connection_compatible(NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
@ -561,7 +551,6 @@ nm_device_vlan_class_init(NMDeviceVlanClass *klass)
|
||||||
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
|
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
|
||||||
device_class->act_stage1_prepare = act_stage1_prepare;
|
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
|
device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent;
|
||||||
device_class->is_available = is_available;
|
|
||||||
device_class->parent_changed_notify = parent_changed_notify;
|
device_class->parent_changed_notify = parent_changed_notify;
|
||||||
|
|
||||||
device_class->check_connection_compatible = check_connection_compatible;
|
device_class->check_connection_compatible = check_connection_compatible;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "nm-active-connection.h"
|
#include "nm-active-connection.h"
|
||||||
#include "nm-act-request.h"
|
#include "nm-act-request.h"
|
||||||
#include "dns/nm-dns-manager.h"
|
#include "dns/nm-dns-manager.h"
|
||||||
|
#include "nm-firewall-utils.h"
|
||||||
|
|
||||||
#define _NMLOG_DEVICE_TYPE NMDeviceWireGuard
|
#define _NMLOG_DEVICE_TYPE NMDeviceWireGuard
|
||||||
#include "nm-device-logging.h"
|
#include "nm-device-logging.h"
|
||||||
|
|
@ -1207,6 +1208,40 @@ skip:
|
||||||
*out_allowed_ips_data = g_steal_pointer(&allowed_ips);
|
*out_allowed_ips_data = g_steal_pointer(&allowed_ips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_configure_firewall(NMDeviceWireGuard *self, NMConnection *connection, int addr_family, gboolean up)
|
||||||
|
{
|
||||||
|
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||||
|
const char *ip_iface;
|
||||||
|
NMSettingIPConfig *ip_config;
|
||||||
|
|
||||||
|
ip_iface = nm_device_get_ip_iface(NM_DEVICE(self));
|
||||||
|
|
||||||
|
nm_assert(ip_iface);
|
||||||
|
|
||||||
|
switch (addr_family) {
|
||||||
|
case AF_INET:
|
||||||
|
if (!priv->auto_default_route_enabled_4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ip_config = nm_connection_get_setting_ip4_config(connection);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
if (!priv->auto_default_route_enabled_6)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ip_config = nm_connection_get_setting_ip6_config(connection);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nm_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_assert(ip_config);
|
||||||
|
nm_assert(priv->auto_default_route_fwmark);
|
||||||
|
|
||||||
|
nm_firewall_config_set_wg_rule(ip_iface, ip_config, priv->auto_default_route_fwmark, up);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1300,6 +1335,18 @@ create_and_realize(NMDevice *device,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
deactivate(NMDevice *device)
|
||||||
|
{
|
||||||
|
NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(device);
|
||||||
|
NMConnection *connection = nm_device_get_applied_connection(NM_DEVICE(self));
|
||||||
|
|
||||||
|
if (connection) {
|
||||||
|
_configure_firewall(self, connection, AF_INET, FALSE);
|
||||||
|
_configure_firewall(self, connection, AF_INET6, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1768,6 +1815,10 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||||
|
|
||||||
l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
|
l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
|
||||||
|
_configure_firewall(NM_DEVICE_WIREGUARD(device),
|
||||||
|
nm_device_get_applied_connection(device),
|
||||||
|
addr_family,
|
||||||
|
TRUE);
|
||||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd);
|
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1866,6 +1917,10 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
|
||||||
|
|
||||||
if (state >= NM_DEVICE_STATE_CONFIG) {
|
if (state >= NM_DEVICE_STATE_CONFIG) {
|
||||||
priv->auto_default_route_refresh = TRUE;
|
priv->auto_default_route_refresh = TRUE;
|
||||||
|
|
||||||
|
_configure_firewall(self, con_old, AF_INET, FALSE);
|
||||||
|
_configure_firewall(self, con_old, AF_INET6, FALSE);
|
||||||
|
|
||||||
link_config(NM_DEVICE_WIREGUARD(device), "reapply", LINK_CONFIG_MODE_REAPPLY, NULL);
|
link_config(NM_DEVICE_WIREGUARD(device), "reapply", LINK_CONFIG_MODE_REAPPLY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2018,6 +2073,7 @@ nm_device_wireguard_class_init(NMDeviceWireGuardClass *klass)
|
||||||
|
|
||||||
device_class->state_changed = device_state_changed;
|
device_class->state_changed = device_state_changed;
|
||||||
device_class->create_and_realize = create_and_realize;
|
device_class->create_and_realize = create_and_realize;
|
||||||
|
device_class->deactivate = deactivate;
|
||||||
device_class->act_stage2_config = act_stage2_config;
|
device_class->act_stage2_config = act_stage2_config;
|
||||||
device_class->act_stage2_config_also_for_external_or_assume = TRUE;
|
device_class->act_stage2_config_also_for_external_or_assume = TRUE;
|
||||||
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
||||||
|
|
|
||||||
|
|
@ -335,6 +335,12 @@ typedef struct {
|
||||||
int addr_family;
|
int addr_family;
|
||||||
} HostnameResolver;
|
} HostnameResolver;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PRIVATE_FILES_STATE_UNKNOWN = 0,
|
||||||
|
PRIVATE_FILES_STATE_READING,
|
||||||
|
PRIVATE_FILES_STATE_DONE,
|
||||||
|
} PrivateFilesState;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -603,6 +609,7 @@ typedef struct _NMDevicePrivate {
|
||||||
|
|
||||||
bool is_attached : 1;
|
bool is_attached : 1;
|
||||||
|
|
||||||
|
bool device_link_carrier_changed_down : 1;
|
||||||
bool device_link_changed_down : 1;
|
bool device_link_changed_down : 1;
|
||||||
|
|
||||||
bool concheck_rp_filter_checked : 1;
|
bool concheck_rp_filter_checked : 1;
|
||||||
|
|
@ -768,6 +775,13 @@ typedef struct _NMDevicePrivate {
|
||||||
guint64 rx_bytes;
|
guint64 rx_bytes;
|
||||||
} stats;
|
} stats;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GHashTable *table;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
char *user;
|
||||||
|
PrivateFilesState state;
|
||||||
|
} private_files;
|
||||||
|
|
||||||
bool mtu_force_set_done : 1;
|
bool mtu_force_set_done : 1;
|
||||||
|
|
||||||
bool needs_ip6_subnet : 1;
|
bool needs_ip6_subnet : 1;
|
||||||
|
|
@ -2759,22 +2773,23 @@ _ethtool_fec_set(NMDevice *self,
|
||||||
|
|
||||||
g_hash_table_iter_init(&iter, hash);
|
g_hash_table_iter_init(&iter, hash);
|
||||||
while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) {
|
while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) {
|
||||||
NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name);
|
if (nm_ethtool_id_is_fec(nm_ethtool_id_get_by_name(name))) {
|
||||||
|
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
|
||||||
if (!nm_ethtool_id_is_fec(ethtool_id))
|
fec_mode = g_variant_get_uint32(variant);
|
||||||
continue;
|
break;
|
||||||
|
}
|
||||||
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
|
|
||||||
fec_mode = g_variant_get_uint32(variant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_platform_ethtool_get_fec_mode(platform, ethtool_state->ifindex, &old_fec_mode);
|
|
||||||
|
|
||||||
/* The NM_SETTING_ETHTOOL_FEC_MODE_NONE is query only value, hence do nothing. */
|
/* The NM_SETTING_ETHTOOL_FEC_MODE_NONE is query only value, hence do nothing. */
|
||||||
if (!fec_mode || fec_mode == NM_SETTING_ETHTOOL_FEC_MODE_NONE) {
|
if (!fec_mode || fec_mode == NM_SETTING_ETHTOOL_FEC_MODE_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nm_platform_ethtool_get_fec_mode(platform, ethtool_state->ifindex, &old_fec_mode)) {
|
||||||
|
_LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d: cannot get current value", fec_mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!nm_platform_ethtool_set_fec_mode(platform, ethtool_state->ifindex, fec_mode))
|
if (!nm_platform_ethtool_set_fec_mode(platform, ethtool_state->ifindex, fec_mode))
|
||||||
_LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d", fec_mode);
|
_LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d", fec_mode);
|
||||||
else {
|
else {
|
||||||
|
|
@ -7123,6 +7138,9 @@ nm_device_controller_release_port(NMDevice *self,
|
||||||
NM_UNMANAGED_IS_PORT,
|
NM_UNMANAGED_IS_PORT,
|
||||||
NM_UNMAN_FLAG_OP_FORGET,
|
NM_UNMAN_FLAG_OP_FORGET,
|
||||||
NM_DEVICE_STATE_REASON_REMOVED);
|
NM_DEVICE_STATE_REASON_REMOVED);
|
||||||
|
|
||||||
|
/* Once the port is detached, unmanaged-external-down might change */
|
||||||
|
_dev_unmanaged_check_external_down(self, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -7558,10 +7576,12 @@ device_link_changed(gpointer user_data)
|
||||||
gboolean carrier_was_up;
|
gboolean carrier_was_up;
|
||||||
gboolean update_unmanaged_specs = FALSE;
|
gboolean update_unmanaged_specs = FALSE;
|
||||||
gboolean got_hw_addr = FALSE, had_hw_addr;
|
gboolean got_hw_addr = FALSE, had_hw_addr;
|
||||||
|
gboolean carrier_seen_down = priv->device_link_carrier_changed_down;
|
||||||
gboolean seen_down = priv->device_link_changed_down;
|
gboolean seen_down = priv->device_link_changed_down;
|
||||||
|
|
||||||
priv->device_link_changed_id = 0;
|
priv->device_link_changed_id = 0;
|
||||||
priv->device_link_changed_down = FALSE;
|
priv->device_link_changed_down = FALSE;
|
||||||
|
priv->device_link_carrier_changed_down = FALSE;
|
||||||
|
|
||||||
ifindex = nm_device_get_ifindex(self);
|
ifindex = nm_device_get_ifindex(self);
|
||||||
if (ifindex <= 0)
|
if (ifindex <= 0)
|
||||||
|
|
@ -7712,7 +7732,8 @@ device_link_changed(gpointer user_data)
|
||||||
if (priv->state >= NM_DEVICE_STATE_IP_CONFIG && priv->state <= NM_DEVICE_STATE_ACTIVATED
|
if (priv->state >= NM_DEVICE_STATE_IP_CONFIG && priv->state <= NM_DEVICE_STATE_ACTIVATED
|
||||||
&& !nm_device_managed_type_is_external(self))
|
&& !nm_device_managed_type_is_external(self))
|
||||||
nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE);
|
nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE);
|
||||||
|
}
|
||||||
|
if (priv->carrier && (!carrier_was_up || carrier_seen_down)) {
|
||||||
/* If the device is active without a carrier (probably because it is
|
/* If the device is active without a carrier (probably because it is
|
||||||
* tagged for carrier ignore) ensure that when the carrier appears we
|
* tagged for carrier ignore) ensure that when the carrier appears we
|
||||||
* renew DHCP leases and such.
|
* renew DHCP leases and such.
|
||||||
|
|
@ -7803,6 +7824,8 @@ link_changed_cb(NMPlatform *platform,
|
||||||
priv = NM_DEVICE_GET_PRIVATE(self);
|
priv = NM_DEVICE_GET_PRIVATE(self);
|
||||||
|
|
||||||
if (ifindex == nm_device_get_ifindex(self)) {
|
if (ifindex == nm_device_get_ifindex(self)) {
|
||||||
|
if (!(pllink->n_ifi_flags & IFF_LOWER_UP))
|
||||||
|
priv->device_link_carrier_changed_down = TRUE;
|
||||||
if (!(pllink->n_ifi_flags & IFF_UP))
|
if (!(pllink->n_ifi_flags & IFF_UP))
|
||||||
priv->device_link_changed_down = TRUE;
|
priv->device_link_changed_down = TRUE;
|
||||||
if (!priv->device_link_changed_id) {
|
if (!priv->device_link_changed_id) {
|
||||||
|
|
@ -8814,6 +8837,9 @@ nm_device_controller_add_port(NMDevice *self, NMDevice *port, gboolean configure
|
||||||
} else
|
} else
|
||||||
g_return_val_if_fail(port_priv->controller == self, FALSE);
|
g_return_val_if_fail(port_priv->controller == self, FALSE);
|
||||||
|
|
||||||
|
/* Once the port is attached, unmanaged-external-down might change */
|
||||||
|
_dev_unmanaged_check_external_down(self, TRUE, FALSE);
|
||||||
|
|
||||||
nm_device_queue_recheck_assume(self);
|
nm_device_queue_recheck_assume(self);
|
||||||
nm_device_queue_recheck_assume(port);
|
nm_device_queue_recheck_assume(port);
|
||||||
|
|
||||||
|
|
@ -10322,6 +10348,43 @@ sriov_params_cb(GError *error, gpointer user_data)
|
||||||
nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
|
nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
sriov_gen_platform_vfs(NMDevice *self,
|
||||||
|
NMSettingSriov *s_sriov,
|
||||||
|
NMPlatformVF ***plat_vfs_out,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
nm_auto_freev NMPlatformVF **plat_vfs = NULL;
|
||||||
|
guint num;
|
||||||
|
|
||||||
|
nm_assert(s_sriov);
|
||||||
|
nm_assert(plat_vfs_out && !*plat_vfs_out);
|
||||||
|
|
||||||
|
num = nm_setting_sriov_get_num_vfs(s_sriov);
|
||||||
|
plat_vfs = g_new0(NMPlatformVF *, num + 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
NMSriovVF *vf = nm_setting_sriov_get_vf(s_sriov, i);
|
||||||
|
gs_free_error GError *local = NULL;
|
||||||
|
|
||||||
|
plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &local);
|
||||||
|
|
||||||
|
if (!plat_vfs[i]) {
|
||||||
|
g_set_error(error,
|
||||||
|
local->domain,
|
||||||
|
local->code,
|
||||||
|
"VF '%s' is invalid: %s",
|
||||||
|
nm_utils_sriov_vf_to_str(vf, FALSE, NULL),
|
||||||
|
local->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*plat_vfs_out = g_steal_pointer(&plat_vfs);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* activate_stage1_device_prepare
|
* activate_stage1_device_prepare
|
||||||
*
|
*
|
||||||
|
|
@ -10368,10 +10431,7 @@ activate_stage1_device_prepare(NMDevice *self)
|
||||||
if (s_sriov && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) {
|
if (s_sriov && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) {
|
||||||
nm_auto_freev NMPlatformVF **plat_vfs = NULL;
|
nm_auto_freev NMPlatformVF **plat_vfs = NULL;
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
NMSriovVF *vf;
|
|
||||||
NMTernary autoprobe;
|
NMTernary autoprobe;
|
||||||
guint num;
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov);
|
autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov);
|
||||||
if (autoprobe == NM_TERNARY_DEFAULT) {
|
if (autoprobe == NM_TERNARY_DEFAULT) {
|
||||||
|
|
@ -10384,21 +10444,12 @@ activate_stage1_device_prepare(NMDevice *self)
|
||||||
NM_OPTION_BOOL_TRUE);
|
NM_OPTION_BOOL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
num = nm_setting_sriov_get_num_vfs(s_sriov);
|
if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &error)) {
|
||||||
plat_vfs = g_new0(NMPlatformVF *, num + 1);
|
_LOGE(LOGD_DEVICE, "cannot parse the VF list: %s", error->message);
|
||||||
for (i = 0; i < num; i++) {
|
nm_device_state_changed(self,
|
||||||
vf = nm_setting_sriov_get_vf(s_sriov, i);
|
NM_DEVICE_STATE_FAILED,
|
||||||
plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &error);
|
NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED);
|
||||||
if (!plat_vfs[i]) {
|
return;
|
||||||
_LOGE(LOGD_DEVICE,
|
|
||||||
"failed to apply SR-IOV VF '%s': %s",
|
|
||||||
nm_utils_sriov_vf_to_str(vf, FALSE, NULL),
|
|
||||||
error->message);
|
|
||||||
nm_device_state_changed(self,
|
|
||||||
NM_DEVICE_STATE_FAILED,
|
|
||||||
NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When changing the number of VFs the kernel can block
|
/* When changing the number of VFs the kernel can block
|
||||||
|
|
@ -10705,6 +10756,49 @@ tc_commit(NMDevice *self)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_private_files_cb(GObject *source_object, GAsyncResult *result, gpointer data)
|
||||||
|
{
|
||||||
|
gs_unref_hashtable GHashTable *table = NULL;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
NMDevice *self;
|
||||||
|
NMDevicePrivate *priv;
|
||||||
|
|
||||||
|
table = nm_utils_read_private_files_finish(result, &error);
|
||||||
|
if (nm_utils_error_is_cancelled(error))
|
||||||
|
return;
|
||||||
|
|
||||||
|
self = NM_DEVICE(data);
|
||||||
|
priv = NM_DEVICE_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
NMConnection *connection = nm_device_get_applied_connection(self);
|
||||||
|
|
||||||
|
_LOGW(LOGD_DEVICE,
|
||||||
|
"could not read files for private connection %s owned by user '%s': %s",
|
||||||
|
connection ? nm_connection_get_uuid(connection) : NULL,
|
||||||
|
priv->private_files.user,
|
||||||
|
error->message);
|
||||||
|
nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGD(LOGD_DEVICE, "private files successfully read");
|
||||||
|
|
||||||
|
priv->private_files.state = PRIVATE_FILES_STATE_DONE;
|
||||||
|
priv->private_files.table = g_steal_pointer(&table);
|
||||||
|
g_clear_pointer(&priv->private_files.user, g_free);
|
||||||
|
g_clear_object(&priv->private_files.cancellable);
|
||||||
|
|
||||||
|
nm_device_activate_schedule_stage2_device_config(self, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GHashTable *
|
||||||
|
nm_device_get_private_files(NMDevice *self)
|
||||||
|
{
|
||||||
|
return NM_DEVICE_GET_PRIVATE(self)->private_files.table;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* activate_stage2_device_config
|
* activate_stage2_device_config
|
||||||
*
|
*
|
||||||
|
|
@ -10717,6 +10811,7 @@ activate_stage2_device_config(NMDevice *self)
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||||
NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
|
NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
|
||||||
|
NMConnection *applied;
|
||||||
NMActStageReturn ret;
|
NMActStageReturn ret;
|
||||||
NMSettingWired *s_wired;
|
NMSettingWired *s_wired;
|
||||||
gboolean no_firmware = FALSE;
|
gboolean no_firmware = FALSE;
|
||||||
|
|
@ -10725,6 +10820,68 @@ activate_stage2_device_config(NMDevice *self)
|
||||||
|
|
||||||
nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
|
||||||
|
|
||||||
|
applied = nm_device_get_applied_connection(self);
|
||||||
|
|
||||||
|
/* If the connection is private (owned by a specific user), we need to
|
||||||
|
* verify that the user has permission to access any files specified in
|
||||||
|
* the connection, such as certificates and keys. We do that by calling
|
||||||
|
* nm_utils_read_private_files() and saving the file contents in a hash
|
||||||
|
* table that can be accessed later during the activation. It is important
|
||||||
|
* to never access the files again to avoid TOCTOU bugs.
|
||||||
|
*/
|
||||||
|
switch (priv->private_files.state) {
|
||||||
|
case PRIVATE_FILES_STATE_UNKNOWN:
|
||||||
|
{
|
||||||
|
gs_free const char **paths = NULL;
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
const char *user;
|
||||||
|
|
||||||
|
s_con = nm_connection_get_setting_connection(applied);
|
||||||
|
nm_assert(s_con);
|
||||||
|
user = _nm_setting_connection_get_first_permissions_user(s_con);
|
||||||
|
|
||||||
|
priv->private_files.user = g_strdup(user);
|
||||||
|
if (!priv->private_files.user) {
|
||||||
|
priv->private_files.state = PRIVATE_FILES_STATE_DONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
paths = nm_utils_get_connection_private_files_paths(applied);
|
||||||
|
if (!paths) {
|
||||||
|
priv->private_files.state = PRIVATE_FILES_STATE_DONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_nm_setting_connection_get_num_permissions_users(s_con) > 1) {
|
||||||
|
_LOGW(LOGD_DEVICE,
|
||||||
|
"private connections with multiple users are not allowed to reference "
|
||||||
|
"certificates and keys on the filesystem. Specify only one user in the "
|
||||||
|
"connection.permissions property.");
|
||||||
|
nm_device_state_changed(self,
|
||||||
|
NM_DEVICE_STATE_FAILED,
|
||||||
|
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->private_files.state = PRIVATE_FILES_STATE_READING;
|
||||||
|
priv->private_files.cancellable = g_cancellable_new();
|
||||||
|
|
||||||
|
_LOGD(LOGD_DEVICE, "reading private files");
|
||||||
|
nm_utils_read_private_files(paths,
|
||||||
|
priv->private_files.user,
|
||||||
|
priv->private_files.cancellable,
|
||||||
|
read_private_files_cb,
|
||||||
|
self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case PRIVATE_FILES_STATE_READING:
|
||||||
|
/* wait */
|
||||||
|
return;
|
||||||
|
case PRIVATE_FILES_STATE_DONE:
|
||||||
|
/* proceed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!nm_device_managed_type_is_external(self)) {
|
if (!nm_device_managed_type_is_external(self)) {
|
||||||
_ethtool_state_set(self);
|
_ethtool_state_set(self);
|
||||||
nm_device_link_properties_set(self, FALSE);
|
nm_device_link_properties_set(self, FALSE);
|
||||||
|
|
@ -10741,7 +10898,7 @@ activate_stage2_device_config(NMDevice *self)
|
||||||
priv->tc_committed = TRUE;
|
priv->tc_committed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_routing_rules_sync(nm_device_get_applied_connection(self),
|
nm_routing_rules_sync(applied,
|
||||||
NM_TERNARY_TRUE,
|
NM_TERNARY_TRUE,
|
||||||
klass->get_extra_rules,
|
klass->get_extra_rules,
|
||||||
self,
|
self,
|
||||||
|
|
@ -13417,6 +13574,8 @@ _dev_ipsharedx_cleanup(NMDevice *self, int addr_family)
|
||||||
nm_clear_l3cd(&priv->ipshared_data_4.v4.l3cd);
|
nm_clear_l3cd(&priv->ipshared_data_4.v4.l3cd);
|
||||||
|
|
||||||
_dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, NULL, FALSE);
|
_dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, NULL, FALSE);
|
||||||
|
} else {
|
||||||
|
_dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_PD_6, NULL, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dev_ipsharedx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
|
_dev_ipsharedx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
|
||||||
|
|
@ -13988,6 +14147,20 @@ can_reapply_change(NMDevice *self,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nm_streq(setting_name, NM_SETTING_BRIDGE_PORT_SETTING_NAME)) {
|
||||||
|
return nm_device_hash_check_invalid_keys(diffs,
|
||||||
|
NM_SETTING_BRIDGE_PORT_SETTING_NAME,
|
||||||
|
error,
|
||||||
|
NM_SETTING_BRIDGE_PORT_VLANS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nm_streq(setting_name, NM_SETTING_SRIOV_SETTING_NAME)) {
|
||||||
|
return nm_device_hash_check_invalid_keys(diffs,
|
||||||
|
NM_SETTING_SRIOV_SETTING_NAME,
|
||||||
|
error,
|
||||||
|
NM_SETTING_SRIOV_VFS);
|
||||||
|
}
|
||||||
|
|
||||||
out_fail:
|
out_fail:
|
||||||
g_set_error(error,
|
g_set_error(error,
|
||||||
NM_DEVICE_ERROR,
|
NM_DEVICE_ERROR,
|
||||||
|
|
@ -14163,9 +14336,35 @@ check_and_reapply_connection(NMDevice *self,
|
||||||
|
|
||||||
nm_device_link_properties_set(self, TRUE);
|
nm_device_link_properties_set(self, TRUE);
|
||||||
|
|
||||||
if (priv->state >= NM_DEVICE_STATE_CONFIG)
|
if (priv->state >= NM_DEVICE_STATE_CONFIG) {
|
||||||
|
GHashTable *sriov_diff;
|
||||||
|
|
||||||
lldp_setup(self, NM_TERNARY_DEFAULT);
|
lldp_setup(self, NM_TERNARY_DEFAULT);
|
||||||
|
|
||||||
|
sriov_diff = nm_g_hash_table_lookup(diffs, NM_SETTING_SRIOV_SETTING_NAME);
|
||||||
|
|
||||||
|
if (sriov_diff && nm_g_hash_table_lookup(sriov_diff, NM_SETTING_SRIOV_VFS)) {
|
||||||
|
nm_auto_freev NMPlatformVF **plat_vfs = NULL;
|
||||||
|
NMSettingSriov *s_sriov;
|
||||||
|
|
||||||
|
s_sriov = (NMSettingSriov *) nm_connection_get_setting(applied, NM_TYPE_SETTING_SRIOV);
|
||||||
|
|
||||||
|
if (s_sriov) {
|
||||||
|
gs_free_error GError *local = NULL;
|
||||||
|
|
||||||
|
if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &local)
|
||||||
|
|| !nm_platform_link_set_sriov_vfs(nm_device_get_platform(self),
|
||||||
|
priv->ifindex,
|
||||||
|
(const NMPlatformVF *const *) plat_vfs)) {
|
||||||
|
_LOGE(LOGD_DEVICE,
|
||||||
|
"failed to reapply SRIOV VFs%s%s",
|
||||||
|
local ? ": " : "",
|
||||||
|
local ? local->message : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) {
|
if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) {
|
||||||
/* Allow reapply of MTU */
|
/* Allow reapply of MTU */
|
||||||
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
|
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
|
||||||
|
|
@ -14619,13 +14818,15 @@ impl_device_delete(NMDBusObject *obj,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
_device_activate(NMDevice *self, NMActRequest *req)
|
_device_activate(NMDevice *self, NMActRequest *req)
|
||||||
{
|
{
|
||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
|
|
||||||
g_return_if_fail(NM_IS_DEVICE(self));
|
/* Returns TRUE on success, FALSE if the activation request could not be started */
|
||||||
g_return_if_fail(NM_IS_ACT_REQUEST(req));
|
|
||||||
|
g_return_val_if_fail(NM_IS_DEVICE(self), FALSE);
|
||||||
|
g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE);
|
||||||
nm_assert(nm_device_is_real(self));
|
nm_assert(nm_device_is_real(self));
|
||||||
|
|
||||||
/* Ensure the activation request is still valid; the controller may have
|
/* Ensure the activation request is still valid; the controller may have
|
||||||
|
|
@ -14633,7 +14834,7 @@ _device_activate(NMDevice *self, NMActRequest *req)
|
||||||
*/
|
*/
|
||||||
if (nm_active_connection_get_state(NM_ACTIVE_CONNECTION(req))
|
if (nm_active_connection_get_state(NM_ACTIVE_CONNECTION(req))
|
||||||
>= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
|
>= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
if (!nm_device_get_managed(self, FALSE)) {
|
if (!nm_device_get_managed(self, FALSE)) {
|
||||||
/* It's unclear why the device would be unmanaged at this point.
|
/* It's unclear why the device would be unmanaged at this point.
|
||||||
|
|
@ -14644,7 +14845,7 @@ _device_activate(NMDevice *self, NMActRequest *req)
|
||||||
nm_active_connection_set_state_fail((NMActiveConnection *) req,
|
nm_active_connection_set_state_fail((NMActiveConnection *) req,
|
||||||
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,
|
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,
|
||||||
NULL);
|
NULL);
|
||||||
return;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection = nm_act_request_get_applied_connection(req);
|
connection = nm_act_request_get_applied_connection(req);
|
||||||
|
|
@ -14660,6 +14861,8 @@ _device_activate(NMDevice *self, NMActRequest *req)
|
||||||
act_request_set(self, req);
|
act_request_set(self, req);
|
||||||
|
|
||||||
nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
|
nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -14679,7 +14882,9 @@ _carrier_wait_check_queued_act_request(NMDevice *self)
|
||||||
|
|
||||||
_LOGD(LOGD_DEVICE, "Activate queued activation request as we now have carrier");
|
_LOGD(LOGD_DEVICE, "Activate queued activation request as we now have carrier");
|
||||||
queued_req = g_steal_pointer(&priv->queued_act_request);
|
queued_req = g_steal_pointer(&priv->queued_act_request);
|
||||||
_device_activate(self, queued_req);
|
if (!_device_activate(self, queued_req)) {
|
||||||
|
delete_on_deactivate_check_and_schedule(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -15085,8 +15290,8 @@ respawn_ping_cb(gpointer user_data)
|
||||||
nm_clear_g_source_inst(&ping_op->watch);
|
nm_clear_g_source_inst(&ping_op->watch);
|
||||||
|
|
||||||
if (!spawn_ping_for_operation(self, ping_op)) {
|
if (!spawn_ping_for_operation(self, ping_op)) {
|
||||||
cleanup_ping_operation(ping_op);
|
|
||||||
priv->ping_operations = g_list_remove(priv->ping_operations, ping_op);
|
priv->ping_operations = g_list_remove(priv->ping_operations, ping_op);
|
||||||
|
cleanup_ping_operation(ping_op);
|
||||||
|
|
||||||
if (g_list_length(priv->ping_operations) == 0) {
|
if (g_list_length(priv->ping_operations) == 0) {
|
||||||
ip_check_pre_up(self);
|
ip_check_pre_up(self);
|
||||||
|
|
@ -15129,7 +15334,6 @@ ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data)
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (ping_op->ping_addresses_require_all) {
|
if (ping_op->ping_addresses_require_all) {
|
||||||
cleanup_ping_operation(ping_op);
|
|
||||||
priv->ping_operations = g_list_remove(priv->ping_operations, ping_op);
|
priv->ping_operations = g_list_remove(priv->ping_operations, ping_op);
|
||||||
if (g_list_length(priv->ping_operations) == 0) {
|
if (g_list_length(priv->ping_operations) == 0) {
|
||||||
_LOGD(ping_op->log_domain,
|
_LOGD(ping_op->log_domain,
|
||||||
|
|
@ -15139,6 +15343,7 @@ ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data)
|
||||||
nm_clear_g_source_inst(&priv->ping_timeout);
|
nm_clear_g_source_inst(&priv->ping_timeout);
|
||||||
ip_check_pre_up(self);
|
ip_check_pre_up(self);
|
||||||
}
|
}
|
||||||
|
cleanup_ping_operation(ping_op);
|
||||||
} else {
|
} else {
|
||||||
nm_assert(priv->ping_operations);
|
nm_assert(priv->ping_operations);
|
||||||
|
|
||||||
|
|
@ -16907,6 +17112,12 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
|
||||||
if (klass->deactivate)
|
if (klass->deactivate)
|
||||||
klass->deactivate(self);
|
klass->deactivate(self);
|
||||||
|
|
||||||
|
/* Clean up private files */
|
||||||
|
nm_clear_g_cancellable(&priv->private_files.cancellable);
|
||||||
|
g_clear_pointer(&priv->private_files.table, g_hash_table_unref);
|
||||||
|
g_clear_pointer(&priv->private_files.user, g_free);
|
||||||
|
priv->private_files.state = PRIVATE_FILES_STATE_UNKNOWN;
|
||||||
|
|
||||||
ifindex = nm_device_get_ip_ifindex(self);
|
ifindex = nm_device_get_ip_ifindex(self);
|
||||||
|
|
||||||
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
||||||
|
|
@ -17442,7 +17653,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
|
||||||
gs_unref_object NMActRequest *queued_req = NULL;
|
gs_unref_object NMActRequest *queued_req = NULL;
|
||||||
|
|
||||||
queued_req = g_steal_pointer(&priv->queued_act_request);
|
queued_req = g_steal_pointer(&priv->queued_act_request);
|
||||||
_device_activate(self, queued_req);
|
if (!_device_activate(self, queued_req))
|
||||||
|
delete_on_deactivate_check_and_schedule(self);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NM_DEVICE_STATE_ACTIVATED:
|
case NM_DEVICE_STATE_ACTIVATED:
|
||||||
|
|
|
||||||
|
|
@ -135,13 +135,36 @@ nm_device_ovs_reapply_connection(NMDevice *self, NMConnection *con_old, NMConnec
|
||||||
nm_ovsdb_set_reapply(nm_ovsdb_get(),
|
nm_ovsdb_set_reapply(nm_ovsdb_get(),
|
||||||
device_type,
|
device_type,
|
||||||
nm_device_get_ip_iface(self),
|
nm_device_get_ip_iface(self),
|
||||||
nm_connection_get_uuid(con_new),
|
nm_simple_connection_new_clone(con_new),
|
||||||
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
|
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
|
||||||
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
|
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
|
||||||
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_OTHER_CONFIG),
|
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_OTHER_CONFIG),
|
||||||
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_OTHER_CONFIG));
|
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_OTHER_CONFIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
can_reapply_change(NMDevice *device,
|
||||||
|
const char *setting_name,
|
||||||
|
NMSetting *s_old,
|
||||||
|
NMSetting *s_new,
|
||||||
|
GHashTable *diffs,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_bridge_parent_class);
|
||||||
|
|
||||||
|
if (nm_streq(setting_name, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) {
|
||||||
|
return nm_device_hash_check_invalid_keys(diffs,
|
||||||
|
NM_SETTING_OVS_BRIDGE_SETTING_NAME,
|
||||||
|
error,
|
||||||
|
NM_SETTING_OVS_BRIDGE_FAIL_MODE,
|
||||||
|
NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE,
|
||||||
|
NM_SETTING_OVS_BRIDGE_RSTP_ENABLE,
|
||||||
|
NM_SETTING_OVS_BRIDGE_STP_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -180,6 +203,7 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass)
|
||||||
device_class->ready_for_ip_config = ready_for_ip_config;
|
device_class->ready_for_ip_config = ready_for_ip_config;
|
||||||
device_class->attach_port = attach_port;
|
device_class->attach_port = attach_port;
|
||||||
device_class->detach_port = detach_port;
|
device_class->detach_port = detach_port;
|
||||||
|
device_class->can_reapply_change = can_reapply_change;
|
||||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,18 @@ typedef struct {
|
||||||
NMOvsdb *ovsdb;
|
NMOvsdb *ovsdb;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* The source for the idle handler to set the TUN ifindex */
|
/* The signal id for the TUN link-changed event */
|
||||||
GSource *tun_set_ifindex_idle_source;
|
gulong tun_link_signal_id;
|
||||||
|
/* The idle handler source for the TUN link-changed event */
|
||||||
|
GSource *tun_link_idle_source;
|
||||||
|
/* The ifindex for the TUN link-changed event */
|
||||||
|
int tun_ifindex;
|
||||||
|
|
||||||
/* The cloned MAC to set */
|
/* The cloned MAC to set */
|
||||||
char *cloned_mac;
|
char *cloned_mac;
|
||||||
/* The id for the signal watching the TUN link to appear/change */
|
|
||||||
gulong tun_link_signal_id;
|
|
||||||
/* The TUN ifindex to set in the idle handler */
|
|
||||||
int tun_ifindex;
|
|
||||||
/* Whether we have determined the cloned MAC */
|
/* Whether we have determined the cloned MAC */
|
||||||
bool cloned_mac_evaluated : 1;
|
bool cloned_mac_evaluated : 1;
|
||||||
|
|
||||||
/* Whether we are waiting for the kernel link */
|
/* Whether we are waiting for the kernel link */
|
||||||
bool waiting : 1;
|
bool waiting : 1;
|
||||||
} wait_link;
|
} wait_link;
|
||||||
|
|
@ -261,39 +263,33 @@ ready_for_ip_config(NMDevice *device, gboolean is_manual)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_set_ip_ifindex_tun(gpointer user_data)
|
_netdev_tun_link_cb_in_idle(gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDevice *device = user_data;
|
NMDevice *device = user_data;
|
||||||
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
|
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
|
||||||
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
|
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
|
||||||
|
|
||||||
_LOGT(LOGD_CORE,
|
if (nm_device_get_ip_ifindex(device) <= 0) {
|
||||||
"ovs-wait-link: setting ip-ifindex %d from tun interface",
|
_LOGT(LOGD_CORE,
|
||||||
priv->wait_link.tun_ifindex);
|
"ovs-wait-link: setting ip-ifindex %d from tun link",
|
||||||
|
priv->wait_link.tun_ifindex);
|
||||||
|
nm_device_set_ip_ifindex(device, priv->wait_link.tun_ifindex);
|
||||||
|
}
|
||||||
|
|
||||||
nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
|
if (check_waiting_for_link(device, "tun-link-changed")) {
|
||||||
|
nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
|
||||||
nm_device_set_ip_ifindex(device, priv->wait_link.tun_ifindex);
|
|
||||||
|
|
||||||
if (check_waiting_for_link(device, "set-ip-ifindex-tun")) {
|
|
||||||
/* If the link is not ready, it means the MAC is not set yet. We don't have
|
|
||||||
* a convenient way to monitor for ip-ifindex changes other than listening
|
|
||||||
* for platform events again.*/
|
|
||||||
nm_assert(!priv->wait_link.tun_link_signal_id);
|
|
||||||
priv->wait_link.tun_link_signal_id = g_signal_connect(nm_device_get_platform(device),
|
|
||||||
NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
|
||||||
G_CALLBACK(_netdev_tun_link_cb),
|
|
||||||
self);
|
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LOGT(LOGD_CORE, "tun link is ready");
|
_LOGT(LOGD_CORE, "ovs-wait-link: tun link is ready");
|
||||||
|
|
||||||
nm_device_link_properties_set(device, FALSE);
|
nm_device_link_properties_set(device, FALSE);
|
||||||
|
nm_device_bring_up(device);
|
||||||
|
|
||||||
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
|
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||||
nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
|
nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||||
nm_device_activate_schedule_stage3_ip_config(device, FALSE);
|
nm_device_activate_schedule_stage3_ip_config(device, FALSE);
|
||||||
|
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
||||||
|
nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
@ -309,40 +305,28 @@ _netdev_tun_link_cb(NMPlatform *platform,
|
||||||
const NMPlatformSignalChangeType change_type = change_type_i;
|
const NMPlatformSignalChangeType change_type = change_type_i;
|
||||||
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
|
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
|
||||||
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
|
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
|
||||||
int ip_ifindex;
|
|
||||||
|
|
||||||
|
/* This is the handler for the link-changed platform events. It is triggered for all
|
||||||
|
* link changes. Keep only the ones matching our device. */
|
||||||
|
if (!NM_IN_SET(change_type, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_SIGNAL_CHANGED))
|
||||||
|
return;
|
||||||
if (pllink->type != NM_LINK_TYPE_TUN || !nm_streq0(pllink->name, nm_device_get_iface(device)))
|
if (pllink->type != NM_LINK_TYPE_TUN || !nm_streq0(pllink->name, nm_device_get_iface(device)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ip_ifindex = nm_device_get_ip_ifindex(device);
|
|
||||||
if (ip_ifindex > 0) {
|
|
||||||
/* When we have an ifindex, we are only waiting for the MAC to settle */
|
|
||||||
if (change_type != NM_PLATFORM_SIGNAL_CHANGED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!check_waiting_for_link(device, "tun-link-changed")) {
|
|
||||||
_LOGT(LOGD_CORE, "ovs-wait-link: tun link is ready, cloned MAC is set");
|
|
||||||
|
|
||||||
nm_clear_g_signal_handler(platform, &priv->wait_link.tun_link_signal_id);
|
|
||||||
nm_device_link_properties_set(device, FALSE);
|
|
||||||
|
|
||||||
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
|
|
||||||
nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
|
|
||||||
nm_device_activate_schedule_stage3_ip_config(device, FALSE);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No ip-ifindex on the device, set it when the link appears */
|
|
||||||
if (change_type != NM_PLATFORM_SIGNAL_ADDED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_LOGT(LOGD_CORE,
|
_LOGT(LOGD_CORE,
|
||||||
"ovs-wait-link: found matching tun interface, schedule set-ip-ifindex(%d)",
|
"ovs-wait-link: got platform event \'%s\' for ifindex %d, scheduling idle handler",
|
||||||
|
change_type == NM_PLATFORM_SIGNAL_ADDED ? "added" : "changed",
|
||||||
ifindex);
|
ifindex);
|
||||||
nm_clear_g_signal_handler(platform, &priv->wait_link.tun_link_signal_id);
|
|
||||||
priv->wait_link.tun_ifindex = ifindex;
|
/* The handler is invoked by the platform synchronously in the netlink receive loop.
|
||||||
priv->wait_link.tun_set_ifindex_idle_source = nm_g_idle_add_source(_set_ip_ifindex_tun, device);
|
* We can't perform other platform operations (like bringing the interface up) since
|
||||||
|
* the code there is not re-entrant. Schedule an idle handler. */
|
||||||
|
nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
|
||||||
|
priv->wait_link.tun_link_idle_source =
|
||||||
|
nm_g_idle_add_source(_netdev_tun_link_cb_in_idle, device);
|
||||||
|
priv->wait_link.tun_ifindex = ifindex;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -464,7 +448,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||||
nm_device_activate_schedule_stage3_ip_config(device, TRUE);
|
nm_device_activate_schedule_stage3_ip_config(device, TRUE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
|
nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
|
||||||
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
||||||
|
|
||||||
nm_device_link_properties_set(device, FALSE);
|
nm_device_link_properties_set(device, FALSE);
|
||||||
|
|
@ -488,7 +472,7 @@ deactivate(NMDevice *device)
|
||||||
priv->wait_link.cloned_mac_evaluated = FALSE;
|
priv->wait_link.cloned_mac_evaluated = FALSE;
|
||||||
nm_clear_g_free(&priv->wait_link.cloned_mac);
|
nm_clear_g_free(&priv->wait_link.cloned_mac);
|
||||||
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
||||||
nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
|
nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -581,7 +565,7 @@ deactivate_async(NMDevice *device,
|
||||||
_LOGT(LOGD_CORE, "deactivate: start async");
|
_LOGT(LOGD_CORE, "deactivate: start async");
|
||||||
|
|
||||||
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
|
||||||
nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
|
nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
|
||||||
priv->wait_link.tun_ifindex = -1;
|
priv->wait_link.tun_ifindex = -1;
|
||||||
priv->wait_link.cloned_mac_evaluated = FALSE;
|
priv->wait_link.cloned_mac_evaluated = FALSE;
|
||||||
nm_clear_g_free(&priv->wait_link.cloned_mac);
|
nm_clear_g_free(&priv->wait_link.cloned_mac);
|
||||||
|
|
@ -682,7 +666,7 @@ dispose(GObject *object)
|
||||||
|
|
||||||
nm_assert(!priv->wait_link.waiting);
|
nm_assert(!priv->wait_link.waiting);
|
||||||
nm_assert(priv->wait_link.tun_link_signal_id == 0);
|
nm_assert(priv->wait_link.tun_link_signal_id == 0);
|
||||||
nm_assert(!priv->wait_link.tun_set_ifindex_idle_source);
|
nm_assert(!priv->wait_link.tun_link_idle_source);
|
||||||
|
|
||||||
if (priv->ovsdb) {
|
if (priv->ovsdb) {
|
||||||
g_signal_handlers_disconnect_by_func(priv->ovsdb, G_CALLBACK(ovsdb_ready), self);
|
g_signal_handlers_disconnect_by_func(priv->ovsdb, G_CALLBACK(ovsdb_ready), self);
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,32 @@ detach_port(NMDevice *device,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
can_reapply_change(NMDevice *device,
|
||||||
|
const char *setting_name,
|
||||||
|
NMSetting *s_old,
|
||||||
|
NMSetting *s_new,
|
||||||
|
GHashTable *diffs,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_port_parent_class);
|
||||||
|
|
||||||
|
if (nm_streq(setting_name, NM_SETTING_OVS_PORT_SETTING_NAME)) {
|
||||||
|
return nm_device_hash_check_invalid_keys(diffs,
|
||||||
|
NM_SETTING_OVS_PORT_SETTING_NAME,
|
||||||
|
error,
|
||||||
|
NM_SETTING_OVS_PORT_TAG,
|
||||||
|
NM_SETTING_OVS_PORT_VLAN_MODE,
|
||||||
|
NM_SETTING_OVS_PORT_BOND_UPDELAY,
|
||||||
|
NM_SETTING_OVS_PORT_BOND_DOWNDELAY,
|
||||||
|
NM_SETTING_OVS_PORT_LACP,
|
||||||
|
NM_SETTING_OVS_PORT_BOND_MODE,
|
||||||
|
NM_SETTING_OVS_PORT_TRUNKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -293,6 +319,7 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass)
|
||||||
device_class->ready_for_ip_config = ready_for_ip_config;
|
device_class->ready_for_ip_config = ready_for_ip_config;
|
||||||
device_class->attach_port = attach_port;
|
device_class->attach_port = attach_port;
|
||||||
device_class->detach_port = detach_port;
|
device_class->detach_port = detach_port;
|
||||||
|
device_class->can_reapply_change = can_reapply_change;
|
||||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,13 +101,13 @@ typedef union {
|
||||||
guint32 mtu;
|
guint32 mtu;
|
||||||
} set_interface_mtu;
|
} set_interface_mtu;
|
||||||
struct {
|
struct {
|
||||||
NMDeviceType device_type;
|
NMDeviceType device_type;
|
||||||
char *ifname;
|
char *ifname;
|
||||||
char *connection_uuid;
|
NMConnection *connection;
|
||||||
GHashTable *external_ids_old;
|
GHashTable *external_ids_old;
|
||||||
GHashTable *external_ids_new;
|
GHashTable *external_ids_new;
|
||||||
GHashTable *other_config_old;
|
GHashTable *other_config_old;
|
||||||
GHashTable *other_config_new;
|
GHashTable *other_config_new;
|
||||||
} set_reapply;
|
} set_reapply;
|
||||||
} OvsdbMethodPayload;
|
} OvsdbMethodPayload;
|
||||||
|
|
||||||
|
|
@ -242,24 +242,21 @@ static void cleanup_check_ready(NMOvsdb *self);
|
||||||
}, \
|
}, \
|
||||||
}))
|
}))
|
||||||
|
|
||||||
#define OVSDB_METHOD_PAYLOAD_SET_REAPPLY(xdevice_type, \
|
#define OVSDB_METHOD_PAYLOAD_SET_REAPPLY(xdevice_type, \
|
||||||
xifname, \
|
xifname, \
|
||||||
xconnection_uuid, \
|
xconnection, \
|
||||||
xexternal_ids_old, \
|
xexternal_ids_old, \
|
||||||
xexternal_ids_new, \
|
xexternal_ids_new, \
|
||||||
xother_config_old, \
|
xother_config_old, \
|
||||||
xother_config_new) \
|
xother_config_new) \
|
||||||
(&((const OvsdbMethodPayload) { \
|
(&((const OvsdbMethodPayload) { \
|
||||||
.set_reapply = \
|
.set_reapply = {.device_type = xdevice_type, \
|
||||||
{ \
|
.ifname = (char *) NM_CONSTCAST(char, (xifname)), \
|
||||||
.device_type = xdevice_type, \
|
.connection = (xconnection), \
|
||||||
.ifname = (char *) NM_CONSTCAST(char, (xifname)), \
|
.external_ids_old = (xexternal_ids_old), \
|
||||||
.connection_uuid = (char *) NM_CONSTCAST(char, (xconnection_uuid)), \
|
.external_ids_new = (xexternal_ids_new), \
|
||||||
.external_ids_old = (xexternal_ids_old), \
|
.other_config_old = (xother_config_old), \
|
||||||
.external_ids_new = (xexternal_ids_new), \
|
.other_config_new = (xother_config_new)}, \
|
||||||
.other_config_old = (xother_config_old), \
|
|
||||||
.other_config_new = (xother_config_new), \
|
|
||||||
}, \
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -316,7 +313,7 @@ _call_complete(OvsdbMethodCall *call, json_t *response, GError *error)
|
||||||
break;
|
break;
|
||||||
case OVSDB_SET_REAPPLY:
|
case OVSDB_SET_REAPPLY:
|
||||||
nm_clear_g_free(&call->payload.set_reapply.ifname);
|
nm_clear_g_free(&call->payload.set_reapply.ifname);
|
||||||
nm_clear_g_free(&call->payload.set_reapply.connection_uuid);
|
nm_clear_g_object(&call->payload.set_reapply.connection);
|
||||||
nm_clear_pointer(&call->payload.set_reapply.external_ids_old, g_hash_table_destroy);
|
nm_clear_pointer(&call->payload.set_reapply.external_ids_old, g_hash_table_destroy);
|
||||||
nm_clear_pointer(&call->payload.set_reapply.external_ids_new, g_hash_table_destroy);
|
nm_clear_pointer(&call->payload.set_reapply.external_ids_new, g_hash_table_destroy);
|
||||||
nm_clear_pointer(&call->payload.set_reapply.other_config_old, g_hash_table_destroy);
|
nm_clear_pointer(&call->payload.set_reapply.other_config_old, g_hash_table_destroy);
|
||||||
|
|
@ -476,9 +473,9 @@ ovsdb_call_method(NMOvsdb *self,
|
||||||
call->payload.set_interface_mtu.mtu);
|
call->payload.set_interface_mtu.mtu);
|
||||||
break;
|
break;
|
||||||
case OVSDB_SET_REAPPLY:
|
case OVSDB_SET_REAPPLY:
|
||||||
call->payload.set_reapply.device_type = payload->set_reapply.device_type;
|
call->payload.set_reapply.device_type = payload->set_reapply.device_type;
|
||||||
call->payload.set_reapply.ifname = g_strdup(payload->set_reapply.ifname);
|
call->payload.set_reapply.ifname = g_strdup(payload->set_reapply.ifname);
|
||||||
call->payload.set_reapply.connection_uuid = g_strdup(payload->set_reapply.connection_uuid);
|
call->payload.set_reapply.connection = payload->set_reapply.connection;
|
||||||
call->payload.set_reapply.external_ids_old =
|
call->payload.set_reapply.external_ids_old =
|
||||||
nm_g_hash_table_ref(payload->set_reapply.external_ids_old);
|
nm_g_hash_table_ref(payload->set_reapply.external_ids_old);
|
||||||
call->payload.set_reapply.external_ids_new =
|
call->payload.set_reapply.external_ids_new =
|
||||||
|
|
@ -488,8 +485,8 @@ ovsdb_call_method(NMOvsdb *self,
|
||||||
call->payload.set_reapply.other_config_new =
|
call->payload.set_reapply.other_config_new =
|
||||||
nm_g_hash_table_ref(payload->set_reapply.other_config_new);
|
nm_g_hash_table_ref(payload->set_reapply.other_config_new);
|
||||||
_LOGT_call(call,
|
_LOGT_call(call,
|
||||||
"new: set external-ids/other-config con-uuid=%s, interface=%s",
|
"new: reapply con-uuid=%s, interface=%s",
|
||||||
call->payload.set_reapply.connection_uuid,
|
nm_connection_get_uuid(payload->set_reapply.connection),
|
||||||
call->payload.set_reapply.ifname);
|
call->payload.set_reapply.ifname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -976,65 +973,79 @@ _insert_interface(json_t *params,
|
||||||
"rowInterface"));
|
"rowInterface"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* _insert_port:
|
|
||||||
*
|
|
||||||
* Returns an commands that adds new port from a given connection.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
_insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
|
ovsdb_row_set_string_or_null(json_t *row, const char *key, const char *str)
|
||||||
|
{
|
||||||
|
/* ovsdb represents a NULL string (no value) as an empty set */
|
||||||
|
if (str) {
|
||||||
|
json_object_set_new(row, key, json_string(str));
|
||||||
|
} else {
|
||||||
|
json_object_set_new(row, key, json_pack("[s, []]", "set"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_t *
|
||||||
|
create_port_row_object(NMConnection *connection)
|
||||||
{
|
{
|
||||||
NMSettingOvsPort *s_ovs_port;
|
NMSettingOvsPort *s_ovs_port;
|
||||||
const char *vlan_mode = NULL;
|
|
||||||
json_t *trunks = NULL;
|
|
||||||
guint tag = 0;
|
|
||||||
const char *lacp = NULL;
|
|
||||||
const char *bond_mode = NULL;
|
|
||||||
guint bond_updelay = 0;
|
|
||||||
guint bond_downdelay = 0;
|
|
||||||
json_t *row;
|
json_t *row;
|
||||||
|
const char *s;
|
||||||
|
guint u;
|
||||||
|
|
||||||
s_ovs_port = nm_connection_get_setting_ovs_port(port);
|
s_ovs_port = nm_connection_get_setting_ovs_port(connection);
|
||||||
|
nm_assert(s_ovs_port);
|
||||||
|
|
||||||
row = json_object();
|
row = json_object();
|
||||||
|
|
||||||
if (s_ovs_port) {
|
s = nm_setting_ovs_port_get_vlan_mode(s_ovs_port);
|
||||||
|
ovsdb_row_set_string_or_null(row, "vlan_mode", s);
|
||||||
|
|
||||||
|
u = nm_setting_ovs_port_get_tag(s_ovs_port);
|
||||||
|
json_object_set_new(row, "tag", u != 0 ? json_integer(u) : json_pack("[s, []]", "set"));
|
||||||
|
|
||||||
|
u = nm_setting_ovs_port_get_bond_updelay(s_ovs_port);
|
||||||
|
json_object_set_new(row, "bond_updelay", json_integer(u));
|
||||||
|
|
||||||
|
u = nm_setting_ovs_port_get_bond_downdelay(s_ovs_port);
|
||||||
|
json_object_set_new(row, "bond_downdelay", json_integer(u));
|
||||||
|
|
||||||
|
s = nm_setting_ovs_port_get_lacp(s_ovs_port);
|
||||||
|
ovsdb_row_set_string_or_null(row, "lacp", s);
|
||||||
|
|
||||||
|
s = nm_setting_ovs_port_get_bond_mode(s_ovs_port);
|
||||||
|
ovsdb_row_set_string_or_null(row, "bond_mode", s);
|
||||||
|
|
||||||
|
{
|
||||||
const GPtrArray *ranges;
|
const GPtrArray *ranges;
|
||||||
guint i;
|
json_t *trunks = json_array();
|
||||||
guint64 start;
|
guint64 start;
|
||||||
guint64 end;
|
guint64 end;
|
||||||
|
guint i;
|
||||||
vlan_mode = nm_setting_ovs_port_get_vlan_mode(s_ovs_port);
|
|
||||||
tag = nm_setting_ovs_port_get_tag(s_ovs_port);
|
|
||||||
lacp = nm_setting_ovs_port_get_lacp(s_ovs_port);
|
|
||||||
bond_mode = nm_setting_ovs_port_get_bond_mode(s_ovs_port);
|
|
||||||
bond_updelay = nm_setting_ovs_port_get_bond_updelay(s_ovs_port);
|
|
||||||
bond_downdelay = nm_setting_ovs_port_get_bond_downdelay(s_ovs_port);
|
|
||||||
|
|
||||||
ranges = _nm_setting_ovs_port_get_trunks_arr(s_ovs_port);
|
ranges = _nm_setting_ovs_port_get_trunks_arr(s_ovs_port);
|
||||||
for (i = 0; i < ranges->len; i++) {
|
for (i = 0; i < ranges->len; i++) {
|
||||||
if (!trunks)
|
|
||||||
trunks = json_array();
|
|
||||||
nm_range_get_range(ranges->pdata[i], &start, &end);
|
nm_range_get_range(ranges->pdata[i], &start, &end);
|
||||||
for (; start <= end; start++)
|
for (; start <= end; start++)
|
||||||
json_array_append_new(trunks, json_integer(start));
|
json_array_append_new(trunks, json_integer(start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json_object_set_new(row, "trunks", json_pack("[s, o]", "set", trunks));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vlan_mode)
|
return row;
|
||||||
json_object_set_new(row, "vlan_mode", json_string(vlan_mode));
|
}
|
||||||
if (tag)
|
|
||||||
json_object_set_new(row, "tag", json_integer(tag));
|
/**
|
||||||
if (trunks)
|
* _insert_port:
|
||||||
json_object_set_new(row, "trunks", json_pack("[s, o]", "set", trunks));
|
*
|
||||||
if (lacp)
|
* Returns a command that adds new port from a given connection.
|
||||||
json_object_set_new(row, "lacp", json_string(lacp));
|
*/
|
||||||
if (bond_mode)
|
static void
|
||||||
json_object_set_new(row, "bond_mode", json_string(bond_mode));
|
_insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
|
||||||
if (bond_updelay)
|
{
|
||||||
json_object_set_new(row, "bond_updelay", json_integer(bond_updelay));
|
json_t *row;
|
||||||
if (bond_downdelay)
|
|
||||||
json_object_set_new(row, "bond_downdelay", json_integer(bond_downdelay));
|
row = create_port_row_object(port);
|
||||||
|
|
||||||
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(port)));
|
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(port)));
|
||||||
json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces));
|
json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces));
|
||||||
|
|
@ -1058,10 +1069,50 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
|
||||||
"rowPort"));
|
"rowPort"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static json_t *
|
||||||
|
create_bridge_row_object(NMConnection *connection, gboolean is_reapply)
|
||||||
|
{
|
||||||
|
NMSettingOvsBridge *s_ovs_bridge;
|
||||||
|
json_t *row;
|
||||||
|
gboolean b;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
s_ovs_bridge = nm_connection_get_setting_ovs_bridge(connection);
|
||||||
|
nm_assert(s_ovs_bridge);
|
||||||
|
|
||||||
|
row = json_object();
|
||||||
|
|
||||||
|
b = nm_setting_ovs_bridge_get_mcast_snooping_enable(s_ovs_bridge);
|
||||||
|
json_object_set_new(row, "mcast_snooping_enable", json_boolean(b));
|
||||||
|
|
||||||
|
b = nm_setting_ovs_bridge_get_rstp_enable(s_ovs_bridge);
|
||||||
|
json_object_set_new(row, "rstp_enable", json_boolean(b));
|
||||||
|
|
||||||
|
b = nm_setting_ovs_bridge_get_stp_enable(s_ovs_bridge);
|
||||||
|
json_object_set_new(row, "stp_enable", json_boolean(b));
|
||||||
|
|
||||||
|
s = nm_setting_ovs_bridge_get_fail_mode(s_ovs_bridge);
|
||||||
|
ovsdb_row_set_string_or_null(row, "fail_mode", s);
|
||||||
|
|
||||||
|
if (!is_reapply) {
|
||||||
|
/* The datapath type can't be reapplied because after changing it,
|
||||||
|
* ovs removes the existing ovs-interface and creates a tun one (or
|
||||||
|
* vice-versa). */
|
||||||
|
s = nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge);
|
||||||
|
if (s) {
|
||||||
|
/* Cannot use ovsdb_row_set_string_or_null() here as the column
|
||||||
|
* is a set and must not be empty. */
|
||||||
|
json_object_set_new(row, "datapath_type", json_string(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _insert_bridge:
|
* _insert_bridge:
|
||||||
*
|
*
|
||||||
* Returns an commands that adds new bridge from a given connection.
|
* Returns a command that adds new bridge from a given connection.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_insert_bridge(json_t *params,
|
_insert_bridge(json_t *params,
|
||||||
|
|
@ -1070,36 +1121,9 @@ _insert_bridge(json_t *params,
|
||||||
json_t *new_ports,
|
json_t *new_ports,
|
||||||
const char *cloned_mac)
|
const char *cloned_mac)
|
||||||
{
|
{
|
||||||
NMSettingOvsBridge *s_ovs_bridge;
|
json_t *row;
|
||||||
const char *fail_mode = NULL;
|
|
||||||
gboolean mcast_snooping_enable = FALSE;
|
|
||||||
gboolean rstp_enable = FALSE;
|
|
||||||
gboolean stp_enable = FALSE;
|
|
||||||
const char *datapath_type = NULL;
|
|
||||||
json_t *row;
|
|
||||||
|
|
||||||
s_ovs_bridge = nm_connection_get_setting_ovs_bridge(bridge);
|
row = create_bridge_row_object(bridge, FALSE);
|
||||||
|
|
||||||
row = json_object();
|
|
||||||
|
|
||||||
if (s_ovs_bridge) {
|
|
||||||
fail_mode = nm_setting_ovs_bridge_get_fail_mode(s_ovs_bridge);
|
|
||||||
mcast_snooping_enable = nm_setting_ovs_bridge_get_mcast_snooping_enable(s_ovs_bridge);
|
|
||||||
rstp_enable = nm_setting_ovs_bridge_get_rstp_enable(s_ovs_bridge);
|
|
||||||
stp_enable = nm_setting_ovs_bridge_get_stp_enable(s_ovs_bridge);
|
|
||||||
datapath_type = nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fail_mode)
|
|
||||||
json_object_set_new(row, "fail_mode", json_string(fail_mode));
|
|
||||||
if (mcast_snooping_enable)
|
|
||||||
json_object_set_new(row, "mcast_snooping_enable", json_boolean(mcast_snooping_enable));
|
|
||||||
if (rstp_enable)
|
|
||||||
json_object_set_new(row, "rstp_enable", json_boolean(rstp_enable));
|
|
||||||
if (stp_enable)
|
|
||||||
json_object_set_new(row, "stp_enable", json_boolean(stp_enable));
|
|
||||||
if (datapath_type)
|
|
||||||
json_object_set_new(row, "datapath_type", json_string(datapath_type));
|
|
||||||
|
|
||||||
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(bridge)));
|
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(bridge)));
|
||||||
json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports));
|
json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports));
|
||||||
|
|
@ -1350,88 +1374,115 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
|
||||||
nm_auto_decref_json json_t *bridges = NULL;
|
nm_auto_decref_json json_t *bridges = NULL;
|
||||||
nm_auto_decref_json json_t *new_bridges = NULL;
|
nm_auto_decref_json json_t *new_bridges = NULL;
|
||||||
gboolean bridges_changed;
|
gboolean bridges_changed;
|
||||||
gboolean ports_changed;
|
|
||||||
gboolean interfaces_changed;
|
|
||||||
int pi;
|
|
||||||
int ii;
|
|
||||||
|
|
||||||
bridges = json_array();
|
bridges = json_array();
|
||||||
new_bridges = json_array();
|
new_bridges = json_array();
|
||||||
bridges_changed = FALSE;
|
bridges_changed = FALSE;
|
||||||
|
|
||||||
|
/* Loop over all bridges */
|
||||||
g_hash_table_iter_init(&iter, priv->bridges);
|
g_hash_table_iter_init(&iter, priv->bridges);
|
||||||
while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) {
|
while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) {
|
||||||
nm_auto_decref_json json_t *ports = NULL;
|
nm_auto_decref_json json_t *ports = NULL;
|
||||||
nm_auto_decref_json json_t *new_ports = NULL;
|
nm_auto_decref_json json_t *new_ports = NULL;
|
||||||
|
guint num_nm_ports = 0;
|
||||||
|
gboolean ports_changed = FALSE;
|
||||||
|
int pi;
|
||||||
|
|
||||||
ports = json_array();
|
ports = json_array();
|
||||||
new_ports = json_array();
|
new_ports = json_array();
|
||||||
ports_changed = FALSE;
|
|
||||||
|
|
||||||
|
/* Add the bridge UUID to the list of known bridges for the "expect" condition */
|
||||||
json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
|
json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
|
||||||
|
|
||||||
|
if (!ovs_bridge->connection_uuid) {
|
||||||
|
/* Externally created, don't touch it */
|
||||||
|
json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over all bridge's ports */
|
||||||
for (pi = 0; pi < ovs_bridge->ports->len; pi++) {
|
for (pi = 0; pi < ovs_bridge->ports->len; pi++) {
|
||||||
nm_auto_decref_json json_t *interfaces = NULL;
|
nm_auto_decref_json json_t *interfaces = NULL;
|
||||||
nm_auto_decref_json json_t *new_interfaces = NULL;
|
nm_auto_decref_json json_t *new_interfaces = NULL;
|
||||||
|
guint num_nm_interfaces = 0;
|
||||||
|
gboolean interfaces_changed = FALSE;
|
||||||
|
int ii;
|
||||||
|
|
||||||
interfaces = json_array();
|
interfaces = json_array();
|
||||||
new_interfaces = json_array();
|
new_interfaces = json_array();
|
||||||
port_uuid = g_ptr_array_index(ovs_bridge->ports, pi);
|
port_uuid = g_ptr_array_index(ovs_bridge->ports, pi);
|
||||||
ovs_port = g_hash_table_lookup(priv->ports, &port_uuid);
|
ovs_port = g_hash_table_lookup(priv->ports, &port_uuid);
|
||||||
|
|
||||||
|
/* Add the port UUID to the list of known bridge port for the "expect" condition */
|
||||||
json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid));
|
json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid));
|
||||||
|
|
||||||
interfaces_changed = FALSE;
|
|
||||||
|
|
||||||
if (!ovs_port) {
|
if (!ovs_port) {
|
||||||
/* This would be a violation of ovsdb's reference integrity (a bug). */
|
/* This would be a violation of ovsdb's reference integrity (a bug). */
|
||||||
_LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid);
|
_LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Loop over all port's interfaces */
|
||||||
for (ii = 0; ii < ovs_port->interfaces->len; ii++) {
|
for (ii = 0; ii < ovs_port->interfaces->len; ii++) {
|
||||||
interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii);
|
interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii);
|
||||||
ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid);
|
ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid);
|
||||||
|
|
||||||
|
/* Add the interface UUID to the list of known port interfaces for the "expect" condition */
|
||||||
json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid));
|
json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid));
|
||||||
|
|
||||||
if (ovs_interface) {
|
if (ovs_interface) {
|
||||||
if (nm_streq(ovs_interface->name, ifname)) {
|
if (nm_streq(ovs_interface->name, ifname)) {
|
||||||
/* skip the interface */
|
/* We are deleting this interface, don't count it */
|
||||||
interfaces_changed = TRUE;
|
interfaces_changed = TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (ovs_interface->connection_uuid)
|
||||||
|
num_nm_interfaces++;
|
||||||
} else {
|
} else {
|
||||||
/* This would be a violation of ovsdb's reference integrity (a bug). */
|
/* This would be a violation of ovsdb's reference integrity (a bug). */
|
||||||
_LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid);
|
_LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add the interface to the list of new interfaces to set on the port */
|
||||||
json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid));
|
json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json_array_size(new_interfaces) == 0) {
|
if (interfaces_changed && num_nm_interfaces == 0) {
|
||||||
|
/* We are deleting the last nm-interface of this port. Don't add it to "new_ports"
|
||||||
|
* and set ports_changed=TRUE, so that it will be deleted. */
|
||||||
ports_changed = TRUE;
|
ports_changed = TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
/* Keep this port: it's still alive, or it's unrelated to the deleted interface */
|
||||||
|
json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid));
|
||||||
|
if (ovs_port->connection_uuid)
|
||||||
|
num_nm_ports++;
|
||||||
|
|
||||||
if (interfaces_changed) {
|
if (interfaces_changed) {
|
||||||
|
/* This port is still alive, but an interface needs to be deleted from it */
|
||||||
_expect_port_interfaces(params, ovs_port->name, interfaces);
|
_expect_port_interfaces(params, ovs_port->name, interfaces);
|
||||||
_set_port_interfaces(params, ovs_port->name, new_interfaces);
|
_set_port_interfaces(params, ovs_port->name, new_interfaces);
|
||||||
}
|
}
|
||||||
json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json_array_size(new_ports) == 0) {
|
if (ports_changed && num_nm_ports == 0) {
|
||||||
|
/* We are deleting the last nm-port of this bridge. Don't add it to "new_bridges"
|
||||||
|
* and set bridges_changed=TRUE, so that it will be deleted. */
|
||||||
bridges_changed = TRUE;
|
bridges_changed = TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
/* Keep this bridge: it's still alive, or it's unrelated to the deleted interface */
|
||||||
|
json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
|
||||||
|
|
||||||
if (ports_changed) {
|
if (ports_changed) {
|
||||||
|
/* This bridge is still alive, but a port needs to be deleted from it */
|
||||||
_expect_bridge_ports(params, ovs_bridge->name, ports);
|
_expect_bridge_ports(params, ovs_bridge->name, ports);
|
||||||
_set_bridge_ports(params, ovs_bridge->name, new_ports);
|
_set_bridge_ports(params, ovs_bridge->name, new_ports);
|
||||||
}
|
}
|
||||||
json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bridges_changed) {
|
if (bridges_changed) {
|
||||||
|
/* A bridge needs to be deleted */
|
||||||
_expect_ovs_bridges(params, priv->db_uuid, bridges);
|
_expect_ovs_bridges(params, priv->db_uuid, bridges);
|
||||||
_set_ovs_bridges(params, priv->db_uuid, new_bridges);
|
_set_ovs_bridges(params, priv->db_uuid, new_bridges);
|
||||||
}
|
}
|
||||||
|
|
@ -1541,13 +1592,47 @@ ovsdb_next_command(NMOvsdb *self)
|
||||||
break;
|
break;
|
||||||
case OVSDB_SET_REAPPLY:
|
case OVSDB_SET_REAPPLY:
|
||||||
{
|
{
|
||||||
json_t *mutations;
|
NMConnection *connection;
|
||||||
|
json_t *mutations;
|
||||||
|
json_t *row;
|
||||||
|
const char *table;
|
||||||
|
|
||||||
|
connection = call->payload.set_reapply.connection;
|
||||||
|
table = _device_type_to_table(call->payload.set_reapply.device_type);
|
||||||
|
|
||||||
|
/* Reapply device properties */
|
||||||
|
switch (call->payload.set_reapply.device_type) {
|
||||||
|
case NM_DEVICE_TYPE_OVS_BRIDGE:
|
||||||
|
row = create_bridge_row_object(connection, TRUE);
|
||||||
|
break;
|
||||||
|
case NM_DEVICE_TYPE_OVS_PORT:
|
||||||
|
row = create_port_row_object(connection);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
row = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row) {
|
||||||
|
json_array_append_new(params,
|
||||||
|
json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
|
||||||
|
"op",
|
||||||
|
"update",
|
||||||
|
"table",
|
||||||
|
table,
|
||||||
|
"row",
|
||||||
|
row,
|
||||||
|
"where",
|
||||||
|
"name",
|
||||||
|
"==",
|
||||||
|
call->payload.set_reapply.ifname));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reapply external-ids and other-config */
|
||||||
mutations = json_array();
|
mutations = json_array();
|
||||||
|
|
||||||
_j_create_strv_array_update(mutations,
|
_j_create_strv_array_update(mutations,
|
||||||
STRDICT_TYPE_EXTERNAL_IDS,
|
STRDICT_TYPE_EXTERNAL_IDS,
|
||||||
call->payload.set_reapply.connection_uuid,
|
nm_connection_get_uuid(connection),
|
||||||
call->payload.set_reapply.external_ids_old,
|
call->payload.set_reapply.external_ids_old,
|
||||||
call->payload.set_reapply.external_ids_new);
|
call->payload.set_reapply.external_ids_new);
|
||||||
_j_create_strv_array_update(mutations,
|
_j_create_strv_array_update(mutations,
|
||||||
|
|
@ -1556,19 +1641,18 @@ ovsdb_next_command(NMOvsdb *self)
|
||||||
call->payload.set_reapply.other_config_old,
|
call->payload.set_reapply.other_config_old,
|
||||||
call->payload.set_reapply.other_config_new);
|
call->payload.set_reapply.other_config_new);
|
||||||
|
|
||||||
json_array_append_new(
|
json_array_append_new(params,
|
||||||
params,
|
json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
|
||||||
json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
|
"op",
|
||||||
"op",
|
"mutate",
|
||||||
"mutate",
|
"table",
|
||||||
"table",
|
table,
|
||||||
_device_type_to_table(call->payload.set_reapply.device_type),
|
"mutations",
|
||||||
"mutations",
|
mutations,
|
||||||
mutations,
|
"where",
|
||||||
"where",
|
"name",
|
||||||
"name",
|
"==",
|
||||||
"==",
|
call->payload.set_reapply.ifname));
|
||||||
call->payload.set_reapply.ifname));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2411,7 +2495,7 @@ again:
|
||||||
* content is broken (_json_read_msg() cannot extract any data) and
|
* content is broken (_json_read_msg() cannot extract any data) and
|
||||||
* we disconnect. */
|
* we disconnect. */
|
||||||
priv->input_timeout_source =
|
priv->input_timeout_source =
|
||||||
nm_g_timeout_add_seconds_source(5, _ovsdb_read_input_timeout_cb, NULL);
|
nm_g_timeout_add_seconds_source(5, _ovsdb_read_input_timeout_cb, self);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2975,7 +3059,7 @@ void
|
||||||
nm_ovsdb_set_reapply(NMOvsdb *self,
|
nm_ovsdb_set_reapply(NMOvsdb *self,
|
||||||
NMDeviceType device_type,
|
NMDeviceType device_type,
|
||||||
const char *ifname,
|
const char *ifname,
|
||||||
const char *connection_uuid,
|
NMConnection *connection_take,
|
||||||
NMSettingOvsExternalIDs *s_external_ids_old,
|
NMSettingOvsExternalIDs *s_external_ids_old,
|
||||||
NMSettingOvsExternalIDs *s_external_ids_new,
|
NMSettingOvsExternalIDs *s_external_ids_new,
|
||||||
NMSettingOvsOtherConfig *s_other_config_old,
|
NMSettingOvsOtherConfig *s_other_config_old,
|
||||||
|
|
@ -2986,6 +3070,11 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
|
||||||
gs_unref_hashtable GHashTable *other_config_old = NULL;
|
gs_unref_hashtable GHashTable *other_config_old = NULL;
|
||||||
gs_unref_hashtable GHashTable *other_config_new = NULL;
|
gs_unref_hashtable GHashTable *other_config_new = NULL;
|
||||||
|
|
||||||
|
nm_assert(NM_IN_SET(device_type,
|
||||||
|
NM_DEVICE_TYPE_OVS_BRIDGE,
|
||||||
|
NM_DEVICE_TYPE_OVS_PORT,
|
||||||
|
NM_DEVICE_TYPE_OVS_INTERFACE));
|
||||||
|
|
||||||
external_ids_old =
|
external_ids_old =
|
||||||
s_external_ids_old
|
s_external_ids_old
|
||||||
? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_external_ids_old))
|
? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_external_ids_old))
|
||||||
|
|
@ -3011,7 +3100,7 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
|
||||||
OVSDB_SET_REAPPLY,
|
OVSDB_SET_REAPPLY,
|
||||||
OVSDB_METHOD_PAYLOAD_SET_REAPPLY(device_type,
|
OVSDB_METHOD_PAYLOAD_SET_REAPPLY(device_type,
|
||||||
ifname,
|
ifname,
|
||||||
connection_uuid,
|
connection_take,
|
||||||
external_ids_old,
|
external_ids_old,
|
||||||
external_ids_new,
|
external_ids_new,
|
||||||
other_config_old,
|
other_config_old,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ void nm_ovsdb_set_interface_mtu(NMOvsdb *self,
|
||||||
void nm_ovsdb_set_reapply(NMOvsdb *self,
|
void nm_ovsdb_set_reapply(NMOvsdb *self,
|
||||||
NMDeviceType device_type,
|
NMDeviceType device_type,
|
||||||
const char *ifname,
|
const char *ifname,
|
||||||
const char *connection_uuid,
|
NMConnection *connection_take,
|
||||||
NMSettingOvsExternalIDs *s_external_ids_old,
|
NMSettingOvsExternalIDs *s_external_ids_old,
|
||||||
NMSettingOvsExternalIDs *s_external_ids_new,
|
NMSettingOvsExternalIDs *s_external_ids_new,
|
||||||
NMSettingOvsOtherConfig *s_other_config_old,
|
NMSettingOvsOtherConfig *s_other_config_old,
|
||||||
|
|
|
||||||
|
|
@ -2935,7 +2935,8 @@ build_supplicant_config(NMDeviceWifi *self,
|
||||||
s_wireless = nm_connection_get_setting_wireless(connection);
|
s_wireless = nm_connection_get_setting_wireless(connection);
|
||||||
g_return_val_if_fail(s_wireless != NULL, NULL);
|
g_return_val_if_fail(s_wireless != NULL, NULL);
|
||||||
|
|
||||||
config = nm_supplicant_config_new(nm_supplicant_interface_get_capabilities(priv->sup_iface));
|
config = nm_supplicant_config_new(nm_supplicant_interface_get_capabilities(priv->sup_iface),
|
||||||
|
nm_utils_get_connection_first_permissions_user(connection));
|
||||||
|
|
||||||
/* Warn if AP mode may not be supported */
|
/* Warn if AP mode may not be supported */
|
||||||
if (nm_streq0(nm_setting_wireless_get_mode(s_wireless), NM_SETTING_WIRELESS_MODE_AP)
|
if (nm_streq0(nm_setting_wireless_get_mode(s_wireless), NM_SETTING_WIRELESS_MODE_AP)
|
||||||
|
|
@ -3011,6 +3012,7 @@ build_supplicant_config(NMDeviceWifi *self,
|
||||||
mtu,
|
mtu,
|
||||||
pmf,
|
pmf,
|
||||||
fils,
|
fils,
|
||||||
|
nm_device_get_private_files(NM_DEVICE(self)),
|
||||||
error)) {
|
error)) {
|
||||||
g_prefix_error(error, "802-11-wireless-security: ");
|
g_prefix_error(error, "802-11-wireless-security: ");
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,15 @@ typedef enum {
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
dnsconfd_change_plugin_state(NMDnsDnsconfd *self, DnsconfdPluginState new_state)
|
||||||
|
{
|
||||||
|
NMDnsDnsconfdPrivate *priv = NM_DNS_DNSCONFD_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
priv->plugin_state = new_state;
|
||||||
|
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dnsconfd_serial_changed(NMDnsDnsconfd *self, guint new_serial)
|
dnsconfd_serial_changed(NMDnsDnsconfd *self, guint new_serial)
|
||||||
{
|
{
|
||||||
|
|
@ -78,12 +87,10 @@ dnsconfd_serial_changed(NMDnsDnsconfd *self, guint new_serial)
|
||||||
priv->present_configuration_serial = new_serial;
|
priv->present_configuration_serial = new_serial;
|
||||||
if (priv->plugin_state == DNSCONFD_PLUGIN_WAIT_SERIAL
|
if (priv->plugin_state == DNSCONFD_PLUGIN_WAIT_SERIAL
|
||||||
&& priv->awaited_configuration_serial == new_serial) {
|
&& priv->awaited_configuration_serial == new_serial) {
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
|
||||||
/* Update finished, serials match */
|
/* Update finished, serials match */
|
||||||
_LOGT("serials match, update finished");
|
_LOGT("serials match, update finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -132,6 +139,12 @@ dnsconfd_serial_retrieval_done(GObject *source_object, GAsyncResult *res, gpoint
|
||||||
self = user_data;
|
self = user_data;
|
||||||
priv = NM_DNS_DNSCONFD_GET_PRIVATE(self);
|
priv = NM_DNS_DNSCONFD_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
_LOGW("dnsconfd serial retrieval failed: %s", error->message);
|
||||||
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nm_clear_g_cancellable(&priv->serial_cancellable);
|
nm_clear_g_cancellable(&priv->serial_cancellable);
|
||||||
|
|
||||||
g_variant_get(response, "(v)", &new_serial_variant);
|
g_variant_get(response, "(v)", &new_serial_variant);
|
||||||
|
|
@ -201,8 +214,11 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
|
||||||
|
|
||||||
nm_clear_g_cancellable(&priv->update_cancellable);
|
nm_clear_g_cancellable(&priv->update_cancellable);
|
||||||
|
|
||||||
if (!response)
|
if (!response) {
|
||||||
_LOGW("dnsconfd update failed: %s", error->message);
|
_LOGW("dnsconfd update failed: %s", error->message);
|
||||||
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* By using &s we will get pointer to char data contained
|
/* By using &s we will get pointer to char data contained
|
||||||
* in variant and thus no freing of dnsconfd_message is required */
|
* in variant and thus no freing of dnsconfd_message is required */
|
||||||
|
|
@ -210,8 +226,7 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
|
||||||
|
|
||||||
if (!awaited_serial) {
|
if (!awaited_serial) {
|
||||||
_LOGW("dnsconfd refused update: %s", dnsconfd_message);
|
_LOGW("dnsconfd refused update: %s", dnsconfd_message);
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
|
||||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,14 +235,12 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
|
||||||
|
|
||||||
if (priv->awaited_configuration_serial == priv->present_configuration_serial) {
|
if (priv->awaited_configuration_serial == priv->present_configuration_serial) {
|
||||||
/* Serials match, update finished */
|
/* Serials match, update finished */
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
|
||||||
_LOGT("after update serials match");
|
_LOGT("after update serials match");
|
||||||
} else {
|
} else {
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_WAIT_SERIAL;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_SERIAL);
|
||||||
_LOGT("after update serials don't match, waiting");
|
_LOGT("after update serials don't match, waiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -478,8 +491,7 @@ name_owner_changed(NMDnsDnsconfd *self, const char *name_owner)
|
||||||
|| priv->plugin_state == DNSCONFD_PLUGIN_WAIT_SERIAL) {
|
|| priv->plugin_state == DNSCONFD_PLUGIN_WAIT_SERIAL) {
|
||||||
/* We were waiting for either serial or confirmation of update and name
|
/* We were waiting for either serial or confirmation of update and name
|
||||||
* disappeared, thus we need to retransmit */
|
* disappeared, thus we need to retransmit */
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_WAIT_CONNECT;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_CONNECT);
|
||||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -490,15 +502,13 @@ name_owner_changed(NMDnsDnsconfd *self, const char *name_owner)
|
||||||
if (!subscribe_serial(self)) {
|
if (!subscribe_serial(self)) {
|
||||||
/* This means that in time between new name and subscribe serial call
|
/* This means that in time between new name and subscribe serial call
|
||||||
* we lost the name again thus wait again */
|
* we lost the name again thus wait again */
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_WAIT_CONNECT;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_CONNECT);
|
||||||
_LOGT("subscription failed, waiting to connect");
|
_LOGT("subscription failed, waiting to connect");
|
||||||
} else {
|
} else {
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_WAIT_UPDATE_DONE;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_UPDATE_DONE);
|
||||||
_LOGT("sending update and waiting for its finish");
|
_LOGT("sending update and waiting for its finish");
|
||||||
send_dnsconfd_update(self);
|
send_dnsconfd_update(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -695,18 +705,16 @@ update(NMDnsPlugin *plugin,
|
||||||
/* We need to consider only whether we are connected, because newer update call
|
/* We need to consider only whether we are connected, because newer update call
|
||||||
* overrides the old one */
|
* overrides the old one */
|
||||||
if (all_connected == CONNECTION_FAIL) {
|
if (all_connected == CONNECTION_FAIL) {
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
|
||||||
_LOGT("failed to connect");
|
_LOGT("failed to connect");
|
||||||
} else if (all_connected == CONNECTION_WAIT) {
|
} else if (all_connected == CONNECTION_WAIT) {
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_WAIT_CONNECT;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_CONNECT);
|
||||||
_LOGT("not connected, waiting to connect");
|
_LOGT("not connected, waiting to connect");
|
||||||
} else {
|
} else {
|
||||||
priv->plugin_state = DNSCONFD_PLUGIN_WAIT_UPDATE_DONE;
|
dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_UPDATE_DONE);
|
||||||
_LOGT("connected, waiting for update to finish");
|
_LOGT("connected, waiting for update to finish");
|
||||||
}
|
}
|
||||||
|
|
||||||
_nm_dns_plugin_update_pending_maybe_changed(plugin);
|
|
||||||
|
|
||||||
if (all_connected == CONNECTION_FAIL) {
|
if (all_connected == CONNECTION_FAIL) {
|
||||||
nm_utils_error_set(error,
|
nm_utils_error_set(error,
|
||||||
NM_UTILS_ERROR_UNKNOWN,
|
NM_UTILS_ERROR_UNKNOWN,
|
||||||
|
|
|
||||||
|
|
@ -882,7 +882,7 @@ nm_bond_manager_send_arp(int bond_ifindex,
|
||||||
.sll_protocol = htons(ETH_P_ARP),
|
.sll_protocol = htons(ETH_P_ARP),
|
||||||
.sll_ifindex = bond_ifindex,
|
.sll_ifindex = bond_ifindex,
|
||||||
};
|
};
|
||||||
ARPPacket data;
|
ARPPacket data = {0};
|
||||||
const guint8 *hwaddr;
|
const guint8 *hwaddr;
|
||||||
gsize hwaddrlen = 0;
|
gsize hwaddrlen = 0;
|
||||||
nm_auto_close int sockfd = -1;
|
nm_auto_close int sockfd = -1;
|
||||||
|
|
@ -940,6 +940,7 @@ nm_bond_manager_send_arp(int bond_ifindex,
|
||||||
data.op = htons(ARP_OP_GARP);
|
data.op = htons(ARP_OP_GARP);
|
||||||
memcpy(data.s_addr, hwaddr, hwaddrlen);
|
memcpy(data.s_addr, hwaddr, hwaddrlen);
|
||||||
memcpy(data.s_hw_addr, hwaddr, hwaddrlen);
|
memcpy(data.s_hw_addr, hwaddr, hwaddrlen);
|
||||||
|
memset(data.d_hw_addr, 0xff, ETH_ALEN);
|
||||||
for (int i = 0; i < addrs_len; i++) {
|
for (int i = 0; i < addrs_len; i++) {
|
||||||
const in_addr_t tmp_addr = addrs_array[i];
|
const in_addr_t tmp_addr = addrs_array[i];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#define HEADER_STATUS_ONLINE "X-NetworkManager-Status: online\r\n"
|
#define HEADER_STATUS_ONLINE "X-NetworkManager-Status: online\r\n"
|
||||||
|
|
||||||
|
#define SD_RESOLVED_DNS ((guint64) (1LL << 0))
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static NM_UTILS_LOOKUP_STR_DEFINE(_state_to_string,
|
static NM_UTILS_LOOKUP_STR_DEFINE(_state_to_string,
|
||||||
|
|
@ -950,9 +952,6 @@ systemd_resolved_resolve_cb(GObject *object, GAsyncResult *res, gpointer user_da
|
||||||
|
|
||||||
do_curl_request(cb_data, nm_str_buf_get_str(&strbuf_hosts));
|
do_curl_request(cb_data, nm_str_buf_get_str(&strbuf_hosts));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SD_RESOLVED_DNS ((guint64) (1LL << 0))
|
|
||||||
|
|
||||||
static NMConnectivityState
|
static NMConnectivityState
|
||||||
check_platform_config(NMConnectivity *self,
|
check_platform_config(NMConnectivity *self,
|
||||||
|
|
@ -1013,6 +1012,7 @@ check_platform_config(NMConnectivity *self,
|
||||||
NM_SET_OUT(reason, NULL);
|
NM_SET_OUT(reason, NULL);
|
||||||
return NM_CONNECTIVITY_UNKNOWN;
|
return NM_CONNECTIVITY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
NMConnectivityCheckHandle *
|
NMConnectivityCheckHandle *
|
||||||
nm_connectivity_check_start(NMConnectivity *self,
|
nm_connectivity_check_start(NMConnectivity *self,
|
||||||
|
|
|
||||||
|
|
@ -5011,6 +5011,7 @@ typedef struct {
|
||||||
int child_stdin;
|
int child_stdin;
|
||||||
int child_stdout;
|
int child_stdout;
|
||||||
int child_stderr;
|
int child_stderr;
|
||||||
|
gboolean binary_output;
|
||||||
GSource *input_source;
|
GSource *input_source;
|
||||||
GSource *output_source;
|
GSource *output_source;
|
||||||
GSource *error_source;
|
GSource *error_source;
|
||||||
|
|
@ -5090,9 +5091,17 @@ helper_complete(HelperInfo *info, GError *error)
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task), &info->cancellable_id);
|
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task), &info->cancellable_id);
|
||||||
g_task_return_pointer(info->task,
|
|
||||||
nm_str_buf_finalize(&info->in_buffer, NULL) ?: g_new0(char, 1),
|
if (info->binary_output) {
|
||||||
g_free);
|
g_task_return_pointer(
|
||||||
|
info->task,
|
||||||
|
g_bytes_new(nm_str_buf_get_str_unsafe(&info->in_buffer), info->in_buffer.len),
|
||||||
|
(GDestroyNotify) (g_bytes_unref));
|
||||||
|
} else {
|
||||||
|
g_task_return_pointer(info->task,
|
||||||
|
nm_str_buf_finalize(&info->in_buffer, NULL) ?: g_new0(char, 1),
|
||||||
|
g_free);
|
||||||
|
}
|
||||||
helper_info_free(info);
|
helper_info_free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5235,6 +5244,7 @@ helper_cancelled(GObject *object, gpointer user_data)
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_utils_spawn_helper(const char *const *args,
|
nm_utils_spawn_helper(const char *const *args,
|
||||||
|
gboolean binary_output,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer cb_data)
|
gpointer cb_data)
|
||||||
|
|
@ -5250,9 +5260,14 @@ nm_utils_spawn_helper(const char *const *args,
|
||||||
|
|
||||||
info = g_new(HelperInfo, 1);
|
info = g_new(HelperInfo, 1);
|
||||||
*info = (HelperInfo) {
|
*info = (HelperInfo) {
|
||||||
.task = nm_g_task_new(NULL, cancellable, nm_utils_spawn_helper, callback, cb_data),
|
.task = nm_g_task_new(NULL, cancellable, nm_utils_spawn_helper, callback, cb_data),
|
||||||
|
.binary_output = binary_output,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Store if the caller requested binary output so that we can check later
|
||||||
|
* that the right result function is called. */
|
||||||
|
g_task_set_task_data(info->task, GINT_TO_POINTER(binary_output), NULL);
|
||||||
|
|
||||||
if (!g_spawn_async_with_pipes("/",
|
if (!g_spawn_async_with_pipes("/",
|
||||||
(char **) NM_MAKE_STRV(LIBEXECDIR "/nm-daemon-helper"),
|
(char **) NM_MAKE_STRV(LIBEXECDIR "/nm-daemon-helper"),
|
||||||
(char **) NM_MAKE_STRV(),
|
(char **) NM_MAKE_STRV(),
|
||||||
|
|
@ -5363,11 +5378,25 @@ nm_utils_spawn_helper(const char *const *args,
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
nm_utils_spawn_helper_finish(GAsyncResult *result, GError **error)
|
nm_utils_spawn_helper_finish_string(GAsyncResult *result, GError **error)
|
||||||
{
|
{
|
||||||
GTask *task = G_TASK(result);
|
GTask *task = G_TASK(result);
|
||||||
|
|
||||||
nm_assert(nm_g_task_is_valid(result, NULL, nm_utils_spawn_helper));
|
nm_assert(nm_g_task_is_valid(result, NULL, nm_utils_spawn_helper));
|
||||||
|
/* Check binary_output */
|
||||||
|
nm_assert(GPOINTER_TO_INT(g_task_get_task_data(task)) == FALSE);
|
||||||
|
|
||||||
|
return g_task_propagate_pointer(task, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
GBytes *
|
||||||
|
nm_utils_spawn_helper_finish_binary(GAsyncResult *result, GError **error)
|
||||||
|
{
|
||||||
|
GTask *task = G_TASK(result);
|
||||||
|
|
||||||
|
nm_assert(nm_g_task_is_valid(result, NULL, nm_utils_spawn_helper));
|
||||||
|
/* Check binary_output */
|
||||||
|
nm_assert(GPOINTER_TO_INT(g_task_get_task_data(task)) == TRUE);
|
||||||
|
|
||||||
return g_task_propagate_pointer(task, error);
|
return g_task_propagate_pointer(task, error);
|
||||||
}
|
}
|
||||||
|
|
@ -5474,3 +5503,185 @@ nm_utils_shorten_hostname(const char *hostname, char **shortened)
|
||||||
*shortened = g_steal_pointer(&s);
|
*shortened = g_steal_pointer(&s);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_utils_get_connection_first_permissions_user(NMConnection *connection)
|
||||||
|
{
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
|
||||||
|
s_con = nm_connection_get_setting_connection(connection);
|
||||||
|
nm_assert(s_con);
|
||||||
|
|
||||||
|
return _nm_setting_connection_get_first_permissions_user(s_con);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const char **
|
||||||
|
nm_utils_get_connection_private_files_paths(NMConnection *connection)
|
||||||
|
{
|
||||||
|
GPtrArray *files;
|
||||||
|
gs_free NMSetting **settings = NULL;
|
||||||
|
guint num_settings;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
files = g_ptr_array_new();
|
||||||
|
settings = nm_connection_get_settings(connection, &num_settings);
|
||||||
|
for (i = 0; i < num_settings; i++) {
|
||||||
|
_nm_setting_get_private_files(settings[i], files);
|
||||||
|
}
|
||||||
|
g_ptr_array_add(files, NULL);
|
||||||
|
|
||||||
|
return (const char **) g_ptr_array_free(files, files->len == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _ReadInfo ReadInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *path;
|
||||||
|
ReadInfo *read_info;
|
||||||
|
} FileInfo;
|
||||||
|
|
||||||
|
struct _ReadInfo {
|
||||||
|
GTask *task;
|
||||||
|
GHashTable *table;
|
||||||
|
GPtrArray *file_infos; /* of FileInfo */
|
||||||
|
GError *first_error;
|
||||||
|
guint num_pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_file_helper_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
|
{
|
||||||
|
FileInfo *file_info = user_data;
|
||||||
|
ReadInfo *read_info = file_info->read_info;
|
||||||
|
gs_unref_bytes GBytes *output = NULL;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
|
||||||
|
output = nm_utils_spawn_helper_finish_binary(result, &error);
|
||||||
|
|
||||||
|
nm_assert(read_info->num_pending > 0);
|
||||||
|
read_info->num_pending--;
|
||||||
|
|
||||||
|
if (nm_utils_error_is_cancelled(error)) {
|
||||||
|
/* nop */
|
||||||
|
} else if (error) {
|
||||||
|
nm_log_dbg(LOGD_CORE,
|
||||||
|
"read-private-files: failed to read file '%s': %s",
|
||||||
|
file_info->path,
|
||||||
|
error->message);
|
||||||
|
if (!read_info->first_error) {
|
||||||
|
/* @error just says "helper process exited with status X".
|
||||||
|
* Return a more human-friendly one. */
|
||||||
|
read_info->first_error = g_error_new(NM_UTILS_ERROR,
|
||||||
|
NM_UTILS_ERROR_UNKNOWN,
|
||||||
|
"error reading file '%s'",
|
||||||
|
file_info->path);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nm_log_dbg(LOGD_SUPPLICANT,
|
||||||
|
"read-private-files: successfully read file '%s'",
|
||||||
|
file_info->path);
|
||||||
|
|
||||||
|
/* Store the file contents in the hash table */
|
||||||
|
if (!read_info->table) {
|
||||||
|
read_info->table = g_hash_table_new_full(nm_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
(GDestroyNotify) g_bytes_unref);
|
||||||
|
}
|
||||||
|
g_hash_table_insert(read_info->table,
|
||||||
|
g_steal_pointer(&file_info->path),
|
||||||
|
g_steal_pointer(&output));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(&file_info->path, g_free);
|
||||||
|
|
||||||
|
/* If all operations are completed, return */
|
||||||
|
if (read_info->num_pending == 0) {
|
||||||
|
if (read_info->first_error) {
|
||||||
|
g_task_return_error(read_info->task, g_steal_pointer(&read_info->first_error));
|
||||||
|
} else {
|
||||||
|
g_task_return_pointer(read_info->task,
|
||||||
|
g_steal_pointer(&read_info->table),
|
||||||
|
(GDestroyNotify) g_hash_table_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_info->table)
|
||||||
|
g_hash_table_unref(read_info->table);
|
||||||
|
if (read_info->file_infos)
|
||||||
|
g_ptr_array_unref(read_info->file_infos);
|
||||||
|
|
||||||
|
g_object_unref(read_info->task);
|
||||||
|
g_free(read_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_utils_read_private_files:
|
||||||
|
* @paths: array of file paths to be read
|
||||||
|
* @user: name of the user to impersonate when reading the files
|
||||||
|
* @cancellable: cancellable to cancel the operation
|
||||||
|
* @callback: callback to invoke on completion
|
||||||
|
* @cb_data: data for @callback
|
||||||
|
*
|
||||||
|
* Reads the given list of files @paths on behalf of user @user. Invokes
|
||||||
|
* @callback asynchronously on completion. The callback must use
|
||||||
|
* nm_utils_read_private_files_finish() to obtain the result.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nm_utils_read_private_files(const char *const *paths,
|
||||||
|
const char *user,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer cb_data)
|
||||||
|
{
|
||||||
|
ReadInfo *read_info;
|
||||||
|
FileInfo *file_info;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_if_fail(paths && paths[0]);
|
||||||
|
g_return_if_fail(cancellable);
|
||||||
|
g_return_if_fail(callback);
|
||||||
|
g_return_if_fail(cb_data);
|
||||||
|
|
||||||
|
read_info = g_new(ReadInfo, 1);
|
||||||
|
*read_info = (ReadInfo) {
|
||||||
|
.task = nm_g_task_new(NULL, cancellable, nm_utils_read_private_files, callback, cb_data),
|
||||||
|
.file_infos = g_ptr_array_new_with_free_func(g_free),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; paths[i]; i++) {
|
||||||
|
file_info = g_new(FileInfo, 1);
|
||||||
|
*file_info = (FileInfo) {
|
||||||
|
.path = g_strdup(paths[i]),
|
||||||
|
.read_info = read_info,
|
||||||
|
};
|
||||||
|
g_ptr_array_add(read_info->file_infos, file_info);
|
||||||
|
read_info->num_pending++;
|
||||||
|
|
||||||
|
nm_utils_spawn_helper(NM_MAKE_STRV("read-file-as-user", user, paths[i]),
|
||||||
|
TRUE,
|
||||||
|
cancellable,
|
||||||
|
read_file_helper_cb,
|
||||||
|
file_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_utils_read_private_files_finish:
|
||||||
|
* @result: the GAsyncResult
|
||||||
|
* @error: on return, the error
|
||||||
|
*
|
||||||
|
* Returns the files read by nm_utils_read_private_files(). The return value
|
||||||
|
* is a hash table {char * -> GBytes *}. Free it with g_hash_table_unref().
|
||||||
|
*/
|
||||||
|
GHashTable *
|
||||||
|
nm_utils_read_private_files_finish(GAsyncResult *result, GError **error)
|
||||||
|
{
|
||||||
|
GTask *task = G_TASK(result);
|
||||||
|
|
||||||
|
nm_assert(nm_g_task_is_valid(result, NULL, nm_utils_read_private_files));
|
||||||
|
|
||||||
|
return g_task_propagate_pointer(task, error);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -478,11 +478,13 @@ guint8 nm_wifi_utils_level_to_quality(int val);
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void nm_utils_spawn_helper(const char *const *args,
|
void nm_utils_spawn_helper(const char *const *args,
|
||||||
|
gboolean binary_output,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer cb_data);
|
gpointer cb_data);
|
||||||
|
|
||||||
char *nm_utils_spawn_helper_finish(GAsyncResult *result, GError **error);
|
char *nm_utils_spawn_helper_finish_string(GAsyncResult *result, GError **error);
|
||||||
|
GBytes *nm_utils_spawn_helper_finish_binary(GAsyncResult *result, GError **error);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -490,4 +492,19 @@ uid_t nm_utils_get_nm_uid(void);
|
||||||
|
|
||||||
gid_t nm_utils_get_nm_gid(void);
|
gid_t nm_utils_get_nm_gid(void);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const char *nm_utils_get_connection_first_permissions_user(NMConnection *connection);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const char **nm_utils_get_connection_private_files_paths(NMConnection *connection);
|
||||||
|
|
||||||
|
void nm_utils_read_private_files(const char *const *paths,
|
||||||
|
const char *user,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer cb_data);
|
||||||
|
GHashTable *nm_utils_read_private_files_finish(GAsyncResult *result, GError **error);
|
||||||
|
|
||||||
#endif /* __NM_CORE_UTILS_H__ */
|
#endif /* __NM_CORE_UTILS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "nm-firewall-utils.h"
|
#include "nm-firewall-utils.h"
|
||||||
|
|
||||||
|
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
||||||
#include "libnm-glib-aux/nm-str-buf.h"
|
#include "libnm-glib-aux/nm-str-buf.h"
|
||||||
#include "libnm-glib-aux/nm-io-utils.h"
|
#include "libnm-glib-aux/nm-io-utils.h"
|
||||||
#include "libnm-platform/nm-platform.h"
|
#include "libnm-platform/nm-platform.h"
|
||||||
|
|
@ -127,7 +128,7 @@ _share_iptables_subnet_to_str(char buf[static _SHARE_IPTABLES_SUBNET_TO_STR
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
_share_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const char *ip_iface)
|
_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const char *ip_iface)
|
||||||
{
|
{
|
||||||
NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE);
|
NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE);
|
||||||
gsize ip_iface_len;
|
gsize ip_iface_len;
|
||||||
|
|
@ -179,13 +180,13 @@ _share_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const c
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_share_iptables_call_v(const char *const *argv)
|
_iptables_call_v(const char *const *argv)
|
||||||
{
|
{
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
gs_free char *argv_str = NULL;
|
gs_free char *argv_str = NULL;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
nm_log_dbg(LOGD_SHARING, "iptables: %s", (argv_str = g_strjoinv(" ", (char **) argv)));
|
nm_log_dbg(LOGD_FIREWALL, "iptables: %s", (argv_str = g_strjoinv(" ", (char **) argv)));
|
||||||
|
|
||||||
if (!g_spawn_sync("/",
|
if (!g_spawn_sync("/",
|
||||||
(char **) argv,
|
(char **) argv,
|
||||||
|
|
@ -197,7 +198,7 @@ _share_iptables_call_v(const char *const *argv)
|
||||||
NULL,
|
NULL,
|
||||||
&status,
|
&status,
|
||||||
&error)) {
|
&error)) {
|
||||||
nm_log_warn(LOGD_SHARING,
|
nm_log_warn(LOGD_FIREWALL,
|
||||||
"iptables: error executing command %s: %s",
|
"iptables: error executing command %s: %s",
|
||||||
argv[0],
|
argv[0],
|
||||||
error->message);
|
error->message);
|
||||||
|
|
@ -205,20 +206,24 @@ _share_iptables_call_v(const char *const *argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_spawn_check_exit_status(status, &error)) {
|
if (!g_spawn_check_exit_status(status, &error)) {
|
||||||
nm_log_warn(LOGD_SHARING, "iptables: command %s failed: %s", argv[0], error->message);
|
nm_log_warn(LOGD_FIREWALL, "iptables: command %s failed: %s", argv[0], error->message);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _share_iptables_call(...) \
|
#define _ipxtables_call(family, ...) \
|
||||||
_share_iptables_call_v(NM_MAKE_STRV("" IPTABLES_PATH "", "--wait", "2", __VA_ARGS__))
|
_iptables_call_v( \
|
||||||
|
NM_MAKE_STRV((family == AF_INET ? "" IPTABLES_PATH "" : "" IP6TABLES_PATH ""), \
|
||||||
|
"--wait", \
|
||||||
|
"2", \
|
||||||
|
__VA_ARGS__))
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_share_iptables_chain_op(const char *table, const char *chain, const char *op)
|
_share_iptables_chain_op(const char *table, const char *chain, const char *op)
|
||||||
{
|
{
|
||||||
return _share_iptables_call("--table", table, op, chain);
|
return _ipxtables_call(AF_INET, "--table", table, op, chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -244,24 +249,25 @@ _share_iptables_set_masquerade_sync(gboolean up, const char *ip_iface, in_addr_t
|
||||||
char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN];
|
char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN];
|
||||||
gs_free char *comment_name = NULL;
|
gs_free char *comment_name = NULL;
|
||||||
|
|
||||||
comment_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface);
|
comment_name = _iptables_get_name(FALSE, "nm-shared", ip_iface);
|
||||||
|
|
||||||
_share_iptables_subnet_to_str(str_subnet, addr, plen);
|
_share_iptables_subnet_to_str(str_subnet, addr, plen);
|
||||||
_share_iptables_call("--table",
|
_ipxtables_call(AF_INET,
|
||||||
"nat",
|
"--table",
|
||||||
up ? "--insert" : "--delete",
|
"nat",
|
||||||
"POSTROUTING",
|
up ? "--insert" : "--delete",
|
||||||
"--source",
|
"POSTROUTING",
|
||||||
str_subnet,
|
"--source",
|
||||||
"!",
|
str_subnet,
|
||||||
"--destination",
|
"!",
|
||||||
str_subnet,
|
"--destination",
|
||||||
"--jump",
|
str_subnet,
|
||||||
"MASQUERADE",
|
"--jump",
|
||||||
"-m",
|
"MASQUERADE",
|
||||||
"comment",
|
"-m",
|
||||||
"--comment",
|
"comment",
|
||||||
comment_name);
|
"--comment",
|
||||||
|
comment_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -297,70 +303,76 @@ _share_iptables_set_shared_chains_add(const char *chain_input,
|
||||||
_share_iptables_chain_add("filter", chain_input);
|
_share_iptables_chain_add("filter", chain_input);
|
||||||
|
|
||||||
for (i = 0; i < (int) G_N_ELEMENTS(input_params); i++) {
|
for (i = 0; i < (int) G_N_ELEMENTS(input_params); i++) {
|
||||||
_share_iptables_call("--table",
|
_ipxtables_call(AF_INET,
|
||||||
"filter",
|
"--table",
|
||||||
"--append",
|
"filter",
|
||||||
chain_input,
|
"--append",
|
||||||
"--protocol",
|
chain_input,
|
||||||
input_params[i][0],
|
"--protocol",
|
||||||
"--destination-port",
|
input_params[i][0],
|
||||||
input_params[i][1],
|
"--destination-port",
|
||||||
"--jump",
|
input_params[i][1],
|
||||||
"ACCEPT");
|
"--jump",
|
||||||
|
"ACCEPT");
|
||||||
}
|
}
|
||||||
|
|
||||||
_share_iptables_chain_add("filter", chain_forward);
|
_share_iptables_chain_add("filter", chain_forward);
|
||||||
|
|
||||||
_share_iptables_call("--table",
|
_ipxtables_call(AF_INET,
|
||||||
"filter",
|
"--table",
|
||||||
"--append",
|
"filter",
|
||||||
chain_forward,
|
"--append",
|
||||||
"--destination",
|
chain_forward,
|
||||||
str_subnet,
|
"--destination",
|
||||||
"--out-interface",
|
str_subnet,
|
||||||
ip_iface,
|
"--out-interface",
|
||||||
"--match",
|
ip_iface,
|
||||||
"state",
|
"--match",
|
||||||
"--state",
|
"state",
|
||||||
"ESTABLISHED,RELATED",
|
"--state",
|
||||||
"--jump",
|
"ESTABLISHED,RELATED",
|
||||||
"ACCEPT");
|
"--jump",
|
||||||
_share_iptables_call("--table",
|
"ACCEPT");
|
||||||
"filter",
|
_ipxtables_call(AF_INET,
|
||||||
"--append",
|
"--table",
|
||||||
chain_forward,
|
"filter",
|
||||||
"--source",
|
"--append",
|
||||||
str_subnet,
|
chain_forward,
|
||||||
"--in-interface",
|
"--source",
|
||||||
ip_iface,
|
str_subnet,
|
||||||
"--jump",
|
"--in-interface",
|
||||||
"ACCEPT");
|
ip_iface,
|
||||||
_share_iptables_call("--table",
|
"--jump",
|
||||||
"filter",
|
"ACCEPT");
|
||||||
"--append",
|
_ipxtables_call(AF_INET,
|
||||||
chain_forward,
|
"--table",
|
||||||
"--in-interface",
|
"filter",
|
||||||
ip_iface,
|
"--append",
|
||||||
"--out-interface",
|
chain_forward,
|
||||||
ip_iface,
|
"--in-interface",
|
||||||
"--jump",
|
ip_iface,
|
||||||
"ACCEPT");
|
"--out-interface",
|
||||||
_share_iptables_call("--table",
|
ip_iface,
|
||||||
"filter",
|
"--jump",
|
||||||
"--append",
|
"ACCEPT");
|
||||||
chain_forward,
|
_ipxtables_call(AF_INET,
|
||||||
"--out-interface",
|
"--table",
|
||||||
ip_iface,
|
"filter",
|
||||||
"--jump",
|
"--append",
|
||||||
"REJECT");
|
chain_forward,
|
||||||
_share_iptables_call("--table",
|
"--out-interface",
|
||||||
"filter",
|
ip_iface,
|
||||||
"--append",
|
"--jump",
|
||||||
chain_forward,
|
"REJECT");
|
||||||
"--in-interface",
|
_ipxtables_call(AF_INET,
|
||||||
ip_iface,
|
"--table",
|
||||||
"--jump",
|
"filter",
|
||||||
"REJECT");
|
"--append",
|
||||||
|
chain_forward,
|
||||||
|
"--in-interface",
|
||||||
|
ip_iface,
|
||||||
|
"--jump",
|
||||||
|
"REJECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -377,36 +389,38 @@ _share_iptables_set_shared_sync(gboolean up, const char *ip_iface, in_addr_t add
|
||||||
gs_free char *chain_input = NULL;
|
gs_free char *chain_input = NULL;
|
||||||
gs_free char *chain_forward = NULL;
|
gs_free char *chain_forward = NULL;
|
||||||
|
|
||||||
comment_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface);
|
comment_name = _iptables_get_name(FALSE, "nm-shared", ip_iface);
|
||||||
chain_input = _share_iptables_get_name(TRUE, "nm-sh-in", ip_iface);
|
chain_input = _iptables_get_name(TRUE, "nm-sh-in", ip_iface);
|
||||||
chain_forward = _share_iptables_get_name(TRUE, "nm-sh-fw", ip_iface);
|
chain_forward = _iptables_get_name(TRUE, "nm-sh-fw", ip_iface);
|
||||||
|
|
||||||
if (up)
|
if (up)
|
||||||
_share_iptables_set_shared_chains_add(chain_input, chain_forward, ip_iface, addr, plen);
|
_share_iptables_set_shared_chains_add(chain_input, chain_forward, ip_iface, addr, plen);
|
||||||
|
|
||||||
_share_iptables_call("--table",
|
_ipxtables_call(AF_INET,
|
||||||
"filter",
|
"--table",
|
||||||
up ? "--insert" : "--delete",
|
"filter",
|
||||||
"INPUT",
|
up ? "--insert" : "--delete",
|
||||||
"--in-interface",
|
"INPUT",
|
||||||
ip_iface,
|
"--in-interface",
|
||||||
"--jump",
|
ip_iface,
|
||||||
chain_input,
|
"--jump",
|
||||||
"-m",
|
chain_input,
|
||||||
"comment",
|
"-m",
|
||||||
"--comment",
|
"comment",
|
||||||
comment_name);
|
"--comment",
|
||||||
|
comment_name);
|
||||||
|
|
||||||
_share_iptables_call("--table",
|
_ipxtables_call(AF_INET,
|
||||||
"filter",
|
"--table",
|
||||||
up ? "--insert" : "--delete",
|
"filter",
|
||||||
"FORWARD",
|
up ? "--insert" : "--delete",
|
||||||
"--jump",
|
"FORWARD",
|
||||||
chain_forward,
|
"--jump",
|
||||||
"-m",
|
chain_forward,
|
||||||
"comment",
|
"-m",
|
||||||
"--comment",
|
"comment",
|
||||||
comment_name);
|
"--comment",
|
||||||
|
comment_name);
|
||||||
|
|
||||||
if (!up)
|
if (!up)
|
||||||
_share_iptables_set_shared_chains_delete(chain_input, chain_forward);
|
_share_iptables_set_shared_chains_delete(chain_input, chain_forward);
|
||||||
|
|
@ -460,19 +474,19 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user
|
||||||
/* on any error, the process might still be running. We need to abort it in
|
/* on any error, the process might still be running. We need to abort it in
|
||||||
* the background... */
|
* the background... */
|
||||||
if (!nm_utils_error_is_cancelled(error)) {
|
if (!nm_utils_error_is_cancelled(error)) {
|
||||||
nm_log_dbg(LOGD_SHARING,
|
nm_log_dbg(LOGD_FIREWALL,
|
||||||
"firewall: nft[%s]: communication failed: %s. Kill process",
|
"firewall: nft[%s]: communication failed: %s. Kill process",
|
||||||
call_data->identifier,
|
call_data->identifier,
|
||||||
error->message);
|
error->message);
|
||||||
} else if (!call_data->timeout_source) {
|
} else if (!call_data->timeout_source) {
|
||||||
nm_log_dbg(LOGD_SHARING,
|
nm_log_dbg(LOGD_FIREWALL,
|
||||||
"firewall: ntf[%s]: communication timed out. Kill process",
|
"firewall: nft[%s]: communication timed out. Kill process",
|
||||||
call_data->identifier);
|
call_data->identifier);
|
||||||
nm_clear_error(&error);
|
nm_clear_error(&error);
|
||||||
nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "timeout communicating with nft");
|
nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "timeout communicating with nft");
|
||||||
} else {
|
} else {
|
||||||
nm_log_dbg(LOGD_SHARING,
|
nm_log_dbg(LOGD_FIREWALL,
|
||||||
"firewall: ntf[%s]: communication cancelled. Kill process",
|
"firewall: nft[%s]: communication cancelled. Kill process",
|
||||||
call_data->identifier);
|
call_data->identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,7 +499,7 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user
|
||||||
nm_g_subprocess_terminate_in_background(call_data->subprocess, 200);
|
nm_g_subprocess_terminate_in_background(call_data->subprocess, 200);
|
||||||
}
|
}
|
||||||
} else if (g_subprocess_get_successful(call_data->subprocess)) {
|
} else if (g_subprocess_get_successful(call_data->subprocess)) {
|
||||||
nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: command successful", call_data->identifier);
|
nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: command successful", call_data->identifier);
|
||||||
} else {
|
} else {
|
||||||
char buf[NM_UTILS_GET_PROCESS_EXIT_STATUS_BUF_LEN];
|
char buf[NM_UTILS_GET_PROCESS_EXIT_STATUS_BUF_LEN];
|
||||||
gs_free char *ss_stdout = NULL;
|
gs_free char *ss_stdout = NULL;
|
||||||
|
|
@ -498,7 +512,7 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user
|
||||||
|
|
||||||
nm_utils_get_process_exit_status_desc_buf(status, buf, sizeof(buf));
|
nm_utils_get_process_exit_status_desc_buf(status, buf, sizeof(buf));
|
||||||
|
|
||||||
nm_log_warn(LOGD_SHARING,
|
nm_log_warn(LOGD_FIREWALL,
|
||||||
"firewall: nft[%s]: command %s:%s%s%s%s%s%s%s",
|
"firewall: nft[%s]: command %s:%s%s%s%s%s%s%s",
|
||||||
call_data->identifier,
|
call_data->identifier,
|
||||||
buf,
|
buf,
|
||||||
|
|
@ -534,7 +548,7 @@ _fw_nft_call_cancelled_cb(GCancellable *cancellable, gpointer user_data)
|
||||||
if (call_data->cancellable_id == 0)
|
if (call_data->cancellable_id == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: operation cancelled", call_data->identifier);
|
nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: operation cancelled", call_data->identifier);
|
||||||
|
|
||||||
nm_clear_g_signal_handler(g_task_get_cancellable(call_data->task), &call_data->cancellable_id);
|
nm_clear_g_signal_handler(g_task_get_cancellable(call_data->task), &call_data->cancellable_id);
|
||||||
nm_clear_g_cancellable(&call_data->intern_cancellable);
|
nm_clear_g_cancellable(&call_data->intern_cancellable);
|
||||||
|
|
@ -546,7 +560,7 @@ _fw_nft_call_timeout_cb(gpointer user_data)
|
||||||
FwNftCallData *call_data = user_data;
|
FwNftCallData *call_data = user_data;
|
||||||
|
|
||||||
nm_clear_g_source_inst(&call_data->timeout_source);
|
nm_clear_g_source_inst(&call_data->timeout_source);
|
||||||
nm_log_dbg(LOGD_SHARING,
|
nm_log_dbg(LOGD_FIREWALL,
|
||||||
"firewall: nft[%s]: cancel operation after timeout",
|
"firewall: nft[%s]: cancel operation after timeout",
|
||||||
call_data->identifier);
|
call_data->identifier);
|
||||||
|
|
||||||
|
|
@ -573,7 +587,7 @@ nm_firewall_nft_call(GBytes *stdin_buf,
|
||||||
.timeout_source = NULL,
|
.timeout_source = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
nm_log_trace(LOGD_SHARING,
|
nm_log_trace(LOGD_FIREWALL,
|
||||||
"firewall: nft: call command: [ '%s' ]",
|
"firewall: nft: call command: [ '%s' ]",
|
||||||
nm_utils_buf_utf8safe_escape_bytes(stdin_buf,
|
nm_utils_buf_utf8safe_escape_bytes(stdin_buf,
|
||||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL,
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL,
|
||||||
|
|
@ -585,7 +599,7 @@ nm_firewall_nft_call(GBytes *stdin_buf,
|
||||||
call_data,
|
call_data,
|
||||||
NULL);
|
NULL);
|
||||||
if (call_data->cancellable_id == 0) {
|
if (call_data->cancellable_id == 0) {
|
||||||
nm_log_dbg(LOGD_SHARING, "firewall: nft: already cancelled");
|
nm_log_dbg(LOGD_FIREWALL, "firewall: nft: already cancelled");
|
||||||
nm_utils_error_set_cancelled(&error, FALSE, NULL);
|
nm_utils_error_set_cancelled(&error, FALSE, NULL);
|
||||||
_fw_nft_call_data_free(call_data, g_steal_pointer(&error));
|
_fw_nft_call_data_free(call_data, g_steal_pointer(&error));
|
||||||
return;
|
return;
|
||||||
|
|
@ -602,14 +616,14 @@ nm_firewall_nft_call(GBytes *stdin_buf,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
if (!call_data->subprocess) {
|
if (!call_data->subprocess) {
|
||||||
nm_log_dbg(LOGD_SHARING, "firewall: nft: spawning nft failed: %s", error->message);
|
nm_log_dbg(LOGD_FIREWALL, "firewall: nft: spawning nft failed: %s", error->message);
|
||||||
_fw_nft_call_data_free(call_data, g_steal_pointer(&error));
|
_fw_nft_call_data_free(call_data, g_steal_pointer(&error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_data->identifier = g_strdup(g_subprocess_get_identifier(call_data->subprocess));
|
call_data->identifier = g_strdup(g_subprocess_get_identifier(call_data->subprocess));
|
||||||
|
|
||||||
nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: communicate with nft", call_data->identifier);
|
nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: communicate with nft", call_data->identifier);
|
||||||
|
|
||||||
nm_shutdown_wait_obj_register_object(call_data->task, "nft-call");
|
nm_shutdown_wait_obj_register_object(call_data->task, "nft-call");
|
||||||
|
|
||||||
|
|
@ -691,7 +705,7 @@ _fw_nft_set_shared_construct(gboolean up, const char *ip_iface, in_addr_t addr,
|
||||||
gs_free char *table_name = NULL;
|
gs_free char *table_name = NULL;
|
||||||
char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN];
|
char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN];
|
||||||
|
|
||||||
table_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface);
|
table_name = _iptables_get_name(FALSE, "nm-shared", ip_iface);
|
||||||
|
|
||||||
_share_iptables_subnet_to_str(str_subnet, addr, plen);
|
_share_iptables_subnet_to_str(str_subnet, addr, plen);
|
||||||
|
|
||||||
|
|
@ -756,6 +770,141 @@ _fw_nft_set_shared_construct(gboolean up, const char *ip_iface, in_addr_t addr,
|
||||||
return nm_str_buf_finalize_to_gbytes(&strbuf);
|
return nm_str_buf_finalize_to_gbytes(&strbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
_fw_nft_wg_default_construct(const char *ip_iface,
|
||||||
|
NMSettingIPConfig *ip_config,
|
||||||
|
int fwmark,
|
||||||
|
gboolean up)
|
||||||
|
{
|
||||||
|
nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
|
||||||
|
gs_free char *table_name = NULL;
|
||||||
|
const char *family_str;
|
||||||
|
|
||||||
|
table_name = _iptables_get_name(FALSE, "nm-wg", ip_iface);
|
||||||
|
family_str = nm_setting_ip_config_get_addr_family(ip_config) == AF_INET ? "ip" : "ip6";
|
||||||
|
|
||||||
|
_fw_nft_append_cmd_table(&strbuf, family_str, table_name, up);
|
||||||
|
|
||||||
|
if (up) {
|
||||||
|
guint n_addresses = nm_setting_ip_config_get_num_addresses(ip_config);
|
||||||
|
|
||||||
|
if (n_addresses) {
|
||||||
|
_append(&strbuf, "add chain %s %s preraw {", family_str, table_name);
|
||||||
|
|
||||||
|
for (guint i = 0; i < n_addresses; i++) {
|
||||||
|
NMIPAddress *addr = nm_setting_ip_config_get_address(ip_config, i);
|
||||||
|
|
||||||
|
_append(&strbuf,
|
||||||
|
" iifname != \"%s\" "
|
||||||
|
" %s daddr %s "
|
||||||
|
" fib saddr type != local "
|
||||||
|
"drop;",
|
||||||
|
ip_iface,
|
||||||
|
family_str,
|
||||||
|
nm_ip_address_get_address(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
_append(&strbuf, "};");
|
||||||
|
}
|
||||||
|
|
||||||
|
_append(&strbuf,
|
||||||
|
"add chain %s %s premangle {"
|
||||||
|
" type filter hook prerouting priority mangle; policy accept; "
|
||||||
|
" meta l4proto udp meta mark set ct mark; "
|
||||||
|
"};",
|
||||||
|
family_str,
|
||||||
|
table_name);
|
||||||
|
|
||||||
|
_append(&strbuf,
|
||||||
|
"add chain %s %s postmangle {"
|
||||||
|
" type filter hook postrouting priority mangle; policy accept; "
|
||||||
|
" meta l4proto udp mark 0x%08x ct mark set meta mark; "
|
||||||
|
"};",
|
||||||
|
family_str,
|
||||||
|
table_name,
|
||||||
|
fwmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nm_str_buf_finalize_to_gbytes(&strbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_fw_iptables_wg_configure(const char *ip_iface,
|
||||||
|
NMSettingIPConfig *ip_config,
|
||||||
|
int fwmark,
|
||||||
|
gboolean up)
|
||||||
|
{
|
||||||
|
gs_free char *comment_name = NULL;
|
||||||
|
char fwmark_str[11];
|
||||||
|
int family = nm_setting_ip_config_get_addr_family(ip_config);
|
||||||
|
guint n_addresses = nm_setting_ip_config_get_num_addresses(ip_config);
|
||||||
|
|
||||||
|
comment_name = _iptables_get_name(FALSE, "nm-wg", ip_iface);
|
||||||
|
g_snprintf(fwmark_str, sizeof(fwmark_str), "%" G_GUINT32_FORMAT, fwmark);
|
||||||
|
|
||||||
|
nm_assert(strlen(fwmark_str) > 0);
|
||||||
|
|
||||||
|
for (guint i = 0; i < n_addresses; i++) {
|
||||||
|
NMIPAddress *addr = nm_setting_ip_config_get_address(ip_config, i);
|
||||||
|
|
||||||
|
_ipxtables_call(family,
|
||||||
|
"--table",
|
||||||
|
"raw",
|
||||||
|
up ? "--insert" : "--delete",
|
||||||
|
"PREROUTING",
|
||||||
|
"!",
|
||||||
|
"--in-interface",
|
||||||
|
ip_iface,
|
||||||
|
"--destination",
|
||||||
|
nm_ip_address_get_address(addr),
|
||||||
|
"--match",
|
||||||
|
"addrtype",
|
||||||
|
"!",
|
||||||
|
"--src-type",
|
||||||
|
"LOCAL",
|
||||||
|
"-j",
|
||||||
|
"DROP",
|
||||||
|
"-m",
|
||||||
|
"comment",
|
||||||
|
"--comment",
|
||||||
|
comment_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ipxtables_call(family,
|
||||||
|
"--table",
|
||||||
|
"mangle",
|
||||||
|
up ? "--insert" : "--delete",
|
||||||
|
"POSTROUTING",
|
||||||
|
"--match",
|
||||||
|
"mark",
|
||||||
|
"--mark",
|
||||||
|
fwmark_str,
|
||||||
|
"--protocol",
|
||||||
|
"udp",
|
||||||
|
"--jump",
|
||||||
|
"CONNMARK",
|
||||||
|
"--save-mark",
|
||||||
|
"-m",
|
||||||
|
"comment",
|
||||||
|
"--comment",
|
||||||
|
comment_name);
|
||||||
|
|
||||||
|
_ipxtables_call(family,
|
||||||
|
"--table",
|
||||||
|
"mangle",
|
||||||
|
up ? "--insert" : "--delete",
|
||||||
|
"PREROUTING",
|
||||||
|
"--protocol",
|
||||||
|
"udp",
|
||||||
|
"--jump",
|
||||||
|
"CONNMARK",
|
||||||
|
"--restore-mark",
|
||||||
|
"-m",
|
||||||
|
"comment",
|
||||||
|
"--comment",
|
||||||
|
comment_name);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
GBytes *
|
GBytes *
|
||||||
|
|
@ -1046,6 +1195,31 @@ nm_firewall_config_free(NMFirewallConfig *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
void
|
||||||
|
nm_firewall_config_set_wg_rule(const char *ifname,
|
||||||
|
NMSettingIPConfig *ip_config,
|
||||||
|
int fwmark,
|
||||||
|
gboolean up)
|
||||||
|
{
|
||||||
|
switch (nm_firewall_utils_get_backend()) {
|
||||||
|
case NM_FIREWALL_BACKEND_NFTABLES:
|
||||||
|
{
|
||||||
|
gs_unref_bytes GBytes *stdin_buf = NULL;
|
||||||
|
|
||||||
|
stdin_buf = _fw_nft_wg_default_construct(ifname, ip_config, fwmark, up);
|
||||||
|
_fw_nft_call_sync(stdin_buf, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NM_FIREWALL_BACKEND_IPTABLES:
|
||||||
|
_fw_iptables_wg_configure(ifname, ip_config, fwmark, up);
|
||||||
|
break;
|
||||||
|
case NM_FIREWALL_BACKEND_NONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nm_assert_not_reached();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up)
|
nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up)
|
||||||
|
|
@ -1124,7 +1298,7 @@ again:
|
||||||
if (!g_atomic_int_compare_and_exchange(&backend, NM_FIREWALL_BACKEND_UNKNOWN, b))
|
if (!g_atomic_int_compare_and_exchange(&backend, NM_FIREWALL_BACKEND_UNKNOWN, b))
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
nm_log_dbg(LOGD_SHARING,
|
nm_log_dbg(LOGD_FIREWALL,
|
||||||
"firewall: use %s backend%s%s%s%s%s%s%s",
|
"firewall: use %s backend%s%s%s%s%s%s%s",
|
||||||
FirewallBackends[b - 1].name,
|
FirewallBackends[b - 1].name,
|
||||||
NM_PRINT_FMT_QUOTED(FirewallBackends[b - 1].path,
|
NM_PRINT_FMT_QUOTED(FirewallBackends[b - 1].path,
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@ NMFirewallConfig *nm_firewall_config_new_shared(const char *ip_iface, in_addr_t
|
||||||
|
|
||||||
void nm_firewall_config_free(NMFirewallConfig *self);
|
void nm_firewall_config_free(NMFirewallConfig *self);
|
||||||
|
|
||||||
|
void nm_firewall_config_set_wg_rule(const char *ifname,
|
||||||
|
NMSettingIPConfig *ip_config,
|
||||||
|
int fwmark,
|
||||||
|
gboolean up);
|
||||||
|
|
||||||
void nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up);
|
void nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -826,7 +826,7 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
|
||||||
if (v_i != v_i_old)
|
if (v_i != v_i_old)
|
||||||
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_PRIORITY];
|
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_PRIORITY];
|
||||||
|
|
||||||
strarr_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len);
|
strarr_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len_old);
|
||||||
strarr = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
|
strarr = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
|
||||||
if (!nm_strv_equal_n(strarr, len, strarr_old, len_old))
|
if (!nm_strv_equal_n(strarr, len, strarr_old, len_old))
|
||||||
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_OPTIONS];
|
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_OPTIONS];
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GHashTable *config;
|
GHashTable *config;
|
||||||
GHashTable *blobs;
|
GHashTable *blobs;
|
||||||
|
char *private_user;
|
||||||
NMSupplCapMask capabilities;
|
NMSupplCapMask capabilities;
|
||||||
guint32 ap_scan;
|
guint32 ap_scan;
|
||||||
bool fast_required : 1;
|
bool fast_required : 1;
|
||||||
|
|
@ -60,7 +61,7 @@ _get_capability(NMSupplicantConfigPrivate *priv, NMSupplCapType type)
|
||||||
}
|
}
|
||||||
|
|
||||||
NMSupplicantConfig *
|
NMSupplicantConfig *
|
||||||
nm_supplicant_config_new(NMSupplCapMask capabilities)
|
nm_supplicant_config_new(NMSupplCapMask capabilities, const char *private_user)
|
||||||
{
|
{
|
||||||
NMSupplicantConfigPrivate *priv;
|
NMSupplicantConfigPrivate *priv;
|
||||||
NMSupplicantConfig *self;
|
NMSupplicantConfig *self;
|
||||||
|
|
@ -69,6 +70,7 @@ nm_supplicant_config_new(NMSupplCapMask capabilities)
|
||||||
priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE(self);
|
priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE(self);
|
||||||
|
|
||||||
priv->capabilities = capabilities;
|
priv->capabilities = capabilities;
|
||||||
|
priv->private_user = g_strdup(private_user);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -258,19 +260,19 @@ static gboolean
|
||||||
nm_supplicant_config_add_blob_for_connection(NMSupplicantConfig *self,
|
nm_supplicant_config_add_blob_for_connection(NMSupplicantConfig *self,
|
||||||
GBytes *field,
|
GBytes *field,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *con_uid,
|
const char *con_uuid,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (field && g_bytes_get_size(field)) {
|
if (field && g_bytes_get_size(field)) {
|
||||||
gs_free char *uid = NULL;
|
gs_free char *blob_id = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
uid = g_strdup_printf("%s-%s", con_uid, name);
|
blob_id = g_strdup_printf("%s-%s", con_uuid, name);
|
||||||
for (p = uid; *p; p++) {
|
for (p = blob_id; *p; p++) {
|
||||||
if (*p == '/')
|
if (*p == '/')
|
||||||
*p = '-';
|
*p = '-';
|
||||||
}
|
}
|
||||||
if (!nm_supplicant_config_add_blob(self, name, field, uid, error))
|
if (!nm_supplicant_config_add_blob(self, name, field, blob_id, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -283,6 +285,7 @@ nm_supplicant_config_finalize(GObject *object)
|
||||||
|
|
||||||
g_hash_table_destroy(priv->config);
|
g_hash_table_destroy(priv->config);
|
||||||
nm_clear_pointer(&priv->blobs, g_hash_table_destroy);
|
nm_clear_pointer(&priv->blobs, g_hash_table_destroy);
|
||||||
|
nm_clear_pointer(&priv->private_user, g_free);
|
||||||
|
|
||||||
G_OBJECT_CLASS(nm_supplicant_config_parent_class)->finalize(object);
|
G_OBJECT_CLASS(nm_supplicant_config_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
@ -930,6 +933,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
|
||||||
guint32 mtu,
|
guint32 mtu,
|
||||||
NMSettingWirelessSecurityPmf pmf,
|
NMSettingWirelessSecurityPmf pmf,
|
||||||
NMSettingWirelessSecurityFils fils,
|
NMSettingWirelessSecurityFils fils,
|
||||||
|
GHashTable *files,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE(self);
|
NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE(self);
|
||||||
|
|
@ -1284,6 +1288,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
|
||||||
con_uuid,
|
con_uuid,
|
||||||
mtu,
|
mtu,
|
||||||
FALSE,
|
FALSE,
|
||||||
|
files,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -1365,6 +1370,7 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
const char *con_uuid,
|
const char *con_uuid,
|
||||||
guint32 mtu,
|
guint32 mtu,
|
||||||
gboolean wired,
|
gboolean wired,
|
||||||
|
GHashTable *files,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
NMSupplicantConfigPrivate *priv;
|
NMSupplicantConfigPrivate *priv;
|
||||||
|
|
@ -1594,24 +1600,21 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CA certificate */
|
/* CA certificate */
|
||||||
|
path = NULL;
|
||||||
|
bytes = NULL;
|
||||||
if (ca_cert_override) {
|
if (ca_cert_override) {
|
||||||
if (!add_string_val(self, ca_cert_override, "ca_cert", FALSE, NULL, error))
|
/* This is a build-time-configured system-wide file path, no need to pass
|
||||||
return FALSE;
|
* it as a blob */
|
||||||
|
path = ca_cert_override;
|
||||||
} else {
|
} else {
|
||||||
switch (nm_setting_802_1x_get_ca_cert_scheme(setting)) {
|
switch (nm_setting_802_1x_get_ca_cert_scheme(setting)) {
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||||
bytes = nm_setting_802_1x_get_ca_cert_blob(setting);
|
bytes = nm_setting_802_1x_get_ca_cert_blob(setting);
|
||||||
if (!nm_supplicant_config_add_blob_for_connection(self,
|
|
||||||
bytes,
|
|
||||||
"ca_cert",
|
|
||||||
con_uuid,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
path = nm_setting_802_1x_get_ca_cert_path(setting);
|
path = nm_setting_802_1x_get_ca_cert_path(setting);
|
||||||
if (!add_string_val(self, path, "ca_cert", FALSE, NULL, error))
|
if (priv->private_user)
|
||||||
return FALSE;
|
bytes = nm_g_hash_table_lookup(files, path);
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||||
if (!add_pkcs11_uri_with_pin(self,
|
if (!add_pkcs11_uri_with_pin(self,
|
||||||
|
|
@ -1627,26 +1630,32 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bytes) {
|
||||||
|
if (!nm_supplicant_config_add_blob_for_connection(self, bytes, "ca_cert", con_uuid, error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (path) {
|
||||||
|
/* Private connections cannot use paths other than the system CA store */
|
||||||
|
g_return_val_if_fail(ca_cert_override || !priv->private_user, FALSE);
|
||||||
|
if (!add_string_val(self, path, "ca_cert", FALSE, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Phase 2 CA certificate */
|
/* Phase 2 CA certificate */
|
||||||
|
path = NULL;
|
||||||
|
bytes = NULL;
|
||||||
if (ca_cert_override) {
|
if (ca_cert_override) {
|
||||||
if (!add_string_val(self, ca_cert_override, "ca_cert2", FALSE, NULL, error))
|
/* This is a build-time-configured system-wide file path, no need to pass
|
||||||
return FALSE;
|
* it as a blob */
|
||||||
|
path = ca_cert_override;
|
||||||
} else {
|
} else {
|
||||||
switch (nm_setting_802_1x_get_phase2_ca_cert_scheme(setting)) {
|
switch (nm_setting_802_1x_get_phase2_ca_cert_scheme(setting)) {
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||||
bytes = nm_setting_802_1x_get_phase2_ca_cert_blob(setting);
|
bytes = nm_setting_802_1x_get_phase2_ca_cert_blob(setting);
|
||||||
if (!nm_supplicant_config_add_blob_for_connection(self,
|
|
||||||
bytes,
|
|
||||||
"ca_cert2",
|
|
||||||
con_uuid,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
path = nm_setting_802_1x_get_phase2_ca_cert_path(setting);
|
path = nm_setting_802_1x_get_phase2_ca_cert_path(setting);
|
||||||
if (!add_string_val(self, path, "ca_cert2", FALSE, NULL, error))
|
if (priv->private_user)
|
||||||
return FALSE;
|
bytes = nm_g_hash_table_lookup(files, path);
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||||
if (!add_pkcs11_uri_with_pin(
|
if (!add_pkcs11_uri_with_pin(
|
||||||
|
|
@ -1663,6 +1672,15 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bytes) {
|
||||||
|
if (!nm_supplicant_config_add_blob_for_connection(self, bytes, "ca_cert2", con_uuid, error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (path) {
|
||||||
|
/* Private connections cannot use paths other than the system CA store */
|
||||||
|
g_return_val_if_fail(ca_cert_override || !priv->private_user, FALSE);
|
||||||
|
if (!add_string_val(self, path, "ca_cert2", FALSE, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Subject match */
|
/* Subject match */
|
||||||
value = nm_setting_802_1x_get_subject_match(setting);
|
value = nm_setting_802_1x_get_subject_match(setting);
|
||||||
|
|
@ -1714,21 +1732,17 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
|
|
||||||
/* Private key */
|
/* Private key */
|
||||||
added = FALSE;
|
added = FALSE;
|
||||||
|
path = NULL;
|
||||||
|
bytes = NULL;
|
||||||
switch (nm_setting_802_1x_get_private_key_scheme(setting)) {
|
switch (nm_setting_802_1x_get_private_key_scheme(setting)) {
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||||
bytes = nm_setting_802_1x_get_private_key_blob(setting);
|
bytes = nm_setting_802_1x_get_private_key_blob(setting);
|
||||||
if (!nm_supplicant_config_add_blob_for_connection(self,
|
|
||||||
bytes,
|
|
||||||
"private_key",
|
|
||||||
con_uuid,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
added = TRUE;
|
added = TRUE;
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
path = nm_setting_802_1x_get_private_key_path(setting);
|
path = nm_setting_802_1x_get_private_key_path(setting);
|
||||||
if (!add_string_val(self, path, "private_key", FALSE, NULL, error))
|
if (priv->private_user)
|
||||||
return FALSE;
|
bytes = nm_g_hash_table_lookup(files, path);
|
||||||
added = TRUE;
|
added = TRUE;
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||||
|
|
@ -1745,6 +1759,19 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (bytes) {
|
||||||
|
if (!nm_supplicant_config_add_blob_for_connection(self,
|
||||||
|
bytes,
|
||||||
|
"private_key",
|
||||||
|
con_uuid,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (path) {
|
||||||
|
/* Private connections cannot use paths */
|
||||||
|
g_return_val_if_fail(!priv->private_user, FALSE);
|
||||||
|
if (!add_string_val(self, path, "private_key", FALSE, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (added) {
|
if (added) {
|
||||||
NMSetting8021xCKFormat format;
|
NMSetting8021xCKFormat format;
|
||||||
|
|
@ -1768,20 +1795,16 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
/* Only add the client cert if the private key is not PKCS#12, as
|
/* Only add the client cert if the private key is not PKCS#12, as
|
||||||
* wpa_supplicant configuration directs us to do.
|
* wpa_supplicant configuration directs us to do.
|
||||||
*/
|
*/
|
||||||
|
path = NULL;
|
||||||
|
bytes = NULL;
|
||||||
switch (nm_setting_802_1x_get_client_cert_scheme(setting)) {
|
switch (nm_setting_802_1x_get_client_cert_scheme(setting)) {
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||||
bytes = nm_setting_802_1x_get_client_cert_blob(setting);
|
bytes = nm_setting_802_1x_get_client_cert_blob(setting);
|
||||||
if (!nm_supplicant_config_add_blob_for_connection(self,
|
|
||||||
bytes,
|
|
||||||
"client_cert",
|
|
||||||
con_uuid,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
path = nm_setting_802_1x_get_client_cert_path(setting);
|
path = nm_setting_802_1x_get_client_cert_path(setting);
|
||||||
if (!add_string_val(self, path, "client_cert", FALSE, NULL, error))
|
if (priv->private_user)
|
||||||
return FALSE;
|
bytes = nm_g_hash_table_lookup(files, path);
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||||
if (!add_pkcs11_uri_with_pin(
|
if (!add_pkcs11_uri_with_pin(
|
||||||
|
|
@ -1797,26 +1820,35 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (bytes) {
|
||||||
|
if (!nm_supplicant_config_add_blob_for_connection(self,
|
||||||
|
bytes,
|
||||||
|
"client_cert",
|
||||||
|
con_uuid,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (path) {
|
||||||
|
/* Private connections cannot use paths */
|
||||||
|
g_return_val_if_fail(!priv->private_user, FALSE);
|
||||||
|
if (!add_string_val(self, path, "client_cert", FALSE, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Phase 2 private key */
|
/* Phase 2 private key */
|
||||||
added = FALSE;
|
added = FALSE;
|
||||||
|
path = NULL;
|
||||||
|
bytes = NULL;
|
||||||
switch (nm_setting_802_1x_get_phase2_private_key_scheme(setting)) {
|
switch (nm_setting_802_1x_get_phase2_private_key_scheme(setting)) {
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||||
bytes = nm_setting_802_1x_get_phase2_private_key_blob(setting);
|
bytes = nm_setting_802_1x_get_phase2_private_key_blob(setting);
|
||||||
if (!nm_supplicant_config_add_blob_for_connection(self,
|
|
||||||
bytes,
|
|
||||||
"private_key2",
|
|
||||||
con_uuid,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
added = TRUE;
|
added = TRUE;
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
path = nm_setting_802_1x_get_phase2_private_key_path(setting);
|
path = nm_setting_802_1x_get_phase2_private_key_path(setting);
|
||||||
if (!add_string_val(self, path, "private_key2", FALSE, NULL, error))
|
if (priv->private_user)
|
||||||
return FALSE;
|
bytes = nm_g_hash_table_lookup(files, path);
|
||||||
added = TRUE;
|
added = TRUE;
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||||
|
|
@ -1834,6 +1866,19 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (bytes) {
|
||||||
|
if (!nm_supplicant_config_add_blob_for_connection(self,
|
||||||
|
bytes,
|
||||||
|
"private_key2",
|
||||||
|
con_uuid,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (path) {
|
||||||
|
/* Private connections cannot use paths */
|
||||||
|
g_return_val_if_fail(!priv->private_user, FALSE);
|
||||||
|
if (!add_string_val(self, path, "private_key2", FALSE, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (added) {
|
if (added) {
|
||||||
NMSetting8021xCKFormat format;
|
NMSetting8021xCKFormat format;
|
||||||
|
|
@ -1857,20 +1902,16 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
/* Only add the client cert if the private key is not PKCS#12, as
|
/* Only add the client cert if the private key is not PKCS#12, as
|
||||||
* wpa_supplicant configuration directs us to do.
|
* wpa_supplicant configuration directs us to do.
|
||||||
*/
|
*/
|
||||||
|
path = NULL;
|
||||||
|
bytes = NULL;
|
||||||
switch (nm_setting_802_1x_get_phase2_client_cert_scheme(setting)) {
|
switch (nm_setting_802_1x_get_phase2_client_cert_scheme(setting)) {
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||||
bytes = nm_setting_802_1x_get_phase2_client_cert_blob(setting);
|
bytes = nm_setting_802_1x_get_phase2_client_cert_blob(setting);
|
||||||
if (!nm_supplicant_config_add_blob_for_connection(self,
|
|
||||||
bytes,
|
|
||||||
"client_cert2",
|
|
||||||
con_uuid,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||||
path = nm_setting_802_1x_get_phase2_client_cert_path(setting);
|
path = nm_setting_802_1x_get_phase2_client_cert_path(setting);
|
||||||
if (!add_string_val(self, path, "client_cert2", FALSE, NULL, error))
|
if (priv->private_user)
|
||||||
return FALSE;
|
bytes = nm_g_hash_table_lookup(files, path);
|
||||||
break;
|
break;
|
||||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||||
if (!add_pkcs11_uri_with_pin(
|
if (!add_pkcs11_uri_with_pin(
|
||||||
|
|
@ -1886,6 +1927,19 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (bytes) {
|
||||||
|
if (!nm_supplicant_config_add_blob_for_connection(self,
|
||||||
|
bytes,
|
||||||
|
"client_cert2",
|
||||||
|
con_uuid,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (path) {
|
||||||
|
/* Private connections cannot use paths */
|
||||||
|
g_return_val_if_fail(!priv->private_user, FALSE);
|
||||||
|
if (!add_string_val(self, path, "client_cert2", FALSE, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ typedef struct _NMSupplicantConfigClass NMSupplicantConfigClass;
|
||||||
|
|
||||||
GType nm_supplicant_config_get_type(void);
|
GType nm_supplicant_config_get_type(void);
|
||||||
|
|
||||||
NMSupplicantConfig *nm_supplicant_config_new(NMSupplCapMask capabilities);
|
NMSupplicantConfig *nm_supplicant_config_new(NMSupplCapMask capabilities, const char *private_user);
|
||||||
|
|
||||||
guint32 nm_supplicant_config_get_ap_scan(NMSupplicantConfig *self);
|
guint32 nm_supplicant_config_get_ap_scan(NMSupplicantConfig *self);
|
||||||
|
|
||||||
|
|
@ -57,6 +57,7 @@ gboolean nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
|
||||||
guint32 mtu,
|
guint32 mtu,
|
||||||
NMSettingWirelessSecurityPmf pmf,
|
NMSettingWirelessSecurityPmf pmf,
|
||||||
NMSettingWirelessSecurityFils fils,
|
NMSettingWirelessSecurityFils fils,
|
||||||
|
GHashTable *files,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean nm_supplicant_config_add_no_security(NMSupplicantConfig *self, GError **error);
|
gboolean nm_supplicant_config_add_no_security(NMSupplicantConfig *self, GError **error);
|
||||||
|
|
@ -66,6 +67,7 @@ gboolean nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
||||||
const char *con_uuid,
|
const char *con_uuid,
|
||||||
guint32 mtu,
|
guint32 mtu,
|
||||||
gboolean wired,
|
gboolean wired,
|
||||||
|
GHashTable *files,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self,
|
gboolean nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self,
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ typedef struct {
|
||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
guint fail_on_idle_id;
|
guint fail_on_idle_id;
|
||||||
guint blobs_left;
|
guint blobs_left;
|
||||||
|
guint remove_blobs_left;
|
||||||
guint calls_left;
|
guint calls_left;
|
||||||
struct _AddNetworkData *add_network_data;
|
struct _AddNetworkData *add_network_data;
|
||||||
} AssocData;
|
} AssocData;
|
||||||
|
|
@ -2264,6 +2265,7 @@ assoc_add_blob_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nm_assert(priv->assoc_data->blobs_left > 0);
|
||||||
priv->assoc_data->blobs_left--;
|
priv->assoc_data->blobs_left--;
|
||||||
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: blob added (%u left)",
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: blob added (%u left)",
|
||||||
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
|
@ -2272,6 +2274,148 @@ assoc_add_blob_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
assoc_call_select_network(self);
|
assoc_call_select_network(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assoc_add_blobs(NMSupplicantInterface *self)
|
||||||
|
{
|
||||||
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self);
|
||||||
|
GHashTable *blobs;
|
||||||
|
GHashTableIter iter;
|
||||||
|
const char *blob_name;
|
||||||
|
GBytes *blob_data;
|
||||||
|
|
||||||
|
blobs = nm_supplicant_config_get_blobs(priv->assoc_data->cfg);
|
||||||
|
priv->assoc_data->blobs_left = nm_g_hash_table_size(blobs);
|
||||||
|
|
||||||
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: need to add %u blobs",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
priv->assoc_data->blobs_left);
|
||||||
|
|
||||||
|
if (priv->assoc_data->blobs_left == 0) {
|
||||||
|
assoc_call_select_network(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init(&iter, blobs);
|
||||||
|
while (g_hash_table_iter_next(&iter, (gpointer) &blob_name, (gpointer) &blob_data)) {
|
||||||
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: adding blob '%s'",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
blob_name);
|
||||||
|
_dbus_connection_call(
|
||||||
|
self,
|
||||||
|
NM_WPAS_DBUS_IFACE_INTERFACE,
|
||||||
|
"AddBlob",
|
||||||
|
g_variant_new("(s@ay)", blob_name, nm_g_bytes_to_variant_ay(blob_data)),
|
||||||
|
G_VARIANT_TYPE("()"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
DBUS_TIMEOUT_MSEC,
|
||||||
|
priv->assoc_data->cancellable,
|
||||||
|
assoc_add_blob_cb,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assoc_remove_blob_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
|
{
|
||||||
|
NMSupplicantInterface *self;
|
||||||
|
NMSupplicantInterfacePrivate *priv;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
gs_unref_variant GVariant *res = NULL;
|
||||||
|
|
||||||
|
res = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error);
|
||||||
|
if (nm_utils_error_is_cancelled(error))
|
||||||
|
return;
|
||||||
|
|
||||||
|
self = NM_SUPPLICANT_INTERFACE(user_data);
|
||||||
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
/* We don't consider a failure fatal. The new association might be able
|
||||||
|
* to proceed even with the existing blobs, if they don't conflict with new
|
||||||
|
* ones. */
|
||||||
|
|
||||||
|
nm_assert(priv->assoc_data->remove_blobs_left > 0);
|
||||||
|
priv->assoc_data->remove_blobs_left--;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
g_dbus_error_strip_remote_error(error);
|
||||||
|
_LOGD("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: failed to delete blob: %s",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
error->message);
|
||||||
|
} else {
|
||||||
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: blob removed (%u left)",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
priv->assoc_data->remove_blobs_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->assoc_data->remove_blobs_left == 0)
|
||||||
|
assoc_add_blobs(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assoc_get_blobs_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
|
{
|
||||||
|
NMSupplicantInterface *self;
|
||||||
|
NMSupplicantInterfacePrivate *priv;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
gs_unref_variant GVariant *res = NULL;
|
||||||
|
gs_unref_variant GVariant *value = NULL;
|
||||||
|
GVariantIter iter;
|
||||||
|
const char *blob_name;
|
||||||
|
GVariant *blob_data;
|
||||||
|
|
||||||
|
res = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error);
|
||||||
|
if (nm_utils_error_is_cancelled(error))
|
||||||
|
return;
|
||||||
|
|
||||||
|
self = NM_SUPPLICANT_INTERFACE(user_data);
|
||||||
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
_LOGD("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: failed to get blob list: %s",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
error->message);
|
||||||
|
assoc_add_blobs(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get(res, "(v)", &value);
|
||||||
|
|
||||||
|
/* While the "Blobs" property is documented as type "as", it is actually "a{say}" */
|
||||||
|
if (!value || !g_variant_is_of_type(value, G_VARIANT_TYPE("a{say}"))) {
|
||||||
|
_LOGD("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: failed to get blob list: wrong return type %s",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
value ? g_variant_get_type_string(value) : "NULL");
|
||||||
|
assoc_add_blobs(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_iter_init(&iter, value);
|
||||||
|
priv->assoc_data->remove_blobs_left = g_variant_iter_n_children(&iter);
|
||||||
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: need to delete %u blobs",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
priv->assoc_data->remove_blobs_left);
|
||||||
|
|
||||||
|
if (priv->assoc_data->remove_blobs_left == 0) {
|
||||||
|
assoc_add_blobs(self);
|
||||||
|
} else {
|
||||||
|
while (g_variant_iter_loop(&iter, "{&s@ay}", &blob_name, &blob_data)) {
|
||||||
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: removing blob '%s'",
|
||||||
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
|
blob_name);
|
||||||
|
_dbus_connection_call(self,
|
||||||
|
NM_WPAS_DBUS_IFACE_INTERFACE,
|
||||||
|
"RemoveBlob",
|
||||||
|
g_variant_new("(s)", blob_name),
|
||||||
|
G_VARIANT_TYPE("()"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
DBUS_TIMEOUT_MSEC,
|
||||||
|
priv->assoc_data->cancellable,
|
||||||
|
assoc_remove_blob_cb,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assoc_add_network_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
assoc_add_network_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
|
@ -2279,12 +2423,8 @@ assoc_add_network_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
AssocData *assoc_data;
|
AssocData *assoc_data;
|
||||||
NMSupplicantInterface *self;
|
NMSupplicantInterface *self;
|
||||||
NMSupplicantInterfacePrivate *priv;
|
NMSupplicantInterfacePrivate *priv;
|
||||||
gs_unref_variant GVariant *res = NULL;
|
gs_unref_variant GVariant *res = NULL;
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
GHashTable *blobs;
|
|
||||||
GHashTableIter iter;
|
|
||||||
const char *blob_name;
|
|
||||||
GBytes *blob_data;
|
|
||||||
nm_auto_ref_string NMRefString *name_owner = NULL;
|
nm_auto_ref_string NMRefString *name_owner = NULL;
|
||||||
nm_auto_ref_string NMRefString *object_path = NULL;
|
nm_auto_ref_string NMRefString *object_path = NULL;
|
||||||
|
|
||||||
|
|
@ -2336,34 +2476,21 @@ assoc_add_network_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
nm_assert(!priv->net_path);
|
nm_assert(!priv->net_path);
|
||||||
g_variant_get(res, "(o)", &priv->net_path);
|
g_variant_get(res, "(o)", &priv->net_path);
|
||||||
|
|
||||||
/* Send blobs first; otherwise jump to selecting the network */
|
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: network added (%s)",
|
||||||
blobs = nm_supplicant_config_get_blobs(priv->assoc_data->cfg);
|
|
||||||
priv->assoc_data->blobs_left = blobs ? g_hash_table_size(blobs) : 0u;
|
|
||||||
|
|
||||||
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: network added (%s) (%u blobs left)",
|
|
||||||
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||||
priv->net_path,
|
priv->net_path);
|
||||||
priv->assoc_data->blobs_left);
|
|
||||||
|
|
||||||
if (priv->assoc_data->blobs_left == 0) {
|
/* Delete any existing blobs before adding new ones */
|
||||||
assoc_call_select_network(self);
|
_dbus_connection_call(self,
|
||||||
return;
|
DBUS_INTERFACE_PROPERTIES,
|
||||||
}
|
"Get",
|
||||||
|
g_variant_new("(ss)", NM_WPAS_DBUS_IFACE_INTERFACE, "Blobs"),
|
||||||
g_hash_table_iter_init(&iter, blobs);
|
G_VARIANT_TYPE("(v)"),
|
||||||
while (g_hash_table_iter_next(&iter, (gpointer) &blob_name, (gpointer) &blob_data)) {
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
_dbus_connection_call(
|
DBUS_TIMEOUT_MSEC,
|
||||||
self,
|
priv->assoc_data->cancellable,
|
||||||
NM_WPAS_DBUS_IFACE_INTERFACE,
|
assoc_get_blobs_cb,
|
||||||
"AddBlob",
|
self);
|
||||||
g_variant_new("(s@ay)", blob_name, nm_g_bytes_to_variant_ay(blob_data)),
|
|
||||||
G_VARIANT_TYPE("()"),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
DBUS_TIMEOUT_MSEC,
|
|
||||||
priv->assoc_data->cancellable,
|
|
||||||
assoc_add_blob_cb,
|
|
||||||
self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,8 @@ build_supplicant_config(NMConnection *connection,
|
||||||
NMSetting8021x *s_8021x;
|
NMSetting8021x *s_8021x;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
config = nm_supplicant_config_new(capabilities);
|
config = nm_supplicant_config_new(capabilities,
|
||||||
|
nm_utils_get_connection_first_permissions_user(connection));
|
||||||
|
|
||||||
s_wifi = nm_connection_get_setting_wireless(connection);
|
s_wifi = nm_connection_get_setting_wireless(connection);
|
||||||
g_assert(s_wifi);
|
g_assert(s_wifi);
|
||||||
|
|
@ -120,6 +121,7 @@ build_supplicant_config(NMConnection *connection,
|
||||||
mtu,
|
mtu,
|
||||||
pmf,
|
pmf,
|
||||||
fils,
|
fils,
|
||||||
|
NULL,
|
||||||
&error);
|
&error);
|
||||||
} else {
|
} else {
|
||||||
success = nm_supplicant_config_add_no_security(config, &error);
|
success = nm_supplicant_config_add_no_security(config, &error);
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ test_config_h(void)
|
||||||
G_STMT_END
|
G_STMT_END
|
||||||
|
|
||||||
ABSOLUTE_PATH(IPTABLES_PATH);
|
ABSOLUTE_PATH(IPTABLES_PATH);
|
||||||
|
ABSOLUTE_PATH(IP6TABLES_PATH);
|
||||||
ABSOLUTE_PATH(NFT_PATH);
|
ABSOLUTE_PATH(NFT_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1899,7 +1899,7 @@ _dbus_signal_config_cb(NMVpnConnection *self, GVariant *dict)
|
||||||
_LOGD("config: reply received (IPv4:%s(%s), IPv6:%s(%s))",
|
_LOGD("config: reply received (IPv4:%s(%s), IPv6:%s(%s))",
|
||||||
priv->ip_data_4.enabled ? "on" : "off",
|
priv->ip_data_4.enabled ? "on" : "off",
|
||||||
priv->ip_data_4.method_auto ? "auto" : "disabled",
|
priv->ip_data_4.method_auto ? "auto" : "disabled",
|
||||||
priv->ip_data_4.enabled ? "on" : "off",
|
priv->ip_data_6.enabled ? "on" : "off",
|
||||||
priv->ip_data_6.method_auto ? "auto" : "disabled");
|
priv->ip_data_6.method_auto ? "auto" : "disabled");
|
||||||
|
|
||||||
if (!priv->ip_data_4.method_auto)
|
if (!priv->ip_data_4.method_auto)
|
||||||
|
|
|
||||||
|
|
@ -2048,3 +2048,9 @@ global:
|
||||||
nm_setting_ethtool_fec_mode_get_type;
|
nm_setting_ethtool_fec_mode_get_type;
|
||||||
nm_ethtool_optname_is_fec;
|
nm_ethtool_optname_is_fec;
|
||||||
} libnm_1_50_0;
|
} libnm_1_50_0;
|
||||||
|
|
||||||
|
libnm_1_52_2 {
|
||||||
|
global:
|
||||||
|
nm_utils_copy_cert_as_user;
|
||||||
|
nm_vpn_plugin_info_supports_safe_private_file_access;
|
||||||
|
} libnm_1_52_0;
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,6 @@ if enable_introspection
|
||||||
'LD_LIBRARY_PATH=' + ld_library_path,
|
'LD_LIBRARY_PATH=' + ld_library_path,
|
||||||
python_path,
|
python_path,
|
||||||
gen_gir_cmd,
|
gen_gir_cmd,
|
||||||
'--lib-path', meson.current_build_dir(),
|
|
||||||
'--gir', libnm_gir[0],
|
'--gir', libnm_gir[0],
|
||||||
'--output', '@OUTPUT@',
|
'--output', '@OUTPUT@',
|
||||||
'--target', name
|
'--target', name
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,7 @@ _notify_update_prop_nameservers(NMClient *client,
|
||||||
goto next;
|
goto next;
|
||||||
nameserver = g_steal_pointer(&val_str);
|
nameserver = g_steal_pointer(&val_str);
|
||||||
} else if (nm_streq(key, "uri")) {
|
} else if (nm_streq(key, "uri")) {
|
||||||
|
g_free(nameserver);
|
||||||
nameserver = g_variant_dup_string(val, NULL);
|
nameserver = g_variant_dup_string(val, NULL);
|
||||||
}
|
}
|
||||||
next:
|
next:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ test_units = [
|
||||||
'test-nm-client',
|
'test-nm-client',
|
||||||
'test-remote-settings-client',
|
'test-remote-settings-client',
|
||||||
'test-secret-agent',
|
'test-secret-agent',
|
||||||
|
'test-copy-cert-as-user'
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach test_unit: test_units
|
foreach test_unit: test_units
|
||||||
|
|
@ -37,12 +38,15 @@ foreach test_unit: test_units
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
# test-copy-cert-as-user is a manual test, don't run it automatically
|
||||||
'src/libnm-client-impl/tests/' + test_unit,
|
if test_unit != 'test-copy-cert-as-user'
|
||||||
test_script,
|
test(
|
||||||
timeout: 90,
|
'src/libnm-client-impl/tests/' + test_unit,
|
||||||
args: test_args + [exe.full_path()],
|
test_script,
|
||||||
)
|
timeout: 90,
|
||||||
|
args: test_args + [exe.full_path()],
|
||||||
|
)
|
||||||
|
endif
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
if enable_introspection
|
if enable_introspection
|
||||||
|
|
|
||||||
32
src/libnm-client-impl/tests/test-copy-cert-as-user.c
Normal file
32
src/libnm-client-impl/tests/test-copy-cert-as-user.c
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a program to manually test the
|
||||||
|
* nm_utils_copy_cert_as_user() libnm function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libnm-client-impl/nm-default-libnm.h"
|
||||||
|
|
||||||
|
#include "nm-utils.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
gs_free char *filename = NULL;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
g_printerr("Usage: %s <FILE> <USER>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = nm_utils_copy_cert_as_user(argv[1], argv[2], &error);
|
||||||
|
if (!filename) {
|
||||||
|
g_printerr("Error: %s\n", error->message);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_print("%s\n", filename);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -93,6 +93,8 @@ def syms_from_ver(verfile):
|
||||||
# hardcode it.
|
# hardcode it.
|
||||||
c_syms["nm_ethtool_optname_is_feature"] = "1.20"
|
c_syms["nm_ethtool_optname_is_feature"] = "1.20"
|
||||||
c_syms["nm_setting_bond_port_get_prio"] = "1.44"
|
c_syms["nm_setting_bond_port_get_prio"] = "1.44"
|
||||||
|
c_syms["nm_utils_copy_cert_as_user"] = "1.56"
|
||||||
|
c_syms["nm_vpn_plugin_info_supports_safe_private_file_access"] = "1.56"
|
||||||
|
|
||||||
return c_syms
|
return c_syms
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,13 @@ typedef struct {
|
||||||
* note that this object will be unrefed after the callback has returned, use
|
* note that this object will be unrefed after the callback has returned, use
|
||||||
* g_object_ref()/g_object_unref() if you want to use this object after the callback
|
* g_object_ref()/g_object_unref() if you want to use this object after the callback
|
||||||
* has returned
|
* has returned
|
||||||
* @secrets: the #GVariant of type %NM_VARIANT_TYPE_CONNECTION containing the requested
|
* @secrets: (nullable): the #GVariant of type %NM_VARIANT_TYPE_CONNECTION containing the requested
|
||||||
* secrets (as created by nm_connection_to_dbus() for example). Each key in @secrets
|
* secrets (as created by nm_connection_to_dbus() for example). Each key in @secrets
|
||||||
* should be the name of a #NMSetting object (like "802-11-wireless-security")
|
* should be the name of a #NMSetting object (like "802-11-wireless-security")
|
||||||
* and each value should be an %NM_VARIANT_TYPE_SETTING variant. The sub-dicts
|
* and each value should be an %NM_VARIANT_TYPE_SETTING variant. The sub-dicts
|
||||||
* map string:value, where the string is the setting property name (like "psk")
|
* map string:value, where the string is the setting property name (like "psk")
|
||||||
* and the value is the secret
|
* and the value is the secret
|
||||||
* @error: if the secrets request failed, give a descriptive error here
|
* @error: (nullable): if the secrets request failed, give a descriptive error here
|
||||||
* @user_data: caller-specific data to be passed to the function
|
* @user_data: caller-specific data to be passed to the function
|
||||||
*
|
*
|
||||||
* Called as a result of a request by NM to retrieve secrets. When the
|
* Called as a result of a request by NM to retrieve secrets. When the
|
||||||
|
|
@ -90,7 +90,7 @@ typedef void (*NMSecretAgentOldGetSecretsFunc)(NMSecretAgentOld *agent,
|
||||||
* note that this object will be unrefed after the callback has returned, use
|
* note that this object will be unrefed after the callback has returned, use
|
||||||
* g_object_ref()/g_object_unref() if you want to use this object after the callback
|
* g_object_ref()/g_object_unref() if you want to use this object after the callback
|
||||||
* has returned
|
* has returned
|
||||||
* @error: if the saving secrets failed, give a descriptive error here
|
* @error: (nullable): if the saving secrets failed, give a descriptive error here
|
||||||
* @user_data: caller-specific data to be passed to the function
|
* @user_data: caller-specific data to be passed to the function
|
||||||
*
|
*
|
||||||
* Called as a result of a request by NM to save secrets. When the
|
* Called as a result of a request by NM to save secrets. When the
|
||||||
|
|
@ -109,7 +109,7 @@ typedef void (*NMSecretAgentOldSaveSecretsFunc)(NMSecretAgentOld *agent,
|
||||||
* note that this object will be unrefed after the callback has returned, use
|
* note that this object will be unrefed after the callback has returned, use
|
||||||
* g_object_ref()/g_object_unref() if you want to use this object after the callback
|
* g_object_ref()/g_object_unref() if you want to use this object after the callback
|
||||||
* has returned
|
* has returned
|
||||||
* @error: if the deleting secrets failed, give a descriptive error here
|
* @error: (nullable): if the deleting secrets failed, give a descriptive error here
|
||||||
* @user_data: caller-specific data to be passed to the function
|
* @user_data: caller-specific data to be passed to the function
|
||||||
*
|
*
|
||||||
* Called as a result of a request by NM to delete secrets. When the
|
* Called as a result of a request by NM to delete secrets. When the
|
||||||
|
|
|
||||||
|
|
@ -431,7 +431,7 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
|
||||||
[NM_META_SETTING_TYPE_OVS_DPDK] =
|
[NM_META_SETTING_TYPE_OVS_DPDK] =
|
||||||
{
|
{
|
||||||
.meta_type = NM_META_SETTING_TYPE_OVS_DPDK,
|
.meta_type = NM_META_SETTING_TYPE_OVS_DPDK,
|
||||||
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
|
.setting_priority = NM_SETTING_PRIORITY_AUX,
|
||||||
.setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME,
|
.setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME,
|
||||||
.get_setting_gtype = nm_setting_ovs_dpdk_get_type,
|
.get_setting_gtype = nm_setting_ovs_dpdk_get_type,
|
||||||
},
|
},
|
||||||
|
|
@ -459,7 +459,7 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
|
||||||
[NM_META_SETTING_TYPE_OVS_PATCH] =
|
[NM_META_SETTING_TYPE_OVS_PATCH] =
|
||||||
{
|
{
|
||||||
.meta_type = NM_META_SETTING_TYPE_OVS_PATCH,
|
.meta_type = NM_META_SETTING_TYPE_OVS_PATCH,
|
||||||
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
|
.setting_priority = NM_SETTING_PRIORITY_AUX,
|
||||||
.setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME,
|
.setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME,
|
||||||
.get_setting_gtype = nm_setting_ovs_patch_get_type,
|
.get_setting_gtype = nm_setting_ovs_patch_get_type,
|
||||||
},
|
},
|
||||||
|
|
@ -656,9 +656,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
|
||||||
NM_META_SETTING_TYPE_MACSEC,
|
NM_META_SETTING_TYPE_MACSEC,
|
||||||
NM_META_SETTING_TYPE_MACVLAN,
|
NM_META_SETTING_TYPE_MACVLAN,
|
||||||
NM_META_SETTING_TYPE_OVS_BRIDGE,
|
NM_META_SETTING_TYPE_OVS_BRIDGE,
|
||||||
NM_META_SETTING_TYPE_OVS_DPDK,
|
|
||||||
NM_META_SETTING_TYPE_OVS_INTERFACE,
|
NM_META_SETTING_TYPE_OVS_INTERFACE,
|
||||||
NM_META_SETTING_TYPE_OVS_PATCH,
|
|
||||||
NM_META_SETTING_TYPE_OVS_PORT,
|
NM_META_SETTING_TYPE_OVS_PORT,
|
||||||
NM_META_SETTING_TYPE_TEAM,
|
NM_META_SETTING_TYPE_TEAM,
|
||||||
NM_META_SETTING_TYPE_TUN,
|
NM_META_SETTING_TYPE_TUN,
|
||||||
|
|
@ -688,8 +686,10 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
|
||||||
NM_META_SETTING_TYPE_ETHTOOL,
|
NM_META_SETTING_TYPE_ETHTOOL,
|
||||||
NM_META_SETTING_TYPE_LINK,
|
NM_META_SETTING_TYPE_LINK,
|
||||||
NM_META_SETTING_TYPE_MATCH,
|
NM_META_SETTING_TYPE_MATCH,
|
||||||
|
NM_META_SETTING_TYPE_OVS_DPDK,
|
||||||
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
||||||
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
|
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
|
||||||
|
NM_META_SETTING_TYPE_OVS_PATCH,
|
||||||
NM_META_SETTING_TYPE_PPP,
|
NM_META_SETTING_TYPE_PPP,
|
||||||
NM_META_SETTING_TYPE_PPPOE,
|
NM_META_SETTING_TYPE_PPPOE,
|
||||||
NM_META_SETTING_TYPE_TEAM_PORT,
|
NM_META_SETTING_TYPE_TEAM_PORT,
|
||||||
|
|
|
||||||
|
|
@ -3133,6 +3133,86 @@ need_secrets(NMSetting *setting, gboolean check_rerequest)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_private_files(NMSetting *setting, GPtrArray *files)
|
||||||
|
{
|
||||||
|
const struct {
|
||||||
|
const char *property;
|
||||||
|
NMSetting8021xCKScheme (*get_scheme_func)(NMSetting8021x *);
|
||||||
|
const char *(*get_path_func)(NMSetting8021x *);
|
||||||
|
} cert_props[] = {
|
||||||
|
{NM_SETTING_802_1X_CA_CERT,
|
||||||
|
nm_setting_802_1x_get_ca_cert_scheme,
|
||||||
|
nm_setting_802_1x_get_ca_cert_path},
|
||||||
|
{NM_SETTING_802_1X_CLIENT_CERT,
|
||||||
|
nm_setting_802_1x_get_client_cert_scheme,
|
||||||
|
nm_setting_802_1x_get_client_cert_path},
|
||||||
|
{NM_SETTING_802_1X_PRIVATE_KEY,
|
||||||
|
nm_setting_802_1x_get_private_key_scheme,
|
||||||
|
nm_setting_802_1x_get_private_key_path},
|
||||||
|
{NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||||
|
nm_setting_802_1x_get_phase2_ca_cert_scheme,
|
||||||
|
nm_setting_802_1x_get_phase2_ca_cert_path},
|
||||||
|
{NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||||
|
nm_setting_802_1x_get_phase2_client_cert_scheme,
|
||||||
|
nm_setting_802_1x_get_phase2_client_cert_path},
|
||||||
|
{NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||||
|
nm_setting_802_1x_get_phase2_private_key_scheme,
|
||||||
|
nm_setting_802_1x_get_phase2_private_key_path},
|
||||||
|
};
|
||||||
|
NMSetting8021x *s_8021x = NM_SETTING_802_1X(setting);
|
||||||
|
const char *path;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (NM_MORE_ASSERT_ONCE(5)) {
|
||||||
|
GObjectClass *klass;
|
||||||
|
gs_free GParamSpec **properties = NULL;
|
||||||
|
guint n_properties;
|
||||||
|
gboolean found;
|
||||||
|
guint j;
|
||||||
|
|
||||||
|
/* Check that all the properties in the setting with flag CERT_KEY_FILE
|
||||||
|
* are listed in the table, and vice versa. */
|
||||||
|
|
||||||
|
klass = G_OBJECT_GET_CLASS(setting);
|
||||||
|
|
||||||
|
properties = g_object_class_list_properties(klass, &n_properties);
|
||||||
|
for (i = 0; i < n_properties; i++) {
|
||||||
|
if (!(properties[i]->flags & NM_SETTING_PARAM_CERT_KEY_FILE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
found = FALSE;
|
||||||
|
for (j = 0; j < G_N_ELEMENTS(cert_props); j++) {
|
||||||
|
if (nm_streq0(properties[i]->name, cert_props[j].property)) {
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_assert(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS(cert_props); i++) {
|
||||||
|
GParamSpec *prop;
|
||||||
|
|
||||||
|
prop = g_object_class_find_property(klass, cert_props[i].property);
|
||||||
|
nm_assert(prop);
|
||||||
|
nm_assert(prop->flags & NM_SETTING_PARAM_CERT_KEY_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS(cert_props); i++) {
|
||||||
|
if (cert_props[i].get_scheme_func(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||||
|
path = cert_props[i].get_path_func(s_8021x);
|
||||||
|
if (path) {
|
||||||
|
g_ptr_array_add(files, (gpointer) path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
|
|
@ -3223,8 +3303,9 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
object_class->set_property = set_property;
|
object_class->set_property = set_property;
|
||||||
object_class->finalize = finalize;
|
object_class->finalize = finalize;
|
||||||
|
|
||||||
setting_class->verify = verify;
|
setting_class->verify = verify;
|
||||||
setting_class->need_secrets = need_secrets;
|
setting_class->need_secrets = need_secrets;
|
||||||
|
setting_class->get_private_files = get_private_files;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NMSetting8021x:eap:
|
* NMSetting8021x:eap:
|
||||||
|
|
@ -3359,7 +3440,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
obj_properties,
|
obj_properties,
|
||||||
NM_SETTING_802_1X_CA_CERT,
|
NM_SETTING_802_1X_CA_CERT,
|
||||||
PROP_CA_CERT,
|
PROP_CA_CERT,
|
||||||
NM_SETTING_PARAM_NONE,
|
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||||
NMSetting8021xPrivate,
|
NMSetting8021xPrivate,
|
||||||
ca_cert);
|
ca_cert);
|
||||||
|
|
||||||
|
|
@ -3556,7 +3637,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
obj_properties,
|
obj_properties,
|
||||||
NM_SETTING_802_1X_CLIENT_CERT,
|
NM_SETTING_802_1X_CLIENT_CERT,
|
||||||
PROP_CLIENT_CERT,
|
PROP_CLIENT_CERT,
|
||||||
NM_SETTING_PARAM_NONE,
|
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||||
NMSetting8021xPrivate,
|
NMSetting8021xPrivate,
|
||||||
client_cert);
|
client_cert);
|
||||||
|
|
||||||
|
|
@ -3803,7 +3884,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
obj_properties,
|
obj_properties,
|
||||||
NM_SETTING_802_1X_PHASE2_CA_CERT,
|
NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||||
PROP_PHASE2_CA_CERT,
|
PROP_PHASE2_CA_CERT,
|
||||||
NM_SETTING_PARAM_NONE,
|
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||||
NMSetting8021xPrivate,
|
NMSetting8021xPrivate,
|
||||||
phase2_ca_cert);
|
phase2_ca_cert);
|
||||||
|
|
||||||
|
|
@ -4006,7 +4087,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
obj_properties,
|
obj_properties,
|
||||||
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||||
PROP_PHASE2_CLIENT_CERT,
|
PROP_PHASE2_CLIENT_CERT,
|
||||||
NM_SETTING_PARAM_NONE,
|
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||||
NMSetting8021xPrivate,
|
NMSetting8021xPrivate,
|
||||||
phase2_client_cert);
|
phase2_client_cert);
|
||||||
|
|
||||||
|
|
@ -4175,7 +4256,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
obj_properties,
|
obj_properties,
|
||||||
NM_SETTING_802_1X_PRIVATE_KEY,
|
NM_SETTING_802_1X_PRIVATE_KEY,
|
||||||
PROP_PRIVATE_KEY,
|
PROP_PRIVATE_KEY,
|
||||||
NM_SETTING_PARAM_NONE,
|
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||||
NMSetting8021xPrivate,
|
NMSetting8021xPrivate,
|
||||||
private_key);
|
private_key);
|
||||||
|
|
||||||
|
|
@ -4276,7 +4357,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
||||||
obj_properties,
|
obj_properties,
|
||||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||||
PROP_PHASE2_PRIVATE_KEY,
|
PROP_PHASE2_PRIVATE_KEY,
|
||||||
NM_SETTING_PARAM_NONE,
|
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||||
NMSetting8021xPrivate,
|
NMSetting8021xPrivate,
|
||||||
phase2_private_key);
|
phase2_private_key);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -431,6 +431,47 @@ nm_setting_connection_permissions_user_allowed_by_uid(NMSettingConnection *setti
|
||||||
return _permissions_user_allowed(setting, NULL, uid);
|
return _permissions_user_allowed(setting, NULL, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
_nm_setting_connection_get_num_permissions_users(NMSettingConnection *setting)
|
||||||
|
{
|
||||||
|
NMSettingConnectionPrivate *priv;
|
||||||
|
guint i;
|
||||||
|
guint count = 0;
|
||||||
|
|
||||||
|
nm_assert(NM_IS_SETTING_CONNECTION(setting));
|
||||||
|
priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting);
|
||||||
|
|
||||||
|
for (i = 0; priv->permissions && i < priv->permissions->len; i++) {
|
||||||
|
const Permission *permission = &nm_g_array_index(priv->permissions, Permission, i);
|
||||||
|
|
||||||
|
if (permission->ptype == PERM_TYPE_USER) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_nm_setting_connection_get_first_permissions_user(NMSettingConnection *setting)
|
||||||
|
{
|
||||||
|
NMSettingConnectionPrivate *priv;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
nm_assert(NM_IS_SETTING_CONNECTION(setting));
|
||||||
|
priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting);
|
||||||
|
|
||||||
|
for (i = 0; priv->permissions && i < priv->permissions->len; i++) {
|
||||||
|
const Permission *permission = &nm_g_array_index(priv->permissions, Permission, i);
|
||||||
|
|
||||||
|
if (permission->ptype == PERM_TYPE_USER) {
|
||||||
|
return permission->item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_setting_connection_add_permission:
|
* nm_setting_connection_add_permission:
|
||||||
* @setting: the #NMSettingConnection
|
* @setting: the #NMSettingConnection
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ nm_setting_macvlan_class_init(NMSettingMacvlanClass *klass)
|
||||||
/**
|
/**
|
||||||
* NMSettingMacvlan:promiscuous:
|
* NMSettingMacvlan:promiscuous:
|
||||||
*
|
*
|
||||||
* Whether the interface should be put in promiscuous mode.
|
* Whether the parent interface should be put in promiscuous mode (true by default).
|
||||||
*
|
*
|
||||||
* Since: 1.2
|
* Since: 1.2
|
||||||
**/
|
**/
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,11 @@ struct _NMSettingClass {
|
||||||
guint /* NMSettingParseFlags */ parse_flags,
|
guint /* NMSettingParseFlags */ parse_flags,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
/* returns a list of certificate/key files referenced in the connection.
|
||||||
|
* When the connection is private, we need to verify that the owner of
|
||||||
|
* the connection has access to them. */
|
||||||
|
void (*get_private_files)(NMSetting *setting, GPtrArray *files);
|
||||||
|
|
||||||
const struct _NMMetaSettingInfo *setting_info;
|
const struct _NMMetaSettingInfo *setting_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -333,6 +338,11 @@ struct _NMRange {
|
||||||
*/
|
*/
|
||||||
#define NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS (1 << (7 + G_PARAM_USER_SHIFT))
|
#define NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS (1 << (7 + G_PARAM_USER_SHIFT))
|
||||||
|
|
||||||
|
/* The property can refer to a certificate or key stored on disk. As such,
|
||||||
|
* special care is needed when accessing the file for private connections.
|
||||||
|
*/
|
||||||
|
#define NM_SETTING_PARAM_CERT_KEY_FILE (1 << (8 + G_PARAM_USER_SHIFT))
|
||||||
|
|
||||||
extern const NMSettInfoPropertType nm_sett_info_propert_type_setting_name;
|
extern const NMSettInfoPropertType nm_sett_info_propert_type_setting_name;
|
||||||
extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name;
|
extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name;
|
||||||
extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i;
|
extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i;
|
||||||
|
|
@ -858,9 +868,10 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
|
||||||
{ \
|
{ \
|
||||||
GParamSpec *_param_spec; \
|
GParamSpec *_param_spec; \
|
||||||
\
|
\
|
||||||
G_STATIC_ASSERT(!NM_FLAGS_ANY((param_flags), \
|
G_STATIC_ASSERT( \
|
||||||
~(NM_SETTING_PARAM_SECRET | NM_SETTING_PARAM_INFERRABLE \
|
!NM_FLAGS_ANY((param_flags), \
|
||||||
| NM_SETTING_PARAM_FUZZY_IGNORE))); \
|
~(NM_SETTING_PARAM_SECRET | NM_SETTING_PARAM_INFERRABLE \
|
||||||
|
| NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_CERT_KEY_FILE))); \
|
||||||
\
|
\
|
||||||
_param_spec = g_param_spec_boxed("" prop_name "", \
|
_param_spec = g_param_spec_boxed("" prop_name "", \
|
||||||
"", \
|
"", \
|
||||||
|
|
|
||||||
|
|
@ -2262,6 +2262,34 @@ init_from_dbus(NMSetting *setting,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_private_files(NMSetting *setting, GPtrArray *files)
|
||||||
|
{
|
||||||
|
if (NM_MORE_ASSERTS) {
|
||||||
|
GParamSpec **properties;
|
||||||
|
guint n_properties;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(setting), &n_properties);
|
||||||
|
for (i = 0; i < n_properties; i++) {
|
||||||
|
if (properties[i]->flags & NM_SETTING_PARAM_CERT_KEY_FILE) {
|
||||||
|
/* Certificates and keys needs special handling, see setting 802.1X */
|
||||||
|
nm_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_nm_setting_get_private_files(NMSetting *setting, GPtrArray *files)
|
||||||
|
{
|
||||||
|
g_return_if_fail(NM_IS_SETTING(setting));
|
||||||
|
g_return_if_fail(files);
|
||||||
|
|
||||||
|
NM_SETTING_GET_CLASS(setting)->get_private_files(setting, files);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_setting_get_dbus_property_type:
|
* nm_setting_get_dbus_property_type:
|
||||||
* @setting: an #NMSetting
|
* @setting: an #NMSetting
|
||||||
|
|
@ -4672,6 +4700,7 @@ nm_setting_class_init(NMSettingClass *setting_class)
|
||||||
setting_class->enumerate_values = enumerate_values;
|
setting_class->enumerate_values = enumerate_values;
|
||||||
setting_class->aggregate = aggregate;
|
setting_class->aggregate = aggregate;
|
||||||
setting_class->init_from_dbus = init_from_dbus;
|
setting_class->init_from_dbus = init_from_dbus;
|
||||||
|
setting_class->get_private_files = get_private_files;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NMSetting:name:
|
* NMSetting:name:
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/pkt_sched.h>
|
#include <linux/pkt_sched.h>
|
||||||
#include <linux/if_infiniband.h>
|
#include <linux/if_infiniband.h>
|
||||||
|
|
||||||
|
#include "libnm-glib-aux/nm-io-utils.h"
|
||||||
#include "libnm-glib-aux/nm-uuid.h"
|
#include "libnm-glib-aux/nm-uuid.h"
|
||||||
#include "libnm-glib-aux/nm-json-aux.h"
|
#include "libnm-glib-aux/nm-json-aux.h"
|
||||||
#include "libnm-glib-aux/nm-str-buf.h"
|
#include "libnm-glib-aux/nm-str-buf.h"
|
||||||
|
|
@ -6195,3 +6196,257 @@ nm_utils_ensure_gtypes(void)
|
||||||
for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++)
|
for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++)
|
||||||
nm_meta_setting_infos[meta_type].get_setting_gtype();
|
nm_meta_setting_infos[meta_type].get_setting_gtype();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GPid pid;
|
||||||
|
GSource *child_watch_source;
|
||||||
|
GMainLoop *loop;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
int child_stdout;
|
||||||
|
int child_stderr;
|
||||||
|
|
||||||
|
GSource *output_source;
|
||||||
|
GSource *error_source;
|
||||||
|
|
||||||
|
NMStrBuf output_buffer;
|
||||||
|
NMStrBuf error_buffer;
|
||||||
|
} HelperInfo;
|
||||||
|
|
||||||
|
static void
|
||||||
|
helper_complete(HelperInfo *info, GError *error_take)
|
||||||
|
{
|
||||||
|
if (error_take) {
|
||||||
|
if (!info->error)
|
||||||
|
info->error = error_take;
|
||||||
|
else
|
||||||
|
g_error_free(error_take);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->output_source || info->error_source || info->pid != -1) {
|
||||||
|
/* Wait that the pipe is closed and process has terminated */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->error && info->error_buffer.len > 0) {
|
||||||
|
/* Prefer the message from stderr as it's more informative */
|
||||||
|
g_error_free(info->error);
|
||||||
|
info->error = g_error_new(NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_FAILED,
|
||||||
|
"%s",
|
||||||
|
nm_str_buf_get_str(&info->error_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_main_loop_quit(info->loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
helper_have_err_data(int fd, GIOCondition condition, gpointer user_data)
|
||||||
|
{
|
||||||
|
HelperInfo *info = user_data;
|
||||||
|
gssize n_read;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
n_read = nm_utils_fd_read(fd, &info->error_buffer);
|
||||||
|
|
||||||
|
if (n_read > 0)
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
|
nm_clear_g_source_inst(&info->error_source);
|
||||||
|
nm_clear_fd(&info->child_stderr);
|
||||||
|
|
||||||
|
if (n_read < 0) {
|
||||||
|
error = g_error_new(NM_UTILS_ERROR,
|
||||||
|
NM_UTILS_ERROR_UNKNOWN,
|
||||||
|
"read from process returned %d (%s)",
|
||||||
|
(int) -n_read,
|
||||||
|
nm_strerror_native((int) -n_read));
|
||||||
|
}
|
||||||
|
|
||||||
|
helper_complete(info, error);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
helper_have_data(int fd, GIOCondition condition, gpointer user_data)
|
||||||
|
{
|
||||||
|
HelperInfo *info = user_data;
|
||||||
|
gssize n_read;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
n_read = nm_utils_fd_read(fd, &info->output_buffer);
|
||||||
|
|
||||||
|
if (n_read > 0)
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
|
nm_clear_g_source_inst(&info->output_source);
|
||||||
|
nm_clear_fd(&info->child_stdout);
|
||||||
|
|
||||||
|
if (n_read < 0) {
|
||||||
|
error = g_error_new(NM_UTILS_ERROR,
|
||||||
|
NM_UTILS_ERROR_UNKNOWN,
|
||||||
|
"read from process returned %d (%s)",
|
||||||
|
(int) -n_read,
|
||||||
|
nm_strerror_native((int) -n_read));
|
||||||
|
}
|
||||||
|
|
||||||
|
helper_complete(info, error);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
helper_child_terminated(GPid pid, int status, gpointer user_data)
|
||||||
|
{
|
||||||
|
HelperInfo *info = user_data;
|
||||||
|
gs_free char *status_desc = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
info->pid = -1;
|
||||||
|
nm_clear_g_source_inst(&info->child_watch_source);
|
||||||
|
|
||||||
|
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||||
|
if (!status_desc)
|
||||||
|
status_desc = nm_utils_get_process_exit_status_desc(status);
|
||||||
|
error =
|
||||||
|
g_error_new(NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "helper process %s", status_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
helper_complete(info, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RUN_CERT_DIR NMRUNDIR "/cert"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_utils_copy_cert_as_user:
|
||||||
|
* @filename: the file name of the certificate or key to copy
|
||||||
|
* @user: the user to impersonate when reading the file
|
||||||
|
* @error: (nullable): return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Reads @filename on behalf of user @user and writes the
|
||||||
|
* content to a new file in /run/NetworkManager/cert/.
|
||||||
|
* The new file has permission 600 and is owned by root.
|
||||||
|
*
|
||||||
|
* This function is useful for VPN plugins that run as root and need
|
||||||
|
* to verify that the user owning the connection (the one listed in the
|
||||||
|
* connection.permissions property) can access the file.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the name of the new temporary file. Or %NULL
|
||||||
|
* if an error occurred, including when the given user can't access the
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* Since: 1.56, 1.52.2
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
nm_utils_copy_cert_as_user(const char *filename, const char *user, GError **error)
|
||||||
|
{
|
||||||
|
gs_unref_bytes GBytes *bytes = NULL;
|
||||||
|
char dst_path[] = RUN_CERT_DIR "/XXXXXX";
|
||||||
|
HelperInfo info = {
|
||||||
|
.child_stdout = -1,
|
||||||
|
.child_stderr = -1,
|
||||||
|
};
|
||||||
|
GMainContext *context;
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
g_return_val_if_fail(filename, NULL);
|
||||||
|
g_return_val_if_fail(user, NULL);
|
||||||
|
g_return_val_if_fail(!error || !*error, NULL);
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("This function needs to be called by root"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_spawn_async_with_pipes(
|
||||||
|
"/",
|
||||||
|
(char **)
|
||||||
|
NM_MAKE_STRV(LIBEXECDIR "/nm-libnm-helper", "read-file-as-user", filename, user),
|
||||||
|
(char **) NM_MAKE_STRV(),
|
||||||
|
G_SPAWN_CLOEXEC_PIPES | G_SPAWN_DO_NOT_REAP_CHILD,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&info.pid,
|
||||||
|
NULL,
|
||||||
|
&info.child_stdout,
|
||||||
|
&info.child_stderr,
|
||||||
|
error)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = g_main_context_new();
|
||||||
|
info.loop = g_main_loop_new(context, FALSE);
|
||||||
|
|
||||||
|
/* Watch process */
|
||||||
|
info.child_watch_source = nm_g_child_watch_source_new(info.pid,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
helper_child_terminated,
|
||||||
|
&info,
|
||||||
|
NULL);
|
||||||
|
g_source_attach(info.child_watch_source, context);
|
||||||
|
|
||||||
|
/* Watch stdout */
|
||||||
|
info.output_buffer = NM_STR_BUF_INIT(0, FALSE);
|
||||||
|
info.output_source = nm_g_unix_fd_source_new(info.child_stdout,
|
||||||
|
G_IO_IN | G_IO_ERR | G_IO_HUP,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
helper_have_data,
|
||||||
|
&info,
|
||||||
|
NULL);
|
||||||
|
g_source_attach(info.output_source, context);
|
||||||
|
|
||||||
|
/* Watch stderr */
|
||||||
|
info.error_buffer = NM_STR_BUF_INIT(0, FALSE);
|
||||||
|
info.error_source = nm_g_unix_fd_source_new(info.child_stderr,
|
||||||
|
G_IO_IN | G_IO_ERR | G_IO_HUP,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
helper_have_err_data,
|
||||||
|
&info,
|
||||||
|
NULL);
|
||||||
|
g_source_attach(info.error_source, context);
|
||||||
|
|
||||||
|
/* Wait termination */
|
||||||
|
g_main_loop_run(info.loop);
|
||||||
|
g_clear_pointer(&info.loop, g_main_loop_unref);
|
||||||
|
g_clear_pointer(&context, g_main_context_unref);
|
||||||
|
|
||||||
|
if (info.error) {
|
||||||
|
nm_str_buf_destroy(&info.output_buffer);
|
||||||
|
nm_str_buf_destroy(&info.error_buffer);
|
||||||
|
g_propagate_error(error, g_steal_pointer(&info.error));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the data to a new file */
|
||||||
|
|
||||||
|
bytes = g_bytes_new(nm_str_buf_get_str_unsafe(&info.output_buffer), info.output_buffer.len);
|
||||||
|
nm_str_buf_destroy(&info.output_buffer);
|
||||||
|
nm_str_buf_destroy(&info.error_buffer);
|
||||||
|
|
||||||
|
mkdir(RUN_CERT_DIR, 0600);
|
||||||
|
fd = mkstemp(dst_path);
|
||||||
|
if (fd < 0) {
|
||||||
|
g_set_error_literal(error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("Failure creating the temporary file"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
nm_close(fd);
|
||||||
|
|
||||||
|
if (!nm_utils_file_set_contents(dst_path,
|
||||||
|
g_bytes_get_data(bytes, NULL),
|
||||||
|
g_bytes_get_size(bytes),
|
||||||
|
0600,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
error)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_strdup(dst_path);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -913,6 +913,29 @@ nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self)
|
||||||
return _nm_utils_ascii_str_to_bool(s, FALSE);
|
return _nm_utils_ascii_str_to_bool(s, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_vpn_plugin_info_supports_safe_private_file_access:
|
||||||
|
* @self: plugin info instance
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the service supports reading files (certificates, keys) of
|
||||||
|
* private connections in a safe way (i.e. checking user permissions), or
|
||||||
|
if the service doesn't need to read any file from disk.
|
||||||
|
*
|
||||||
|
* Since: 1.56, 1.52.2
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_vpn_plugin_info_supports_safe_private_file_access(NMVpnPluginInfo *self)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
g_return_val_if_fail(NM_IS_VPN_PLUGIN_INFO(self), FALSE);
|
||||||
|
|
||||||
|
s = nm_vpn_plugin_info_lookup_property(self,
|
||||||
|
NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION,
|
||||||
|
"supports-safe-private-file-access");
|
||||||
|
return _nm_utils_ascii_str_to_bool(s, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_vpn_plugin_info_get_aliases:
|
* nm_vpn_plugin_info_get_aliases:
|
||||||
* @self: plugin info instance
|
* @self: plugin info instance
|
||||||
|
|
|
||||||
|
|
@ -1186,4 +1186,11 @@ gboolean nm_connection_need_secrets_for_rerequest(NMConnection *connection);
|
||||||
|
|
||||||
const GPtrArray *_nm_setting_ovs_port_get_trunks_arr(NMSettingOvsPort *self);
|
const GPtrArray *_nm_setting_ovs_port_get_trunks_arr(NMSettingOvsPort *self);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
guint _nm_setting_connection_get_num_permissions_users(NMSettingConnection *setting);
|
||||||
|
const char *_nm_setting_connection_get_first_permissions_user(NMSettingConnection *setting);
|
||||||
|
|
||||||
|
void _nm_setting_get_private_files(NMSetting *setting, GPtrArray *files);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,9 @@ nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, gui
|
||||||
NM_AVAILABLE_IN_1_42
|
NM_AVAILABLE_IN_1_42
|
||||||
void nm_utils_ensure_gtypes(void);
|
void nm_utils_ensure_gtypes(void);
|
||||||
|
|
||||||
|
NM_AVAILABLE_IN_1_52_2
|
||||||
|
char *nm_utils_copy_cert_as_user(const char *filename, const char *user, GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __NM_UTILS_H__ */
|
#endif /* __NM_UTILS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@
|
||||||
#define NM_VERSION_1_48 (NM_ENCODE_VERSION(1, 48, 0))
|
#define NM_VERSION_1_48 (NM_ENCODE_VERSION(1, 48, 0))
|
||||||
#define NM_VERSION_1_50 (NM_ENCODE_VERSION(1, 50, 0))
|
#define NM_VERSION_1_50 (NM_ENCODE_VERSION(1, 50, 0))
|
||||||
#define NM_VERSION_1_52 (NM_ENCODE_VERSION(1, 52, 0))
|
#define NM_VERSION_1_52 (NM_ENCODE_VERSION(1, 52, 0))
|
||||||
|
#define NM_VERSION_1_52_2 (NM_ENCODE_VERSION(1, 52, 2))
|
||||||
|
|
||||||
/* For releases, NM_API_VERSION is equal to NM_VERSION.
|
/* For releases, NM_API_VERSION is equal to NM_VERSION.
|
||||||
*
|
*
|
||||||
|
|
@ -85,10 +86,10 @@
|
||||||
* version, you are already using the future API, even if
|
* version, you are already using the future API, even if
|
||||||
* it is not yet released. Hence, the currently used API
|
* it is not yet released. Hence, the currently used API
|
||||||
* version is the future one. */
|
* version is the future one. */
|
||||||
#define NM_API_VERSION \
|
#define NM_API_VERSION \
|
||||||
(((NM_MINOR_VERSION % 2) == 1) \
|
(((NM_MINOR_VERSION % 2) == 1) \
|
||||||
? NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION + 1, 0 ) \
|
? NM_ENCODE_VERSION(NM_MAJOR_VERSION, NM_MINOR_VERSION + 1, 0) \
|
||||||
: NM_ENCODE_VERSION (NM_MAJOR_VERSION, NM_MINOR_VERSION , ((NM_MICRO_VERSION + 1) / 2) * 2))
|
: NM_ENCODE_VERSION(NM_MAJOR_VERSION, NM_MINOR_VERSION, NM_MICRO_VERSION + 1))
|
||||||
|
|
||||||
/* deprecated. */
|
/* deprecated. */
|
||||||
#define NM_VERSION_CUR_STABLE NM_API_VERSION
|
#define NM_VERSION_CUR_STABLE NM_API_VERSION
|
||||||
|
|
|
||||||
|
|
@ -425,6 +425,12 @@
|
||||||
#define NM_AVAILABLE_IN_1_52
|
#define NM_AVAILABLE_IN_1_52
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_52_2
|
||||||
|
#define NM_AVAILABLE_IN_1_52_2 G_UNAVAILABLE(1, 52.2)
|
||||||
|
#else
|
||||||
|
#define NM_AVAILABLE_IN_1_52_2
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Synchronous API for calling D-Bus in libnm is deprecated. See
|
* Synchronous API for calling D-Bus in libnm is deprecated. See
|
||||||
* https://networkmanager.dev/docs/libnm/latest/usage.html#sync-api
|
* https://networkmanager.dev/docs/libnm/latest/usage.html#sync-api
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ NM_AVAILABLE_IN_1_4
|
||||||
gboolean nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self);
|
gboolean nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self);
|
||||||
NM_AVAILABLE_IN_1_42
|
NM_AVAILABLE_IN_1_42
|
||||||
gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self);
|
gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self);
|
||||||
|
NM_AVAILABLE_IN_1_52_2
|
||||||
|
gboolean nm_vpn_plugin_info_supports_safe_private_file_access(NMVpnPluginInfo *self);
|
||||||
NM_AVAILABLE_IN_1_4
|
NM_AVAILABLE_IN_1_4
|
||||||
const char *const *nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self);
|
const char *const *nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self);
|
||||||
NM_AVAILABLE_IN_1_2
|
NM_AVAILABLE_IN_1_2
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
|
|
||||||
#include "nm-std-utils.h"
|
#include "nm-std-utils.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -95,6 +99,114 @@ out_huge:
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
nm_utils_set_effective_user(const char *user, char *errbuf, size_t errbuf_len)
|
||||||
|
{
|
||||||
|
struct passwd *pwentry;
|
||||||
|
int errsv;
|
||||||
|
char error[1024];
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
pwentry = getpwnam(user);
|
||||||
|
if (!pwentry) {
|
||||||
|
errsv = errno;
|
||||||
|
if (errsv == 0) {
|
||||||
|
snprintf(errbuf, errbuf_len, "user not found");
|
||||||
|
} else {
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"error getting user entry: %d (%s)\n",
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setgid(pwentry->pw_gid) != 0) {
|
||||||
|
errsv = errno;
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"failed to change group to %u: %d (%s)\n",
|
||||||
|
pwentry->pw_gid,
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initgroups(user, pwentry->pw_gid) != 0) {
|
||||||
|
errsv = errno;
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"failed to reset supplementary group list to %u: %d (%s)\n",
|
||||||
|
pwentry->pw_gid,
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setuid(pwentry->pw_uid) != 0) {
|
||||||
|
errsv = errno;
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"failed to change user to %u: %d (%s)\n",
|
||||||
|
pwentry->pw_uid,
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
nm_utils_read_file_to_stdout(const char *filename, char *errbuf, size_t errbuf_len)
|
||||||
|
{
|
||||||
|
nm_auto_close int fd = -1;
|
||||||
|
char buffer[4096];
|
||||||
|
char error[1024];
|
||||||
|
ssize_t bytes_read;
|
||||||
|
int errsv;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
errsv = errno;
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"error opening the file: %d (%s)",
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||||
|
if (fwrite(buffer, 1, bytes_read, stdout) != (size_t) bytes_read) {
|
||||||
|
errsv = errno;
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"error writing to stdout: %d (%s)",
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read < 0) {
|
||||||
|
errsv = errno;
|
||||||
|
snprintf(errbuf,
|
||||||
|
errbuf_len,
|
||||||
|
"error reading the file: %d (%s)",
|
||||||
|
errsv,
|
||||||
|
_nm_strerror_r(errsv, error, sizeof(error)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _nm_strerror_r:
|
* _nm_strerror_r:
|
||||||
* @errsv: the errno passed to strerror_r()
|
* @errsv: the errno passed to strerror_r()
|
||||||
|
|
|
||||||
|
|
@ -37,4 +37,8 @@ size_t nm_utils_get_next_realloc_size(bool true_realloc, size_t requested);
|
||||||
|
|
||||||
const char *_nm_strerror_r(int errsv, char *buf, size_t buf_size);
|
const char *_nm_strerror_r(int errsv, char *buf, size_t buf_size);
|
||||||
|
|
||||||
|
bool nm_utils_set_effective_user(const char *user, char *errbuf, size_t errbuf_size);
|
||||||
|
|
||||||
|
bool nm_utils_read_file_to_stdout(const char *filename, char *errbuf, size_t errbuf_len);
|
||||||
|
|
||||||
#endif /* __NM_STD_UTILS_H__ */
|
#endif /* __NM_STD_UTILS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -431,7 +431,7 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
|
||||||
[NM_META_SETTING_TYPE_OVS_DPDK] =
|
[NM_META_SETTING_TYPE_OVS_DPDK] =
|
||||||
{
|
{
|
||||||
.meta_type = NM_META_SETTING_TYPE_OVS_DPDK,
|
.meta_type = NM_META_SETTING_TYPE_OVS_DPDK,
|
||||||
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
|
.setting_priority = NM_SETTING_PRIORITY_AUX,
|
||||||
.setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME,
|
.setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME,
|
||||||
.get_setting_gtype = nm_setting_ovs_dpdk_get_type,
|
.get_setting_gtype = nm_setting_ovs_dpdk_get_type,
|
||||||
},
|
},
|
||||||
|
|
@ -459,7 +459,7 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
|
||||||
[NM_META_SETTING_TYPE_OVS_PATCH] =
|
[NM_META_SETTING_TYPE_OVS_PATCH] =
|
||||||
{
|
{
|
||||||
.meta_type = NM_META_SETTING_TYPE_OVS_PATCH,
|
.meta_type = NM_META_SETTING_TYPE_OVS_PATCH,
|
||||||
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
|
.setting_priority = NM_SETTING_PRIORITY_AUX,
|
||||||
.setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME,
|
.setting_name = NM_SETTING_OVS_PATCH_SETTING_NAME,
|
||||||
.get_setting_gtype = nm_setting_ovs_patch_get_type,
|
.get_setting_gtype = nm_setting_ovs_patch_get_type,
|
||||||
},
|
},
|
||||||
|
|
@ -656,9 +656,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
|
||||||
NM_META_SETTING_TYPE_MACSEC,
|
NM_META_SETTING_TYPE_MACSEC,
|
||||||
NM_META_SETTING_TYPE_MACVLAN,
|
NM_META_SETTING_TYPE_MACVLAN,
|
||||||
NM_META_SETTING_TYPE_OVS_BRIDGE,
|
NM_META_SETTING_TYPE_OVS_BRIDGE,
|
||||||
NM_META_SETTING_TYPE_OVS_DPDK,
|
|
||||||
NM_META_SETTING_TYPE_OVS_INTERFACE,
|
NM_META_SETTING_TYPE_OVS_INTERFACE,
|
||||||
NM_META_SETTING_TYPE_OVS_PATCH,
|
|
||||||
NM_META_SETTING_TYPE_OVS_PORT,
|
NM_META_SETTING_TYPE_OVS_PORT,
|
||||||
NM_META_SETTING_TYPE_TEAM,
|
NM_META_SETTING_TYPE_TEAM,
|
||||||
NM_META_SETTING_TYPE_TUN,
|
NM_META_SETTING_TYPE_TUN,
|
||||||
|
|
@ -688,8 +686,10 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
|
||||||
NM_META_SETTING_TYPE_ETHTOOL,
|
NM_META_SETTING_TYPE_ETHTOOL,
|
||||||
NM_META_SETTING_TYPE_LINK,
|
NM_META_SETTING_TYPE_LINK,
|
||||||
NM_META_SETTING_TYPE_MATCH,
|
NM_META_SETTING_TYPE_MATCH,
|
||||||
|
NM_META_SETTING_TYPE_OVS_DPDK,
|
||||||
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
|
||||||
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
|
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
|
||||||
|
NM_META_SETTING_TYPE_OVS_PATCH,
|
||||||
NM_META_SETTING_TYPE_PPP,
|
NM_META_SETTING_TYPE_PPP,
|
||||||
NM_META_SETTING_TYPE_PPPOE,
|
NM_META_SETTING_TYPE_PPPOE,
|
||||||
NM_META_SETTING_TYPE_TEAM_PORT,
|
NM_META_SETTING_TYPE_TEAM_PORT,
|
||||||
|
|
|
||||||
|
|
@ -9133,12 +9133,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
|
||||||
NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE),
|
NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SETTING_INFO (OVS_DPDK,
|
SETTING_INFO (OVS_DPDK),
|
||||||
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
|
||||||
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
|
|
||||||
NM_META_SETTING_VALID_PART_ITEM (OVS_DPDK, TRUE),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SETTING_INFO_EMPTY (OVS_OTHER_CONFIG),
|
SETTING_INFO_EMPTY (OVS_OTHER_CONFIG),
|
||||||
SETTING_INFO_EMPTY (OVS_EXTERNAL_IDS),
|
SETTING_INFO_EMPTY (OVS_EXTERNAL_IDS),
|
||||||
SETTING_INFO (OVS_INTERFACE,
|
SETTING_INFO (OVS_INTERFACE,
|
||||||
|
|
@ -9153,12 +9148,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
|
||||||
NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE),
|
NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SETTING_INFO (OVS_PATCH,
|
SETTING_INFO (OVS_PATCH),
|
||||||
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
|
||||||
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
|
|
||||||
NM_META_SETTING_VALID_PART_ITEM (OVS_PATCH, TRUE),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SETTING_INFO (OVS_PORT,
|
SETTING_INFO (OVS_PORT,
|
||||||
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
.valid_parts = NM_META_SETTING_VALID_PARTS (
|
||||||
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
|
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MACSEC_VALIDATION N_("Specifies the validation mode for incoming frames.")
|
#define DESCRIBE_DOC_NM_SETTING_MACSEC_VALIDATION N_("Specifies the validation mode for incoming frames.")
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_MODE N_("The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.")
|
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_MODE N_("The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.")
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created. If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
|
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created. If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PROMISCUOUS N_("Whether the interface should be put in promiscuous mode.")
|
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PROMISCUOUS N_("Whether the parent interface should be put in promiscuous mode (true by default).")
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_TAP N_("Whether the interface should be a MACVTAP.")
|
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_TAP N_("Whether the interface should be a MACVTAP.")
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_DRIVER N_("A list of driver names to match. Each element is a shell wildcard pattern. See NMSettingMatch:interface-name for how special characters '|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.")
|
#define DESCRIBE_DOC_NM_SETTING_MATCH_DRIVER N_("A list of driver names to match. Each element is a shell wildcard pattern. See NMSettingMatch:interface-name for how special characters '|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.")
|
||||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_INTERFACE_NAME N_("A list of interface names to match. Each element is a shell wildcard pattern. An element can be prefixed with a pipe symbol (|) or an ampersand (&). The former means that the element is optional and the latter means that it is mandatory. If there are any optional elements, than the match evaluates to true if at least one of the optional element matches (logical OR). If there are any mandatory elements, then they all must match (logical AND). By default, an element is optional. This means that an element \"foo\" behaves the same as \"|foo\". An element can also be inverted with exclamation mark (!) between the pipe symbol (or the ampersand) and before the pattern. Note that \"!foo\" is a shortcut for the mandatory match \"&!foo\". Finally, a backslash can be used at the beginning of the element (after the optional special characters) to escape the start of the pattern. For example, \"&\\!a\" is an mandatory match for literally \"!a\".")
|
#define DESCRIBE_DOC_NM_SETTING_MATCH_INTERFACE_NAME N_("A list of interface names to match. Each element is a shell wildcard pattern. An element can be prefixed with a pipe symbol (|) or an ampersand (&). The former means that the element is optional and the latter means that it is mandatory. If there are any optional elements, than the match evaluates to true if at least one of the optional element matches (logical OR). If there are any mandatory elements, then they all must match (logical AND). By default, an element is optional. This means that an element \"foo\" behaves the same as \"|foo\". An element can also be inverted with exclamation mark (!) between the pipe symbol (or the ampersand) and before the pattern. Note that \"!foo\" is a shortcut for the mandatory match \"&!foo\". Finally, a backslash can be used at the beginning of the element (after the optional special characters) to escape the start of the pattern. For example, \"&\\!a\" is an mandatory match for literally \"!a\".")
|
||||||
|
|
|
||||||
|
|
@ -103,8 +103,7 @@ if enable_nmtui
|
||||||
endif
|
endif
|
||||||
subdir('nmcli')
|
subdir('nmcli')
|
||||||
subdir('nm-dispatcher')
|
subdir('nm-dispatcher')
|
||||||
subdir('nm-priv-helper')
|
subdir('nm-helpers')
|
||||||
subdir('nm-daemon-helper')
|
|
||||||
subdir('nm-online')
|
subdir('nm-online')
|
||||||
if enable_nmtui
|
if enable_nmtui
|
||||||
subdir('nmtui')
|
subdir('nmtui')
|
||||||
|
|
|
||||||
|
|
@ -1140,8 +1140,6 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco
|
||||||
r = n_dhcp4_c_connection_send_request(&probe->connection, request, ns_now);
|
r = n_dhcp4_c_connection_send_request(&probe->connection, request, ns_now);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
else
|
|
||||||
request = NULL; /* consumed */
|
|
||||||
|
|
||||||
n_dhcp4_client_lease_unlink(probe->current_lease);
|
n_dhcp4_client_lease_unlink(probe->current_lease);
|
||||||
probe->current_lease = n_dhcp4_client_lease_unref(probe->current_lease);
|
probe->current_lease = n_dhcp4_client_lease_unref(probe->current_lease);
|
||||||
|
|
@ -1346,7 +1344,6 @@ int n_dhcp4_client_probe_release(NDhcp4ClientProbe *probe) {
|
||||||
|
|
||||||
probe->state = N_DHCP4_CLIENT_PROBE_STATE_INIT;
|
probe->state = N_DHCP4_CLIENT_PROBE_STATE_INIT;
|
||||||
n_dhcp4_client_lease_unlink(probe->current_lease);
|
n_dhcp4_client_lease_unlink(probe->current_lease);
|
||||||
request_out = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,17 +387,6 @@ _nmc_skip_connection_by_user_data(NMConnection *connection)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_nmc_skip_connection_by_type(NMConnection *connection, const char *connection_type)
|
|
||||||
{
|
|
||||||
if (!nm_streq0(nm_connection_get_connection_type(connection), connection_type))
|
|
||||||
return TRUE;
|
|
||||||
if (!nm_connection_get_setting_ip4_config(connection))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_nmc_mangle_connection(NMDevice *device,
|
_nmc_mangle_connection(NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
|
@ -618,8 +607,14 @@ try_again:
|
||||||
return any_changes;
|
return any_changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_nmc_skip_connection_by_type(applied_connection, connection_type)) {
|
if (!nm_streq0(nm_connection_get_connection_type(applied_connection), connection_type)) {
|
||||||
_LOGD("config device %s: device has no suitable applied connection. Skip", hwaddr);
|
_LOGD("config device %s: skip applied connection due to type mismatch", hwaddr);
|
||||||
|
return any_changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_connection_get_setting_ip4_config(applied_connection)) {
|
||||||
|
_LOGD("config device %s: skip applied connection due to missing IPv4 configuration",
|
||||||
|
hwaddr);
|
||||||
return any_changes;
|
return any_changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -696,13 +691,34 @@ try_again:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NMConnection *
|
||||||
|
_new_connection(void)
|
||||||
|
{
|
||||||
|
NMConnection *connection;
|
||||||
|
NMSetting *s_user;
|
||||||
|
|
||||||
|
connection = nm_simple_connection_new();
|
||||||
|
s_user = nm_setting_user_new();
|
||||||
|
nm_connection_add_setting(connection, s_user);
|
||||||
|
nm_setting_user_set_data(NM_SETTING_USER(s_user),
|
||||||
|
"org.freedesktop.NetworkManager.origin",
|
||||||
|
"nm-cloud-setup",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_config_ethernet(SigTermData *sigterm_data,
|
_config_ethernet(SigTermData *sigterm_data,
|
||||||
const NMCSProviderGetConfigIfaceData *config_data,
|
const NMCSProviderGetConfigIfaceData *config_data,
|
||||||
NMClient *nmc,
|
NMClient *nmc,
|
||||||
const NMCSProviderGetConfigResult *result)
|
const NMCSProviderGetConfigResult *result,
|
||||||
|
gboolean allow_new_connections)
|
||||||
{
|
{
|
||||||
gs_unref_object NMDevice *device = NULL;
|
gs_unref_object NMDevice *device = NULL;
|
||||||
|
gs_unref_object NMConnection *connection = NULL;
|
||||||
|
gs_unref_object NMActiveConnection *active_connection = NULL;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
|
||||||
device = nm_g_object_ref(
|
device = nm_g_object_ref(
|
||||||
_nmc_get_device_by_hwaddr(nmc, NM_TYPE_DEVICE_ETHERNET, config_data->hwaddr));
|
_nmc_get_device_by_hwaddr(nmc, NM_TYPE_DEVICE_ETHERNET, config_data->hwaddr));
|
||||||
|
|
@ -711,12 +727,52 @@ _config_ethernet(SigTermData *sigterm_data,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _config_existing(sigterm_data,
|
if (allow_new_connections && nm_device_get_state(device) == NM_DEVICE_STATE_DISCONNECTED) {
|
||||||
config_data,
|
connection = _new_connection();
|
||||||
nmc,
|
nm_connection_add_setting(connection,
|
||||||
result,
|
g_object_new(NM_TYPE_SETTING_CONNECTION,
|
||||||
NM_SETTING_WIRED_SETTING_NAME,
|
NM_SETTING_CONNECTION_TYPE,
|
||||||
device);
|
NM_SETTING_WIRED_SETTING_NAME,
|
||||||
|
NULL));
|
||||||
|
nm_connection_add_setting(connection,
|
||||||
|
g_object_new(NM_TYPE_SETTING_IP4_CONFIG,
|
||||||
|
NM_SETTING_IP_CONFIG_METHOD,
|
||||||
|
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
nm_connection_add_setting(connection,
|
||||||
|
g_object_new(NM_TYPE_SETTING_WIRED,
|
||||||
|
NM_SETTING_WIRED_MAC_ADDRESS,
|
||||||
|
config_data->hwaddr,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
_nmc_mangle_connection(device, connection, result, config_data, NULL, NULL);
|
||||||
|
|
||||||
|
active_connection = nmcs_add_and_activate(nmc, NULL, device, connection, &error);
|
||||||
|
if (!active_connection) {
|
||||||
|
if (!nm_utils_error_is_cancelled(error)) {
|
||||||
|
_LOGD("config device %s: failure to activate connection: %s",
|
||||||
|
nm_device_get_iface(NM_DEVICE(device)),
|
||||||
|
error->message);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGD("config device %s: connection \"%s\" (%s) created",
|
||||||
|
nm_device_get_iface(NM_DEVICE(device)),
|
||||||
|
nm_active_connection_get_id(active_connection),
|
||||||
|
nm_active_connection_get_uuid(active_connection));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return _config_existing(sigterm_data,
|
||||||
|
config_data,
|
||||||
|
nmc,
|
||||||
|
result,
|
||||||
|
NM_SETTING_WIRED_SETTING_NAME,
|
||||||
|
device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
@ -738,9 +794,8 @@ _oci_new_vlan_dev(SigTermData *sigterm_data,
|
||||||
const char *wired_mac_addr = NULL;
|
const char *wired_mac_addr = NULL;
|
||||||
const NMUtilsNamedValue *map = NULL;
|
const NMUtilsNamedValue *map = NULL;
|
||||||
const char *ip4_config_method;
|
const char *ip4_config_method;
|
||||||
NMSetting *s_user;
|
|
||||||
|
|
||||||
connection = nm_simple_connection_new();
|
connection = _new_connection();
|
||||||
|
|
||||||
macvlan_name = g_strdup_printf("macvlan%ld", config_data->iface_idx);
|
macvlan_name = g_strdup_printf("macvlan%ld", config_data->iface_idx);
|
||||||
connection_id = g_strdup_printf("%s%ld", connection_type, config_data->iface_idx);
|
connection_id = g_strdup_printf("%s%ld", connection_type, config_data->iface_idx);
|
||||||
|
|
@ -811,13 +866,6 @@ _oci_new_vlan_dev(SigTermData *sigterm_data,
|
||||||
hwaddr,
|
hwaddr,
|
||||||
NULL));
|
NULL));
|
||||||
|
|
||||||
s_user = nm_setting_user_new();
|
|
||||||
nm_connection_add_setting(connection, s_user);
|
|
||||||
nm_setting_user_set_data(NM_SETTING_USER(s_user),
|
|
||||||
"org.freedesktop.NetworkManager.origin",
|
|
||||||
"nm-cloud-setup",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
_nmc_mangle_connection(NULL, connection, result, config_data, NULL, NULL);
|
_nmc_mangle_connection(NULL, connection, result, config_data, NULL, NULL);
|
||||||
|
|
||||||
_LOGD("config device %s: creating %s connection for VLAN %d on %s...",
|
_LOGD("config device %s: creating %s connection for VLAN %d on %s...",
|
||||||
|
|
@ -826,7 +874,7 @@ _oci_new_vlan_dev(SigTermData *sigterm_data,
|
||||||
config_data->priv.oci.vlan_tag,
|
config_data->priv.oci.vlan_tag,
|
||||||
parent_hwaddr);
|
parent_hwaddr);
|
||||||
|
|
||||||
active_connection = nmcs_add_and_activate(nmc, NULL, connection, &error);
|
active_connection = nmcs_add_and_activate(nmc, NULL, NULL, connection, &error);
|
||||||
if (active_connection == NULL) {
|
if (active_connection == NULL) {
|
||||||
if (!nm_utils_error_is_cancelled(error)) {
|
if (!nm_utils_error_is_cancelled(error)) {
|
||||||
_LOGD("config device %s: failure to activate connection: %s", hwaddr, error->message);
|
_LOGD("config device %s: failure to activate connection: %s", hwaddr, error->message);
|
||||||
|
|
@ -877,6 +925,7 @@ _config_one(SigTermData *sigterm_data,
|
||||||
guint idx)
|
guint idx)
|
||||||
{
|
{
|
||||||
const NMCSProviderGetConfigIfaceData *config_data = result->iface_datas_arr[idx];
|
const NMCSProviderGetConfigIfaceData *config_data = result->iface_datas_arr[idx];
|
||||||
|
gboolean allow_new_connections;
|
||||||
gboolean any_changes;
|
gboolean any_changes;
|
||||||
|
|
||||||
g_main_context_iteration(NULL, FALSE);
|
g_main_context_iteration(NULL, FALSE);
|
||||||
|
|
@ -899,7 +948,13 @@ _config_one(SigTermData *sigterm_data,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NMCS_IS_PROVIDER_OCI(provider) && config_data->priv.oci.vlan_tag != 0) {
|
/* Default on on OCI, with an environment variable serving as a chicken bit. */
|
||||||
|
allow_new_connections =
|
||||||
|
_nm_utils_ascii_str_to_bool(g_getenv(NMCS_ENV_NM_CLOUD_SETUP_ALLOW_NEW_CONN),
|
||||||
|
NMCS_IS_PROVIDER_OCI(provider));
|
||||||
|
|
||||||
|
if (allow_new_connections && NMCS_IS_PROVIDER_OCI(provider)
|
||||||
|
&& config_data->priv.oci.vlan_tag != 0) {
|
||||||
if (config_data->priv.oci.parent_hwaddr == NULL) {
|
if (config_data->priv.oci.parent_hwaddr == NULL) {
|
||||||
_LOGW("config device %s: has vlan id %d but no parent device",
|
_LOGW("config device %s: has vlan id %d but no parent device",
|
||||||
config_data->hwaddr,
|
config_data->hwaddr,
|
||||||
|
|
@ -924,7 +979,8 @@ _config_one(SigTermData *sigterm_data,
|
||||||
config_data->hwaddr);
|
config_data->hwaddr);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
any_changes = _config_ethernet(sigterm_data, config_data, nmc, result);
|
any_changes =
|
||||||
|
_config_ethernet(sigterm_data, config_data, nmc, result, allow_new_connections);
|
||||||
}
|
}
|
||||||
|
|
||||||
return any_changes;
|
return any_changes;
|
||||||
|
|
|
||||||
|
|
@ -637,6 +637,7 @@ _nmcs_add_and_activate_cb(GObject *source, GAsyncResult *result, gpointer user_d
|
||||||
NMActiveConnection *
|
NMActiveConnection *
|
||||||
nmcs_add_and_activate(NMClient *client,
|
nmcs_add_and_activate(NMClient *client,
|
||||||
GCancellable *sigterm_cancellable,
|
GCancellable *sigterm_cancellable,
|
||||||
|
NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
|
@ -648,7 +649,7 @@ nmcs_add_and_activate(NMClient *client,
|
||||||
|
|
||||||
nm_client_add_and_activate_connection_async(client,
|
nm_client_add_and_activate_connection_async(client,
|
||||||
connection,
|
connection,
|
||||||
NULL,
|
device,
|
||||||
NULL,
|
NULL,
|
||||||
sigterm_cancellable,
|
sigterm_cancellable,
|
||||||
_nmcs_add_and_activate_cb,
|
_nmcs_add_and_activate_cb,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#define NMCS_ENV_NM_CLOUD_SETUP_GCP_HOST "NM_CLOUD_SETUP_GCP_HOST"
|
#define NMCS_ENV_NM_CLOUD_SETUP_GCP_HOST "NM_CLOUD_SETUP_GCP_HOST"
|
||||||
#define NMCS_ENV_NM_CLOUD_SETUP_OCI_HOST "NM_CLOUD_SETUP_OCI_HOST"
|
#define NMCS_ENV_NM_CLOUD_SETUP_OCI_HOST "NM_CLOUD_SETUP_OCI_HOST"
|
||||||
#define NMCS_ENV_NM_CLOUD_SETUP_MAP_INTERFACES "NM_CLOUD_SETUP_MAP_INTERFACES"
|
#define NMCS_ENV_NM_CLOUD_SETUP_MAP_INTERFACES "NM_CLOUD_SETUP_MAP_INTERFACES"
|
||||||
|
#define NMCS_ENV_NM_CLOUD_SETUP_ALLOW_NEW_CONN "NM_CLOUD_SETUP_ALLOW_NEW_CONN"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
@ -155,6 +156,7 @@ NMConnection *nmcs_device_get_applied_connection(NMDevice *device,
|
||||||
|
|
||||||
NMActiveConnection *nmcs_add_and_activate(NMClient *client,
|
NMActiveConnection *nmcs_add_and_activate(NMClient *client,
|
||||||
GCancellable *sigterm_cancellable,
|
GCancellable *sigterm_cancellable,
|
||||||
|
NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
nm-daemon-helper
|
|
||||||
================
|
|
||||||
|
|
||||||
A internal helper application that is spawned by NetworkManager
|
|
||||||
to perform certain actions.
|
|
||||||
|
|
||||||
Currently all it does is doing a reverse DNS lookup, which
|
|
||||||
cannot be done by NetworkManager because the operation requires
|
|
||||||
to reconfigure the libc resolver (which is a process-wide operation).
|
|
||||||
|
|
||||||
This is not directly useful to the user.
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
executable(
|
|
||||||
'nm-daemon-helper',
|
|
||||||
'nm-daemon-helper.c',
|
|
||||||
include_directories : [
|
|
||||||
src_inc,
|
|
||||||
top_inc,
|
|
||||||
],
|
|
||||||
link_with: [
|
|
||||||
libnm_std_aux,
|
|
||||||
],
|
|
||||||
link_args: ldflags_linker_script_binary,
|
|
||||||
link_depends: linker_script_binary,
|
|
||||||
install: true,
|
|
||||||
install_dir: nm_libexecdir,
|
|
||||||
)
|
|
||||||
|
|
@ -1,5 +1,32 @@
|
||||||
|
nm-helpers
|
||||||
|
==========
|
||||||
|
|
||||||
|
This directory contains stand-alone helper programs used by various
|
||||||
|
components.
|
||||||
|
|
||||||
|
nm-daemon-helper
|
||||||
|
----------------
|
||||||
|
|
||||||
|
A internal helper application that is spawned by NetworkManager to
|
||||||
|
perform certain actions which can't be done in the daemon.
|
||||||
|
|
||||||
|
Currently it's used to do a reverse DNS lookup after reconfiguring the
|
||||||
|
libc resolver (which is a process-wide operation), and to read files
|
||||||
|
on behalf of unprivileged users (which requires a seteuid that affects
|
||||||
|
all the threads of the process).
|
||||||
|
|
||||||
|
This is not directly useful to the user.
|
||||||
|
|
||||||
|
nm-libnm-helper
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A internal helper application that is spawned by libnm to perform
|
||||||
|
certain actions without impacting the calling process.
|
||||||
|
|
||||||
|
This is not directly useful to the user.
|
||||||
|
|
||||||
nm-priv-helper
|
nm-priv-helper
|
||||||
==============
|
--------------
|
||||||
|
|
||||||
This is a D-Bus activatable, exit-on-idle service, which
|
This is a D-Bus activatable, exit-on-idle service, which
|
||||||
provides an internal API to NetworkManager daemon.
|
provides an internal API to NetworkManager daemon.
|
||||||
|
|
@ -1,5 +1,45 @@
|
||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
# nm-daemon-helper
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'nm-daemon-helper',
|
||||||
|
'nm-daemon-helper.c',
|
||||||
|
include_directories : [
|
||||||
|
src_inc,
|
||||||
|
top_inc,
|
||||||
|
],
|
||||||
|
link_with: [
|
||||||
|
libnm_std_aux,
|
||||||
|
],
|
||||||
|
link_args: ldflags_linker_script_binary,
|
||||||
|
link_depends: linker_script_binary,
|
||||||
|
install: true,
|
||||||
|
install_dir: nm_libexecdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
# nm-libnm-helper
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'nm-libnm-helper',
|
||||||
|
['nm-libnm-helper.c'],
|
||||||
|
include_directories : [
|
||||||
|
src_inc,
|
||||||
|
top_inc,
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
glib_dep,
|
||||||
|
],
|
||||||
|
link_with: [
|
||||||
|
libnm_glib_aux,
|
||||||
|
libnm_std_aux,
|
||||||
|
],
|
||||||
|
install: true,
|
||||||
|
install_dir: nm_libexecdir,
|
||||||
|
)
|
||||||
|
|
||||||
|
# nm-priv-helper
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
input: 'org.freedesktop.nm_priv_helper.service.in',
|
input: 'org.freedesktop.nm_priv_helper.service.in',
|
||||||
output: '@BASENAME@',
|
output: '@BASENAME@',
|
||||||
|
|
@ -137,6 +137,37 @@ cmd_resolve_address(void)
|
||||||
return RETURN_ERROR;
|
return RETURN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_read_file_as_user(void)
|
||||||
|
{
|
||||||
|
nm_auto_free char *user = NULL;
|
||||||
|
nm_auto_free char *filename = NULL;
|
||||||
|
char error[1024];
|
||||||
|
|
||||||
|
user = read_arg();
|
||||||
|
if (!user)
|
||||||
|
return RETURN_INVALID_ARGS;
|
||||||
|
|
||||||
|
filename = read_arg();
|
||||||
|
if (!filename)
|
||||||
|
return RETURN_INVALID_ARGS;
|
||||||
|
|
||||||
|
if (more_args())
|
||||||
|
return RETURN_INVALID_ARGS;
|
||||||
|
|
||||||
|
if (!nm_utils_set_effective_user(user, error, sizeof(error))) {
|
||||||
|
fprintf(stderr, "Failed to set effective user '%s': %s", user, error);
|
||||||
|
return RETURN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_utils_read_file_to_stdout(filename, error, sizeof(error))) {
|
||||||
|
fprintf(stderr, "Failed to read file '%s' as user '%s': %s", filename, user, error);
|
||||||
|
return RETURN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
@ -150,6 +181,8 @@ main(int argc, char **argv)
|
||||||
return cmd_version();
|
return cmd_version();
|
||||||
if (nm_streq(cmd, "resolve-address"))
|
if (nm_streq(cmd, "resolve-address"))
|
||||||
return cmd_resolve_address();
|
return cmd_resolve_address();
|
||||||
|
if (nm_streq(cmd, "read-file-as-user"))
|
||||||
|
return cmd_read_file_as_user();
|
||||||
|
|
||||||
return RETURN_INVALID_CMD;
|
return RETURN_INVALID_CMD;
|
||||||
}
|
}
|
||||||
45
src/nm-helpers/nm-libnm-helper.c
Normal file
45
src/nm-helpers/nm-libnm-helper.c
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "libnm-std-aux/nm-default-std.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RETURN_SUCCESS = 0,
|
||||||
|
RETURN_INVALID_CMD = 1,
|
||||||
|
RETURN_INVALID_ARGS = 2,
|
||||||
|
RETURN_ERROR = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_file_as_user(const char *filename, const char *user)
|
||||||
|
{
|
||||||
|
char error[1024];
|
||||||
|
|
||||||
|
if (!nm_utils_set_effective_user(user, error, sizeof(error))) {
|
||||||
|
fprintf(stderr, "Failed to set effective user '%s': %s", user, error);
|
||||||
|
return RETURN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_utils_read_file_to_stdout(filename, error, sizeof(error))) {
|
||||||
|
fprintf(stderr, "Failed to read file '%s' as user '%s': %s", filename, user, error);
|
||||||
|
return RETURN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc <= 1)
|
||||||
|
return RETURN_INVALID_CMD;
|
||||||
|
|
||||||
|
if (nm_streq(argv[1], "read-file-as-user")) {
|
||||||
|
if (argc != 4)
|
||||||
|
return RETURN_INVALID_ARGS;
|
||||||
|
return read_file_as_user(argv[2], argv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RETURN_INVALID_CMD;
|
||||||
|
}
|
||||||
|
|
@ -299,33 +299,44 @@ get_word(char **argument, const char separator)
|
||||||
{
|
{
|
||||||
char *word;
|
char *word;
|
||||||
int nest = 0;
|
int nest = 0;
|
||||||
|
char *last_ch;
|
||||||
|
char *first_close = NULL;
|
||||||
|
|
||||||
if (*argument == NULL)
|
if (*argument == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (**argument == '[') {
|
word = last_ch = *argument;
|
||||||
nest++;
|
|
||||||
(*argument)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
word = *argument;
|
|
||||||
|
|
||||||
while (**argument != '\0') {
|
while (**argument != '\0') {
|
||||||
if (nest && **argument == ']') {
|
|
||||||
**argument = '\0';
|
|
||||||
(*argument)++;
|
|
||||||
nest--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nest == 0 && **argument == separator) {
|
if (nest == 0 && **argument == separator) {
|
||||||
**argument = '\0';
|
**argument = '\0';
|
||||||
(*argument)++;
|
(*argument)++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (**argument == '[') {
|
||||||
|
nest++;
|
||||||
|
} else if (nest && **argument == ']') {
|
||||||
|
nest--;
|
||||||
|
if (!first_close && nest == 0)
|
||||||
|
first_close = *argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_ch = *argument;
|
||||||
(*argument)++;
|
(*argument)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the word is surrounded with the nesting symbols [], strip them so we return
|
||||||
|
* the inner content only.
|
||||||
|
* If there were nesting symbols but embracing only part of the inner content, don't
|
||||||
|
* remove them. Example:
|
||||||
|
* Remove [] in get_word("[fc08::1]:other_token", ":")
|
||||||
|
* Don't remove [] in get_word("ip6=[fc08::1]:other_token", ":")
|
||||||
|
*/
|
||||||
|
if (*word == '[' && *last_ch == ']' && last_ch == first_close) {
|
||||||
|
word++;
|
||||||
|
*last_ch = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
return *word ? word : NULL;
|
return *word ? word : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -533,7 +544,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
||||||
NMSettingConnection *s_con;
|
NMSettingConnection *s_con;
|
||||||
NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL;
|
NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL;
|
||||||
gs_unref_hashtable GHashTable *ibft = NULL;
|
gs_unref_hashtable GHashTable *ibft = NULL;
|
||||||
const char *tmp;
|
char *tmp;
|
||||||
const char *tmp2;
|
const char *tmp2;
|
||||||
const char *tmp3;
|
const char *tmp3;
|
||||||
const char *kind;
|
const char *kind;
|
||||||
|
|
@ -578,15 +589,25 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
||||||
kind = tmp3;
|
kind = tmp3;
|
||||||
} else {
|
} else {
|
||||||
/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */
|
/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */
|
||||||
client_ip = tmp;
|
|
||||||
|
/* note: split here address and prefix to normalize IPs defined as
|
||||||
|
* [dead::beef]/64. Latter parsing would fail due to the '[]'. */
|
||||||
|
client_ip = get_word(&tmp, '/');
|
||||||
|
|
||||||
if (client_ip) {
|
if (client_ip) {
|
||||||
client_ip_family = get_ip_address_family(client_ip, TRUE);
|
client_ip_family = get_ip_address_family(client_ip, FALSE);
|
||||||
if (client_ip_family == AF_UNSPEC) {
|
if (client_ip_family == AF_UNSPEC) {
|
||||||
_LOGW(LOGD_CORE, "Invalid IP address '%s'.", client_ip);
|
_LOGW(LOGD_CORE, "Invalid IP address '%s'.", client_ip);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nm_str_is_empty(tmp)) {
|
||||||
|
gboolean is_ipv4 = client_ip_family == AF_INET;
|
||||||
|
|
||||||
|
client_ip_prefix = _nm_utils_ascii_str_to_int64(tmp, 10, 0, is_ipv4 ? 32 : 128, -1);
|
||||||
|
}
|
||||||
|
|
||||||
peer = tmp2;
|
peer = tmp2;
|
||||||
gateway_ip = get_word(&argument, ':');
|
gateway_ip = get_word(&argument, ':');
|
||||||
netmask = get_word(&argument, ':');
|
netmask = get_word(&argument, ':');
|
||||||
|
|
@ -661,11 +682,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
||||||
NMIPAddress *address = NULL;
|
NMIPAddress *address = NULL;
|
||||||
NMIPAddr addr;
|
NMIPAddr addr;
|
||||||
|
|
||||||
if (nm_inet_parse_with_prefix_bin(client_ip_family,
|
if (nm_inet_parse_bin(client_ip_family, client_ip, NULL, &addr)) {
|
||||||
client_ip,
|
|
||||||
NULL,
|
|
||||||
&addr,
|
|
||||||
client_ip_prefix == -1 ? &client_ip_prefix : NULL)) {
|
|
||||||
if (client_ip_prefix == -1) {
|
if (client_ip_prefix == -1) {
|
||||||
switch (client_ip_family) {
|
switch (client_ip_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
|
|
@ -905,14 +922,25 @@ reader_parse_controller(Reader *reader,
|
||||||
|
|
||||||
opts = get_word(&argument, ':');
|
opts = get_word(&argument, ':');
|
||||||
while (opts && *opts) {
|
while (opts && *opts) {
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
char *opt;
|
char *tmp;
|
||||||
const char *opt_name;
|
const char *opt_name;
|
||||||
|
char *opt;
|
||||||
|
const char *opt_value;
|
||||||
|
nm_auto_unref_ptrarray GPtrArray *opt_values = g_ptr_array_new();
|
||||||
|
gs_free char *opt_normalized = NULL;
|
||||||
|
|
||||||
|
opt_name = get_word(&opts, '=');
|
||||||
opt = get_word(&opts, ',');
|
opt = get_word(&opts, ',');
|
||||||
opt_name = get_word(&opt, '=');
|
|
||||||
|
|
||||||
if (!_nm_setting_bond_validate_option(opt_name, opt, &error)) {
|
/* Normalize: convert ';' to ',' and remove '[]' from IPv6 addresses */
|
||||||
|
tmp = opt;
|
||||||
|
while ((opt_value = get_word(&tmp, ';')))
|
||||||
|
g_ptr_array_add(opt_values, (gpointer) opt_value);
|
||||||
|
g_ptr_array_add(opt_values, NULL);
|
||||||
|
opt_normalized = g_strjoinv(",", (char **) opt_values->pdata);
|
||||||
|
|
||||||
|
if (!_nm_setting_bond_validate_option(opt_name, opt_normalized, &error)) {
|
||||||
_LOGW(LOGD_CORE,
|
_LOGW(LOGD_CORE,
|
||||||
"Ignoring invalid bond option: %s%s%s = %s%s%s: %s",
|
"Ignoring invalid bond option: %s%s%s = %s%s%s: %s",
|
||||||
NM_PRINT_FMT_QUOTE_STRING(opt_name),
|
NM_PRINT_FMT_QUOTE_STRING(opt_name),
|
||||||
|
|
@ -920,7 +948,7 @@ reader_parse_controller(Reader *reader,
|
||||||
error->message);
|
error->message);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nm_setting_bond_add_option(s_bond, opt_name, opt);
|
nm_setting_bond_add_option(s_bond, opt_name, opt_normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
mtu = get_word(&argument, ':');
|
mtu = get_word(&argument, ':');
|
||||||
|
|
|
||||||
|
|
@ -597,7 +597,7 @@ static void
|
||||||
test_if_ip6_manual(void)
|
test_if_ip6_manual(void)
|
||||||
{
|
{
|
||||||
gs_unref_hashtable GHashTable *connections = NULL;
|
gs_unref_hashtable GHashTable *connections = NULL;
|
||||||
const char *const *ARGV = NM_MAKE_STRV("ip=[2001:0db8::02]/64::[2001:0db8::01]::"
|
const char *const *ARGV = NM_MAKE_STRV("ip=[2001:0db8::02]/56::[2001:0db8::01]::"
|
||||||
"hostname0.example.com:eth4::[2001:0db8::53]");
|
"hostname0.example.com:eth4::[2001:0db8::53]");
|
||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
NMSettingIPConfig *s_ip4;
|
NMSettingIPConfig *s_ip4;
|
||||||
|
|
@ -633,7 +633,7 @@ test_if_ip6_manual(void)
|
||||||
ip_addr = nm_setting_ip_config_get_address(s_ip6, 0);
|
ip_addr = nm_setting_ip_config_get_address(s_ip6, 0);
|
||||||
g_assert(ip_addr);
|
g_assert(ip_addr);
|
||||||
g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "2001:db8::2");
|
g_assert_cmpstr(nm_ip_address_get_address(ip_addr), ==, "2001:db8::2");
|
||||||
g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 64);
|
g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 56);
|
||||||
g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "2001:db8::1");
|
g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "2001:db8::1");
|
||||||
g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, NULL);
|
g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip6), ==, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -975,8 +975,8 @@ static void
|
||||||
test_bond(void)
|
test_bond(void)
|
||||||
{
|
{
|
||||||
gs_unref_hashtable GHashTable *connections = NULL;
|
gs_unref_hashtable GHashTable *connections = NULL;
|
||||||
const char *const *ARGV = NM_MAKE_STRV("rd.route=192.0.2.53::bong0",
|
const char *const *ARGV = NM_MAKE_STRV("rd.route=192.0.2.53::bond0",
|
||||||
"bond=bong0:eth0,eth1:mode=balance-rr:9000",
|
"bond=bond0:eth0,eth1:mode=balance-rr:9000",
|
||||||
"nameserver=203.0.113.53");
|
"nameserver=203.0.113.53");
|
||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
NMSettingConnection *s_con;
|
NMSettingConnection *s_con;
|
||||||
|
|
@ -990,12 +990,12 @@ test_bond(void)
|
||||||
connections = _parse_cons(ARGV);
|
connections = _parse_cons(ARGV);
|
||||||
g_assert_cmpint(g_hash_table_size(connections), ==, 3);
|
g_assert_cmpint(g_hash_table_size(connections), ==, 3);
|
||||||
|
|
||||||
connection = g_hash_table_lookup(connections, "bong0");
|
connection = g_hash_table_lookup(connections, "bond0");
|
||||||
nmtst_assert_connection_verifies_without_normalization(connection);
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
g_assert_cmpstr(nm_connection_get_connection_type(connection),
|
g_assert_cmpstr(nm_connection_get_connection_type(connection),
|
||||||
==,
|
==,
|
||||||
NM_SETTING_BOND_SETTING_NAME);
|
NM_SETTING_BOND_SETTING_NAME);
|
||||||
g_assert_cmpstr(nm_connection_get_id(connection), ==, "bong0");
|
g_assert_cmpstr(nm_connection_get_id(connection), ==, "bond0");
|
||||||
controller_uuid = nm_connection_get_uuid(connection);
|
controller_uuid = nm_connection_get_uuid(connection);
|
||||||
g_assert(controller_uuid);
|
g_assert(controller_uuid);
|
||||||
|
|
||||||
|
|
@ -1162,6 +1162,118 @@ test_bond_ip(void)
|
||||||
NM_CONNECTION_MULTI_CONNECT_SINGLE);
|
NM_CONNECTION_MULTI_CONNECT_SINGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_bond_ip6_option(void)
|
||||||
|
{
|
||||||
|
/* Test that IPv6 addresses within [] are parsed fine in different positions */
|
||||||
|
|
||||||
|
gs_unref_hashtable GHashTable *connections = NULL;
|
||||||
|
const char *const *ARGV =
|
||||||
|
NM_MAKE_STRV("bond=bond0:eth0,eth1:arp_interval=100,ns_ip6_target=[fc08::1]",
|
||||||
|
"bond=bond1:eth2,eth3:arp_interval=100,ns_ip6_target=[fc08::1]:9000",
|
||||||
|
"bond=bond2:eth4,eth5:ns_ip6_target=[fc08::1],arp_interval=100");
|
||||||
|
NMConnection *connection;
|
||||||
|
NMSettingBond *s_bond;
|
||||||
|
|
||||||
|
connections = _parse_cons(ARGV);
|
||||||
|
g_assert_cmpint(g_hash_table_size(connections), ==, 9);
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond0");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "ns_ip6_target"), ==, "fc08::1");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond1");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "ns_ip6_target"), ==, "fc08::1");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond2");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "ns_ip6_target"), ==, "fc08::1");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_bond_multi_values_option(void)
|
||||||
|
{
|
||||||
|
/* Test that semicolon-separated multi-valued options are parsed fine in different positions */
|
||||||
|
|
||||||
|
gs_unref_hashtable GHashTable *connections = NULL;
|
||||||
|
const char *const *ARGV =
|
||||||
|
NM_MAKE_STRV("bond=bond0:eth0,eth1:arp_interval=100,ns_ip6_target=[fc08::1];[fc08::2]",
|
||||||
|
"bond=bond1:eth2,eth3:arp_interval=100,ns_ip6_target=[fc08::1];[fc08::2]:9000",
|
||||||
|
"bond=bond2:eth4,eth5:ns_ip6_target=[fc08::1];[fc08::2],arp_interval=100",
|
||||||
|
"bond=bond3:eth6,eth7:arp_interval=100,arp_ip_target=10.0.0.1;10.0.0.2",
|
||||||
|
"bond=bond4:eth8,eth9:arp_interval=100,arp_ip_target=10.0.0.1;10.0.0.2:9000",
|
||||||
|
"bond=bond5:eth10,eth11:arp_ip_target=10.0.0.1;10.0.0.2,arp_interval=100");
|
||||||
|
NMConnection *connection;
|
||||||
|
NMSettingBond *s_bond;
|
||||||
|
|
||||||
|
connections = _parse_cons(ARGV);
|
||||||
|
g_assert_cmpint(g_hash_table_size(connections), ==, 18);
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond0");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "ns_ip6_target"),
|
||||||
|
==,
|
||||||
|
"fc08::1,fc08::2");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond1");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "ns_ip6_target"),
|
||||||
|
==,
|
||||||
|
"fc08::1,fc08::2");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond2");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "ns_ip6_target"),
|
||||||
|
==,
|
||||||
|
"fc08::1,fc08::2");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond3");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "arp_ip_target"),
|
||||||
|
==,
|
||||||
|
"10.0.0.1,10.0.0.2");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond4");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "arp_ip_target"),
|
||||||
|
==,
|
||||||
|
"10.0.0.1,10.0.0.2");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "bond5");
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
s_bond = nm_connection_get_setting_bond(connection);
|
||||||
|
g_assert(s_bond);
|
||||||
|
g_assert_cmpint(nm_setting_bond_get_num_options(s_bond), ==, 3);
|
||||||
|
g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "arp_ip_target"),
|
||||||
|
==,
|
||||||
|
"10.0.0.1,10.0.0.2");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_bond_default(void)
|
test_bond_default(void)
|
||||||
{
|
{
|
||||||
|
|
@ -2701,6 +2813,8 @@ main(int argc, char **argv)
|
||||||
g_test_add_func("/initrd/cmdline/bootdev", test_bootdev);
|
g_test_add_func("/initrd/cmdline/bootdev", test_bootdev);
|
||||||
g_test_add_func("/initrd/cmdline/bond", test_bond);
|
g_test_add_func("/initrd/cmdline/bond", test_bond);
|
||||||
g_test_add_func("/initrd/cmdline/bond/ip", test_bond_ip);
|
g_test_add_func("/initrd/cmdline/bond/ip", test_bond_ip);
|
||||||
|
g_test_add_func("/initrd/cmdline/bond/ip6-option", test_bond_ip6_option);
|
||||||
|
g_test_add_func("/initrd/cmdline/bond/multi-values-option", test_bond_multi_values_option);
|
||||||
g_test_add_func("/initrd/cmdline/bond/default", test_bond_default);
|
g_test_add_func("/initrd/cmdline/bond/default", test_bond_default);
|
||||||
g_test_add_func("/initrd/cmdline/team", test_team);
|
g_test_add_func("/initrd/cmdline/team", test_team);
|
||||||
g_test_add_func("/initrd/cmdline/vlan", test_vlan);
|
g_test_add_func("/initrd/cmdline/vlan", test_vlan);
|
||||||
|
|
|
||||||
|
|
@ -629,7 +629,7 @@
|
||||||
alias="type"
|
alias="type"
|
||||||
nmcli-description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, "vpn" or "bridge", etc)."
|
nmcli-description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, "vpn" or "bridge", etc)."
|
||||||
format="string"
|
format="string"
|
||||||
values="6lowpan, 802-11-olpc-mesh, 802-11-wireless, 802-3-ethernet, adsl, bluetooth, bond, bridge, cdma, dummy, generic, gsm, hsr, infiniband, ip-tunnel, ipvlan, loopback, macsec, macvlan, ovs-bridge, ovs-dpdk, ovs-interface, ovs-patch, ovs-port, pppoe, team, tun, veth, vlan, vpn, vrf, vxlan, wifi-p2p, wimax, wireguard, wpan" />
|
values="6lowpan, 802-11-olpc-mesh, 802-11-wireless, 802-3-ethernet, adsl, bluetooth, bond, bridge, cdma, dummy, generic, gsm, hsr, infiniband, ip-tunnel, ipvlan, loopback, macsec, macvlan, ovs-bridge, ovs-interface, ovs-port, pppoe, team, tun, veth, vlan, vpn, vrf, vxlan, wifi-p2p, wimax, wireguard, wpan" />
|
||||||
<property name="interface-name"
|
<property name="interface-name"
|
||||||
alias="ifname"
|
alias="ifname"
|
||||||
nmcli-description="The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface."
|
nmcli-description="The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface."
|
||||||
|
|
@ -1698,7 +1698,7 @@
|
||||||
format="choice (NMSettingMacvlanMode)"
|
format="choice (NMSettingMacvlanMode)"
|
||||||
values="vepa (1), bridge (2), private (3), passthru (4), source (5)" />
|
values="vepa (1), bridge (2), private (3), passthru (4), source (5)" />
|
||||||
<property name="promiscuous"
|
<property name="promiscuous"
|
||||||
nmcli-description="Whether the interface should be put in promiscuous mode."
|
nmcli-description="Whether the parent interface should be put in promiscuous mode (true by default)."
|
||||||
format="boolean"
|
format="boolean"
|
||||||
values="true/yes/on, false/no/off" />
|
values="true/yes/on, false/no/off" />
|
||||||
<property name="tap"
|
<property name="tap"
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,89 @@
|
||||||
size: 376
|
size: 382
|
||||||
location: src/tests/client/test-client.py:test_002()/1
|
location: src/tests/client/test-client.py:test_002()/1
|
||||||
cmd: $NMCLI d
|
cmd: $NMCLI d
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 258 bytes
|
stdout: 264 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE CONNECTION
|
DEVICE TYPE STATE CONNECTION
|
||||||
eth0 ethernet unavailable --
|
eth0 ethernet disconnected --
|
||||||
eth1 ethernet unavailable --
|
eth1 ethernet disconnected --
|
||||||
wlan0 wifi unavailable --
|
wlan0 wifi disconnected --
|
||||||
wlan1 wifi unavailable --
|
wlan1 wifi disconnected --
|
||||||
wlan1 wifi unavailable --
|
wlan1 wifi disconnected --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 391
|
size: 390
|
||||||
location: src/tests/client/test-client.py:test_002()/2
|
location: src/tests/client/test-client.py:test_002()/2
|
||||||
cmd: $NMCLI d
|
cmd: $NMCLI d
|
||||||
lang: pl_PL.UTF-8
|
lang: pl_PL.UTF-8
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 263 bytes
|
stdout: 262 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE CONNECTION
|
DEVICE TYPE STATE CONNECTION
|
||||||
eth0 ethernet niedostępne --
|
eth0 ethernet rozłączono --
|
||||||
eth1 ethernet niedostępne --
|
eth1 ethernet rozłączono --
|
||||||
wlan0 wifi niedostępne --
|
wlan0 wifi rozłączono --
|
||||||
wlan1 wifi niedostępne --
|
wlan1 wifi rozłączono --
|
||||||
wlan1 wifi niedostępne --
|
wlan1 wifi rozłączono --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 977
|
size: 983
|
||||||
location: src/tests/client/test-client.py:test_002()/3
|
location: src/tests/client/test-client.py:test_002()/3
|
||||||
cmd: $NMCLI -f all d
|
cmd: $NMCLI -f all d
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 852 bytes
|
stdout: 858 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth0 ethernet unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/1 -- -- --
|
eth0 ethernet disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/1 -- -- --
|
||||||
eth1 ethernet unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
eth1 ethernet disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
||||||
wlan0 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 992
|
size: 991
|
||||||
location: src/tests/client/test-client.py:test_002()/4
|
location: src/tests/client/test-client.py:test_002()/4
|
||||||
cmd: $NMCLI -f all d
|
cmd: $NMCLI -f all d
|
||||||
lang: pl_PL.UTF-8
|
lang: pl_PL.UTF-8
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 857 bytes
|
stdout: 856 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth0 ethernet niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 -- -- --
|
eth0 ethernet rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 -- -- --
|
||||||
eth1 ethernet niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
eth1 ethernet rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
||||||
wlan0 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 738
|
size: 791
|
||||||
location: src/tests/client/test-client.py:test_002()/5
|
location: src/tests/client/test-client.py:test_002()/5
|
||||||
cmd: $NMCLI
|
cmd: $NMCLI
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 621 bytes
|
stdout: 674 bytes
|
||||||
>>>
|
>>>
|
||||||
eth0: unavailable
|
eth0: disconnected
|
||||||
"eth0"
|
"eth0"
|
||||||
|
1 connection available
|
||||||
ethernet (virtual), 65:2E:D3:9E:0A:0D, hw
|
ethernet (virtual), 65:2E:D3:9E:0A:0D, hw
|
||||||
|
|
||||||
eth1: unavailable
|
eth1: disconnected
|
||||||
"eth1"
|
"eth1"
|
||||||
|
1 connection available
|
||||||
ethernet (virtual), 47:D5:6B:65:FD:6A, hw
|
ethernet (virtual), 47:D5:6B:65:FD:6A, hw
|
||||||
|
|
||||||
wlan0: unavailable
|
wlan0: disconnected
|
||||||
"wlan0"
|
"wlan0"
|
||||||
wifi (virtual), 3D:99:1D:8B:74:4D, hw
|
wifi (virtual), 3D:99:1D:8B:74:4D, hw
|
||||||
|
|
||||||
wlan1: unavailable
|
wlan1: disconnected
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), 99:09:77:FD:FE:1D, hw
|
wifi (virtual), 99:09:77:FD:FE:1D, hw
|
||||||
|
|
||||||
wlan1: unavailable
|
wlan1: disconnected
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), 5D:30:4A:EC:3F:61, hw
|
wifi (virtual), 5D:30:4A:EC:3F:61, hw
|
||||||
|
|
||||||
|
|
@ -94,30 +96,32 @@ Use "nmcli device show" to get complete information about known devices and
|
||||||
Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.
|
Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 811
|
size: 873
|
||||||
location: src/tests/client/test-client.py:test_002()/6
|
location: src/tests/client/test-client.py:test_002()/6
|
||||||
cmd: $NMCLI
|
cmd: $NMCLI
|
||||||
lang: pl_PL.UTF-8
|
lang: pl_PL.UTF-8
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 684 bytes
|
stdout: 746 bytes
|
||||||
>>>
|
>>>
|
||||||
eth0: niedostępne
|
eth0: rozłączono
|
||||||
"eth0"
|
"eth0"
|
||||||
|
1 połączenie jest dostępne
|
||||||
ethernet (virtual), 65:2E:D3:9E:0A:0D, sprzęt
|
ethernet (virtual), 65:2E:D3:9E:0A:0D, sprzęt
|
||||||
|
|
||||||
eth1: niedostępne
|
eth1: rozłączono
|
||||||
"eth1"
|
"eth1"
|
||||||
|
1 połączenie jest dostępne
|
||||||
ethernet (virtual), 47:D5:6B:65:FD:6A, sprzęt
|
ethernet (virtual), 47:D5:6B:65:FD:6A, sprzęt
|
||||||
|
|
||||||
wlan0: niedostępne
|
wlan0: rozłączono
|
||||||
"wlan0"
|
"wlan0"
|
||||||
wifi (virtual), 3D:99:1D:8B:74:4D, sprzęt
|
wifi (virtual), 3D:99:1D:8B:74:4D, sprzęt
|
||||||
|
|
||||||
wlan1: niedostępne
|
wlan1: rozłączono
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), 99:09:77:FD:FE:1D, sprzęt
|
wifi (virtual), 99:09:77:FD:FE:1D, sprzęt
|
||||||
|
|
||||||
wlan1: niedostępne
|
wlan1: rozłączono
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), 5D:30:4A:EC:3F:61, sprzęt
|
wifi (virtual), 5D:30:4A:EC:3F:61, sprzęt
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1868,34 +1868,34 @@ GENERAL.ZONE: --
|
||||||
GENERAL.MASTER-PATH: --
|
GENERAL.MASTER-PATH: --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 1408
|
size: 1414
|
||||||
location: src/tests/client/test-client.py:test_003()/43
|
location: src/tests/client/test-client.py:test_003()/43
|
||||||
cmd: $NMCLI -f ALL dev status
|
cmd: $NMCLI -f ALL dev status
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 1272 bytes
|
stdout: 1278 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth0 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
eth0 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
||||||
eth1 ethernet unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
eth1 ethernet disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
||||||
wlan0 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 1424
|
size: 1422
|
||||||
location: src/tests/client/test-client.py:test_003()/44
|
location: src/tests/client/test-client.py:test_003()/44
|
||||||
cmd: $NMCLI -f ALL dev status
|
cmd: $NMCLI -f ALL dev status
|
||||||
lang: pl_PL.UTF-8
|
lang: pl_PL.UTF-8
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 1278 bytes
|
stdout: 1276 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth0 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
eth0 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
||||||
eth1 ethernet niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
eth1 ethernet rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 -- -- --
|
||||||
wlan0 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 172
|
size: 172
|
||||||
|
|
@ -2960,34 +2960,34 @@ GENERAL.ZONE: --
|
||||||
GENERAL.MASTER-PATH: --
|
GENERAL.MASTER-PATH: --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 1408
|
size: 1414
|
||||||
location: src/tests/client/test-client.py:test_003()/68
|
location: src/tests/client/test-client.py:test_003()/68
|
||||||
cmd: $NMCLI -f ALL dev status
|
cmd: $NMCLI -f ALL dev status
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 1272 bytes
|
stdout: 1278 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth0 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
eth0 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
||||||
eth1 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
eth1 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
||||||
wlan0 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 1425
|
size: 1422
|
||||||
location: src/tests/client/test-client.py:test_003()/69
|
location: src/tests/client/test-client.py:test_003()/69
|
||||||
cmd: $NMCLI -f ALL dev status
|
cmd: $NMCLI -f ALL dev status
|
||||||
lang: pl_PL.UTF-8
|
lang: pl_PL.UTF-8
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 1279 bytes
|
stdout: 1276 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth0 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
eth0 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
||||||
eth1 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
eth1 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
||||||
wlan0 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 172
|
size: 172
|
||||||
|
|
@ -3298,42 +3298,42 @@ CONNECTIONS.AVAILABLE-CONNECTIONS[2]:UUID-con-xx1-REPLACED-REPLACED-REPLA | con-
|
||||||
CONNECTIONS.AVAILABLE-CONNECTIONS[3]:UUID-ethernet-REPLACED-REPLACED-REPL | ethernet
|
CONNECTIONS.AVAILABLE-CONNECTIONS[3]:UUID-ethernet-REPLACED-REPLACED-REPL | ethernet
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 1399
|
size: 1405
|
||||||
location: src/tests/client/test-client.py:test_003()/76
|
location: src/tests/client/test-client.py:test_003()/76
|
||||||
cmd: $NMCLI -f all d
|
cmd: $NMCLI -f all d
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 1272 bytes
|
stdout: 1278 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth1 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
eth1 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
||||||
eth0 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
eth0 ethernet connected unknown unknown /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
||||||
wlan0 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi unavailable unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi disconnected unknown unknown /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 1416
|
size: 1413
|
||||||
location: src/tests/client/test-client.py:test_003()/77
|
location: src/tests/client/test-client.py:test_003()/77
|
||||||
cmd: $NMCLI -f all d
|
cmd: $NMCLI -f all d
|
||||||
lang: pl_PL.UTF-8
|
lang: pl_PL.UTF-8
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 1279 bytes
|
stdout: 1276 bytes
|
||||||
>>>
|
>>>
|
||||||
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
DEVICE TYPE STATE IP4-CONNECTIVITY IP6-CONNECTIVITY DBUS-PATH CONNECTION CON-UUID CON-PATH
|
||||||
eth1 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
eth1 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/2 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/2
|
||||||
eth0 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
eth0 ethernet połączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/1 ethernet UUID-ethernet-REPLACED-REPLACED-REPL /org/freedesktop/NetworkManager/ActiveConnection/1
|
||||||
wlan0 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
wlan0 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/3 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/4 -- -- --
|
||||||
wlan1 wifi niedostępne nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
wlan1 wifi rozłączono nieznane nieznane /org/freedesktop/NetworkManager/Devices/5 -- -- --
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
size: 759
|
size: 762
|
||||||
location: src/tests/client/test-client.py:test_003()/78
|
location: src/tests/client/test-client.py:test_003()/78
|
||||||
cmd: $NMCLI
|
cmd: $NMCLI
|
||||||
lang: C
|
lang: C
|
||||||
returncode: 0
|
returncode: 0
|
||||||
stdout: 641 bytes
|
stdout: 644 bytes
|
||||||
>>>
|
>>>
|
||||||
eth1: connected to ethernet
|
eth1: connected to ethernet
|
||||||
"eth1"
|
"eth1"
|
||||||
|
|
@ -3343,15 +3343,15 @@ eth0: connected to ethernet
|
||||||
"eth0"
|
"eth0"
|
||||||
ethernet (virtual), C0:61:AE:26:4D:D7, hw
|
ethernet (virtual), C0:61:AE:26:4D:D7, hw
|
||||||
|
|
||||||
wlan0: unavailable
|
wlan0: disconnected
|
||||||
"wlan0"
|
"wlan0"
|
||||||
wifi (virtual), DC:39:87:BA:3E:5D, hw
|
wifi (virtual), DC:39:87:BA:3E:5D, hw
|
||||||
|
|
||||||
wlan1: unavailable
|
wlan1: disconnected
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), AC:4E:5B:7B:57:49, hw
|
wifi (virtual), AC:4E:5B:7B:57:49, hw
|
||||||
|
|
||||||
wlan1: unavailable
|
wlan1: disconnected
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), 24:C4:52:BC:3D:37, hw
|
wifi (virtual), 24:C4:52:BC:3D:37, hw
|
||||||
|
|
||||||
|
|
@ -3379,15 +3379,15 @@ eth0: połączono do ethernet
|
||||||
"eth0"
|
"eth0"
|
||||||
ethernet (virtual), C0:61:AE:26:4D:D7, sprzęt
|
ethernet (virtual), C0:61:AE:26:4D:D7, sprzęt
|
||||||
|
|
||||||
wlan0: niedostępne
|
wlan0: rozłączono
|
||||||
"wlan0"
|
"wlan0"
|
||||||
wifi (virtual), DC:39:87:BA:3E:5D, sprzęt
|
wifi (virtual), DC:39:87:BA:3E:5D, sprzęt
|
||||||
|
|
||||||
wlan1: niedostępne
|
wlan1: rozłączono
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), AC:4E:5B:7B:57:49, sprzęt
|
wifi (virtual), AC:4E:5B:7B:57:49, sprzęt
|
||||||
|
|
||||||
wlan1: niedostępne
|
wlan1: rozłączono
|
||||||
"wlan1"
|
"wlan1"
|
||||||
wifi (virtual), 24:C4:52:BC:3D:37, sprzęt
|
wifi (virtual), 24:C4:52:BC:3D:37, sprzęt
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2445,8 +2445,11 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def _mock_devices(self):
|
def _mock_devices(self):
|
||||||
# Add a device with an active connection that has IPv4 configured
|
self.ctx.srv.op_AddObj("WiredDevice", iface="eth0", mac=self._mac1)
|
||||||
self.ctx.srv.op_AddObj("WiredDevice", iface="eth0", mac="cc:00:00:00:00:01")
|
self.ctx.srv.op_AddObj("WiredDevice", iface="eth1", mac=self._mac2)
|
||||||
|
|
||||||
|
def _mock_connection1(self):
|
||||||
|
# Active connection that has IPv4 configured for device1
|
||||||
self.ctx.srv.addAndActivateConnection(
|
self.ctx.srv.addAndActivateConnection(
|
||||||
{
|
{
|
||||||
"connection": {"type": "802-3-ethernet", "id": "con-eth0"},
|
"connection": {"type": "802-3-ethernet", "id": "con-eth0"},
|
||||||
|
|
@ -2456,8 +2459,8 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
delay=0,
|
delay=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _mock_connection2(self):
|
||||||
# The second connection has no IPv4
|
# The second connection has no IPv4
|
||||||
self.ctx.srv.op_AddObj("WiredDevice", iface="eth1", mac="cc:00:00:00:00:02")
|
|
||||||
self.ctx.srv.addAndActivateConnection(
|
self.ctx.srv.addAndActivateConnection(
|
||||||
{"connection": {"type": "802-3-ethernet", "id": "con-eth1"}},
|
{"connection": {"type": "802-3-ethernet", "id": "con-eth1"}},
|
||||||
"/org/freedesktop/NetworkManager/Devices/2",
|
"/org/freedesktop/NetworkManager/Devices/2",
|
||||||
|
|
@ -2465,13 +2468,18 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
delay=0,
|
delay=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _mock_connections(self):
|
||||||
|
self._mock_devices()
|
||||||
|
self._mock_connection1()
|
||||||
|
self._mock_connection2()
|
||||||
|
|
||||||
def _mock_path(self, path, body):
|
def _mock_path(self, path, body):
|
||||||
self.md_conn.request("PUT", path, body=body)
|
self.md_conn.request("PUT", path, body=body)
|
||||||
self.md_conn.getresponse().read()
|
self.md_conn.getresponse().read()
|
||||||
|
|
||||||
@cloud_setup_test
|
@cloud_setup_test
|
||||||
def test_aliyun(self):
|
def test_aliyun(self):
|
||||||
self._mock_devices()
|
self._mock_connections()
|
||||||
|
|
||||||
_aliyun_meta = "/2016-01-01/meta-data/"
|
_aliyun_meta = "/2016-01-01/meta-data/"
|
||||||
_aliyun_macs = _aliyun_meta + "network/interfaces/macs/"
|
_aliyun_macs = _aliyun_meta + "network/interfaces/macs/"
|
||||||
|
|
@ -2527,12 +2535,15 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider aliyun detected")
|
pexp.expect("provider aliyun detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: start fetching meta data")
|
pexp.expect("get-config: start fetching meta data")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
# One of the devices has no IPv4 configuration to be modified
|
# One of the devices has no IPv4 configuration to be modified
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
# The other one was lacking an address set it up.
|
# The other one was lacking an address set it up.
|
||||||
pexp.expect("some changes were applied for provider aliyun")
|
pexp.expect("some changes were applied for provider aliyun")
|
||||||
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
|
@ -2555,7 +2566,10 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider aliyun detected")
|
pexp.expect("provider aliyun detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
|
|
@ -2572,7 +2586,7 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
|
|
||||||
@cloud_setup_test
|
@cloud_setup_test
|
||||||
def test_azure(self):
|
def test_azure(self):
|
||||||
self._mock_devices()
|
self._mock_connections()
|
||||||
|
|
||||||
_azure_meta = "/metadata/instance"
|
_azure_meta = "/metadata/instance"
|
||||||
_azure_iface = _azure_meta + "/network/interface/"
|
_azure_iface = _azure_meta + "/network/interface/"
|
||||||
|
|
@ -2616,7 +2630,10 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider azure detected")
|
pexp.expect("provider azure detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("found azure interfaces: 2")
|
pexp.expect("found azure interfaces: 2")
|
||||||
pexp.expect(r"interface\[0]: found a matching device with hwaddr")
|
pexp.expect(r"interface\[0]: found a matching device with hwaddr")
|
||||||
pexp.expect(
|
pexp.expect(
|
||||||
|
|
@ -2628,7 +2645,7 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
# One of the devices has no IPv4 configuration to be modified
|
# One of the devices has no IPv4 configuration to be modified
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
# The other one was lacking an address set it up.
|
# The other one was lacking an address set it up.
|
||||||
pexp.expect("some changes were applied for provider azure")
|
pexp.expect("some changes were applied for provider azure")
|
||||||
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
|
@ -2651,7 +2668,10 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider azure detected")
|
pexp.expect("provider azure detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
|
|
@ -2668,7 +2688,7 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
|
|
||||||
@cloud_setup_test
|
@cloud_setup_test
|
||||||
def test_ec2(self):
|
def test_ec2(self):
|
||||||
self._mock_devices()
|
self._mock_connections()
|
||||||
|
|
||||||
_ec2_macs = "/2018-09-24/meta-data/network/interfaces/macs/"
|
_ec2_macs = "/2018-09-24/meta-data/network/interfaces/macs/"
|
||||||
self._mock_path("/latest/meta-data/", "ami-id\n")
|
self._mock_path("/latest/meta-data/", "ami-id\n")
|
||||||
|
|
@ -2702,12 +2722,15 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider ec2 detected")
|
pexp.expect("provider ec2 detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
# One of the devices has no IPv4 configuration to be modified
|
# One of the devices has no IPv4 configuration to be modified
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
# The other one was lacking an address set it up.
|
# The other one was lacking an address set it up.
|
||||||
pexp.expect("some changes were applied for provider ec2")
|
pexp.expect("some changes were applied for provider ec2")
|
||||||
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
|
@ -2730,7 +2753,10 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider ec2 detected")
|
pexp.expect("provider ec2 detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
|
|
@ -2747,7 +2773,7 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
|
|
||||||
@cloud_setup_test
|
@cloud_setup_test
|
||||||
def test_gcp(self):
|
def test_gcp(self):
|
||||||
self._mock_devices()
|
self._mock_connections()
|
||||||
|
|
||||||
gcp_meta = "/computeMetadata/v1/instance/"
|
gcp_meta = "/computeMetadata/v1/instance/"
|
||||||
gcp_iface = gcp_meta + "network-interfaces/"
|
gcp_iface = gcp_meta + "network-interfaces/"
|
||||||
|
|
@ -2772,13 +2798,16 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider GCP detected")
|
pexp.expect("provider GCP detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("found GCP interfaces: 2")
|
pexp.expect("found GCP interfaces: 2")
|
||||||
pexp.expect(r"GCP interface\[0]: found a requested device with hwaddr")
|
pexp.expect(r"GCP interface\[0]: found a requested device with hwaddr")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
# One of the devices has no IPv4 configuration to be modified
|
# One of the devices has no IPv4 configuration to be modified
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
# The other one was lacking an address set it up.
|
# The other one was lacking an address set it up.
|
||||||
pexp.expect("some changes were applied for provider GCP")
|
pexp.expect("some changes were applied for provider GCP")
|
||||||
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
|
@ -2801,7 +2830,10 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider GCP detected")
|
pexp.expect("provider GCP detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
|
|
@ -2818,7 +2850,7 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
|
|
||||||
@cloud_setup_test
|
@cloud_setup_test
|
||||||
def test_oci(self):
|
def test_oci(self):
|
||||||
self._mock_devices()
|
self._mock_connections()
|
||||||
|
|
||||||
oci_meta = "/opc/v2/"
|
oci_meta = "/opc/v2/"
|
||||||
self._mock_path(oci_meta + "instance", "{}")
|
self._mock_path(oci_meta + "instance", "{}")
|
||||||
|
|
@ -2864,12 +2896,15 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider oci detected")
|
pexp.expect("provider oci detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
# One of the devices has no IPv4 configuration to be modified
|
# One of the devices has no IPv4 configuration to be modified
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
# The other one was lacking an address set it up.
|
# The other one was lacking an address set it up.
|
||||||
pexp.expect("some changes were applied for provider oci")
|
pexp.expect("some changes were applied for provider oci")
|
||||||
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
|
@ -2892,7 +2927,10 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider oci detected")
|
pexp.expect("provider oci detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
|
|
@ -2909,7 +2947,7 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
|
|
||||||
@cloud_setup_test
|
@cloud_setup_test
|
||||||
def test_oci_vlans(self):
|
def test_oci_vlans(self):
|
||||||
self._mock_devices()
|
self._mock_connections()
|
||||||
|
|
||||||
oci_meta = "/opc/v2/"
|
oci_meta = "/opc/v2/"
|
||||||
self._mock_path(oci_meta + "instance", "{}")
|
self._mock_path(oci_meta + "instance", "{}")
|
||||||
|
|
@ -2966,17 +3004,23 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
pexp.expect("provider oci detected")
|
pexp.expect("provider oci detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
|
|
||||||
# No configuration for the ethernets
|
# No configuration for the ethernets
|
||||||
pexp.expect('configuring "eth0"')
|
pexp.expect('configuring "eth0"')
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
|
|
||||||
# Setting up the VLAN
|
# Setting up the VLAN
|
||||||
pexp.expect("creating macvlan2 connection for VLAN 700 on CC:00:00:00:00:01...")
|
pexp.expect(
|
||||||
|
"creating macvlan2 connection for VLAN 700 on %s..."
|
||||||
|
% (TestNmCloudSetup._mac1.upper())
|
||||||
|
)
|
||||||
pexp.expect("creating vlan connection for VLAN 700 on C0:00:00:00:00:10...")
|
pexp.expect("creating vlan connection for VLAN 700 on C0:00:00:00:00:10...")
|
||||||
pexp.expect("some changes were applied for provider oci")
|
pexp.expect("some changes were applied for provider oci")
|
||||||
|
|
||||||
|
|
@ -3008,12 +3052,15 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
|
|
||||||
# Just the same ol' thing, just no changes this time
|
# Just the same ol' thing, just no changes this time
|
||||||
pexp.expect("provider oci detected")
|
pexp.expect("provider oci detected")
|
||||||
pexp.expect("found interfaces: CC:00:00:00:00:01, CC:00:00:00:00:02")
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
pexp.expect("get-config: starting")
|
pexp.expect("get-config: starting")
|
||||||
pexp.expect("get-config: success")
|
pexp.expect("get-config: success")
|
||||||
pexp.expect("meta data received")
|
pexp.expect("meta data received")
|
||||||
pexp.expect('configuring "eth0"')
|
pexp.expect('configuring "eth0"')
|
||||||
pexp.expect("device has no suitable applied connection. Skip")
|
pexp.expect("skip applied connection due to missing IPv4 configuration")
|
||||||
pexp.expect("no changes were applied for provider oci")
|
pexp.expect("no changes were applied for provider oci")
|
||||||
|
|
||||||
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
|
@ -3024,6 +3071,89 @@ class TestNmCloudSetup(unittest.TestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(exitstatus, 0, "Unexpectedly returned a non-zero status")
|
self.assertEqual(exitstatus, 0, "Unexpectedly returned a non-zero status")
|
||||||
|
|
||||||
|
@cloud_setup_test
|
||||||
|
def test_oci_vm_vnic(self):
|
||||||
|
# One device unconnected, and one with a connection that needs changes
|
||||||
|
self._mock_devices()
|
||||||
|
self._mock_connection2()
|
||||||
|
|
||||||
|
oci_meta = "/opc/v2/"
|
||||||
|
self._mock_path(oci_meta + "instance", "{}")
|
||||||
|
self._mock_path(
|
||||||
|
oci_meta + "vnics",
|
||||||
|
"""
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"macAddr": "%s",
|
||||||
|
"privateIp": "%s",
|
||||||
|
"subnetCidrBlock": "172.31.16.0/20",
|
||||||
|
"virtualRouterIp": "172.31.16.1",
|
||||||
|
"vlanTag": 1337,
|
||||||
|
"vnicId": "ocid1.vnic.oc1.cz-adamov1.foobarbaz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"macAddr": "%s",
|
||||||
|
"privateIp": "%s",
|
||||||
|
"subnetCidrBlock": "172.31.166.0/20",
|
||||||
|
"virtualRouterIp": "172.31.166.1",
|
||||||
|
"vlanTag": 8086,
|
||||||
|
"vnicId": "ocid1.vnic.oc1.uk-hogwarts.expelliarmus"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
% (
|
||||||
|
TestNmCloudSetup._mac1,
|
||||||
|
TestNmCloudSetup._ip1,
|
||||||
|
TestNmCloudSetup._mac2,
|
||||||
|
TestNmCloudSetup._ip2,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
pexp = self.ctx.cmd_call_pexpect(
|
||||||
|
ENV_NM_TEST_CLIENT_CLOUD_SETUP_PATH,
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
"NM_CLOUD_SETUP_OCI_HOST": self.md_url,
|
||||||
|
"NM_CLOUD_SETUP_LOG": "trace",
|
||||||
|
"NM_CLOUD_SETUP_OCI": "yes",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
pexp.expect("provider oci detected")
|
||||||
|
pexp.expect(
|
||||||
|
"found interfaces: %s, %s"
|
||||||
|
% (TestNmCloudSetup._mac1.upper(), TestNmCloudSetup._mac2.upper())
|
||||||
|
)
|
||||||
|
pexp.expect("get-config: starting")
|
||||||
|
pexp.expect("get-config: success")
|
||||||
|
pexp.expect("meta data received")
|
||||||
|
|
||||||
|
# First device lacks a connection: a new one will be created
|
||||||
|
pexp.expect('config device eth0: connection "connection-2"')
|
||||||
|
|
||||||
|
# Second device is skipped because it's activated without IPv4
|
||||||
|
pexp.expect(
|
||||||
|
"config device CC:00:00:00:00:02: skip applied connection due to missing IPv4 configuration"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Finished!
|
||||||
|
pexp.expect("some changes were applied for provider oci")
|
||||||
|
|
||||||
|
(exitstatus, signalstatus, valgrind_log) = self.ctx.cmd_close_pexpect(pexp)
|
||||||
|
Util.valgrind_check_log(valgrind_log, "test_oci_vm_vnic")
|
||||||
|
self.assertIsNone(
|
||||||
|
signalstatus,
|
||||||
|
"Unexpectedly got " + Util.signal_no_to_str(signalstatus or 0),
|
||||||
|
)
|
||||||
|
self.assertEqual(exitstatus, 0, "Unexpectedly returned a non-zero status")
|
||||||
|
|
||||||
|
# TODO: Actually check the contents of the connection
|
||||||
|
# Probably needs changes to the mock service API
|
||||||
|
conn_macvlan = self.ctx.srv.findConnections(con_id="connection-3")
|
||||||
|
assert conn_macvlan is not None
|
||||||
|
conn_vlan = self.ctx.srv.findConnections(con_id="connection-4")
|
||||||
|
assert conn_vlan is not None
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,26 +6,9 @@
|
||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
import gi
|
import gi
|
||||||
import re
|
import re
|
||||||
|
|
||||||
gi.require_version("GIRepository", "2.0")
|
|
||||||
from gi.repository import GIRepository
|
|
||||||
|
|
||||||
try:
|
|
||||||
libs = os.environ["LD_LIBRARY_PATH"].split(":")
|
|
||||||
libs.reverse()
|
|
||||||
for lib in libs:
|
|
||||||
GIRepository.Repository.prepend_library_path(lib)
|
|
||||||
except AttributeError:
|
|
||||||
# An old GI version, that has no prepend_library_path
|
|
||||||
# It's alright, it probably interprets LD_LIBRARY_PATH
|
|
||||||
# correctly.
|
|
||||||
pass
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
gi.require_version("NM", "1.0")
|
gi.require_version("NM", "1.0")
|
||||||
from gi.repository import NM, GObject
|
from gi.repository import NM, GObject
|
||||||
|
|
||||||
|
|
@ -354,13 +337,6 @@ def main(gir_path_str, output_path_str, output_target):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument(
|
|
||||||
"-l",
|
|
||||||
"--lib-path",
|
|
||||||
metavar="PATH",
|
|
||||||
action="append",
|
|
||||||
help="path to scan for shared libraries",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-g",
|
"-g",
|
||||||
"--gir",
|
"--gir",
|
||||||
|
|
@ -384,8 +360,4 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.lib_path:
|
|
||||||
for lib in args.lib_path:
|
|
||||||
GIRepository.Repository.prepend_library_path(lib)
|
|
||||||
|
|
||||||
main(args.gir, args.output, args.target)
|
main(args.gir, args.output, args.target)
|
||||||
|
|
|
||||||
|
|
@ -868,7 +868,7 @@ class Device(ExportedObj):
|
||||||
self.activation_state_change_delay_ms = 50
|
self.activation_state_change_delay_ms = 50
|
||||||
self.hwaddr = hwaddr is None if "" else hwaddr
|
self.hwaddr = hwaddr is None if "" else hwaddr
|
||||||
|
|
||||||
self.prp_state = NM.DeviceState.UNAVAILABLE
|
self.prp_state = NM.DeviceState.DISCONNECTED
|
||||||
|
|
||||||
if devtype == NM.DeviceType.MODEM:
|
if devtype == NM.DeviceType.MODEM:
|
||||||
udi = "/org/freedesktop/ModemManager1/Modem/0"
|
udi = "/org/freedesktop/ModemManager1/Modem/0"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue