mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 07:00:05 +01:00
Compare commits
63 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8caccc6bed | ||
|
|
c8384fd528 | ||
|
|
8efa30db90 | ||
|
|
4393b37686 | ||
|
|
4587832735 | ||
|
|
15346f1a4f | ||
|
|
ce4ec4ac80 | ||
|
|
9bc4d62680 | ||
|
|
f08ee617b9 | ||
|
|
b8f8731636 | ||
|
|
399d7be771 | ||
|
|
b7926872e1 | ||
|
|
7acf70dfb9 | ||
|
|
4f3597448d | ||
|
|
310887be71 | ||
|
|
d1776c5394 | ||
|
|
abdf3385d6 | ||
|
|
dc3beb479f | ||
|
|
2ef71cf17d | ||
|
|
6d3cfda43e | ||
|
|
2a264ee841 | ||
|
|
d8e3561eaf | ||
|
|
edf0dd2901 | ||
|
|
62d6ff49e4 | ||
|
|
11482237e4 | ||
|
|
21b89a1267 | ||
|
|
51fc8af385 | ||
|
|
1423c4c46d | ||
|
|
9449189b50 | ||
|
|
dba8ba8e6f | ||
|
|
cd3d492618 | ||
|
|
d3d545deca | ||
|
|
afc1a88f64 | ||
|
|
b25276135c | ||
|
|
6f454c98a9 | ||
|
|
b2d8f60c49 | ||
|
|
c0048e0d26 | ||
|
|
6f9ba5fcc5 | ||
|
|
8326cc32d6 | ||
|
|
2450d860c6 | ||
|
|
ec0db2b22e | ||
|
|
824ebf8c2e | ||
|
|
0c4647d507 | ||
|
|
dff8f43adf | ||
|
|
44e406c1de | ||
|
|
2de3de0c28 | ||
|
|
58e776c3a8 | ||
|
|
f92a2bfd1f | ||
|
|
48eae2e76d | ||
|
|
ec93c9d282 | ||
|
|
de46cf1ee9 | ||
|
|
7e1c72fa63 | ||
|
|
96a8982e5d | ||
|
|
7121b42179 | ||
|
|
a25a6f5a1e | ||
|
|
6cd3d19ae9 | ||
|
|
cb61701649 | ||
|
|
1f23bb18ad | ||
|
|
a14f07484e | ||
|
|
ccd5a0226b | ||
|
|
32f801dec8 | ||
|
|
2df9da3d2b | ||
|
|
862277bda9 |
102 changed files with 3342 additions and 731 deletions
346
.gitlab-ci.yml
346
.gitlab-ci.yml
|
|
@ -60,11 +60,11 @@ variables:
|
|||
#
|
||||
# This is done by running `ci-fairy generate-template` and possibly bumping
|
||||
# ".default_tag".
|
||||
ALPINE_TAG: 'tag-da1ae96102c6'
|
||||
CENTOS_TAG: 'tag-c8df7d2b249f'
|
||||
DEBIAN_TAG: 'tag-e68f538711ec'
|
||||
FEDORA_TAG: 'tag-c8df7d2b249f'
|
||||
UBUNTU_TAG: 'tag-e68f538711ec'
|
||||
ALPINE_TAG: 'tag-dcc430216167'
|
||||
CENTOS_TAG: 'tag-feb1adbc208e'
|
||||
DEBIAN_TAG: 'tag-afb784497c2f'
|
||||
FEDORA_TAG: 'tag-feb1adbc208e'
|
||||
UBUNTU_TAG: 'tag-afb784497c2f'
|
||||
|
||||
ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh'
|
||||
CENTOS_EXEC: 'bash .gitlab-ci/fedora-install.sh'
|
||||
|
|
@ -102,7 +102,19 @@ variables:
|
|||
# Build a container for each distribution + version. The ci-templates
|
||||
# will re-use the containers if the tag doesn't change.
|
||||
|
||||
tier1:fedora:42@prep:
|
||||
tier1:fedora:43@prep:
|
||||
extends:
|
||||
- .fdo.container-build@fedora
|
||||
stage: prep
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
FDO_DISTRIBUTION_VERSION: '43'
|
||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||
FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule' || $SCHEDULED_PIPELINE_NAME == "weekly"
|
||||
|
||||
tier3:fedora:42@prep:
|
||||
extends:
|
||||
- .fdo.container-build@fedora
|
||||
stage: prep
|
||||
|
|
@ -111,88 +123,6 @@ tier1:fedora:42@prep:
|
|||
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: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
|
||||
|
|
@ -226,20 +156,6 @@ tier3:ubuntu:25.04@prep:
|
|||
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:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
tier3:ubuntu:24.04@prep:
|
||||
extends:
|
||||
- .fdo.container-build@ubuntu
|
||||
|
|
@ -268,6 +184,20 @@ tier3:ubuntu:22.04@prep:
|
|||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
tier3: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
|
||||
|
||||
tier3:debian:12@prep:
|
||||
extends:
|
||||
- .fdo.container-build@debian
|
||||
|
|
@ -282,6 +212,20 @@ tier3:debian:12@prep:
|
|||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
tier3: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:alpine:3.21@prep:
|
||||
extends:
|
||||
- .fdo.container-build@alpine
|
||||
|
|
@ -324,6 +268,34 @@ tier3:alpine:3.19@prep:
|
|||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
tier3:centos:stream10@prep:
|
||||
extends:
|
||||
- .fdo.container-build@centos
|
||||
stage: prep
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
FDO_DISTRIBUTION_VERSION: 'stream10'
|
||||
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
||||
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:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# tierN stage #
|
||||
|
|
@ -340,7 +312,7 @@ tier3:alpine:3.19@prep:
|
|||
dependencies: []
|
||||
|
||||
|
||||
t_fedora:42:
|
||||
t_fedora:43:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@fedora
|
||||
|
|
@ -356,94 +328,24 @@ t_fedora:42:
|
|||
- tarball
|
||||
- subtree
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '42'
|
||||
FDO_DISTRIBUTION_VERSION: '43'
|
||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||
needs:
|
||||
- "tier1:fedora:42@prep"
|
||||
- "tier1:fedora:43@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_fedora:rawhide:
|
||||
t_fedora:42:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@fedora
|
||||
- .nm_artifacts_debug
|
||||
stage: tier2
|
||||
stage: tier3
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 'rawhide'
|
||||
FDO_DISTRIBUTION_VERSION: '42'
|
||||
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:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@ubuntu
|
||||
- .nm_artifacts_debug
|
||||
stage: tier2
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 'devel'
|
||||
FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
|
||||
needs:
|
||||
- "tier2:ubuntu:devel@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_debian:testing:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@debian
|
||||
- .nm_artifacts_debug
|
||||
stage: tier2
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 'testing'
|
||||
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
||||
needs:
|
||||
- "tier2:debian:testing@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_debian:sid:
|
||||
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:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@alpine
|
||||
- .nm_artifacts_debug
|
||||
stage: tier2
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 'edge'
|
||||
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
||||
needs:
|
||||
- "tier2:alpine:edge@prep"
|
||||
- "tier3:fedora:42@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
|
|
@ -475,20 +377,6 @@ t_ubuntu:25.04:
|
|||
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:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_ubuntu:24.04:
|
||||
extends:
|
||||
- .build@template
|
||||
|
|
@ -517,6 +405,20 @@ t_ubuntu:22.04:
|
|||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_debian:13:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@debian
|
||||
- .nm_artifacts_debug
|
||||
stage: tier3
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '13'
|
||||
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
|
||||
needs:
|
||||
- "tier3:debian:13@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_debian:12:
|
||||
extends:
|
||||
- .build@template
|
||||
|
|
@ -531,6 +433,20 @@ t_debian:12:
|
|||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_alpine:3.22:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@alpine
|
||||
- .nm_artifacts_debug
|
||||
stage: tier3
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '3.22'
|
||||
FDO_DISTRIBUTION_TAG: $ALPINE_TAG
|
||||
needs:
|
||||
- "tier3:alpine:3.22@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_alpine:3.21:
|
||||
extends:
|
||||
- .build@template
|
||||
|
|
@ -573,6 +489,34 @@ t_alpine:3.19:
|
|||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
t_centos:stream10:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@centos
|
||||
- .nm_artifacts_debug
|
||||
stage: tier3
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 'stream10'
|
||||
FDO_DISTRIBUTION_TAG: $CENTOS_TAG
|
||||
needs:
|
||||
- "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:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# specific jobs #
|
||||
|
|
@ -583,10 +527,10 @@ check-patch:
|
|||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '42'
|
||||
FDO_DISTRIBUTION_VERSION: '43'
|
||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||
needs:
|
||||
- "tier1:fedora:42@prep"
|
||||
- "tier1:fedora:43@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE != 'schedule'
|
||||
stage: tier1
|
||||
|
|
@ -598,10 +542,10 @@ check-tree:
|
|||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '42'
|
||||
FDO_DISTRIBUTION_VERSION: '43'
|
||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||
needs:
|
||||
- "tier1:fedora:42@prep"
|
||||
- "tier1:fedora:43@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
|
||||
allow_failure: true
|
||||
|
|
@ -631,9 +575,9 @@ pages:
|
|||
when: never
|
||||
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'main'
|
||||
dependencies:
|
||||
- "t_fedora:42: [meson+gcc+docs+valgrind]"
|
||||
- "t_fedora:43: [meson+gcc+docs+valgrind]"
|
||||
needs:
|
||||
- "t_fedora:42: [meson+gcc+docs+valgrind]"
|
||||
- "t_fedora:43: [meson+gcc+docs+valgrind]"
|
||||
|
||||
triage:issues:
|
||||
stage: triage
|
||||
|
|
@ -650,11 +594,11 @@ coverity:
|
|||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '42'
|
||||
FDO_DISTRIBUTION_VERSION: '43'
|
||||
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
|
||||
stage: coverity
|
||||
needs:
|
||||
- "tier1:fedora:42@prep"
|
||||
- "tier1:fedora:43@prep"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_PIPELINE_NAME == "weekly"
|
||||
script:
|
||||
|
|
|
|||
|
|
@ -23,52 +23,38 @@ distributions:
|
|||
- name: fedora
|
||||
tier: 1
|
||||
versions:
|
||||
- '42'
|
||||
- '43'
|
||||
|
||||
# TIER 2: distribution versions that will or might use the current NM version.
|
||||
# Run when doing a release.
|
||||
- name: fedora
|
||||
tier: 2
|
||||
versions:
|
||||
- 'rawhide'
|
||||
- name: centos
|
||||
tier: 2
|
||||
versions:
|
||||
- 'stream9'
|
||||
- name: ubuntu
|
||||
tier: 2
|
||||
versions:
|
||||
- 'devel'
|
||||
- name: debian
|
||||
tier: 2
|
||||
versions:
|
||||
- 'testing'
|
||||
- 'sid'
|
||||
- name: alpine
|
||||
tier: 2
|
||||
versions:
|
||||
- 'edge'
|
||||
|
||||
# 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.
|
||||
- name: fedora
|
||||
tier: 3
|
||||
versions:
|
||||
- '42'
|
||||
- '41'
|
||||
- name: ubuntu
|
||||
tier: 3
|
||||
versions:
|
||||
- '25.04'
|
||||
- '24.10'
|
||||
- '24.04'
|
||||
- '22.04'
|
||||
- name: debian
|
||||
tier: 3
|
||||
versions:
|
||||
- '13'
|
||||
- '12'
|
||||
- name: alpine
|
||||
tier: 3
|
||||
versions:
|
||||
- '3.22'
|
||||
- '3.21'
|
||||
- '3.20'
|
||||
- '3.19'
|
||||
- name: centos
|
||||
tier: 3
|
||||
versions:
|
||||
- 'stream10'
|
||||
- 'stream9'
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ if [ $IS_CENTOS = 1 ]; then
|
|||
CENTOS_VERSION=8
|
||||
elif grep -q '^VERSION_ID=.*\<9\>' /etc/os-release ; then
|
||||
CENTOS_VERSION=9
|
||||
elif grep -q '^VERSION_ID=.*\<10\>' /etc/os-release ; then
|
||||
CENTOS_VERSION=10
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -33,6 +35,11 @@ fi
|
|||
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-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
|
||||
exit 1
|
||||
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=.*\(Alpine\)' /etc/os-release && IS_ALPINE=1
|
||||
|
||||
IS_CENTOS_7=0
|
||||
if [ $IS_CENTOS = 1 ]; then
|
||||
if grep -q '^VERSION_ID=.*\<7\>' /etc/os-release ; then
|
||||
IS_CENTOS_7=1
|
||||
CENTOS_VER_LINE="$(grep '^VERSION_ID=' /etc/os-release)"
|
||||
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
|
||||
|
||||
|
|
|
|||
34
NEWS
34
NEWS
|
|
@ -1,3 +1,37 @@
|
|||
===============================================
|
||||
NetworkManager-1.54.3
|
||||
Overview of changes since NetworkManager-1.54.2
|
||||
===============================================
|
||||
|
||||
* For private connections (the ones that specify a user in the
|
||||
"connection.permissions" property), verify that the user can access
|
||||
the 802.1X certificates and keys set in the connection.
|
||||
* Introduce a libnm function that can be used by VPN plugins to check
|
||||
user permissions on certificate and keys.
|
||||
|
||||
===============================================
|
||||
NetworkManager-1.54.2
|
||||
Overview of changes since NetworkManager-1.54.1
|
||||
===============================================
|
||||
|
||||
* Support reapplying the "sriov.vfs" property as long as
|
||||
"sriov.total-vfs" is not changed.
|
||||
* Support configuring the HSR protocol version via the
|
||||
"hsr.protocol-version" property.
|
||||
* Support configuring the HSR interlink port via the
|
||||
"hsr.interlink" property.
|
||||
|
||||
===============================================
|
||||
NetworkManager-1.54.1
|
||||
Overview of changes since NetworkManager-1.54.0
|
||||
===============================================
|
||||
|
||||
* Make that global-dns configuration overwrites DNS searches and
|
||||
options from connections, instead of merging all together.
|
||||
* Add support for a new rd.net.dhcp.client-id option in
|
||||
nm-initrd-generator.
|
||||
* Minor bug fixes.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.54
|
||||
Overview of changes since NetworkManager-1.52
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ apk add \
|
|||
'clang' \
|
||||
'curl-dev' \
|
||||
'dbus' \
|
||||
'dbus-dev' \
|
||||
'elogind-dev' \
|
||||
'eudev-dev' \
|
||||
'gcc' \
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ Preferably use nmcli instead.
|
|||
-Dsession_tracking=systemd \
|
||||
-Dsuspend_resume=systemd \
|
||||
-Dsystemdsystemunitdir=%{_unitdir} \
|
||||
-Dsystem_ca_path=/etc/pki/tls/cert.pem \
|
||||
-Dsystem_ca_path=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \
|
||||
-Ddbus_conf_dir=%{dbus_sys_dir} \
|
||||
-Dtests=yes \
|
||||
-Dvalgrind=no \
|
||||
|
|
@ -896,6 +896,7 @@ fi
|
|||
%{_libexecdir}/nm-dispatcher
|
||||
%{_libexecdir}/nm-initrd-generator
|
||||
%{_libexecdir}/nm-daemon-helper
|
||||
%{_libexecdir}/nm-libnm-helper
|
||||
%{_libexecdir}/nm-priv-helper
|
||||
%dir %{_libdir}/%{name}
|
||||
%dir %{nmplugindir}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,14 @@ if [ "$CC" != gcc ]; then
|
|||
_WITH_CRYPTO=nss
|
||||
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 _is_true "$WITH_DOCS"; then
|
||||
_WITH_DOCS="true"
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ static const char *
|
|||
nm_state_to_string(NMState state)
|
||||
{
|
||||
switch (state) {
|
||||
case NM_STATE_ASLEEP:
|
||||
return "asleep";
|
||||
case NM_STATE_DISABLED:
|
||||
return "network off";
|
||||
case NM_STATE_CONNECTING:
|
||||
return "connecting";
|
||||
case NM_STATE_CONNECTED_LOCAL:
|
||||
|
|
|
|||
|
|
@ -1540,8 +1540,12 @@ managed=1
|
|||
|
||||
<refsect1>
|
||||
<title><literal>global-dns</literal> section</title>
|
||||
<para>This section specifies DNS settings that are applied
|
||||
globally, in addition to connection-specific ones.</para>
|
||||
<para>This section specifies DNS settings that are applied globally. They
|
||||
override the equivalent options defined in individual connections, making
|
||||
them to be ignored. If a [global-dns-domain-*] section is defined, but this
|
||||
section isn't, an empty [global-dns] section is assumed, thus overwriting
|
||||
connection specific configurations too.
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
|
|
@ -1601,6 +1605,10 @@ managed=1
|
|||
default domain "*". When the global DNS domains are valid, the
|
||||
name servers and domains defined globally override the ones from
|
||||
active connections.
|
||||
|
||||
If any global DNS domain is defined but a [global-dns] section isn't,
|
||||
an empty [global-dns] section is assumed, thus overwriting its
|
||||
connection specific configurations too.
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@
|
|||
<member><option>rd.net.dns-backend</option></member>
|
||||
<member><option>rd.net.dns-resolve-mode</option></member>
|
||||
<member><option>rd.net.timeout.dhcp</option></member>
|
||||
<member><option>rd.net.dhcp.client-id</option></member>
|
||||
<member><option>rd.net.dhcp.retry</option></member>
|
||||
<member><option>rd.net.dhcp.vendor-class</option></member>
|
||||
<member><option>rd.net.dhcp.dscp</option></member>
|
||||
|
|
@ -268,6 +269,23 @@
|
|||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>NetworkManager supports the
|
||||
<option>rd.net.dhcp.client-id</option>=<replaceable>interface</replaceable>:<replaceable>client-id</replaceable>
|
||||
kernel command line option to set a specific DHCPv4 client identifier
|
||||
for the given interface. The client-id can be specified either as a
|
||||
sequence of bytes in hexadecimal format separated by dashes, or as the
|
||||
character '@' followed by a non-empty string. When using the second
|
||||
format, NetworkManager prepends a zero byte to the given string,
|
||||
according to section 9.14 of RFC 2132. See the "ipv4.dhcp-client-id"
|
||||
section of <link
|
||||
linkend='nm-settings-nmcli'><citerefentry><refentrytitle>nm-settings-nmcli</refentrytitle><manvolnum>5</manvolnum></citerefentry></link>
|
||||
for more details. Examples:
|
||||
<literal>rd.net.dhcp.client-id=eth0:01-52-54-00-45-87-42</literal>,
|
||||
<literal>rd.net.dhcp.client-id=enp1s0:@example.com</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
|
|
@ -278,6 +296,7 @@
|
|||
|
||||
<refsect1 id='see_also'><title>See Also</title>
|
||||
<para><link linkend='dracut.cmdline'><citerefentry><refentrytitle>dracut.cmdline</refentrytitle><manvolnum>7</manvolnum></citerefentry></link>,
|
||||
<link linkend='NetworkManager'><citerefentry><refentrytitle>NetworkManager</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>.</para>
|
||||
<link linkend='NetworkManager'><citerefentry><refentrytitle>NetworkManager</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
|
||||
<link linkend='nm-settings-nmcli'><citerefentry><refentrytitle>nm-settings-nmcli</refentrytitle><manvolnum>5</manvolnum></citerefentry></link>.</para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@
|
|||
NetworkManager inserts the records for Bridges into OVSDB when a Port is
|
||||
attached.
|
||||
</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>
|
||||
|
|
@ -102,6 +106,10 @@
|
|||
exist. Ports can also be configured to do VLAN tagging or Bonding.
|
||||
NetworkManager inserts the records for Ports into OVSDB when an Interface is
|
||||
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>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ project(
|
|||
# NOTE: When incrementing version also add corresponding
|
||||
# NM_VERSION_x_y_z macros in
|
||||
# "src/libnm-core-public/nm-version-macros.h.in"
|
||||
version: '1.54.0',
|
||||
version: '1.54.3',
|
||||
license: 'GPL2+',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@
|
|||
NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, \
|
||||
NM_SETTING_BOND_OPTION_RESEND_IGMP, NM_SETTING_BOND_OPTION_USE_CARRIER, \
|
||||
NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, \
|
||||
NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX, \
|
||||
NM_SETTING_BOND_OPTION_LACP_ACTIVE
|
||||
NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, NM_SETTING_BOND_OPTION_ARP_MISSED_MAX
|
||||
|
||||
#define OPTIONS_REAPPLY_FULL \
|
||||
OPTIONS_REAPPLY_SUBSET, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, \
|
||||
|
|
|
|||
|
|
@ -630,10 +630,17 @@ build_supplicant_config(NMDeviceEthernet *self, GError **error)
|
|||
mtu = nm_platform_link_get_mtu(nm_device_get_platform(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);
|
||||
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_clear_object(&config);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,29 +116,51 @@ create_and_realize(NMDevice *device,
|
|||
const NMPlatformLink **out_plink,
|
||||
GError **error)
|
||||
{
|
||||
const char *iface = nm_device_get_iface(device);
|
||||
NMSettingHsr *s_hsr;
|
||||
NMPlatformLnkHsr lnk = {};
|
||||
int r;
|
||||
const char *iface = nm_device_get_iface(device);
|
||||
nm_auto_free char *err_msg = NULL;
|
||||
NMSettingHsr *s_hsr;
|
||||
NMPlatformLnkHsr lnk = {};
|
||||
int r = 0;
|
||||
|
||||
s_hsr = _nm_connection_get_setting(connection, NM_TYPE_SETTING_HSR);
|
||||
|
||||
nm_assert(s_hsr);
|
||||
|
||||
if (nm_setting_hsr_get_port1(s_hsr) != NULL)
|
||||
lnk.port1 = nm_platform_link_get_ifindex(NM_PLATFORM_GET, nm_setting_hsr_get_port1(s_hsr));
|
||||
if (nm_setting_hsr_get_port2(s_hsr) != NULL)
|
||||
lnk.port2 = nm_platform_link_get_ifindex(NM_PLATFORM_GET, nm_setting_hsr_get_port2(s_hsr));
|
||||
lnk.multicast_spec = nm_setting_hsr_get_multicast_spec(s_hsr);
|
||||
lnk.prp = nm_setting_hsr_get_prp(s_hsr);
|
||||
if (nm_setting_hsr_get_interlink(s_hsr) != NULL) {
|
||||
const char *ifname = nm_setting_hsr_get_interlink(s_hsr);
|
||||
int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, ifname);
|
||||
|
||||
if (ifindex <= 0) {
|
||||
err_msg = g_strdup_printf("interlink port '%s' does not exist", ifname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lnk.interlink = ifindex;
|
||||
}
|
||||
|
||||
lnk.multicast_spec = nm_setting_hsr_get_multicast_spec(s_hsr);
|
||||
lnk.prp = nm_setting_hsr_get_prp(s_hsr);
|
||||
lnk.protocol_version = nm_setting_hsr_get_protocol_version(s_hsr);
|
||||
|
||||
r = nm_platform_link_hsr_add(nm_device_get_platform(device), iface, &lnk, out_plink);
|
||||
|
||||
if (r < 0) {
|
||||
err_msg = g_strdup(nm_strerror(r) ?: "unknown");
|
||||
}
|
||||
|
||||
out:
|
||||
if (err_msg) {
|
||||
g_set_error(error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create HSR interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id(connection),
|
||||
nm_strerror(r));
|
||||
err_msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,8 @@ build_supplicant_config(NMDeviceMacsec *self, GError **error)
|
|||
mtu = nm_platform_link_get_mtu(nm_device_get_platform(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);
|
||||
|
||||
|
|
@ -227,7 +228,13 @@ build_supplicant_config(NMDeviceMacsec *self, GError **error)
|
|||
|
||||
if (nm_setting_macsec_get_mode(s_macsec) == NM_SETTING_MACSEC_MODE_EAP) {
|
||||
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: ");
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,4 +179,6 @@ void nm_device_auth_request(NMDevice *self,
|
|||
|
||||
void nm_device_link_properties_set(NMDevice *self, gboolean reapply);
|
||||
|
||||
GHashTable *nm_device_get_private_files(NMDevice *self);
|
||||
|
||||
#endif /* NM_DEVICE_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -135,13 +135,15 @@ NM_UTILS_LOOKUP_STR_DEFINE(
|
|||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_LINK_NOT_INIT,
|
||||
"unmanaged-link-not-init"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING, "unmanaged-quitting"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING, "unmanaged-sleeping"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED,
|
||||
"unmanaged-nm-disabled"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_CONF, "unmanaged-user-conf"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_EXPLICIT,
|
||||
"unmanaged-user-explicit"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_SETTINGS,
|
||||
"unmanaged-user-settings"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_UDEV, "unmanaged-user-udev"), );
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_UDEV, "unmanaged-user-udev"),
|
||||
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NETWORKING_OFF, "networking-off"), );
|
||||
|
||||
NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_string,
|
||||
NMDeviceMtuSource,
|
||||
|
|
@ -235,7 +237,7 @@ resolve_addr_helper_cb(GObject *source, GAsyncResult *result, gpointer user_data
|
|||
gs_free_error GError *error = 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))
|
||||
return;
|
||||
|
||||
|
|
@ -274,6 +276,7 @@ resolve_addr_spawn_helper(ResolveAddrInfo *info, ResolveAddrService services)
|
|||
nm_inet_ntop(info->addr_family, &info->address, addr_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),
|
||||
FALSE,
|
||||
g_task_get_cancellable(info->task),
|
||||
resolve_addr_helper_cb,
|
||||
info);
|
||||
|
|
|
|||
|
|
@ -335,6 +335,12 @@ typedef struct {
|
|||
int addr_family;
|
||||
} HostnameResolver;
|
||||
|
||||
typedef enum {
|
||||
PRIVATE_FILES_STATE_UNKNOWN = 0,
|
||||
PRIVATE_FILES_STATE_READING,
|
||||
PRIVATE_FILES_STATE_DONE,
|
||||
} PrivateFilesState;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum {
|
||||
|
|
@ -692,6 +698,8 @@ typedef struct _NMDevicePrivate {
|
|||
|
||||
IPDevStateData ipdev_data_unspec;
|
||||
|
||||
gulong sharing_ipv4_changed_id;
|
||||
|
||||
struct {
|
||||
/* If we set the addrgenmode6, this records the previously set value. */
|
||||
guint8 previous_mode_val;
|
||||
|
|
@ -769,6 +777,13 @@ typedef struct _NMDevicePrivate {
|
|||
guint64 rx_bytes;
|
||||
} stats;
|
||||
|
||||
struct {
|
||||
GHashTable *table;
|
||||
GCancellable *cancellable;
|
||||
char *user;
|
||||
PrivateFilesState state;
|
||||
} private_files;
|
||||
|
||||
bool mtu_force_set_done : 1;
|
||||
|
||||
bool needs_ip6_subnet : 1;
|
||||
|
|
@ -779,7 +794,6 @@ typedef struct _NMDevicePrivate {
|
|||
char *prop_ip_iface; /* IP interface D-Bus property */
|
||||
GList *ping_operations;
|
||||
GSource *ping_timeout;
|
||||
bool refresh_forwarding_done : 1;
|
||||
} NMDevicePrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT)
|
||||
|
|
@ -867,6 +881,8 @@ static void _dev_ipshared4_spawn_dnsmasq(NMDevice *self);
|
|||
|
||||
static void _dev_ipshared6_start(NMDevice *self);
|
||||
|
||||
static void _dev_ipforwarding4_start(NMDevice *self, int addr_family);
|
||||
|
||||
static void
|
||||
_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean preserve_dhcp);
|
||||
|
||||
|
|
@ -2131,8 +2147,8 @@ _prop_get_ipvx_dhcp_send_hostname(NMDevice *self, int addr_family)
|
|||
return send_hostname_v2;
|
||||
}
|
||||
|
||||
NMSettingIPConfigForwarding
|
||||
nm_device_get_ipv4_forwarding(NMDevice *self)
|
||||
static NMSettingIPConfigForwarding
|
||||
_prop_get_ipv4_forwarding(NMDevice *self)
|
||||
{
|
||||
NMSettingIPConfig *s_ip;
|
||||
NMSettingIPConfigForwarding forwarding;
|
||||
|
|
@ -3778,7 +3794,7 @@ nm_device_assume_state_reset(NMDevice *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *
|
||||
static char *
|
||||
nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property)
|
||||
{
|
||||
const char *ifname;
|
||||
|
|
@ -6645,7 +6661,7 @@ concheck_update_state(NMDevice *self,
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family)
|
||||
{
|
||||
NMDeviceClass *klass;
|
||||
|
|
@ -8639,6 +8655,8 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error)
|
|||
|
||||
g_object_thaw_notify(G_OBJECT(self));
|
||||
|
||||
nm_device_managed_type_set(self, NM_DEVICE_MANAGED_TYPE_REMOVED);
|
||||
|
||||
nm_device_set_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT, TRUE);
|
||||
|
||||
nm_device_set_unmanaged_flags(self,
|
||||
|
|
@ -9164,6 +9182,10 @@ is_available(NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
|
||||
/* unrealized software devices are always available, hardware devices never */
|
||||
if (!nm_device_is_real(self))
|
||||
return nm_device_is_software(self);
|
||||
|
||||
if (priv->carrier || priv->ignore_carrier)
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -10390,6 +10412,43 @@ sriov_params_cb(GError *error, gpointer user_data)
|
|||
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
|
||||
*
|
||||
|
|
@ -10436,10 +10495,7 @@ activate_stage1_device_prepare(NMDevice *self)
|
|||
if (s_sriov && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) {
|
||||
nm_auto_freev NMPlatformVF **plat_vfs = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMSriovVF *vf;
|
||||
NMTernary autoprobe;
|
||||
guint num;
|
||||
guint i;
|
||||
|
||||
autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov);
|
||||
if (autoprobe == NM_TERNARY_DEFAULT) {
|
||||
|
|
@ -10452,21 +10508,12 @@ activate_stage1_device_prepare(NMDevice *self)
|
|||
NM_OPTION_BOOL_TRUE);
|
||||
}
|
||||
|
||||
num = nm_setting_sriov_get_num_vfs(s_sriov);
|
||||
plat_vfs = g_new0(NMPlatformVF *, num + 1);
|
||||
for (i = 0; i < num; i++) {
|
||||
vf = nm_setting_sriov_get_vf(s_sriov, i);
|
||||
plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &error);
|
||||
if (!plat_vfs[i]) {
|
||||
_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;
|
||||
}
|
||||
if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &error)) {
|
||||
_LOGE(LOGD_DEVICE, "cannot parse the VF list: %s", 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
|
||||
|
|
@ -10773,6 +10820,49 @@ tc_commit(NMDevice *self)
|
|||
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
|
||||
*
|
||||
|
|
@ -10785,6 +10875,7 @@ activate_stage2_device_config(NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
|
||||
NMConnection *applied;
|
||||
NMActStageReturn ret;
|
||||
NMSettingWired *s_wired;
|
||||
gboolean no_firmware = FALSE;
|
||||
|
|
@ -10793,6 +10884,68 @@ activate_stage2_device_config(NMDevice *self)
|
|||
|
||||
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)) {
|
||||
_ethtool_state_set(self);
|
||||
nm_device_link_properties_set(self, FALSE);
|
||||
|
|
@ -10809,7 +10962,7 @@ activate_stage2_device_config(NMDevice *self)
|
|||
priv->tc_committed = TRUE;
|
||||
}
|
||||
|
||||
nm_routing_rules_sync(nm_device_get_applied_connection(self),
|
||||
nm_routing_rules_sync(applied,
|
||||
NM_TERNARY_TRUE,
|
||||
klass->get_extra_rules,
|
||||
self,
|
||||
|
|
@ -13135,17 +13288,12 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family)
|
|||
goto out_devip;
|
||||
|
||||
if (IS_IPv4) {
|
||||
NMSettingIPConfigForwarding ipv4_forwarding = nm_device_get_ipv4_forwarding(self);
|
||||
|
||||
if (NM_IN_SET(ipv4_forwarding,
|
||||
NM_SETTING_IP_CONFIG_FORWARDING_NO,
|
||||
NM_SETTING_IP_CONFIG_FORWARDING_YES)) {
|
||||
nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", ipv4_forwarding ? "1" : "0");
|
||||
}
|
||||
priv->ipll_data_4.v4.mode = _prop_get_ipv4_link_local(self);
|
||||
if (priv->ipll_data_4.v4.mode == NM_SETTING_IP4_LL_ENABLED)
|
||||
_dev_ipll4_start(self);
|
||||
|
||||
_dev_ipforwarding4_start(self, addr_family);
|
||||
|
||||
if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
|
||||
_dev_ipdhcpx_start(self, AF_INET);
|
||||
else if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
|
|
@ -13465,15 +13613,21 @@ nm_device_activate_schedule_stage3_ip_config(NMDevice *self, gboolean do_sync)
|
|||
static void
|
||||
_dev_ipsharedx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
NMDeviceIPState old_state = priv->ipshared_data_x[IS_IPv4].state;
|
||||
|
||||
if (priv->ipshared_data_x[IS_IPv4].state != state) {
|
||||
if (old_state != state) {
|
||||
_LOGD_ipshared(addr_family,
|
||||
"set state %s (was %s)",
|
||||
nm_device_ip_state_to_string(state),
|
||||
nm_device_ip_state_to_string(priv->ipshared_data_x[IS_IPv4].state));
|
||||
nm_device_ip_state_to_string(old_state));
|
||||
priv->ipshared_data_x[IS_IPv4].state = state;
|
||||
|
||||
if (old_state == NM_DEVICE_IP_STATE_READY || state == NM_DEVICE_IP_STATE_READY)
|
||||
nm_manager_update_shared_connection(NM_MANAGER_GET,
|
||||
addr_family,
|
||||
state == NM_DEVICE_IP_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13768,6 +13922,106 @@ _dev_ipshared6_start(NMDevice *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Set the device's forwarding to the specified value. If %NM_TERNARY_DEFAULT is specified,
|
||||
* it's set to the kernel's default, otherwise it's set to the specific value.
|
||||
*/
|
||||
static void
|
||||
_dev_ipforwarding4_set(NMDevice *self, NMTernary val)
|
||||
{
|
||||
gs_free const char *default_forwarding = NULL;
|
||||
gs_free const char *current_forwarding = NULL;
|
||||
const char *val_str;
|
||||
|
||||
if (val != NM_TERNARY_DEFAULT) {
|
||||
val_str = val ? "1" : "0";
|
||||
} else {
|
||||
default_forwarding = nm_platform_sysctl_get(
|
||||
nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"));
|
||||
|
||||
if (!default_forwarding) {
|
||||
_LOGW(LOGD_DEVICE,
|
||||
"error setting IPv4 forwarding: can't read default forwarding value: %s",
|
||||
nm_strerror_native(errno));
|
||||
return; /* Non fatal */
|
||||
}
|
||||
|
||||
val_str = default_forwarding;
|
||||
}
|
||||
|
||||
current_forwarding = nm_device_sysctl_ip_conf_get(self, AF_INET, "forwarding");
|
||||
if (nm_streq0(current_forwarding, val_str))
|
||||
return;
|
||||
|
||||
if (!nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", val_str))
|
||||
_LOGW(LOGD_DEVICE,
|
||||
"error setting IPv4 forwarding to '%s': %s",
|
||||
val_str,
|
||||
nm_strerror_native(errno));
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipforwarding4_auto_cb(NMManager *manager, gboolean sharing_ipv4, gpointer data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE(data);
|
||||
|
||||
_dev_ipforwarding4_set(self, sharing_ipv4 ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipforwarding4_start(NMDevice *self, int addr_family)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
NMSettingIPConfigForwarding ipv4_forwarding = _prop_get_ipv4_forwarding(self);
|
||||
NMTernary new_forwarding = NM_TERNARY_DEFAULT;
|
||||
|
||||
/* IPv6 per-interface forwarding not supported yet */
|
||||
if (addr_family != AF_INET)
|
||||
return;
|
||||
|
||||
if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
|
||||
new_forwarding = NM_TERNARY_TRUE;
|
||||
} else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_YES) {
|
||||
new_forwarding = NM_TERNARY_TRUE;
|
||||
} else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_NO) {
|
||||
new_forwarding = NM_TERNARY_FALSE;
|
||||
} else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_AUTO) {
|
||||
if (nm_manager_get_sharing_ipv4(NM_MANAGER_GET))
|
||||
new_forwarding = NM_TERNARY_TRUE;
|
||||
else
|
||||
new_forwarding = NM_TERNARY_DEFAULT;
|
||||
|
||||
if (!priv->sharing_ipv4_changed_id)
|
||||
priv->sharing_ipv4_changed_id = g_signal_connect(NM_MANAGER_GET,
|
||||
NM_MANAGER_SHARING_IPV4_CHANGED,
|
||||
G_CALLBACK(_dev_ipforwarding4_auto_cb),
|
||||
self);
|
||||
} else {
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
||||
_dev_ipforwarding4_set(self, new_forwarding);
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipforwarding_cleanup(NMDevice *self, int addr_family, CleanupType cleanup_type)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
|
||||
if (!NM_IS_IPv4(addr_family))
|
||||
return;
|
||||
|
||||
nm_clear_g_signal_handler(NM_MANAGER_GET, &priv->sharing_ipv4_changed_id);
|
||||
|
||||
if (NM_IN_SET(cleanup_type, CLEANUP_TYPE_DECONFIGURE, CLEANUP_TYPE_KEEP_REAPPLY)) {
|
||||
/* Deconfigure by restoring kernel's default */
|
||||
_dev_ipforwarding4_set(self, NM_TERNARY_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
act_request_set(NMDevice *self, NMActRequest *act_request)
|
||||
{
|
||||
|
|
@ -13880,6 +14134,8 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gbool
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
gboolean keep_reapply = (cleanup_type == CLEANUP_TYPE_KEEP_REAPPLY);
|
||||
|
||||
_dev_ipforwarding_cleanup(self, addr_family, cleanup_type);
|
||||
|
||||
_dev_ipsharedx_cleanup(self, addr_family);
|
||||
|
||||
_dev_ipdev_cleanup(self, AF_UNSPEC);
|
||||
|
|
@ -14062,7 +14318,8 @@ can_reapply_change(NMDevice *self,
|
|||
return nm_device_hash_check_invalid_keys(diffs,
|
||||
NM_SETTING_SRIOV_SETTING_NAME,
|
||||
error,
|
||||
NM_SETTING_SRIOV_PRESERVE_ON_DOWN);
|
||||
NM_SETTING_SRIOV_PRESERVE_ON_DOWN,
|
||||
NM_SETTING_SRIOV_VFS);
|
||||
}
|
||||
|
||||
out_fail:
|
||||
|
|
@ -14240,9 +14497,35 @@ check_and_reapply_connection(NMDevice *self,
|
|||
|
||||
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);
|
||||
|
||||
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) {
|
||||
/* Allow reapply of MTU */
|
||||
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
|
||||
|
|
@ -14696,13 +14979,15 @@ impl_device_delete(NMDBusObject *obj,
|
|||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
_device_activate(NMDevice *self, NMActRequest *req)
|
||||
{
|
||||
NMConnection *connection;
|
||||
|
||||
g_return_if_fail(NM_IS_DEVICE(self));
|
||||
g_return_if_fail(NM_IS_ACT_REQUEST(req));
|
||||
/* Returns TRUE on success, FALSE if the activation request could not be started */
|
||||
|
||||
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));
|
||||
|
||||
/* Ensure the activation request is still valid; the controller may have
|
||||
|
|
@ -14710,7 +14995,7 @@ _device_activate(NMDevice *self, NMActRequest *req)
|
|||
*/
|
||||
if (nm_active_connection_get_state(NM_ACTIVE_CONNECTION(req))
|
||||
>= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
if (!nm_device_get_managed(self, FALSE)) {
|
||||
/* It's unclear why the device would be unmanaged at this point.
|
||||
|
|
@ -14721,7 +15006,7 @@ _device_activate(NMDevice *self, NMActRequest *req)
|
|||
nm_active_connection_set_state_fail((NMActiveConnection *) req,
|
||||
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,
|
||||
NULL);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
connection = nm_act_request_get_applied_connection(req);
|
||||
|
|
@ -14737,6 +15022,8 @@ _device_activate(NMDevice *self, NMActRequest *req)
|
|||
act_request_set(self, req);
|
||||
|
||||
nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -14756,7 +15043,9 @@ _carrier_wait_check_queued_act_request(NMDevice *self)
|
|||
|
||||
_LOGD(LOGD_DEVICE, "Activate queued activation request as we now have carrier");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -15603,7 +15892,7 @@ nm_device_get_firmware_missing(NMDevice *self)
|
|||
|
||||
NM_UTILS_FLAGS2STR_DEFINE(nm_unmanaged_flags2str,
|
||||
NMUnmanagedFlags,
|
||||
NM_UTILS_FLAGS2STR(NM_UNMANAGED_SLEEPING, "sleeping"),
|
||||
NM_UTILS_FLAGS2STR(NM_UNMANAGED_MANAGER_DISABLED, "nm-disabled"),
|
||||
NM_UTILS_FLAGS2STR(NM_UNMANAGED_QUITTING, "quitting"),
|
||||
NM_UTILS_FLAGS2STR(NM_UNMANAGED_PLATFORM_INIT, "platform-init"),
|
||||
NM_UTILS_FLAGS2STR(NM_UNMANAGED_USER_EXPLICIT, "user-explicit"),
|
||||
|
|
@ -15667,8 +15956,8 @@ unmanaged_flags_to_reason(NMUnmanagedFlags flags)
|
|||
/* Even if there are multiple flags, we can only return one reason.
|
||||
* Return the most important reason.
|
||||
*/
|
||||
if (NM_FLAGS_HAS(flags, NM_UNMANAGED_SLEEPING))
|
||||
return NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING;
|
||||
if (NM_FLAGS_HAS(flags, NM_UNMANAGED_MANAGER_DISABLED))
|
||||
return NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED;
|
||||
if (NM_FLAGS_HAS(flags, NM_UNMANAGED_QUITTING))
|
||||
return NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING;
|
||||
if (NM_FLAGS_HAS(flags, NM_UNMANAGED_USER_SETTINGS))
|
||||
|
|
@ -16913,8 +17202,6 @@ _cleanup_generic_post(NMDevice *self, NMDeviceStateReason reason, CleanupType cl
|
|||
priv->v4_route_table_all_sync_before = FALSE;
|
||||
priv->v6_route_table_all_sync_before = FALSE;
|
||||
|
||||
priv->refresh_forwarding_done = FALSE;
|
||||
|
||||
priv->mtu_force_set_done = FALSE;
|
||||
|
||||
priv->needs_ip6_subnet = FALSE;
|
||||
|
|
@ -16960,7 +17247,6 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
|
|||
NMDevicePrivate *priv;
|
||||
NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
|
||||
int ifindex;
|
||||
gint32 default_forwarding_v4;
|
||||
|
||||
g_return_if_fail(NM_IS_DEVICE(self));
|
||||
|
||||
|
|
@ -16983,21 +17269,16 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
|
|||
nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0");
|
||||
}
|
||||
|
||||
/* Restoring the device's forwarding to the sysctl default is necessary because
|
||||
* `refresh_forwarding()` only updates forwarding on activated devices. */
|
||||
default_forwarding_v4 = nm_platform_sysctl_get_int32(
|
||||
nm_device_get_platform(self),
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"),
|
||||
0);
|
||||
nm_device_sysctl_ip_conf_set(self,
|
||||
AF_INET,
|
||||
"forwarding",
|
||||
default_forwarding_v4 == 1 ? "1" : "0");
|
||||
|
||||
/* Call device type-specific deactivation */
|
||||
if (klass->deactivate)
|
||||
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);
|
||||
|
||||
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
||||
|
|
@ -17534,7 +17815,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
|
|||
gs_unref_object NMActRequest *queued_req = NULL;
|
||||
|
||||
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;
|
||||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
|
|
@ -18936,19 +19218,6 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean
|
|||
return nm_assert_unreachable_val(NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_device_get_refresh_forwarding_done(NMDevice *self)
|
||||
{
|
||||
return NM_DEVICE_GET_PRIVATE(self)->refresh_forwarding_done;
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_set_refresh_forwarding_done(NMDevice *self, gboolean is_refresh_forwarding_done)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
priv->refresh_forwarding_done = is_refresh_forwarding_done;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
|
|
|
|||
|
|
@ -581,7 +581,8 @@ void nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device);
|
|||
/**
|
||||
* NMUnmanagedFlags:
|
||||
* @NM_UNMANAGED_NONE: placeholder value
|
||||
* @NM_UNMANAGED_SLEEPING: %TRUE when unmanaged because NM is sleeping.
|
||||
* @NM_UNMANAGED_MANAGER_DISABLED: %TRUE when unmanaged because NM is disabled.
|
||||
* Currently, this happens when sleeping or with networking disabled.
|
||||
* @NM_UNMANAGED_QUITTING: %TRUE when unmanaged because NM is shutting down.
|
||||
* @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not
|
||||
* yet initialized. Unrealized device are also unmanaged for this reason.
|
||||
|
|
@ -610,11 +611,11 @@ typedef enum {
|
|||
|
||||
/* these flags are authoritative. If one of them is set,
|
||||
* the device cannot be managed. */
|
||||
NM_UNMANAGED_SLEEPING = (1LL << 0),
|
||||
NM_UNMANAGED_QUITTING = (1LL << 1),
|
||||
NM_UNMANAGED_PLATFORM_INIT = (1LL << 2),
|
||||
NM_UNMANAGED_USER_EXPLICIT = (1LL << 3),
|
||||
NM_UNMANAGED_USER_SETTINGS = (1LL << 4),
|
||||
NM_UNMANAGED_MANAGER_DISABLED = (1LL << 0),
|
||||
NM_UNMANAGED_QUITTING = (1LL << 1),
|
||||
NM_UNMANAGED_PLATFORM_INIT = (1LL << 2),
|
||||
NM_UNMANAGED_USER_EXPLICIT = (1LL << 3),
|
||||
NM_UNMANAGED_USER_SETTINGS = (1LL << 4),
|
||||
|
||||
/* These flags can be non-effective and be overwritten
|
||||
* by other flags. */
|
||||
|
|
@ -852,14 +853,4 @@ void nm_routing_rules_sync(NMConnection *applied_connection,
|
|||
NMDevice *self,
|
||||
NMNetns *netns);
|
||||
|
||||
NMSettingIPConfigForwarding nm_device_get_ipv4_forwarding(NMDevice *self);
|
||||
|
||||
const char *nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family);
|
||||
|
||||
char *nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property);
|
||||
|
||||
gboolean nm_device_get_refresh_forwarding_done(NMDevice *self);
|
||||
|
||||
void nm_device_set_refresh_forwarding_done(NMDevice *self, gboolean is_refresh_forwarding_done);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DEVICE_H__ */
|
||||
|
|
|
|||
|
|
@ -1460,40 +1460,42 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
|
|||
json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid));
|
||||
}
|
||||
|
||||
if (num_nm_interfaces == 0) {
|
||||
/* The port no longer has any NM interface. Don't add it to "new_ports" and set
|
||||
* ports_changed=TRUE, so that it will be deleted. */
|
||||
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;
|
||||
} else {
|
||||
if (interfaces_changed) {
|
||||
/* An interface needs to be deleted from this port */
|
||||
_expect_port_interfaces(params, ovs_port->name, interfaces);
|
||||
_set_port_interfaces(params, ovs_port->name, new_interfaces);
|
||||
}
|
||||
/* The port is still alive */
|
||||
/* 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) {
|
||||
/* This port is still alive, but an interface needs to be deleted from it */
|
||||
_expect_port_interfaces(params, ovs_port->name, interfaces);
|
||||
_set_port_interfaces(params, ovs_port->name, new_interfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_nm_ports == 0) {
|
||||
/* The bridge no longer has any NM port. Don't add it to "new_bridges" and set
|
||||
* bridges_changed=TRUE, so that it will be deleted. */
|
||||
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;
|
||||
} 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) {
|
||||
/* A port needs to be deleted from this bridge */
|
||||
/* This bridge is still alive, but a port needs to be deleted from it */
|
||||
_expect_bridge_ports(params, ovs_bridge->name, ports);
|
||||
_set_bridge_ports(params, ovs_bridge->name, new_ports);
|
||||
}
|
||||
/* The bridge is still alive */
|
||||
json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
|
||||
}
|
||||
}
|
||||
|
||||
if (bridges_changed) {
|
||||
/* A port needs to be deleted from this bridge */
|
||||
/* A bridge needs to be deleted */
|
||||
_expect_ovs_bridges(params, priv->db_uuid, bridges);
|
||||
_set_ovs_bridges(params, priv->db_uuid, new_bridges);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,8 @@ static void periodic_update(NMDeviceWifi *self);
|
|||
static void ap_add_remove(NMDeviceWifi *self,
|
||||
gboolean is_adding,
|
||||
NMWifiAP *ap,
|
||||
gboolean recheck_available_connections);
|
||||
gboolean recheck_available_connections,
|
||||
gboolean recheck_auto_activate);
|
||||
|
||||
static void _hw_addr_set_scanning(NMDeviceWifi *self, gboolean do_reset);
|
||||
|
||||
|
|
@ -714,7 +715,10 @@ update_seen_bssids_cache(NMDeviceWifi *self, NMWifiAP *ap)
|
|||
}
|
||||
|
||||
static void
|
||||
set_current_ap(NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available_connections)
|
||||
set_current_ap(NMDeviceWifi *self,
|
||||
NMWifiAP *new_ap,
|
||||
gboolean recheck_available_connections,
|
||||
gboolean recheck_auto_activate)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv;
|
||||
NMWifiAP *old_ap;
|
||||
|
|
@ -741,7 +745,11 @@ set_current_ap(NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available_
|
|||
/* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */
|
||||
if (NM_IN_SET(mode, _NM_802_11_MODE_ADHOC, _NM_802_11_MODE_AP)
|
||||
|| nm_wifi_ap_get_fake(old_ap))
|
||||
ap_add_remove(self, FALSE, old_ap, recheck_available_connections);
|
||||
ap_add_remove(self,
|
||||
FALSE,
|
||||
old_ap,
|
||||
recheck_available_connections,
|
||||
recheck_auto_activate);
|
||||
g_object_unref(old_ap);
|
||||
}
|
||||
|
||||
|
|
@ -814,7 +822,8 @@ static void
|
|||
ap_add_remove(NMDeviceWifi *self,
|
||||
gboolean is_adding, /* or else removing */
|
||||
NMWifiAP *ap,
|
||||
gboolean recheck_available_connections)
|
||||
gboolean recheck_available_connections,
|
||||
gboolean recheck_auto_activate)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self);
|
||||
|
||||
|
|
@ -845,13 +854,14 @@ ap_add_remove(NMDeviceWifi *self,
|
|||
nm_dbus_object_clear_and_unexport(&ap);
|
||||
}
|
||||
|
||||
nm_device_recheck_auto_activate_schedule(NM_DEVICE(self));
|
||||
if (recheck_auto_activate)
|
||||
nm_device_recheck_auto_activate_schedule(NM_DEVICE(self));
|
||||
if (recheck_available_connections)
|
||||
nm_device_recheck_available_connections(NM_DEVICE(self));
|
||||
}
|
||||
|
||||
static void
|
||||
remove_all_aps(NMDeviceWifi *self)
|
||||
remove_all_aps(NMDeviceWifi *self, gboolean disposing)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self);
|
||||
NMWifiAP *ap;
|
||||
|
|
@ -859,12 +869,13 @@ remove_all_aps(NMDeviceWifi *self)
|
|||
if (c_list_is_empty(&priv->aps_lst_head))
|
||||
return;
|
||||
|
||||
set_current_ap(self, NULL, FALSE);
|
||||
set_current_ap(self, NULL, FALSE, !disposing);
|
||||
|
||||
while ((ap = c_list_first_entry(&priv->aps_lst_head, NMWifiAP, aps_lst)))
|
||||
ap_add_remove(self, FALSE, ap, FALSE);
|
||||
ap_add_remove(self, FALSE, ap, FALSE, !disposing);
|
||||
|
||||
nm_device_recheck_available_connections(NM_DEVICE(self));
|
||||
if (!disposing)
|
||||
nm_device_recheck_available_connections(NM_DEVICE(self));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -951,7 +962,7 @@ deactivate(NMDevice *device)
|
|||
|
||||
priv->rate = 0;
|
||||
|
||||
set_current_ap(self, NULL, TRUE);
|
||||
set_current_ap(self, NULL, TRUE, TRUE);
|
||||
|
||||
if (!wake_on_wlan_restore(self))
|
||||
_LOGW(LOGD_DEVICE | LOGD_WIFI, "Cannot unconfigure WoWLAN.");
|
||||
|
|
@ -2000,7 +2011,7 @@ supplicant_iface_bss_changed_cb(NMSupplicantInterface *iface,
|
|||
if (nm_wifi_ap_set_fake(found_ap, TRUE))
|
||||
_ap_dump(self, LOGL_DEBUG, found_ap, "updated", 0);
|
||||
} else {
|
||||
ap_add_remove(self, FALSE, found_ap, TRUE);
|
||||
ap_add_remove(self, FALSE, found_ap, TRUE, TRUE);
|
||||
schedule_ap_list_dump(self);
|
||||
}
|
||||
return;
|
||||
|
|
@ -2043,7 +2054,7 @@ supplicant_iface_bss_changed_cb(NMSupplicantInterface *iface,
|
|||
}
|
||||
}
|
||||
|
||||
ap_add_remove(self, TRUE, ap, TRUE);
|
||||
ap_add_remove(self, TRUE, ap, TRUE, TRUE);
|
||||
}
|
||||
|
||||
/* Update the current AP if the supplicant notified a current BSS change
|
||||
|
|
@ -2268,7 +2279,7 @@ link_timeout_cb(gpointer user_data)
|
|||
if (nm_device_get_state(device) != NM_DEVICE_STATE_ACTIVATED)
|
||||
return FALSE;
|
||||
|
||||
set_current_ap(self, NULL, TRUE);
|
||||
set_current_ap(self, NULL, TRUE, TRUE);
|
||||
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
|
|
@ -2684,7 +2695,7 @@ supplicant_iface_notify_current_bss(NMSupplicantInterface *iface,
|
|||
}
|
||||
}
|
||||
|
||||
set_current_ap(self, new_ap, TRUE);
|
||||
set_current_ap(self, new_ap, TRUE, TRUE);
|
||||
|
||||
req = nm_device_get_act_request(NM_DEVICE(self));
|
||||
if (req) {
|
||||
|
|
@ -2935,7 +2946,8 @@ build_supplicant_config(NMDeviceWifi *self,
|
|||
s_wireless = nm_connection_get_setting_wireless(connection);
|
||||
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 */
|
||||
if (nm_streq0(nm_setting_wireless_get_mode(s_wireless), NM_SETTING_WIRELESS_MODE_AP)
|
||||
|
|
@ -3011,6 +3023,7 @@ build_supplicant_config(NMDeviceWifi *self,
|
|||
mtu,
|
||||
pmf,
|
||||
fils,
|
||||
nm_device_get_private_files(NM_DEVICE(self)),
|
||||
error)) {
|
||||
g_prefix_error(error, "802-11-wireless-security: ");
|
||||
goto error;
|
||||
|
|
@ -3118,7 +3131,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
priv->mode = _NM_802_11_MODE_AP;
|
||||
|
||||
/* Scanning not done in AP mode; clear the scan list */
|
||||
remove_all_aps(self);
|
||||
remove_all_aps(self, FALSE);
|
||||
} else if (g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_MESH) == 0)
|
||||
priv->mode = _NM_802_11_MODE_MESH;
|
||||
_notify(self, PROP_MODE);
|
||||
|
|
@ -3155,14 +3168,14 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
nm_wifi_ap_set_address(ap_fake, nm_device_get_hw_address(device));
|
||||
|
||||
g_object_freeze_notify(G_OBJECT(self));
|
||||
ap_add_remove(self, TRUE, ap_fake, TRUE);
|
||||
ap_add_remove(self, TRUE, ap_fake, TRUE, TRUE);
|
||||
g_object_thaw_notify(G_OBJECT(self));
|
||||
ap = ap_fake;
|
||||
}
|
||||
|
||||
_scan_notify_allowed(self, NM_TERNARY_DEFAULT);
|
||||
|
||||
set_current_ap(self, ap, FALSE);
|
||||
set_current_ap(self, ap, FALSE, TRUE);
|
||||
nm_active_connection_set_specific_object(NM_ACTIVE_CONNECTION(req),
|
||||
nm_dbus_object_get_path(NM_DBUS_OBJECT(ap)));
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
|
|
@ -3528,7 +3541,7 @@ device_state_changed(NMDevice *device,
|
|||
|
||||
cleanup_association_attempt(self, TRUE);
|
||||
cleanup_supplicant_failures(self);
|
||||
remove_all_aps(self);
|
||||
remove_all_aps(self, FALSE);
|
||||
}
|
||||
|
||||
switch (new_state) {
|
||||
|
|
@ -3566,7 +3579,7 @@ device_state_changed(NMDevice *device,
|
|||
}
|
||||
|
||||
if (clear_aps)
|
||||
remove_all_aps(self);
|
||||
remove_all_aps(self, FALSE);
|
||||
|
||||
_scan_notify_allowed(self, NM_TERNARY_DEFAULT);
|
||||
}
|
||||
|
|
@ -3808,7 +3821,7 @@ dispose(GObject *object)
|
|||
|
||||
g_clear_object(&priv->sup_mgr);
|
||||
|
||||
remove_all_aps(self);
|
||||
remove_all_aps(self, TRUE);
|
||||
|
||||
if (priv->p2p_device) {
|
||||
/* Destroy the P2P device. */
|
||||
|
|
|
|||
|
|
@ -586,7 +586,11 @@ add_dns_domains(GPtrArray *array,
|
|||
}
|
||||
|
||||
static void
|
||||
merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3ConfigData *l3cd)
|
||||
merge_one_l3cd(NMResolvConfData *rc,
|
||||
int addr_family,
|
||||
int ifindex,
|
||||
const NML3ConfigData *l3cd,
|
||||
gboolean ignore_searches_and_options)
|
||||
{
|
||||
char buf[NM_INET_ADDRSTRLEN + 50];
|
||||
gboolean has_trust_ad;
|
||||
|
|
@ -624,30 +628,32 @@ merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3Con
|
|||
add_string_item(rc->nameservers, buf, TRUE);
|
||||
}
|
||||
|
||||
add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE);
|
||||
if (!ignore_searches_and_options) {
|
||||
add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE);
|
||||
|
||||
has_trust_ad = FALSE;
|
||||
strarr = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num);
|
||||
for (i = 0; i < num; i++) {
|
||||
const char *option = strarr[i];
|
||||
has_trust_ad = FALSE;
|
||||
strarr = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num);
|
||||
for (i = 0; i < num; i++) {
|
||||
const char *option = strarr[i];
|
||||
|
||||
if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) {
|
||||
has_trust_ad = TRUE;
|
||||
continue;
|
||||
if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) {
|
||||
has_trust_ad = TRUE;
|
||||
continue;
|
||||
}
|
||||
add_dns_option_item(rc->options, option);
|
||||
}
|
||||
add_dns_option_item(rc->options, option);
|
||||
}
|
||||
|
||||
if (num_nameservers == 0) {
|
||||
/* If the @l3cd contributes no DNS servers, ignore whether trust-ad is set or unset
|
||||
* for this @l3cd. */
|
||||
} else if (has_trust_ad) {
|
||||
/* We only set has_trust_ad to TRUE, if all IP configs agree (or don't contribute).
|
||||
* Once set to FALSE, it doesn't get reset. */
|
||||
if (rc->has_trust_ad == NM_TERNARY_DEFAULT)
|
||||
rc->has_trust_ad = NM_TERNARY_TRUE;
|
||||
} else
|
||||
rc->has_trust_ad = NM_TERNARY_FALSE;
|
||||
if (num_nameservers == 0) {
|
||||
/* If the @l3cd contributes no DNS servers, ignore whether trust-ad is set or unset
|
||||
* for this @l3cd. */
|
||||
} else if (has_trust_ad) {
|
||||
/* We only set has_trust_ad to TRUE, if all IP configs agree (or don't contribute).
|
||||
* Once set to FALSE, it doesn't get reset. */
|
||||
if (rc->has_trust_ad == NM_TERNARY_DEFAULT)
|
||||
rc->has_trust_ad = NM_TERNARY_TRUE;
|
||||
} else
|
||||
rc->has_trust_ad = NM_TERNARY_FALSE;
|
||||
}
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
const in_addr_t *nis_servers;
|
||||
|
|
@ -1231,12 +1237,15 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[
|
|||
{
|
||||
nm_auto_free_checksum GChecksum *sum = NULL;
|
||||
NMDnsConfigIPData *ip_data;
|
||||
gboolean has_global_dns_section = FALSE;
|
||||
|
||||
sum = g_checksum_new(G_CHECKSUM_SHA1);
|
||||
nm_assert(HASH_LEN == g_checksum_type_get_length(G_CHECKSUM_SHA1));
|
||||
|
||||
if (global)
|
||||
if (global) {
|
||||
nm_global_dns_config_update_checksum(global, sum);
|
||||
has_global_dns_section = nm_global_dns_has_global_dns_section(global);
|
||||
}
|
||||
|
||||
if (!global || !nm_global_dns_config_lookup_domain(global, "*")) {
|
||||
const CList *head;
|
||||
|
|
@ -1248,7 +1257,8 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[
|
|||
nm_l3_config_data_hash_dns(ip_data->l3cd,
|
||||
sum,
|
||||
ip_data->addr_family,
|
||||
ip_data->ip_config_type);
|
||||
ip_data->ip_config_type,
|
||||
has_global_dns_section);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1264,6 +1274,9 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
|
|||
const char *const *servers;
|
||||
guint i;
|
||||
|
||||
/* Global config must be processed before connections' config */
|
||||
nm_assert(rc->nameservers->len == 0);
|
||||
|
||||
if (!global_conf)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -1351,12 +1364,17 @@ _collect_resolv_conf_data(NMDnsManager *self,
|
|||
.nis_servers = g_ptr_array_new(),
|
||||
.has_trust_ad = NM_TERNARY_DEFAULT,
|
||||
};
|
||||
gboolean has_global_dns_section = FALSE;
|
||||
|
||||
priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
if (global_config)
|
||||
if (global_config) {
|
||||
merge_global_dns_config(&rc, global_config);
|
||||
has_global_dns_section = nm_global_dns_has_global_dns_section(global_config);
|
||||
}
|
||||
|
||||
/* If global nameservers are defined, no DNS configs are used from connections at all,
|
||||
* including searches and options. */
|
||||
if (!global_config || !nm_global_dns_config_lookup_domain(global_config, "*")) {
|
||||
nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE);
|
||||
int first_prio = 0;
|
||||
|
|
@ -1390,8 +1408,16 @@ _collect_resolv_conf_data(NMDnsManager *self,
|
|||
skip ? "<SKIP>" : "",
|
||||
get_nameserver_list(ip_data->addr_family, ip_data->l3cd, &tmp_strbuf));
|
||||
|
||||
if (!skip)
|
||||
merge_one_l3cd(&rc, ip_data->addr_family, ip_data->data->ifindex, ip_data->l3cd);
|
||||
if (!skip) {
|
||||
/* Merge the configs from connections. However, if there was a [global-dns]
|
||||
* it overwrites searches and options from the connections, thus we only
|
||||
* merge the nameservers. */
|
||||
merge_one_l3cd(&rc,
|
||||
ip_data->addr_family,
|
||||
ip_data->data->ifindex,
|
||||
ip_data->l3cd,
|
||||
has_global_dns_section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ struct _NMGlobalDnsConfig {
|
|||
char **options;
|
||||
GHashTable *domains;
|
||||
const char **domain_list;
|
||||
gboolean internal;
|
||||
char *cert_authority;
|
||||
NMDnsResolveMode resolve_mode;
|
||||
gboolean internal;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -941,6 +941,14 @@ next:
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_global_dns_has_global_dns_section(const NMGlobalDnsConfig *dns_config)
|
||||
{
|
||||
g_return_val_if_fail(dns_config, FALSE);
|
||||
|
||||
return dns_config->searches != NULL || dns_config->options != NULL;
|
||||
}
|
||||
|
||||
const char *const *
|
||||
nm_global_dns_config_get_searches(const NMGlobalDnsConfig *dns_config)
|
||||
{
|
||||
|
|
@ -1236,6 +1244,7 @@ load_global_dns(GKeyFile *keyfile, gboolean internal)
|
|||
gs_free char *cert_authority = NULL;
|
||||
gs_free char *resolve_mode = NULL;
|
||||
NMDnsResolveMode parsed_resolve_mode;
|
||||
gboolean has_global_dns_section;
|
||||
|
||||
if (internal) {
|
||||
group = NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS;
|
||||
|
|
@ -1386,6 +1395,22 @@ load_global_dns(GKeyFile *keyfile, gboolean internal)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Defining [global-dns-domain-*] implies defining [global-dns] too (maybe empty) */
|
||||
if (default_found)
|
||||
has_global_dns_section = TRUE;
|
||||
else
|
||||
has_global_dns_section = g_key_file_has_group(keyfile, group);
|
||||
|
||||
/* If there exist a [global-dns] section, always initialize "searches" and "options" so
|
||||
* they appear in D-Bus. Clients can use this to know if it's defined, so they can know
|
||||
* if DNS configs from connections are relevant or not. */
|
||||
if (has_global_dns_section) {
|
||||
if (!dns_config->searches)
|
||||
dns_config->searches = nm_strv_empty_new();
|
||||
if (!dns_config->options)
|
||||
dns_config->options = nm_strv_empty_new();
|
||||
}
|
||||
|
||||
dns_config->internal = internal;
|
||||
global_dns_config_seal_domains(dns_config);
|
||||
return dns_config;
|
||||
|
|
@ -1606,17 +1631,6 @@ nm_global_dns_config_from_dbus(const GValue *value, GError **error)
|
|||
g_variant_unref(val);
|
||||
}
|
||||
|
||||
/* An empty value is valid and clears the internal configuration */
|
||||
if (!nm_global_dns_config_is_empty(dns_config)
|
||||
&& !nm_global_dns_config_lookup_domain(dns_config, "*")) {
|
||||
g_set_error_literal(error,
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
"Global DNS configuration is missing the default domain");
|
||||
nm_global_dns_config_free(dns_config);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
global_dns_config_seal_domains(dns_config);
|
||||
return dns_config;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,6 +274,7 @@ gboolean nm_config_data_is_intern_atomic_group(const NMConfigData *self, const c
|
|||
|
||||
GKeyFile *nm_config_data_clone_keyfile_intern(const NMConfigData *self);
|
||||
|
||||
gboolean nm_global_dns_has_global_dns_section(const NMGlobalDnsConfig *dns_config);
|
||||
const char *const *nm_global_dns_config_get_searches(const NMGlobalDnsConfig *dns_config);
|
||||
const char *const *nm_global_dns_config_get_options(const NMGlobalDnsConfig *dns_config);
|
||||
const char *nm_global_dns_config_get_certification_authority(const NMGlobalDnsConfig *dns_config);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "libnm-core-intern/nm-keyfile-internal.h"
|
||||
#include "libnm-core-intern/nm-keyfile-utils.h"
|
||||
#include "libnm-glib-aux/nm-keyfile-aux.h"
|
||||
|
||||
#define DEFAULT_CONFIG_MAIN_FILE NMCONFDIR "/NetworkManager.conf"
|
||||
#define DEFAULT_CONFIG_DIR NMCONFDIR "/conf.d"
|
||||
|
|
@ -1046,6 +1047,10 @@ read_config(GKeyFile *keyfile,
|
|||
/* internal groups cannot be set by user configuration. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!g_key_file_has_group(keyfile, group))
|
||||
nm_key_file_add_group(keyfile, group);
|
||||
|
||||
keys = g_key_file_get_keys(kf, group, &nkeys, NULL);
|
||||
if (!keys)
|
||||
continue;
|
||||
|
|
@ -1639,6 +1644,12 @@ intern_config_read(const char *filename,
|
|||
"");
|
||||
}
|
||||
|
||||
if (!g_key_file_has_group(keyfile_intern, group)) {
|
||||
nm_key_file_add_group(keyfile_intern, group);
|
||||
if (is_intern)
|
||||
has_intern = TRUE;
|
||||
}
|
||||
|
||||
for (k = 0; keys[k]; k++) {
|
||||
gs_free char *value_set = NULL;
|
||||
const char *key = keys[k];
|
||||
|
|
@ -1823,6 +1834,9 @@ intern_config_write(const char *filename,
|
|||
}
|
||||
}
|
||||
|
||||
if (!g_key_file_has_group(keyfile, group))
|
||||
nm_key_file_add_group(keyfile, group);
|
||||
|
||||
for (k = 0; keys[k]; k++) {
|
||||
const char *key = keys[k];
|
||||
gs_free char *value_set = NULL;
|
||||
|
|
|
|||
|
|
@ -5011,6 +5011,7 @@ typedef struct {
|
|||
int child_stdin;
|
||||
int child_stdout;
|
||||
int child_stderr;
|
||||
gboolean binary_output;
|
||||
GSource *input_source;
|
||||
GSource *output_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);
|
||||
g_task_return_pointer(info->task,
|
||||
nm_str_buf_finalize(&info->in_buffer, NULL) ?: g_new0(char, 1),
|
||||
g_free);
|
||||
|
||||
if (info->binary_output) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -5235,6 +5244,7 @@ helper_cancelled(GObject *object, gpointer user_data)
|
|||
|
||||
void
|
||||
nm_utils_spawn_helper(const char *const *args,
|
||||
gboolean binary_output,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer cb_data)
|
||||
|
|
@ -5250,9 +5260,14 @@ nm_utils_spawn_helper(const char *const *args,
|
|||
|
||||
info = g_new(HelperInfo, 1);
|
||||
*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("/",
|
||||
(char **) NM_MAKE_STRV(LIBEXECDIR "/nm-daemon-helper"),
|
||||
(char **) NM_MAKE_STRV(),
|
||||
|
|
@ -5363,11 +5378,25 @@ nm_utils_spawn_helper(const char *const *args,
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -5474,3 +5503,185 @@ nm_utils_shorten_hostname(const char *hostname, char **shortened)
|
|||
*shortened = g_steal_pointer(&s);
|
||||
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,
|
||||
gboolean binary_output,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
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);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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__ */
|
||||
|
|
|
|||
|
|
@ -3139,7 +3139,8 @@ void
|
|||
nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd,
|
||||
GChecksum *sum,
|
||||
int addr_family,
|
||||
NMDnsIPConfigType dns_ip_config_type)
|
||||
NMDnsIPConfigType dns_ip_config_type,
|
||||
gboolean ignore_searches_and_options)
|
||||
{
|
||||
guint i;
|
||||
int val;
|
||||
|
|
@ -3178,16 +3179,18 @@ nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd,
|
|||
empty = FALSE;
|
||||
}
|
||||
|
||||
searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches);
|
||||
for (i = 0; i < num_searches; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) searches[i], strlen(searches[i]));
|
||||
empty = FALSE;
|
||||
}
|
||||
if (!ignore_searches_and_options) {
|
||||
searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches);
|
||||
for (i = 0; i < num_searches; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) searches[i], strlen(searches[i]));
|
||||
empty = FALSE;
|
||||
}
|
||||
|
||||
options = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num_options);
|
||||
for (i = 0; i < num_options; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) options[i], strlen(options[i]));
|
||||
empty = FALSE;
|
||||
options = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num_options);
|
||||
for (i = 0; i < num_options; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) options[i], strlen(options[i]));
|
||||
empty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
val = nm_l3_config_data_get_mdns(l3cd);
|
||||
|
|
|
|||
|
|
@ -615,6 +615,7 @@ nmtst_l3_config_data_get_best_gateway(const NML3ConfigData *self, int addr_famil
|
|||
void nm_l3_config_data_hash_dns(const NML3ConfigData *l3cd,
|
||||
GChecksum *sum,
|
||||
int addr_family,
|
||||
NMDnsIPConfigType dns_ip_config_type);
|
||||
NMDnsIPConfigType dns_ip_config_type,
|
||||
gboolean ignore_searches_and_options);
|
||||
|
||||
#endif /* __NM_L3_CONFIG_DATA_H__ */
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ enum {
|
|||
ACTIVE_CONNECTION_REMOVED,
|
||||
CONFIGURE_QUIT,
|
||||
DEVICE_IFINDEX_CHANGED,
|
||||
SHARING_IPV4_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
|
@ -238,6 +239,8 @@ typedef struct {
|
|||
|
||||
guint8 device_state_prune_ratelimit_count;
|
||||
|
||||
guint shared_connections_ip4_count;
|
||||
|
||||
bool startup : 1;
|
||||
bool devices_inited : 1;
|
||||
|
||||
|
|
@ -1960,7 +1963,7 @@ find_device_by_iface(NMManager *self,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
manager_sleeping(NMManager *self)
|
||||
manager_is_disabled(NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
|
|
@ -1973,8 +1976,8 @@ static const char *
|
|||
_nm_state_to_string(NMState state)
|
||||
{
|
||||
switch (state) {
|
||||
case NM_STATE_ASLEEP:
|
||||
return "ASLEEP";
|
||||
case NM_STATE_DISABLED:
|
||||
return "DISABLED";
|
||||
case NM_STATE_DISCONNECTED:
|
||||
return "DISCONNECTED";
|
||||
case NM_STATE_DISCONNECTING:
|
||||
|
|
@ -2078,15 +2081,18 @@ nm_manager_update_state(NMManager *self)
|
|||
{
|
||||
NMManagerPrivate *priv;
|
||||
NMState new_state = NM_STATE_DISCONNECTED;
|
||||
const char *detail = "";
|
||||
|
||||
g_return_if_fail(NM_IS_MANAGER(self));
|
||||
|
||||
priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
if (manager_sleeping(self))
|
||||
new_state = NM_STATE_ASLEEP;
|
||||
else
|
||||
if (manager_is_disabled(self)) {
|
||||
new_state = NM_STATE_DISABLED;
|
||||
detail = priv->sleeping ? " (ASLEEP)" : " (NETWORKING OFF)";
|
||||
} else {
|
||||
new_state = find_best_device_state(self);
|
||||
}
|
||||
|
||||
if (new_state >= NM_STATE_CONNECTED_LOCAL && priv->connectivity_state == NM_CONNECTIVITY_FULL) {
|
||||
new_state = NM_STATE_CONNECTED_GLOBAL;
|
||||
|
|
@ -2097,7 +2103,7 @@ nm_manager_update_state(NMManager *self)
|
|||
|
||||
priv->state = new_state;
|
||||
|
||||
_LOGI(LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string(new_state));
|
||||
_LOGI(LOGD_CORE, "NetworkManager state is now %s%s", _nm_state_to_string(new_state), detail);
|
||||
|
||||
_notify(self, PROP_STATE);
|
||||
nm_dbus_object_emit_signal(NM_DBUS_OBJECT(self),
|
||||
|
|
@ -2956,7 +2962,7 @@ _rfkill_update_devices(NMManager *self, NMRfkillType rtype, gboolean enabled)
|
|||
_notify(self, _rfkill_type_desc[rtype].prop_id);
|
||||
|
||||
/* Don't touch devices if asleep/networking disabled */
|
||||
if (manager_sleeping(self))
|
||||
if (manager_is_disabled(self))
|
||||
return;
|
||||
|
||||
/* enable/disable wireless devices as required */
|
||||
|
|
@ -3120,7 +3126,7 @@ _rfkill_update_from_user(NMManager *self, NMRfkillType rtype, gboolean enabled)
|
|||
gboolean old_enabled, new_enabled;
|
||||
|
||||
/* Don't touch devices if asleep/networking disabled */
|
||||
if (manager_sleeping(self))
|
||||
if (manager_is_disabled(self))
|
||||
return;
|
||||
|
||||
_LOGD(LOGD_RFKILL,
|
||||
|
|
@ -4079,7 +4085,7 @@ add_device(NMManager *self, NMDevice *device, GError **error)
|
|||
|
||||
nm_device_set_unmanaged_by_user_settings(device, TRUE);
|
||||
|
||||
nm_device_set_unmanaged_flags(device, NM_UNMANAGED_SLEEPING, manager_sleeping(self));
|
||||
nm_device_set_unmanaged_flags(device, NM_UNMANAGED_MANAGER_DISABLED, manager_is_disabled(self));
|
||||
|
||||
dbus_path = nm_dbus_object_export(NM_DBUS_OBJECT(device));
|
||||
_LOG2I(LOGD_DEVICE, device, "new %s device (%s)", type_desc, dbus_path);
|
||||
|
|
@ -5718,6 +5724,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
GError *local = NULL;
|
||||
NMConnectionMultiConnect multi_connect;
|
||||
const char *parent_spec;
|
||||
gboolean did_realize = FALSE;
|
||||
|
||||
g_return_val_if_fail(NM_IS_MANAGER(self), FALSE);
|
||||
g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(active), FALSE);
|
||||
|
|
@ -5892,6 +5899,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
nm_device_get_iface(device));
|
||||
return FALSE;
|
||||
}
|
||||
did_realize = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5923,7 +5931,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
"The controller connection '%s' is not compatible with '%s'",
|
||||
nm_settings_connection_get_id(controller_connection),
|
||||
nm_settings_connection_get_id(sett_conn));
|
||||
return FALSE;
|
||||
goto err_unrealize;
|
||||
}
|
||||
|
||||
if (!controller_ac) {
|
||||
|
|
@ -5946,7 +5954,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
"Controller connection '%s' can't be activated: ",
|
||||
nm_settings_connection_get_id(controller_connection));
|
||||
}
|
||||
return FALSE;
|
||||
goto err_unrealize;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6040,7 +6048,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_DEPENDENCY_FAILED,
|
||||
"Activation failed because the device is unmanaged");
|
||||
return FALSE;
|
||||
goto err_unrealize;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6048,6 +6056,11 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
active_connection_add(self, active);
|
||||
nm_device_queue_activation(device, NM_ACT_REQUEST(active));
|
||||
return TRUE;
|
||||
|
||||
err_unrealize:
|
||||
if (did_realize)
|
||||
nm_device_unrealize(device, TRUE, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -7292,7 +7305,7 @@ device_sleep_cb(NMDevice *device, GParamSpec *pspec, NMManager *self)
|
|||
case NM_DEVICE_STATE_DISCONNECTED:
|
||||
_LOGD(LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface(device));
|
||||
nm_device_set_unmanaged_by_flags_queue(device,
|
||||
NM_UNMANAGED_SLEEPING,
|
||||
NM_UNMANAGED_MANAGER_DISABLED,
|
||||
NM_UNMAN_FLAG_OP_SET_UNMANAGED,
|
||||
NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
break;
|
||||
|
|
@ -7314,24 +7327,26 @@ _handle_device_takedown(NMManager *self,
|
|||
gboolean suspending,
|
||||
gboolean is_shutdown)
|
||||
{
|
||||
gboolean is_sleep = suspending || is_shutdown;
|
||||
NMDeviceStateReason reason =
|
||||
is_sleep ? NM_DEVICE_STATE_REASON_SLEEPING : NM_DEVICE_STATE_REASON_NETWORKING_OFF;
|
||||
|
||||
nm_device_notify_sleeping(device);
|
||||
|
||||
if (nm_device_is_activating(device)
|
||||
|| nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) {
|
||||
_LOGD(LOGD_SUSPEND,
|
||||
_LOGD(is_sleep ? LOGD_SUSPEND : LOGD_CORE,
|
||||
"%s: wait disconnection of device %s",
|
||||
is_shutdown ? "shutdown" : "sleep",
|
||||
is_sleep ? (is_shutdown ? "shutdown" : "sleep") : "networking off",
|
||||
nm_device_get_ip_iface(device));
|
||||
|
||||
if (sleep_devices_add(self, device, suspending))
|
||||
nm_device_queue_state(device,
|
||||
NM_DEVICE_STATE_DEACTIVATING,
|
||||
NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
nm_device_queue_state(device, NM_DEVICE_STATE_DEACTIVATING, reason);
|
||||
} else {
|
||||
nm_device_set_unmanaged_by_flags(device,
|
||||
NM_UNMANAGED_SLEEPING,
|
||||
NM_UNMANAGED_MANAGER_DISABLED,
|
||||
NM_UNMAN_FLAG_OP_SET_UNMANAGED,
|
||||
NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7345,8 +7360,10 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed)
|
|||
suspending = sleeping_changed && priv->sleeping;
|
||||
waking_from_suspend = sleeping_changed && !priv->sleeping;
|
||||
|
||||
if (manager_sleeping(self)) {
|
||||
_LOGD(LOGD_SUSPEND, "sleep: %s...", suspending ? "sleeping" : "disabling");
|
||||
if (manager_is_disabled(self)) {
|
||||
_LOGD(suspending ? LOGD_SUSPEND : LOGD_CORE,
|
||||
"%s...",
|
||||
suspending ? "sleep: sleeping" : "networking: disabling");
|
||||
|
||||
/* FIXME: are there still hardware devices that need to be disabled around
|
||||
* suspend/resume?
|
||||
|
|
@ -7372,7 +7389,9 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed)
|
|||
_handle_device_takedown(self, device, suspending, FALSE);
|
||||
}
|
||||
} else {
|
||||
_LOGD(LOGD_SUSPEND, "sleep: %s...", waking_from_suspend ? "waking up" : "re-enabling");
|
||||
_LOGD(waking_from_suspend ? LOGD_SUSPEND : LOGD_CORE,
|
||||
"%s...",
|
||||
waking_from_suspend ? "sleep: waking up" : "networking: re-enabling");
|
||||
|
||||
sleep_devices_clear(self);
|
||||
|
||||
|
|
@ -7386,7 +7405,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed)
|
|||
*/
|
||||
if (device_is_wake_on_lan(priv->platform, device))
|
||||
nm_device_set_unmanaged_by_flags(device,
|
||||
NM_UNMANAGED_SLEEPING,
|
||||
NM_UNMANAGED_MANAGER_DISABLED,
|
||||
NM_UNMAN_FLAG_OP_SET_UNMANAGED,
|
||||
NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
|
||||
|
|
@ -7414,10 +7433,12 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed)
|
|||
guint i;
|
||||
|
||||
if (nm_device_is_software(device)
|
||||
&& !nm_device_get_unmanaged_flags(device, NM_UNMANAGED_SLEEPING)) {
|
||||
&& !nm_device_get_unmanaged_flags(device, NM_UNMANAGED_MANAGER_DISABLED)) {
|
||||
/* DHCP leases of software devices could have gone stale
|
||||
* so we need to renew them. */
|
||||
nm_device_update_dynamic_ip_setup(device, "wake up");
|
||||
nm_device_update_dynamic_ip_setup(device,
|
||||
waking_from_suspend ? "wake up"
|
||||
: "networking on");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -7448,7 +7469,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed)
|
|||
? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED
|
||||
: NM_DEVICE_STATE_REASON_NOW_MANAGED;
|
||||
nm_device_set_unmanaged_by_flags(device,
|
||||
NM_UNMANAGED_SLEEPING,
|
||||
NM_UNMANAGED_MANAGER_DISABLED,
|
||||
NM_UNMAN_FLAG_OP_SET_MANAGED,
|
||||
reason);
|
||||
}
|
||||
|
|
@ -8811,6 +8832,41 @@ nm_manager_emit_device_ifindex_changed(NMManager *self, NMDevice *device)
|
|||
g_signal_emit(self, signals[DEVICE_IFINDEX_CHANGED], 0, device);
|
||||
}
|
||||
|
||||
void
|
||||
nm_manager_update_shared_connection(NMManager *self, int addr_family, gboolean enabled)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
gboolean state_changed, state;
|
||||
|
||||
/* Only IPv4 supported for the moment */
|
||||
if (addr_family != AF_INET)
|
||||
return;
|
||||
|
||||
if (enabled) {
|
||||
g_return_if_fail(priv->shared_connections_ip4_count < G_MAXUINT);
|
||||
priv->shared_connections_ip4_count++;
|
||||
state_changed = priv->shared_connections_ip4_count == 1;
|
||||
} else {
|
||||
g_return_if_fail(priv->shared_connections_ip4_count > 0);
|
||||
priv->shared_connections_ip4_count--;
|
||||
state_changed = priv->shared_connections_ip4_count == 0;
|
||||
}
|
||||
|
||||
if (state_changed) {
|
||||
state = priv->shared_connections_ip4_count > 0;
|
||||
_LOGD(LOGD_SHARING, "sharing-ipv4 state change %d -> %d", !state, state);
|
||||
g_signal_emit(self, signals[SHARING_IPV4_CHANGED], 0, state);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_manager_get_sharing_ipv4(NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
return priv->shared_connections_ip4_count > 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_DEFINE_SINGLETON_REGISTER(NMManager);
|
||||
|
|
@ -9914,6 +9970,17 @@ nm_manager_class_init(NMManagerClass *manager_class)
|
|||
G_TYPE_NONE,
|
||||
1,
|
||||
NM_TYPE_DEVICE);
|
||||
|
||||
signals[SHARING_IPV4_CHANGED] = g_signal_new(NM_MANAGER_SHARING_IPV4_CHANGED,
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_BOOLEAN);
|
||||
}
|
||||
|
||||
NMConfig *
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#define NM_MANAGER_CONFIGURE_QUIT "configure-quit"
|
||||
#define NM_MANAGER_INTERNAL_DEVICE_ADDED "internal-device-added"
|
||||
#define NM_MANAGER_INTERNAL_DEVICE_REMOVED "internal-device-removed"
|
||||
#define NM_MANAGER_SHARING_IPV4_CHANGED "sharing-ipv4-changed"
|
||||
|
||||
GType nm_manager_get_type(void);
|
||||
|
||||
|
|
@ -212,6 +213,9 @@ struct _NMDnsManager;
|
|||
|
||||
struct _NMDnsManager *nm_manager_get_dns_manager(NMManager *self);
|
||||
|
||||
void nm_manager_update_shared_connection(NMManager *self, int addr_family, gboolean enabled);
|
||||
gboolean nm_manager_get_sharing_ipv4(NMManager *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_manager_notify_delete_settings_connections(NMManager *self,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "devices/nm-device.h"
|
||||
#include "devices/nm-device-factory.h"
|
||||
#include "devices/nm-device-private.h"
|
||||
#include "dns/nm-dns-manager.h"
|
||||
#include "nm-act-request.h"
|
||||
#include "nm-auth-utils.h"
|
||||
|
|
@ -98,6 +97,7 @@ typedef struct {
|
|||
bool updating_dns : 1;
|
||||
|
||||
GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */
|
||||
|
||||
} NMPolicyPrivate;
|
||||
|
||||
struct _NMPolicy {
|
||||
|
|
@ -1845,7 +1845,7 @@ nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device
|
|||
|
||||
priv = NM_POLICY_GET_PRIVATE(self);
|
||||
|
||||
if (nm_manager_get_state(priv->manager) == NM_STATE_ASLEEP)
|
||||
if (nm_manager_get_state(priv->manager) == NM_STATE_DISABLED)
|
||||
return;
|
||||
|
||||
if (!nm_device_autoconnect_allowed(device))
|
||||
|
|
@ -2083,65 +2083,6 @@ unblock_autoconnect_for_ports_for_sett_conn(NMPolicy *self, NMSettingsConnection
|
|||
unblock_autoconnect_for_ports(self, controller_device, controller_uuid_settings, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_forwarding(NMPolicy *self, NMDevice *device, gboolean is_activated_shared_device)
|
||||
{
|
||||
NMActiveConnection *ac;
|
||||
NMDevice *tmp_device;
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
const CList *tmp_lst;
|
||||
gboolean any_shared_active = false;
|
||||
gint32 default_forwarding_v4;
|
||||
const char *new_value = NULL;
|
||||
|
||||
/* FIXME: This implementation is still inefficient because refresh_forwarding()
|
||||
* is called every time a device goes up or down, requiring a full scan of all
|
||||
* active connections to determine if any shared connection is active. */
|
||||
nm_manager_for_each_active_connection (priv->manager, ac, tmp_lst) {
|
||||
NMSettingIPConfig *s_ip;
|
||||
NMDevice *to_device = nm_active_connection_get_device(ac);
|
||||
|
||||
if (to_device) {
|
||||
s_ip = nm_device_get_applied_setting(to_device, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
if (s_ip) {
|
||||
if (nm_streq0(nm_device_get_effective_ip_config_method(to_device, AF_INET),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
|
||||
any_shared_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default_forwarding_v4 = nm_platform_sysctl_get_int32(
|
||||
NM_PLATFORM_GET,
|
||||
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"),
|
||||
0);
|
||||
|
||||
new_value = any_shared_active ? "1" : (default_forwarding_v4 ? "1" : "0");
|
||||
|
||||
nm_manager_for_each_device (priv->manager, tmp_device, tmp_lst) {
|
||||
NMDeviceState state;
|
||||
NMSettingIPConfigForwarding ipv4_forwarding;
|
||||
|
||||
state = nm_device_get_state(tmp_device);
|
||||
if (state != NM_DEVICE_STATE_ACTIVATED)
|
||||
continue;
|
||||
|
||||
ipv4_forwarding = nm_device_get_ipv4_forwarding(tmp_device);
|
||||
|
||||
if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_AUTO
|
||||
|| (device == tmp_device && is_activated_shared_device)) {
|
||||
gs_free char *sysctl_value = NULL;
|
||||
|
||||
sysctl_value = nm_device_sysctl_ip_conf_get(tmp_device, AF_INET, "forwarding");
|
||||
|
||||
if (!nm_streq0(sysctl_value, new_value))
|
||||
nm_device_sysctl_ip_conf_set(tmp_device, AF_INET, "forwarding", new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
activate_port_or_children_connections(NMPolicy *self,
|
||||
NMDevice *device,
|
||||
|
|
@ -2286,9 +2227,8 @@ device_state_changed(NMDevice *device,
|
|||
NMPolicyPrivate *priv = user_data;
|
||||
NMPolicy *self = _PRIV_TO_SELF(priv);
|
||||
NMActiveConnection *ac;
|
||||
NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device);
|
||||
NMSettingConnection *s_con = NULL;
|
||||
gboolean is_activated_shared_device = FALSE;
|
||||
NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device);
|
||||
NMSettingConnection *s_con = NULL;
|
||||
|
||||
switch (nm_device_state_reason_check(reason)) {
|
||||
case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
|
||||
|
|
@ -2404,10 +2344,6 @@ device_state_changed(NMDevice *device,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!nm_device_get_refresh_forwarding_done(device)) {
|
||||
refresh_forwarding(self, device, FALSE);
|
||||
nm_device_set_refresh_forwarding_done(device, TRUE);
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE) {
|
||||
|
|
@ -2440,20 +2376,11 @@ device_state_changed(NMDevice *device,
|
|||
update_system_hostname(self, "routing and dns", TRUE);
|
||||
nm_dns_manager_end_updates(priv->dns_manager, __func__);
|
||||
|
||||
is_activated_shared_device =
|
||||
nm_streq0(nm_device_get_effective_ip_config_method(device, AF_INET),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_SHARED);
|
||||
refresh_forwarding(self, device, is_activated_shared_device);
|
||||
nm_device_set_refresh_forwarding_done(device, FALSE);
|
||||
break;
|
||||
case NM_DEVICE_STATE_UNMANAGED:
|
||||
case NM_DEVICE_STATE_UNAVAILABLE:
|
||||
if (old_state > NM_DEVICE_STATE_DISCONNECTED)
|
||||
update_routing_and_dns(self, FALSE, device);
|
||||
if (!nm_device_get_refresh_forwarding_done(device)) {
|
||||
refresh_forwarding(self, device, FALSE);
|
||||
nm_device_set_refresh_forwarding_done(device, TRUE);
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_DEACTIVATING:
|
||||
if (sett_conn) {
|
||||
|
|
@ -2489,10 +2416,6 @@ device_state_changed(NMDevice *device,
|
|||
}
|
||||
}
|
||||
ip6_remove_device_prefix_delegations(self, device);
|
||||
if (!nm_device_get_refresh_forwarding_done(device)) {
|
||||
refresh_forwarding(self, device, FALSE);
|
||||
nm_device_set_refresh_forwarding_done(device, TRUE);
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_DISCONNECTED:
|
||||
g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
|
||||
|
|
@ -2509,10 +2432,6 @@ device_state_changed(NMDevice *device,
|
|||
|
||||
/* Device is now available for auto-activation */
|
||||
nm_policy_device_recheck_auto_activate_schedule(self, device);
|
||||
if (!nm_device_get_refresh_forwarding_done(device)) {
|
||||
refresh_forwarding(self, device, FALSE);
|
||||
nm_device_set_refresh_forwarding_done(device, TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NM_DEVICE_STATE_PREPARE:
|
||||
|
|
@ -2528,10 +2447,6 @@ device_state_changed(NMDevice *device,
|
|||
g_object_weak_unref(G_OBJECT(ac), pending_ac_gone, self);
|
||||
g_object_unref(self);
|
||||
}
|
||||
if (!nm_device_get_refresh_forwarding_done(device)) {
|
||||
refresh_forwarding(self, device, FALSE);
|
||||
nm_device_set_refresh_forwarding_done(device, TRUE);
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_IP_CONFIG:
|
||||
/* We must have secrets if we got here. */
|
||||
|
|
@ -2542,10 +2457,6 @@ device_state_changed(NMDevice *device,
|
|||
sett_conn,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
FALSE);
|
||||
if (!nm_device_get_refresh_forwarding_done(device)) {
|
||||
refresh_forwarding(self, device, FALSE);
|
||||
nm_device_set_refresh_forwarding_done(device, TRUE);
|
||||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_SECONDARIES:
|
||||
if (sett_conn)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
GHashTable *config;
|
||||
GHashTable *blobs;
|
||||
char *private_user;
|
||||
NMSupplCapMask capabilities;
|
||||
guint32 ap_scan;
|
||||
bool fast_required : 1;
|
||||
|
|
@ -60,7 +61,7 @@ _get_capability(NMSupplicantConfigPrivate *priv, NMSupplCapType type)
|
|||
}
|
||||
|
||||
NMSupplicantConfig *
|
||||
nm_supplicant_config_new(NMSupplCapMask capabilities)
|
||||
nm_supplicant_config_new(NMSupplCapMask capabilities, const char *private_user)
|
||||
{
|
||||
NMSupplicantConfigPrivate *priv;
|
||||
NMSupplicantConfig *self;
|
||||
|
|
@ -69,6 +70,7 @@ nm_supplicant_config_new(NMSupplCapMask capabilities)
|
|||
priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE(self);
|
||||
|
||||
priv->capabilities = capabilities;
|
||||
priv->private_user = g_strdup(private_user);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
|
@ -258,19 +260,19 @@ static gboolean
|
|||
nm_supplicant_config_add_blob_for_connection(NMSupplicantConfig *self,
|
||||
GBytes *field,
|
||||
const char *name,
|
||||
const char *con_uid,
|
||||
const char *con_uuid,
|
||||
GError **error)
|
||||
{
|
||||
if (field && g_bytes_get_size(field)) {
|
||||
gs_free char *uid = NULL;
|
||||
gs_free char *blob_id = NULL;
|
||||
char *p;
|
||||
|
||||
uid = g_strdup_printf("%s-%s", con_uid, name);
|
||||
for (p = uid; *p; p++) {
|
||||
blob_id = g_strdup_printf("%s-%s", con_uuid, name);
|
||||
for (p = blob_id; *p; p++) {
|
||||
if (*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 TRUE;
|
||||
|
|
@ -283,6 +285,7 @@ nm_supplicant_config_finalize(GObject *object)
|
|||
|
||||
g_hash_table_destroy(priv->config);
|
||||
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);
|
||||
}
|
||||
|
|
@ -930,6 +933,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
|
|||
guint32 mtu,
|
||||
NMSettingWirelessSecurityPmf pmf,
|
||||
NMSettingWirelessSecurityFils fils,
|
||||
GHashTable *files,
|
||||
GError **error)
|
||||
{
|
||||
NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE(self);
|
||||
|
|
@ -1284,6 +1288,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
|
|||
con_uuid,
|
||||
mtu,
|
||||
FALSE,
|
||||
files,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1365,6 +1370,7 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
const char *con_uuid,
|
||||
guint32 mtu,
|
||||
gboolean wired,
|
||||
GHashTable *files,
|
||||
GError **error)
|
||||
{
|
||||
NMSupplicantConfigPrivate *priv;
|
||||
|
|
@ -1594,24 +1600,21 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
}
|
||||
|
||||
/* CA certificate */
|
||||
path = NULL;
|
||||
bytes = NULL;
|
||||
if (ca_cert_override) {
|
||||
if (!add_string_val(self, ca_cert_override, "ca_cert", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
/* This is a build-time-configured system-wide file path, no need to pass
|
||||
* it as a blob */
|
||||
path = ca_cert_override;
|
||||
} else {
|
||||
switch (nm_setting_802_1x_get_ca_cert_scheme(setting)) {
|
||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||
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;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||
path = nm_setting_802_1x_get_ca_cert_path(setting);
|
||||
if (!add_string_val(self, path, "ca_cert", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
if (priv->private_user)
|
||||
bytes = nm_g_hash_table_lookup(files, path);
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||
if (!add_pkcs11_uri_with_pin(self,
|
||||
|
|
@ -1627,26 +1630,32 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
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 */
|
||||
path = NULL;
|
||||
bytes = NULL;
|
||||
if (ca_cert_override) {
|
||||
if (!add_string_val(self, ca_cert_override, "ca_cert2", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
/* This is a build-time-configured system-wide file path, no need to pass
|
||||
* it as a blob */
|
||||
path = ca_cert_override;
|
||||
} else {
|
||||
switch (nm_setting_802_1x_get_phase2_ca_cert_scheme(setting)) {
|
||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||
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;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||
path = nm_setting_802_1x_get_phase2_ca_cert_path(setting);
|
||||
if (!add_string_val(self, path, "ca_cert2", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
if (priv->private_user)
|
||||
bytes = nm_g_hash_table_lookup(files, path);
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||
if (!add_pkcs11_uri_with_pin(
|
||||
|
|
@ -1663,6 +1672,15 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
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 */
|
||||
value = nm_setting_802_1x_get_subject_match(setting);
|
||||
|
|
@ -1714,21 +1732,17 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
|
||||
/* Private key */
|
||||
added = FALSE;
|
||||
path = NULL;
|
||||
bytes = NULL;
|
||||
switch (nm_setting_802_1x_get_private_key_scheme(setting)) {
|
||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||
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;
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||
path = nm_setting_802_1x_get_private_key_path(setting);
|
||||
if (!add_string_val(self, path, "private_key", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
if (priv->private_user)
|
||||
bytes = nm_g_hash_table_lookup(files, path);
|
||||
added = TRUE;
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||
|
|
@ -1745,6 +1759,19 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
default:
|
||||
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) {
|
||||
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
|
||||
* wpa_supplicant configuration directs us to do.
|
||||
*/
|
||||
path = NULL;
|
||||
bytes = NULL;
|
||||
switch (nm_setting_802_1x_get_client_cert_scheme(setting)) {
|
||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||
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;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||
path = nm_setting_802_1x_get_client_cert_path(setting);
|
||||
if (!add_string_val(self, path, "client_cert", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
if (priv->private_user)
|
||||
bytes = nm_g_hash_table_lookup(files, path);
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||
if (!add_pkcs11_uri_with_pin(
|
||||
|
|
@ -1797,26 +1820,35 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
default:
|
||||
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 */
|
||||
added = FALSE;
|
||||
path = NULL;
|
||||
bytes = NULL;
|
||||
switch (nm_setting_802_1x_get_phase2_private_key_scheme(setting)) {
|
||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||
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;
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||
path = nm_setting_802_1x_get_phase2_private_key_path(setting);
|
||||
if (!add_string_val(self, path, "private_key2", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
if (priv->private_user)
|
||||
bytes = nm_g_hash_table_lookup(files, path);
|
||||
added = TRUE;
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||
|
|
@ -1834,6 +1866,19 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
default:
|
||||
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) {
|
||||
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
|
||||
* wpa_supplicant configuration directs us to do.
|
||||
*/
|
||||
path = NULL;
|
||||
bytes = NULL;
|
||||
switch (nm_setting_802_1x_get_phase2_client_cert_scheme(setting)) {
|
||||
case NM_SETTING_802_1X_CK_SCHEME_BLOB:
|
||||
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;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PATH:
|
||||
path = nm_setting_802_1x_get_phase2_client_cert_path(setting);
|
||||
if (!add_string_val(self, path, "client_cert2", FALSE, NULL, error))
|
||||
return FALSE;
|
||||
if (priv->private_user)
|
||||
bytes = nm_g_hash_table_lookup(files, path);
|
||||
break;
|
||||
case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
|
||||
if (!add_pkcs11_uri_with_pin(
|
||||
|
|
@ -1886,6 +1927,19 @@ nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
|
|||
default:
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -57,6 +57,7 @@ gboolean nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
|
|||
guint32 mtu,
|
||||
NMSettingWirelessSecurityPmf pmf,
|
||||
NMSettingWirelessSecurityFils fils,
|
||||
GHashTable *files,
|
||||
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,
|
||||
guint32 mtu,
|
||||
gboolean wired,
|
||||
GHashTable *files,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ typedef struct {
|
|||
gpointer user_data;
|
||||
guint fail_on_idle_id;
|
||||
guint blobs_left;
|
||||
guint remove_blobs_left;
|
||||
guint calls_left;
|
||||
struct _AddNetworkData *add_network_data;
|
||||
} AssocData;
|
||||
|
|
@ -2264,6 +2265,7 @@ assoc_add_blob_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
|||
return;
|
||||
}
|
||||
|
||||
nm_assert(priv->assoc_data->blobs_left > 0);
|
||||
priv->assoc_data->blobs_left--;
|
||||
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: blob added (%u left)",
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
NMSupplicantInterface *self;
|
||||
NMSupplicantInterfacePrivate *priv;
|
||||
gs_unref_variant GVariant *res = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
GHashTable *blobs;
|
||||
GHashTableIter iter;
|
||||
const char *blob_name;
|
||||
GBytes *blob_data;
|
||||
gs_unref_variant GVariant *res = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
nm_auto_ref_string NMRefString *name_owner = 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);
|
||||
g_variant_get(res, "(o)", &priv->net_path);
|
||||
|
||||
/* Send blobs first; otherwise jump to selecting the network */
|
||||
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)",
|
||||
_LOGT("assoc[" NM_HASH_OBFUSCATE_PTR_FMT "]: network added (%s)",
|
||||
NM_HASH_OBFUSCATE_PTR(priv->assoc_data),
|
||||
priv->net_path,
|
||||
priv->assoc_data->blobs_left);
|
||||
priv->net_path);
|
||||
|
||||
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)) {
|
||||
_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);
|
||||
}
|
||||
/* Delete any existing blobs before adding new ones */
|
||||
_dbus_connection_call(self,
|
||||
DBUS_INTERFACE_PROPERTIES,
|
||||
"Get",
|
||||
g_variant_new("(ss)", NM_WPAS_DBUS_IFACE_INTERFACE, "Blobs"),
|
||||
G_VARIANT_TYPE("(v)"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
DBUS_TIMEOUT_MSEC,
|
||||
priv->assoc_data->cancellable,
|
||||
assoc_get_blobs_cb,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ build_supplicant_config(NMConnection *connection,
|
|||
NMSetting8021x *s_8021x;
|
||||
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);
|
||||
g_assert(s_wifi);
|
||||
|
|
@ -120,6 +121,7 @@ build_supplicant_config(NMConnection *connection,
|
|||
mtu,
|
||||
pmf,
|
||||
fils,
|
||||
NULL,
|
||||
&error);
|
||||
} else {
|
||||
success = nm_supplicant_config_add_no_security(config, &error);
|
||||
|
|
|
|||
3
src/core/tests/config/global-dns-empty.conf
Normal file
3
src/core/tests/config/global-dns-empty.conf
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Good configuration, an empty global-dns section must be valid
|
||||
|
||||
[global-dns]
|
||||
5
src/core/tests/config/global-dns-not-set.conf
Normal file
5
src/core/tests/config/global-dns-not-set.conf
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Good configuration, an empty [global-dns] must be implicitly assumed because a domain is defined
|
||||
|
||||
[global-dns-domain-*]
|
||||
servers=4.5.6.7
|
||||
options=myoption1
|
||||
|
|
@ -387,7 +387,27 @@ test_config_global_dns(void)
|
|||
g_assert(dns);
|
||||
g_object_unref(config);
|
||||
|
||||
/* Check that a file with a domain domain, but without a default one gives a NULL configuration */
|
||||
/* Check that a file with an empty global-dns section gives a good configuration.
|
||||
* Check also that searches and options are not NULL, as this is how we expose to
|
||||
* D-Bus that global-dns is defined. */
|
||||
config =
|
||||
setup_config(NULL, TEST_DIR "/global-dns-empty.conf", "", NULL, "/no/such/dir", "", NULL);
|
||||
dns = nm_config_data_get_global_dns_config(nm_config_get_data_orig(config));
|
||||
g_assert(dns);
|
||||
g_assert(nm_global_dns_config_get_searches(dns));
|
||||
g_assert(nm_global_dns_config_get_options(dns));
|
||||
g_object_unref(config);
|
||||
|
||||
/* Check that a file with a domain, but no global-dns, assumes an implicit empty global-dns */
|
||||
config =
|
||||
setup_config(NULL, TEST_DIR "/global-dns-not-set.conf", "", NULL, "/no/such/dir", "", NULL);
|
||||
dns = nm_config_data_get_global_dns_config(nm_config_get_data_orig(config));
|
||||
g_assert(dns);
|
||||
g_assert(nm_global_dns_config_get_searches(dns));
|
||||
g_assert(nm_global_dns_config_get_options(dns));
|
||||
g_object_unref(config);
|
||||
|
||||
/* Check that a file with a domain, but without a default one, gives a NULL configuration */
|
||||
config =
|
||||
setup_config(NULL, TEST_DIR "/global-dns-invalid.conf", "", NULL, "/no/such/dir", "", NULL);
|
||||
dns = nm_config_data_get_global_dns_config(nm_config_get_data_orig(config));
|
||||
|
|
|
|||
|
|
@ -2076,3 +2076,16 @@ global:
|
|||
nm_setting_sriov_get_preserve_on_down;
|
||||
nm_sriov_preserve_on_down_get_type;
|
||||
} libnm_1_52_0;
|
||||
|
||||
libnm_1_54_2 {
|
||||
global:
|
||||
nm_setting_hsr_get_interlink;
|
||||
nm_setting_hsr_get_protocol_version;
|
||||
nm_setting_hsr_protocol_version_get_type;
|
||||
} libnm_1_54_0;
|
||||
|
||||
libnm_1_54_3 {
|
||||
global:
|
||||
nm_utils_copy_cert_as_user;
|
||||
nm_vpn_plugin_info_supports_safe_private_file_access;
|
||||
} libnm_1_54_2;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ test_units = [
|
|||
'test-nm-client',
|
||||
'test-remote-settings-client',
|
||||
'test-secret-agent',
|
||||
'test-copy-cert-as-user'
|
||||
]
|
||||
|
||||
foreach test_unit: test_units
|
||||
|
|
@ -37,12 +38,15 @@ foreach test_unit: test_units
|
|||
],
|
||||
)
|
||||
|
||||
test(
|
||||
'src/libnm-client-impl/tests/' + test_unit,
|
||||
test_script,
|
||||
timeout: 90,
|
||||
args: test_args + [exe.full_path()],
|
||||
)
|
||||
# test-copy-cert-as-user is a manual test, don't run it automatically
|
||||
if test_unit != 'test-copy-cert-as-user'
|
||||
test(
|
||||
'src/libnm-client-impl/tests/' + test_unit,
|
||||
test_script,
|
||||
timeout: 90,
|
||||
args: test_args + [exe.full_path()],
|
||||
)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
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.
|
||||
c_syms["nm_ethtool_optname_is_feature"] = "1.20"
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -1432,13 +1432,13 @@ test_client_wait_shutdown(void)
|
|||
nmtst_assert_success(dbus_connection, error);
|
||||
|
||||
for (i_run = 0; i_run < N_RUN; i_run++) {
|
||||
gs_unref_object GCancellable *init_cancellable = g_cancellable_new();
|
||||
gs_unref_object NMClient *nmc = NULL;
|
||||
nm_auto_pop_gmaincontext GMainContext *client_context = NULL;
|
||||
gboolean b;
|
||||
gboolean context_integrated = FALSE;
|
||||
gs_unref_object GCancellable *cancellable_1 = NULL;
|
||||
GMainContext *ctx;
|
||||
gs_unref_object GCancellable *init_cancellable = g_cancellable_new();
|
||||
gs_unref_object NMClient *nmc = NULL;
|
||||
nm_auto_pop_and_unref_gmaincontext GMainContext *client_context = NULL;
|
||||
gboolean b;
|
||||
gboolean context_integrated = FALSE;
|
||||
gs_unref_object GCancellable *cancellable_1 = NULL;
|
||||
GMainContext *ctx;
|
||||
|
||||
/* Choose a random context for the client. */
|
||||
ctx = contexts->pdata[nmtst_get_rand_uint32() % contexts->len];
|
||||
|
|
|
|||
|
|
@ -1516,6 +1516,10 @@
|
|||
<setting name="hsr"
|
||||
gtype="NMSettingHsr"
|
||||
>
|
||||
<property name="interlink"
|
||||
dbus-type="s"
|
||||
gprop-type="gchararray"
|
||||
/>
|
||||
<property name="multicast-spec"
|
||||
dbus-type="u"
|
||||
gprop-type="guint"
|
||||
|
|
@ -1528,6 +1532,10 @@
|
|||
dbus-type="s"
|
||||
gprop-type="gchararray"
|
||||
/>
|
||||
<property name="protocol-version"
|
||||
dbus-type="i"
|
||||
gprop-type="gint"
|
||||
/>
|
||||
<property name="prp"
|
||||
dbus-type="b"
|
||||
gprop-type="gboolean"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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->finalize = finalize;
|
||||
|
||||
setting_class->verify = verify;
|
||||
setting_class->need_secrets = need_secrets;
|
||||
setting_class->verify = verify;
|
||||
setting_class->need_secrets = need_secrets;
|
||||
setting_class->get_private_files = get_private_files;
|
||||
|
||||
/**
|
||||
* NMSetting8021x:eap:
|
||||
|
|
@ -3359,7 +3440,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
|||
obj_properties,
|
||||
NM_SETTING_802_1X_CA_CERT,
|
||||
PROP_CA_CERT,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||
NMSetting8021xPrivate,
|
||||
ca_cert);
|
||||
|
||||
|
|
@ -3556,7 +3637,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
|||
obj_properties,
|
||||
NM_SETTING_802_1X_CLIENT_CERT,
|
||||
PROP_CLIENT_CERT,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||
NMSetting8021xPrivate,
|
||||
client_cert);
|
||||
|
||||
|
|
@ -3803,7 +3884,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
|||
obj_properties,
|
||||
NM_SETTING_802_1X_PHASE2_CA_CERT,
|
||||
PROP_PHASE2_CA_CERT,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||
NMSetting8021xPrivate,
|
||||
phase2_ca_cert);
|
||||
|
||||
|
|
@ -4006,7 +4087,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
|||
obj_properties,
|
||||
NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
|
||||
PROP_PHASE2_CLIENT_CERT,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||
NMSetting8021xPrivate,
|
||||
phase2_client_cert);
|
||||
|
||||
|
|
@ -4175,7 +4256,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
|||
obj_properties,
|
||||
NM_SETTING_802_1X_PRIVATE_KEY,
|
||||
PROP_PRIVATE_KEY,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||
NMSetting8021xPrivate,
|
||||
private_key);
|
||||
|
||||
|
|
@ -4276,7 +4357,7 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass)
|
|||
obj_properties,
|
||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
|
||||
PROP_PHASE2_PRIVATE_KEY,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NM_SETTING_PARAM_CERT_KEY_FILE,
|
||||
NMSetting8021xPrivate,
|
||||
phase2_private_key);
|
||||
|
||||
|
|
|
|||
|
|
@ -431,6 +431,47 @@ nm_setting_connection_permissions_user_allowed_by_uid(NMSettingConnection *setti
|
|||
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:
|
||||
* @setting: the #NMSettingConnection
|
||||
|
|
|
|||
|
|
@ -23,12 +23,20 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMSettingHsr, PROP_PORT1, PROP_PORT2, PROP_MULTICAST_SPEC, PROP_PRP, );
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMSettingHsr,
|
||||
PROP_PORT1,
|
||||
PROP_PORT2,
|
||||
PROP_MULTICAST_SPEC,
|
||||
PROP_PRP,
|
||||
PROP_PROTOCOL_VERSION,
|
||||
PROP_INTERLINK, );
|
||||
|
||||
typedef struct {
|
||||
char *port1;
|
||||
char *port2;
|
||||
char *interlink;
|
||||
guint32 multicast_spec;
|
||||
int protocol_version;
|
||||
bool prp;
|
||||
} NMSettingHsrPrivate;
|
||||
|
||||
|
|
@ -117,6 +125,38 @@ nm_setting_hsr_get_prp(NMSettingHsr *setting)
|
|||
return NM_SETTING_HSR_GET_PRIVATE(setting)->prp;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_hsr_get_protocol_version:
|
||||
* @setting: the #NMSettingHsr
|
||||
*
|
||||
* Returns: the #NMSettingHsr:protocol-version property of the setting
|
||||
*
|
||||
* Since: 1.56, 1.54.2
|
||||
**/
|
||||
NMSettingHsrProtocolVersion
|
||||
nm_setting_hsr_get_protocol_version(NMSettingHsr *setting)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_SETTING_HSR(setting), NM_SETTING_HSR_PROTOCOL_VERSION_DEFAULT);
|
||||
|
||||
return NM_SETTING_HSR_GET_PRIVATE(setting)->protocol_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_hsr_get_interlink:
|
||||
* @setting: the #NMSettingHsr
|
||||
*
|
||||
* Returns: the #NMSettingHsr:interlink property of the setting
|
||||
*
|
||||
* Since: 1.56, 1.54.2
|
||||
**/
|
||||
const char *
|
||||
nm_setting_hsr_get_interlink(NMSettingHsr *setting)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_SETTING_HSR(setting), NULL);
|
||||
|
||||
return NM_SETTING_HSR_GET_PRIVATE(setting)->interlink;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
|
|
@ -160,6 +200,18 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (priv->prp && priv->protocol_version != NM_SETTING_HSR_PROTOCOL_VERSION_DEFAULT) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("HSR protocol cannot be configured for PRP interfaces"));
|
||||
g_prefix_error(error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_HSR_SETTING_NAME,
|
||||
NM_SETTING_HSR_PROTOCOL_VERSION);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -260,6 +312,42 @@ nm_setting_hsr_class_init(NMSettingHsrClass *klass)
|
|||
NMSettingHsr,
|
||||
_priv.prp);
|
||||
|
||||
/**
|
||||
* NMSettingHsr:protocol-version:
|
||||
*
|
||||
* Configures the protocol version to be used for the HSR/PRP interface.
|
||||
* %NM_SETTING_HSR_PROTOCOL_VERSION_DEFAULT sets the protocol version to the default version for the protocol.
|
||||
* %NM_SETTING_HSR_PROTOCOL_VERSION_HSR_2010 sets the protocol version to HSRv0 (IEC 62439-3:2010).
|
||||
* %NM_SETTING_HSR_PROTOCOL_VERSION_HSR_2012 sets the protocol version to HSRv1 (IEC 62439-3:2012).
|
||||
*
|
||||
* Since: 1.56, 1.54.2
|
||||
**/
|
||||
_nm_setting_property_define_direct_enum(properties_override,
|
||||
obj_properties,
|
||||
NM_SETTING_HSR_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_VERSION,
|
||||
NM_TYPE_SETTING_HSR_PROTOCOL_VERSION,
|
||||
NM_SETTING_HSR_PROTOCOL_VERSION_DEFAULT,
|
||||
NM_SETTING_PARAM_NONE,
|
||||
NULL,
|
||||
NMSettingHsr,
|
||||
_priv.protocol_version);
|
||||
|
||||
/**
|
||||
* NMSettingHsr:interlink:
|
||||
*
|
||||
* The optional interlink port name of the HSR interface.
|
||||
*
|
||||
* Since: 1.56, 1.54.2
|
||||
**/
|
||||
_nm_setting_property_define_direct_string(properties_override,
|
||||
obj_properties,
|
||||
NM_SETTING_HSR_INTERLINK,
|
||||
PROP_INTERLINK,
|
||||
NM_SETTING_PARAM_INFERRABLE,
|
||||
NMSettingHsr,
|
||||
_priv.interlink);
|
||||
|
||||
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
|
||||
_nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_HSR, NULL, properties_override, 0);
|
||||
|
|
|
|||
|
|
@ -154,6 +154,11 @@ struct _NMSettingClass {
|
|||
guint /* NMSettingParseFlags */ parse_flags,
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
@ -334,6 +339,11 @@ struct _NMRange {
|
|||
*/
|
||||
#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_deprecated_interface_name;
|
||||
extern const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_ignore_i;
|
||||
|
|
@ -859,9 +869,10 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
|
|||
{ \
|
||||
GParamSpec *_param_spec; \
|
||||
\
|
||||
G_STATIC_ASSERT(!NM_FLAGS_ANY((param_flags), \
|
||||
~(NM_SETTING_PARAM_SECRET | NM_SETTING_PARAM_INFERRABLE \
|
||||
| NM_SETTING_PARAM_FUZZY_IGNORE))); \
|
||||
G_STATIC_ASSERT( \
|
||||
!NM_FLAGS_ANY((param_flags), \
|
||||
~(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 "", \
|
||||
"", \
|
||||
|
|
|
|||
|
|
@ -1477,6 +1477,7 @@ peers_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
|
|||
for (i_peer = 0; i_peer < n_peers; i_peer++) {
|
||||
const NMWireGuardPeer *peer = _peers_get(priv, i_peer)->peer;
|
||||
GVariantBuilder builder;
|
||||
gboolean has_secrets = FALSE;
|
||||
|
||||
if (!peer->public_key)
|
||||
continue;
|
||||
|
|
@ -1496,11 +1497,13 @@ peers_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
|
|||
g_variant_new_string(nm_sock_addr_endpoint_get_endpoint(peer->endpoint)));
|
||||
|
||||
if (_nm_connection_serialize_secrets(flags, peer->preshared_key_flags)
|
||||
&& peer->preshared_key)
|
||||
&& peer->preshared_key) {
|
||||
g_variant_builder_add(&builder,
|
||||
"{sv}",
|
||||
NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY,
|
||||
g_variant_new_string(peer->preshared_key));
|
||||
has_secrets = TRUE;
|
||||
}
|
||||
|
||||
if (_nm_connection_serialize_non_secret(flags)
|
||||
&& peer->preshared_key_flags != NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
|
||||
|
|
@ -1546,6 +1549,20 @@ peers_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
|
|||
g_variant_new_strv(strv, peer->allowed_ips->len));
|
||||
}
|
||||
|
||||
if (NM_FLAGS_ANY(flags,
|
||||
NM_CONNECTION_SERIALIZE_ONLY_SECRETS
|
||||
| NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED
|
||||
| NM_CONNECTION_SERIALIZE_WITH_SECRETS_SYSTEM_OWNED
|
||||
| NM_CONNECTION_SERIALIZE_WITH_SECRETS_NOT_SAVED)
|
||||
&& !_nm_connection_serialize_non_secret(flags)) {
|
||||
/* The flags indicate that only secrets must be serialized and this
|
||||
* peer doesn't contain any. Skip the peer. */
|
||||
if (!has_secrets) {
|
||||
g_variant_builder_clear(&builder);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_peers) {
|
||||
g_variant_builder_init(&peers_builder, G_VARIANT_TYPE("aa{sv}"));
|
||||
any_peers = TRUE;
|
||||
|
|
|
|||
|
|
@ -2262,6 +2262,34 @@ init_from_dbus(NMSetting *setting,
|
|||
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:
|
||||
* @setting: an #NMSetting
|
||||
|
|
@ -4672,6 +4700,7 @@ nm_setting_class_init(NMSettingClass *setting_class)
|
|||
setting_class->enumerate_values = enumerate_values;
|
||||
setting_class->aggregate = aggregate;
|
||||
setting_class->init_from_dbus = init_from_dbus;
|
||||
setting_class->get_private_files = get_private_files;
|
||||
|
||||
/**
|
||||
* NMSetting:name:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pkt_sched.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-json-aux.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++)
|
||||
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.54.3
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.54.3
|
||||
*/
|
||||
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:
|
||||
* @self: plugin info instance
|
||||
|
|
|
|||
|
|
@ -5522,6 +5522,223 @@ test_bond_meta(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
check_wg_setting_str(NMSetting *s_wg,
|
||||
const char *exp_all,
|
||||
const char *exp_nonsec,
|
||||
const char *exp_sec)
|
||||
{
|
||||
gs_unref_variant GVariant *dict_all = NULL;
|
||||
gs_unref_variant GVariant *dict_nonsec = NULL;
|
||||
gs_unref_variant GVariant *dict_sec = NULL;
|
||||
gs_free char *str_all = NULL;
|
||||
gs_free char *str_nonsec = NULL;
|
||||
gs_free char *str_sec = NULL;
|
||||
|
||||
dict_all = _nm_setting_to_dbus(s_wg, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
||||
dict_nonsec = _nm_setting_to_dbus(s_wg, NULL, NM_CONNECTION_SERIALIZE_WITH_NON_SECRET, NULL);
|
||||
dict_sec = _nm_setting_to_dbus(s_wg, NULL, NM_CONNECTION_SERIALIZE_ONLY_SECRETS, NULL);
|
||||
|
||||
str_all = g_variant_print(dict_all, TRUE);
|
||||
str_nonsec = g_variant_print(dict_nonsec, TRUE);
|
||||
str_sec = g_variant_print(dict_sec, TRUE);
|
||||
|
||||
g_assert_cmpstr(exp_all, ==, str_all);
|
||||
g_assert_cmpstr(exp_nonsec, ==, str_nonsec);
|
||||
g_assert_cmpstr(exp_sec, ==, str_sec);
|
||||
}
|
||||
|
||||
static void
|
||||
test_wireguard_to_dbus(void)
|
||||
{
|
||||
gs_unref_object NMSetting *s_wg = NULL;
|
||||
nm_auto_unref_wgpeer NMWireGuardPeer *peer1 = NULL;
|
||||
nm_auto_unref_wgpeer NMWireGuardPeer *peer2 = NULL;
|
||||
gs_unref_variant GVariant *dict_all = NULL;
|
||||
gs_unref_variant GVariant *dict_non_secret = NULL;
|
||||
gs_unref_variant GVariant *dict_only_secrets = NULL;
|
||||
gs_free char *dict_str = NULL;
|
||||
const char *test_private_key = "cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM=";
|
||||
const char *test_public_key1 = "OMhgSum5+NamArI/LTp1mCZQD+CbzZxtOuvDC/RaGWU=";
|
||||
const char *test_public_key2 = "2S7mA0vEMethVGG0qBm4T5EXbcQ2WYHOuP14Seb7jEM=";
|
||||
const char *test_preshared_key = "yFGq76ej4lNI0pLLu36L0DgJMxWs4HmH5qNDNOt8AmM=";
|
||||
|
||||
/* Test case 1: Minimal WireGuard setting without peers or private key */
|
||||
s_wg = nm_setting_wireguard_new();
|
||||
g_object_set(s_wg,
|
||||
NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
51820U,
|
||||
NM_SETTING_WIREGUARD_FWMARK,
|
||||
42U,
|
||||
NULL);
|
||||
|
||||
check_wg_setting_str(s_wg,
|
||||
/* clang-format off */
|
||||
/* all */
|
||||
"{'fwmark': <uint32 42>, 'listen-port': <uint32 51820>}",
|
||||
/* non secrets */
|
||||
"{'fwmark': <uint32 42>, 'listen-port': <uint32 51820>}",
|
||||
/* secrets */
|
||||
"@a{sv} {}"
|
||||
/* clang-format on */
|
||||
);
|
||||
g_clear_object(&s_wg);
|
||||
|
||||
/* Test case 2: WireGuard setting with private key, no peers */
|
||||
s_wg = nm_setting_wireguard_new();
|
||||
g_object_set(s_wg,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY,
|
||||
test_private_key,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS,
|
||||
NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
51820U,
|
||||
NM_SETTING_WIREGUARD_FWMARK,
|
||||
42U,
|
||||
NULL);
|
||||
|
||||
check_wg_setting_str(s_wg,
|
||||
/* clang-format off */
|
||||
/* all */
|
||||
"{"
|
||||
"'fwmark': <uint32 42>, "
|
||||
"'listen-port': <uint32 51820>, "
|
||||
"'private-key': <'cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM='>"
|
||||
"}",
|
||||
/* non secrets */
|
||||
"{"
|
||||
"'fwmark': <uint32 42>, "
|
||||
"'listen-port': <uint32 51820>"
|
||||
"}",
|
||||
/* secrets */
|
||||
"{"
|
||||
"'private-key': <'cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM='>"
|
||||
"}"
|
||||
/* clang-format on */
|
||||
);
|
||||
g_clear_object(&s_wg);
|
||||
|
||||
/* Test case 3: WireGuard setting with peers (no PSK) */
|
||||
s_wg = nm_setting_wireguard_new();
|
||||
g_object_set(s_wg,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY,
|
||||
test_private_key,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS,
|
||||
NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
51820U,
|
||||
NULL);
|
||||
peer1 = nm_wireguard_peer_new();
|
||||
nm_wireguard_peer_set_public_key(peer1, test_public_key1, FALSE);
|
||||
nm_wireguard_peer_set_endpoint(peer1, "192.168.1.1:51820", FALSE);
|
||||
nm_wireguard_peer_append_allowed_ip(peer1, "10.0.0.0/8", FALSE);
|
||||
nm_setting_wireguard_append_peer(NM_SETTING_WIREGUARD(s_wg), peer1);
|
||||
|
||||
check_wg_setting_str(s_wg,
|
||||
/* clang-format off */
|
||||
/* all */
|
||||
"{"
|
||||
"'listen-port': <uint32 51820>, "
|
||||
"'peers': <[{"
|
||||
"'public-key': <'OMhgSum5+NamArI/LTp1mCZQD+CbzZxtOuvDC/RaGWU='>, "
|
||||
"'endpoint': <'192.168.1.1:51820'>, "
|
||||
"'allowed-ips': <['10.0.0.0/8']>"
|
||||
"}]>, "
|
||||
"'private-key': <'cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM='>"
|
||||
"}",
|
||||
/* non secrets */
|
||||
"{"
|
||||
"'listen-port': <uint32 51820>, "
|
||||
"'peers': <[{"
|
||||
"'public-key': <'OMhgSum5+NamArI/LTp1mCZQD+CbzZxtOuvDC/RaGWU='>, "
|
||||
"'endpoint': <'192.168.1.1:51820'>, "
|
||||
"'allowed-ips': <['10.0.0.0/8']>"
|
||||
"}]>"
|
||||
"}",
|
||||
/* secrets */
|
||||
"{"
|
||||
"'private-key': <'cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM='>"
|
||||
"}"
|
||||
/* clang-format on */
|
||||
);
|
||||
g_clear_object(&s_wg);
|
||||
nm_clear_pointer(&peer1, nm_wireguard_peer_unref);
|
||||
|
||||
/* Test case 4: WireGuard setting with peers, one has PSK */
|
||||
s_wg = nm_setting_wireguard_new();
|
||||
g_object_set(s_wg,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY,
|
||||
test_private_key,
|
||||
NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS,
|
||||
NM_SETTING_SECRET_FLAG_NONE,
|
||||
NM_SETTING_WIREGUARD_LISTEN_PORT,
|
||||
51820U,
|
||||
NULL);
|
||||
|
||||
/* Peer without PSK */
|
||||
peer1 = nm_wireguard_peer_new();
|
||||
nm_wireguard_peer_set_public_key(peer1, test_public_key1, FALSE);
|
||||
nm_wireguard_peer_set_endpoint(peer1, "192.168.1.1:51820", FALSE);
|
||||
nm_wireguard_peer_append_allowed_ip(peer1, "10.0.0.0/8", FALSE);
|
||||
nm_setting_wireguard_append_peer(NM_SETTING_WIREGUARD(s_wg), peer1);
|
||||
|
||||
/* Peer with PSK */
|
||||
peer2 = nm_wireguard_peer_new();
|
||||
nm_wireguard_peer_set_public_key(peer2, test_public_key2, FALSE);
|
||||
nm_wireguard_peer_set_endpoint(peer2, "192.168.2.1:51820", FALSE);
|
||||
nm_wireguard_peer_append_allowed_ip(peer2, "172.16.0.0/12", FALSE);
|
||||
nm_wireguard_peer_set_preshared_key(peer2, test_preshared_key, FALSE);
|
||||
nm_wireguard_peer_set_preshared_key_flags(peer2, NM_SETTING_SECRET_FLAG_NONE);
|
||||
nm_setting_wireguard_append_peer(NM_SETTING_WIREGUARD(s_wg), peer2);
|
||||
|
||||
check_wg_setting_str(s_wg,
|
||||
/* clang-format off */
|
||||
/* all */
|
||||
"{"
|
||||
"'listen-port': <uint32 51820>, "
|
||||
"'peers': <[{"
|
||||
"'public-key': <'OMhgSum5+NamArI/LTp1mCZQD+CbzZxtOuvDC/RaGWU='>, "
|
||||
"'endpoint': <'192.168.1.1:51820'>, "
|
||||
"'allowed-ips': <['10.0.0.0/8']>"
|
||||
"}, {"
|
||||
"'public-key': <'2S7mA0vEMethVGG0qBm4T5EXbcQ2WYHOuP14Seb7jEM='>, "
|
||||
"'endpoint': <'192.168.2.1:51820'>, "
|
||||
"'preshared-key': <'yFGq76ej4lNI0pLLu36L0DgJMxWs4HmH5qNDNOt8AmM='>, "
|
||||
"'preshared-key-flags': <uint32 0>, "
|
||||
"'allowed-ips': <['172.16.0.0/12']>"
|
||||
"}]>, "
|
||||
"'private-key': <'cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM='>"
|
||||
"}",
|
||||
/* non secrets */
|
||||
"{"
|
||||
"'listen-port': <uint32 51820>, "
|
||||
"'peers': <[{"
|
||||
"'public-key': <'OMhgSum5+NamArI/LTp1mCZQD+CbzZxtOuvDC/RaGWU='>, "
|
||||
"'endpoint': <'192.168.1.1:51820'>, "
|
||||
"'allowed-ips': <['10.0.0.0/8']>"
|
||||
"}, {"
|
||||
"'public-key': <'2S7mA0vEMethVGG0qBm4T5EXbcQ2WYHOuP14Seb7jEM='>, "
|
||||
"'endpoint': <'192.168.2.1:51820'>, "
|
||||
"'preshared-key-flags': <uint32 0>, "
|
||||
"'allowed-ips': <['172.16.0.0/12']>"
|
||||
"}]>"
|
||||
"}",
|
||||
/* secrets */
|
||||
"{"
|
||||
"'peers': <[{"
|
||||
"'public-key': <'2S7mA0vEMethVGG0qBm4T5EXbcQ2WYHOuP14Seb7jEM='>, "
|
||||
"'preshared-key': <'yFGq76ej4lNI0pLLu36L0DgJMxWs4HmH5qNDNOt8AmM='>"
|
||||
"}]>, "
|
||||
"'private-key': <'cFoJbK9bSrYrQrjFQGgqsWTO4IUIX0+rsaqNeCw2IWM='>}"
|
||||
/* clang-format on */
|
||||
);
|
||||
g_clear_object(&s_wg);
|
||||
nm_clear_pointer(&peer1, nm_wireguard_peer_unref);
|
||||
nm_clear_pointer(&peer2, nm_wireguard_peer_unref);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
|
|
@ -5649,5 +5866,7 @@ main(int argc, char **argv)
|
|||
|
||||
g_test_add_func("/libnm/test_bond_meta", test_bond_meta);
|
||||
|
||||
g_test_add_func("/libnm/test_wireguard_to_dbus", test_wireguard_to_dbus);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1187,4 +1187,11 @@ gboolean nm_connection_need_secrets_for_rerequest(NMConnection *connection);
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -145,8 +145,10 @@ typedef enum {
|
|||
* and not disable controls that require network access.
|
||||
* The graphical shells may hide the network accessibility indicator altogether
|
||||
* since no meaningful status indication can be provided.
|
||||
* @NM_STATE_ASLEEP: Networking is not enabled, the system is being suspended or
|
||||
* resumed from suspend.
|
||||
* @NM_STATE_ASLEEP: Deprecated: 1.56: Use %NM_STATE_DISABLED instead.
|
||||
* @NM_STATE_DISABLED: NetworkManager is disabled, either because the user requested
|
||||
* to disable networking or because the system is suspended or resuming from suspend.
|
||||
* Since: 1.56.
|
||||
* @NM_STATE_DISCONNECTED: There is no active network connection.
|
||||
* The graphical shell should indicate no network connectivity and the
|
||||
* applications should not attempt to access the network.
|
||||
|
|
@ -170,7 +172,8 @@ typedef enum {
|
|||
**/
|
||||
typedef enum {
|
||||
NM_STATE_UNKNOWN = 0,
|
||||
NM_STATE_ASLEEP = 10,
|
||||
NM_STATE_ASLEEP = 10, /* Deprecated */
|
||||
NM_STATE_DISABLED = 10,
|
||||
NM_STATE_DISCONNECTED = 20,
|
||||
NM_STATE_DISCONNECTING = 30,
|
||||
NM_STATE_CONNECTING = 40,
|
||||
|
|
@ -632,8 +635,10 @@ typedef enum {
|
|||
* not initialized by udev. Since: 1.48
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING: The device is unmanaged because NetworkManager is
|
||||
* quitting. Since: 1.48
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING: The device is unmanaged because networking is
|
||||
* disabled or the system is suspended. Since: 1.48
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING: Since: 1.48. Deprecated: 1.56: Use
|
||||
* %NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED instead.
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED: The device is unmanaged because networking is
|
||||
* disabled or the system is suspended. Since: 1.56
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_USER_CONF: The device is unmanaged by user decision in
|
||||
* NetworkManager.conf ('unmanaged' in a [device*] section). Since: 1.48
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_USER_EXPLICIT: The device is unmanaged by explicit user
|
||||
|
|
@ -642,7 +647,7 @@ typedef enum {
|
|||
* via settings plugin ('unmanaged-devices' for keyfile or 'NM_CONTROLLED=no' for ifcfg-rh).
|
||||
* Since: 1.48
|
||||
* @NM_DEVICE_STATE_REASON_UNMANAGED_USER_UDEV: The device is unmanaged via udev rule. Since: 1.48
|
||||
|
||||
* @NM_DEVICE_STATE_REASON_NETWORKING_OFF: NetworkManager was disabled (networking off). Since: 1.56
|
||||
*
|
||||
* Device state change reason codes
|
||||
*/
|
||||
|
|
@ -720,11 +725,13 @@ typedef enum {
|
|||
NM_DEVICE_STATE_REASON_UNMANAGED_EXTERNAL_DOWN = 70,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_LINK_NOT_INIT = 71,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING = 72,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING = 73,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING = 73, /* Deprecated */
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED = 73,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_USER_CONF = 74,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_USER_EXPLICIT = 75,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_USER_SETTINGS = 76,
|
||||
NM_DEVICE_STATE_REASON_UNMANAGED_USER_UDEV = 77,
|
||||
NM_DEVICE_STATE_REASON_NETWORKING_OFF = 78,
|
||||
} NMDeviceStateReason;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,10 +23,28 @@ G_BEGIN_DECLS
|
|||
|
||||
#define NM_SETTING_HSR_SETTING_NAME "hsr"
|
||||
|
||||
#define NM_SETTING_HSR_PORT1 "port1"
|
||||
#define NM_SETTING_HSR_PORT2 "port2"
|
||||
#define NM_SETTING_HSR_MULTICAST_SPEC "multicast-spec"
|
||||
#define NM_SETTING_HSR_PRP "prp"
|
||||
#define NM_SETTING_HSR_PORT1 "port1"
|
||||
#define NM_SETTING_HSR_PORT2 "port2"
|
||||
#define NM_SETTING_HSR_MULTICAST_SPEC "multicast-spec"
|
||||
#define NM_SETTING_HSR_PRP "prp"
|
||||
#define NM_SETTING_HSR_PROTOCOL_VERSION "protocol-version"
|
||||
#define NM_SETTING_HSR_INTERLINK "interlink"
|
||||
|
||||
/**
|
||||
* NMSettingHsrProtocolVersion:
|
||||
* @NM_SETTING_HSR_PROTOCOL_VERSION_DEFAULT: Default version for the protocol
|
||||
* @NM_SETTING_HSR_PROTOCOL_VERSION_HSR_2010: HSRv0, IEC 62439-3:2010
|
||||
* @NM_SETTING_HSR_PROTOCOL_VERSION_HSR_2012: HSRv1, IEC 62439-3:2012
|
||||
*
|
||||
* #NMSettingHsrProtocolVersion values indicate the HSR protocol version.
|
||||
*
|
||||
* Since: 1.56, 1.54.2
|
||||
*/
|
||||
typedef enum {
|
||||
NM_SETTING_HSR_PROTOCOL_VERSION_DEFAULT = -1,
|
||||
NM_SETTING_HSR_PROTOCOL_VERSION_HSR_2010 = 0,
|
||||
NM_SETTING_HSR_PROTOCOL_VERSION_HSR_2012 = 1,
|
||||
} NMSettingHsrProtocolVersion;
|
||||
|
||||
typedef struct _NMSettingHsrClass NMSettingHsrClass;
|
||||
|
||||
|
|
@ -43,6 +61,10 @@ NM_AVAILABLE_IN_1_46
|
|||
guint32 nm_setting_hsr_get_multicast_spec(NMSettingHsr *setting);
|
||||
NM_AVAILABLE_IN_1_46
|
||||
gboolean nm_setting_hsr_get_prp(NMSettingHsr *setting);
|
||||
NM_AVAILABLE_IN_1_54_2
|
||||
NMSettingHsrProtocolVersion nm_setting_hsr_get_protocol_version(NMSettingHsr *setting);
|
||||
NM_AVAILABLE_IN_1_54_2
|
||||
const char *nm_setting_hsr_get_interlink(NMSettingHsr *setting);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -261,6 +261,9 @@ nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, gui
|
|||
NM_AVAILABLE_IN_1_42
|
||||
void nm_utils_ensure_gtypes(void);
|
||||
|
||||
NM_AVAILABLE_IN_1_54_3
|
||||
char *nm_utils_copy_cert_as_user(const char *filename, const char *user, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NM_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@
|
|||
#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_54 (NM_ENCODE_VERSION(1, 54, 0))
|
||||
#define NM_VERSION_1_54_2 (NM_ENCODE_VERSION(1, 54, 2))
|
||||
#define NM_VERSION_1_54_3 (NM_ENCODE_VERSION(1, 54, 3))
|
||||
|
||||
/* For releases, NM_API_VERSION is equal to NM_VERSION.
|
||||
*
|
||||
|
|
@ -86,10 +88,10 @@
|
|||
* version, you are already using the future API, even if
|
||||
* it is not yet released. Hence, the currently used API
|
||||
* version is the future one. */
|
||||
#define NM_API_VERSION \
|
||||
(((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 , ((NM_MICRO_VERSION + 1) / 2) * 2))
|
||||
#define NM_API_VERSION \
|
||||
(((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, NM_MICRO_VERSION + 1))
|
||||
|
||||
/* deprecated. */
|
||||
#define NM_VERSION_CUR_STABLE NM_API_VERSION
|
||||
|
|
|
|||
|
|
@ -439,6 +439,18 @@
|
|||
#define NM_AVAILABLE_IN_1_54
|
||||
#endif
|
||||
|
||||
#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_54_2
|
||||
#define NM_AVAILABLE_IN_1_54_2 G_UNAVAILABLE(1, 54.2)
|
||||
#else
|
||||
#define NM_AVAILABLE_IN_1_54_2
|
||||
#endif
|
||||
|
||||
#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_54_3
|
||||
#define NM_AVAILABLE_IN_1_54_3 G_UNAVAILABLE(1, 54.3)
|
||||
#else
|
||||
#define NM_AVAILABLE_IN_1_54_3
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Synchronous API for calling D-Bus in libnm is deprecated. See
|
||||
* 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);
|
||||
NM_AVAILABLE_IN_1_42
|
||||
gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self);
|
||||
NM_AVAILABLE_IN_1_54_3
|
||||
gboolean nm_vpn_plugin_info_supports_safe_private_file_access(NMVpnPluginInfo *self);
|
||||
NM_AVAILABLE_IN_1_4
|
||||
const char *const *nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self);
|
||||
NM_AVAILABLE_IN_1_2
|
||||
|
|
|
|||
|
|
@ -253,7 +253,8 @@ G_STATIC_ASSERT(RTA_MAX == (__RTA_MAX - 1));
|
|||
#define IFLA_HSR_SEQ_NR 5
|
||||
#define IFLA_HSR_VERSION 6
|
||||
#define IFLA_HSR_PROTOCOL 7
|
||||
#define __IFLA_HSR_MAX 8
|
||||
#define IFLA_HSR_INTERLINK 8
|
||||
#define __IFLA_HSR_MAX 9
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -5196,6 +5197,15 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo
|
|||
NLA_PUT_U8(msg, IFLA_HSR_MULTICAST_SPEC, props->multicast_spec);
|
||||
|
||||
NLA_PUT_U8(msg, IFLA_HSR_PROTOCOL, props->prp);
|
||||
|
||||
if (!props->prp && props->protocol_version >= 0) {
|
||||
NLA_PUT_U8(msg, IFLA_HSR_VERSION, props->protocol_version);
|
||||
}
|
||||
|
||||
if (props->interlink > 0) {
|
||||
NLA_PUT_U32(msg, IFLA_HSR_INTERLINK, props->interlink);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NM_LINK_TYPE_SIT:
|
||||
|
|
|
|||
|
|
@ -6560,6 +6560,8 @@ nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len)
|
|||
const char *
|
||||
nm_platform_lnk_hsr_to_string(const NMPlatformLnkHsr *lnk, char *buf, gsize len)
|
||||
{
|
||||
char interlink_buf[30];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len))
|
||||
return buf;
|
||||
|
||||
|
|
@ -6569,12 +6571,17 @@ nm_platform_lnk_hsr_to_string(const NMPlatformLnkHsr *lnk, char *buf, gsize len)
|
|||
"port1 %d "
|
||||
"port2 %d "
|
||||
"supervision_address " NM_ETHER_ADDR_FORMAT_STR " multicast_spec %u "
|
||||
"prp %s",
|
||||
"prp %s "
|
||||
"protocol_version %d"
|
||||
"%s", /* interlink */
|
||||
lnk->port1,
|
||||
lnk->port2,
|
||||
NM_ETHER_ADDR_FORMAT_VAL(&lnk->supervision_address),
|
||||
lnk->multicast_spec,
|
||||
lnk->prp ? "on" : "off");
|
||||
lnk->prp ? "on" : "off",
|
||||
lnk->protocol_version,
|
||||
lnk->interlink ? nm_sprintf_buf(interlink_buf, " interlink %d", lnk->interlink)
|
||||
: "");
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
@ -8488,7 +8495,9 @@ nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h)
|
|||
obj->port2,
|
||||
obj->supervision_address,
|
||||
obj->multicast_spec,
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->prp));
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->prp),
|
||||
obj->protocol_version,
|
||||
obj->interlink);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -8500,6 +8509,8 @@ nm_platform_lnk_hsr_cmp(const NMPlatformLnkHsr *a, const NMPlatformLnkHsr *b)
|
|||
NM_CMP_FIELD_MEMCMP(a, b, supervision_address);
|
||||
NM_CMP_FIELD(a, b, multicast_spec);
|
||||
NM_CMP_FIELD_BOOL(a, b, prp);
|
||||
NM_CMP_FIELD(a, b, protocol_version);
|
||||
NM_CMP_FIELD(a, b, interlink);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -845,7 +845,9 @@ typedef struct {
|
|||
typedef struct {
|
||||
int port1;
|
||||
int port2;
|
||||
int interlink;
|
||||
NMEtherAddr supervision_address;
|
||||
gint8 protocol_version;
|
||||
guint8 multicast_spec;
|
||||
bool prp : 1;
|
||||
} _nm_alignas(NMPlatformObject) NMPlatformLnkHsr;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,14 @@
|
|||
|
||||
#include "nm-std-utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <limits.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:
|
||||
* @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);
|
||||
|
||||
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__ */
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ NM_UTILS_LOOKUP_STR_DEFINE(
|
|||
N_("The Wi-Fi P2P peer could not be found")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED,
|
||||
N_("The device handler dispatcher returned an error")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING,
|
||||
NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED,
|
||||
N_("The device is unmanaged because networking is disabled "
|
||||
"or the system is suspended")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING,
|
||||
|
|
@ -492,6 +492,7 @@ NM_UTILS_LOOKUP_STR_DEFINE(
|
|||
NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_EXTERNAL_DOWN,
|
||||
N_("The device is unmanaged because it is an external device and is "
|
||||
"unconfigured (down or without addresses)")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NETWORKING_OFF, N_("Networking was disabled")),
|
||||
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6198,6 +6198,12 @@ static const NMMetaPropertyInfo *const property_infos_HSR[] = {
|
|||
PROPERTY_INFO_WITH_DESC (NM_SETTING_HSR_PRP,
|
||||
.property_type = &_pt_gobject_bool,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_HSR_PROTOCOL_VERSION,
|
||||
.property_type = &_pt_gobject_enum,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_HSR_INTERLINK,
|
||||
.property_type = &_pt_gobject_string,
|
||||
),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ typedef enum {
|
|||
NM_META_COLOR_PERMISSION_UNKNOWN,
|
||||
NM_META_COLOR_PERMISSION_YES,
|
||||
NM_META_COLOR_PROMPT,
|
||||
NM_META_COLOR_STATE_ASLEEP,
|
||||
NM_META_COLOR_STATE_DISABLED,
|
||||
NM_META_COLOR_STATE_ASLEEP = NM_META_COLOR_STATE_DISABLED, /* Deprecated */
|
||||
NM_META_COLOR_STATE_CONNECTED_GLOBAL,
|
||||
NM_META_COLOR_STATE_CONNECTED_LOCAL,
|
||||
NM_META_COLOR_STATE_CONNECTED_SITE,
|
||||
|
|
|
|||
|
|
@ -171,9 +171,11 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_ID N_("The SIM card unique identifier (as given by the WWAN management service) which this connection applies to. If given, the connection will apply to any device also allowed by \"device-id\" which contains a SIM card matching the given identifier.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_OPERATOR_ID N_("A MCC/MNC string like \"310260\" or \"21601\" identifying the specific mobile network operator which this connection applies to. If given, the connection will apply to any device also allowed by \"device-id\" and \"sim-id\" which contains a SIM card provisioned by the given operator.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_USERNAME N_("The username used to authenticate with the network, if required. Many providers do not require a username, or accept any username. But if a username is required, it is specified here.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HSR_INTERLINK N_("The optional interlink port name of the HSR interface.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HSR_MULTICAST_SPEC N_("The last byte of supervision address.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HSR_PORT1 N_("The port1 interface name of the HSR. This property is mandatory.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HSR_PORT2 N_("The port2 interface name of the HSR. This property is mandatory.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HSR_PROTOCOL_VERSION N_("Configures the protocol version to be used for the HSR/PRP interface. \"default\" (-1) sets the protocol version to the default version for the protocol. \"hsr-2010\" (0) sets the protocol version to HSRv0 (IEC 62439-3:2010). \"hsr-2012\" (1) sets the protocol version to HSRv1 (IEC 62439-3:2012).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HSR_PRP N_("The protocol used by the interface, whether it is PRP or HSR.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MAC_ADDRESS N_("If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
|
||||
|
|
|
|||
|
|
@ -103,8 +103,7 @@ if enable_nmtui
|
|||
endif
|
||||
subdir('nmcli')
|
||||
subdir('nm-dispatcher')
|
||||
subdir('nm-priv-helper')
|
||||
subdir('nm-daemon-helper')
|
||||
subdir('nm-helpers')
|
||||
subdir('nm-online')
|
||||
if enable_nmtui
|
||||
subdir('nmtui')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
==============
|
||||
--------------
|
||||
|
||||
This is a D-Bus activatable, exit-on-idle service, which
|
||||
provides an internal API to NetworkManager daemon.
|
||||
|
|
@ -1,5 +1,45 @@
|
|||
# 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(
|
||||
input: 'org.freedesktop.nm_priv_helper.service.in',
|
||||
output: '@BASENAME@',
|
||||
|
|
@ -137,6 +137,37 @@ cmd_resolve_address(void)
|
|||
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
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -150,6 +181,8 @@ main(int argc, char **argv)
|
|||
return cmd_version();
|
||||
if (nm_streq(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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -1349,6 +1349,67 @@ reader_parse_ethtool(Reader *reader, char *argument)
|
|||
_LOGW(LOGD_CORE, "rd.ethtool: extra argument ignored");
|
||||
}
|
||||
|
||||
static void
|
||||
reader_parse_dhcp_client_id(Reader *reader, char *argument)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
const char *interface;
|
||||
gs_free char *client_id = NULL;
|
||||
gs_free guint8 *buf = NULL;
|
||||
gsize len = 0;
|
||||
|
||||
interface = get_word(&argument, ':');
|
||||
if (!interface) {
|
||||
_LOGW(LOGD_CORE, "rd.net.dhcp.client-id: missing interface");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!argument || !*argument) {
|
||||
_LOGW(LOGD_CORE, "rd.net.dhcp.client-id: missing client-id");
|
||||
return;
|
||||
}
|
||||
|
||||
if (argument[0] == '@') {
|
||||
/* The client-id is a plain string but we still encode it as
|
||||
* hex string. Otherwise, we could pass the string as-is, but we
|
||||
* would need to handle special keywords like "mac", "perm-mac", etc.
|
||||
*/
|
||||
if (argument[1] != '\0') {
|
||||
len = strlen(argument);
|
||||
buf = (guint8 *) nm_memdup(argument, len + 1);
|
||||
buf[0] = '\0';
|
||||
}
|
||||
} else {
|
||||
/* Try to parse it as hex string */
|
||||
buf = nm_utils_hexstr2bin_alloc(argument, FALSE, FALSE, "-", 0, &len);
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
client_id = nm_utils_bin2hexstr_full(buf, len, ':', FALSE, NULL);
|
||||
}
|
||||
|
||||
if (!client_id) {
|
||||
_LOGW(LOGD_CORE,
|
||||
"rd.net.dhcp.client-id: invalid client-id \"%s\". Must be hexadecimal bytes "
|
||||
"separated by dashes (for example \"00-01-02-03-04-05-06\"), or '@' followed by a "
|
||||
"string",
|
||||
argument);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
_LOGW(LOGD_CORE,
|
||||
"rd.net.dhcp.client-id: invalid client-id \"%s\". Must be at least two bytes",
|
||||
argument);
|
||||
return;
|
||||
}
|
||||
|
||||
connection = reader_get_connection(reader, interface, NULL, TRUE);
|
||||
s_ip4 = nm_connection_get_setting_ip4_config(connection);
|
||||
g_object_set(s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, client_id, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_normalize_conn(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
|
|
@ -1365,6 +1426,8 @@ _normalize_conn(gpointer key, gpointer value, gpointer user_data)
|
|||
NULL,
|
||||
NM_SETTING_IP_CONFIG_DHCP_TIMEOUT,
|
||||
NULL,
|
||||
NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,
|
||||
NULL,
|
||||
NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER,
|
||||
NULL,
|
||||
NM_SETTING_IP_CONFIG_DHCP_DSCP,
|
||||
|
|
@ -1583,6 +1646,8 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
|
|||
g_ptr_array_add(znets, g_strdup(argument));
|
||||
} else if (nm_streq(tag, "rd.znet_ifname")) {
|
||||
reader_parse_znet_ifname(reader, argument);
|
||||
} else if (nm_streq(tag, "rd.net.dhcp.client-id")) {
|
||||
reader_parse_dhcp_client_id(reader, argument);
|
||||
} else if (g_ascii_strcasecmp(tag, "BOOTIF") == 0) {
|
||||
nm_clear_g_free(&bootif_val);
|
||||
bootif_val = g_strdup(argument);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,33 @@ find_conn_for_wired_mac(GPtrArray *a, const char *hwaddr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
hfi_is_dhcp(struct nbft_info_hfi *hfi, int family)
|
||||
{
|
||||
/* There are several flags that may indicate the HFI is set for DHCP
|
||||
* per NVM Express® Boot Specification, Revision 1.3. As the HFI
|
||||
* Transport Flags (HFITFLAGS) are not publicly exposed by the libnvme
|
||||
* API, only the DHCP Override (DHCPO) flag and the IP Origin (IPORIG)
|
||||
* value is available.
|
||||
*
|
||||
* The bit 03 of the HFI Transport Flags (HFITFLAGS) is about an advanced
|
||||
* stateless mechanism - IPv6-SLAAC and IPv6-ND, stating that "the DHCP
|
||||
* Override bit shall be cleared to 0, and the IP Origin field shall
|
||||
* be cleared to 0". This nm-initrd-generator will ignore this flag,
|
||||
* expecting an IP address to be provided by the usual HFI fields
|
||||
* just like in a static adressing case.
|
||||
*
|
||||
* DHCP Override (DHCPO): "The HFI information was populated by
|
||||
* consuming the DHCP on this interface."
|
||||
*
|
||||
* IP Origin (IPORIG): "If set to 3h (IpPrefixOriginDhcp), then the
|
||||
* IP Address was acquired through DHCP, and the IP Address specified
|
||||
* in this HFI should not be reused by the OS."
|
||||
*/
|
||||
return hfi->tcp_info.dhcp_override || hfi->tcp_info.ip_origin == 3 /* IpPrefixOriginDhcp */
|
||||
|| is_valid_addr(family, hfi->tcp_info.dhcp_server_ipaddr);
|
||||
}
|
||||
|
||||
static NMConnection *
|
||||
create_wired_conn(struct nbft_info_hfi *hfi,
|
||||
const char *conn_name,
|
||||
|
|
@ -183,6 +210,7 @@ parse_hfi(GPtrArray *a, struct nbft_info_hfi *hfi, const char *table_name, char
|
|||
return;
|
||||
}
|
||||
g_ptr_array_add(a, parent_connection);
|
||||
nm_clear_g_free(&conn_name);
|
||||
}
|
||||
|
||||
conn_name = format_conn_name(table_name, hfi, TRUE);
|
||||
|
|
@ -208,7 +236,7 @@ parse_hfi(GPtrArray *a, struct nbft_info_hfi *hfi, const char *table_name, char
|
|||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
if (is_valid_addr(AF_INET, hfi->tcp_info.dhcp_server_ipaddr)) {
|
||||
if (hfi_is_dhcp(hfi, family)) {
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
||||
|
|
@ -260,7 +288,7 @@ parse_hfi(GPtrArray *a, struct nbft_info_hfi *hfi, const char *table_name, char
|
|||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
if (is_valid_addr(AF_INET6, hfi->tcp_info.dhcp_server_ipaddr)) {
|
||||
if (hfi_is_dhcp(hfi, family)) {
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ test_units = [
|
|||
'test-cmdline-reader',
|
||||
]
|
||||
|
||||
if enable_nbft
|
||||
test_units += [ 'test-nbft-reader' ]
|
||||
endif
|
||||
|
||||
foreach test_unit : test_units
|
||||
exe = executable(
|
||||
test_unit,
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -2786,6 +2786,149 @@ test_plain_equal_char(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _dhcp_client_id_check_invalid(arg) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
gs_unref_hashtable GHashTable *_connections2 = NULL; \
|
||||
\
|
||||
_connections2 = _parse_cons(NM_MAKE_STRV(arg)); \
|
||||
g_test_assert_expected_messages(); \
|
||||
g_assert_cmpint(g_hash_table_size(_connections2), ==, 0); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define _dhcp_client_id_check_v(strv, exp_ifname, exp_client_id) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
gs_unref_object NMConnection *_connection = NULL; \
|
||||
NMSettingIPConfig *_s_ip4; \
|
||||
\
|
||||
_connection = _parse_con(strv, exp_ifname); \
|
||||
\
|
||||
g_test_assert_expected_messages(); \
|
||||
\
|
||||
g_assert(nm_connection_get_setting_connection(_connection)); \
|
||||
g_assert(nm_connection_is_type(_connection, NM_SETTING_WIRED_SETTING_NAME)); \
|
||||
g_assert(nm_connection_get_setting_ip4_config(_connection)); \
|
||||
g_assert(nm_connection_get_setting_ip6_config(_connection)); \
|
||||
_s_ip4 = nm_connection_get_setting_ip4_config(_connection); \
|
||||
g_assert(NM_IS_SETTING_IP_CONFIG(_s_ip4)); \
|
||||
\
|
||||
g_assert_cmpstr(nm_setting_ip4_config_get_dhcp_client_id(NM_SETTING_IP4_CONFIG(_s_ip4)), \
|
||||
==, \
|
||||
(exp_client_id)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define _dhcp_client_id_check(arg, exp_ifname, exp_client_id) \
|
||||
_dhcp_client_id_check_v(NM_MAKE_STRV("" arg ""), (exp_ifname), (exp_client_id))
|
||||
|
||||
#define DHCP_CLIENT_ID_INVALID_MSG(_id) \
|
||||
"cmdline-reader: " \
|
||||
"rd.net.dhcp.client-id: invalid client-id \"" _id "\". Must be hexadecimal bytes " \
|
||||
"separated by dashes (for example \"00-01-02-03-04-05-06\"), or '@' followed by a string"
|
||||
|
||||
static void
|
||||
test_rd_dhcp_client_id(void)
|
||||
{
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dhcp.client-id: missing interface");
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=");
|
||||
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dhcp.client-id: missing interface");
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=:");
|
||||
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dhcp.client-id: missing client-id");
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=eth0:");
|
||||
|
||||
NMTST_EXPECT_NM_WARN(DHCP_CLIENT_ID_INVALID_MSG("invalid"));
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=eth0:invalid");
|
||||
|
||||
NMTST_EXPECT_NM_WARN(DHCP_CLIENT_ID_INVALID_MSG("01:AA:BB:CC:DD:EE:FF"));
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=eth0:01:AA:BB:CC:DD:EE:FF");
|
||||
|
||||
NMTST_EXPECT_NM_WARN(DHCP_CLIENT_ID_INVALID_MSG("@"));
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=eth0:@");
|
||||
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dhcp.client-id: invalid client-id \"01\". Must be "
|
||||
"at least two bytes");
|
||||
_dhcp_client_id_check_invalid("rd.net.dhcp.client-id=eth0:01");
|
||||
|
||||
/* Client-id with hex string */
|
||||
_dhcp_client_id_check("rd.net.dhcp.client-id=eth0:01-aa-BB-cc-dd-EE-ff",
|
||||
"eth0",
|
||||
"01:aa:bb:cc:dd:ee:ff");
|
||||
|
||||
/* Client-id with plain string */
|
||||
_dhcp_client_id_check("rd.net.dhcp.client-id=eth0:@test.com",
|
||||
"eth0",
|
||||
"00:74:65:73:74:2e:63:6f:6d");
|
||||
|
||||
/* Minimal client-id, hex */
|
||||
_dhcp_client_id_check("rd.net.dhcp.client-id=eth1:01-02", "eth1", "01:02");
|
||||
|
||||
/* Minimal client-id, string */
|
||||
_dhcp_client_id_check("rd.net.dhcp.client-id=eth1:@1", "eth1", "00:31");
|
||||
|
||||
/* Long client-id */
|
||||
_dhcp_client_id_check(
|
||||
"rd.net.dhcp.client-id=enp1s0:"
|
||||
"01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-"
|
||||
"25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40-41-42-43-44-45-46-47-48-"
|
||||
"49-50-51-52-53-54-55-56-57-58-59-60-61-62-63-64-65-66-67-68-69-70-71-72",
|
||||
"enp1s0",
|
||||
"01:02:03:04:05:06:07:08:09:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:"
|
||||
"25:26:27:28:29:30:31:32:33:34:35:36:37:38:39:40:41:42:43:44:45:46:47:48:"
|
||||
"49:50:51:52:53:54:55:56:57:58:59:60:61:62:63:64:65:66:67:68:69:70:71:72");
|
||||
|
||||
/* Test ordering: client-id before ip= */
|
||||
_dhcp_client_id_check_v(
|
||||
NM_MAKE_STRV("rd.net.dhcp.client-id=eth0:aa-bb-cc-dd-ee-ff", "ip=eth0:dhcp"),
|
||||
"eth0",
|
||||
"aa:bb:cc:dd:ee:ff");
|
||||
|
||||
/* Test ordering: client-id after ip= */
|
||||
_dhcp_client_id_check_v(
|
||||
NM_MAKE_STRV("ip=eth2:dhcp", "rd.net.dhcp.client-id=eth2:ba-da-cc-dd-ee-ff"),
|
||||
"eth2",
|
||||
"ba:da:cc:dd:ee:ff");
|
||||
|
||||
/* Duplicate option: last wins */
|
||||
_dhcp_client_id_check_v(NM_MAKE_STRV("ip=eth3:dhcp",
|
||||
"rd.net.dhcp.client-id=eth3:01-02",
|
||||
"rd.net.dhcp.client-id=eth3:01-03"),
|
||||
"eth3",
|
||||
"01:03");
|
||||
|
||||
/* Multiple connections */
|
||||
{
|
||||
gs_unref_hashtable GHashTable *connections = NULL;
|
||||
NMConnection *connection;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
|
||||
connections = _parse_cons(NM_MAKE_STRV("ip=eth0:dhcp",
|
||||
"ip=eth1:dhcp",
|
||||
"rd.net.dhcp.client-id=eth1:01-01-01",
|
||||
"rd.net.dhcp.client-id=eth0:00-00-00"));
|
||||
|
||||
g_assert_nonnull(connections);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 2);
|
||||
|
||||
connection = g_hash_table_lookup(connections, "eth0");
|
||||
g_assert_nonnull(connection);
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting_ip4_config(connection);
|
||||
g_assert_nonnull(s_ip4);
|
||||
g_assert_cmpstr(nm_setting_ip4_config_get_dhcp_client_id(s_ip4), ==, "00:00:00");
|
||||
|
||||
connection = g_hash_table_lookup(connections, "eth1");
|
||||
g_assert_nonnull(connection);
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting_ip4_config(connection);
|
||||
g_assert_nonnull(s_ip4);
|
||||
g_assert_cmpstr(nm_setting_ip4_config_get_dhcp_client_id(s_ip4), ==, "01:01:01");
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
|
|
@ -2848,6 +2991,7 @@ main(int argc, char **argv)
|
|||
g_test_add_func("/initrd/cmdline/rd_ethtool", test_rd_ethtool);
|
||||
g_test_add_func("/initrd/cmdline/plain_equal_char", test_plain_equal_char);
|
||||
g_test_add_func("/initrd/cmdline/global_dns", test_global_dns);
|
||||
g_test_add_func("/initrd/cmdline/rd_dhcp_client_id", test_rd_dhcp_client_id);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
397
src/nm-initrd-generator/tests/test-nbft-reader.c
Normal file
397
src/nm-initrd-generator/tests/test-nbft-reader.c
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2025 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "src/core/nm-default-daemon.h"
|
||||
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "libnm-glib-aux/nm-test-utils.h"
|
||||
|
||||
#include "nm-initrd-generator/nm-initrd-generator.h"
|
||||
|
||||
#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/nm-initrd-generator/tests"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMConnection *
|
||||
find_connection_for_mac(NMConnection **nbft_connections, const char *expected_mac, guint32 vlan_id)
|
||||
{
|
||||
NMConnection **c;
|
||||
NMSettingWired *s_wired;
|
||||
NMSettingVlan *s_vlan;
|
||||
const char *mac_address;
|
||||
|
||||
for (c = nbft_connections; c && *c; c++) {
|
||||
s_wired = nm_connection_get_setting_wired(*c);
|
||||
g_assert(s_wired);
|
||||
mac_address = nm_setting_wired_get_mac_address(s_wired);
|
||||
g_assert(mac_address);
|
||||
if (!nm_utils_hwaddr_matches(mac_address, -1, expected_mac, -1))
|
||||
continue;
|
||||
s_vlan = nm_connection_get_setting_vlan(*c);
|
||||
if (vlan_id > 0) {
|
||||
if (!s_vlan)
|
||||
continue;
|
||||
if (nm_setting_vlan_get_id(s_vlan) != vlan_id)
|
||||
continue;
|
||||
} else if (s_vlan)
|
||||
continue;
|
||||
return *c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
verify_connection(NMConnection *c, const char *expected_mac, guint32 expected_vlan_id)
|
||||
{
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingWired *s_wired;
|
||||
NMSettingVlan *s_vlan;
|
||||
const char *mac_address;
|
||||
|
||||
nmtst_assert_connection_verifies_without_normalization(c);
|
||||
|
||||
s_con = nm_connection_get_setting_connection(c);
|
||||
g_assert(s_con);
|
||||
|
||||
g_assert(g_str_has_prefix(nm_setting_connection_get_id(s_con), "NBFT"));
|
||||
g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL);
|
||||
g_assert(nm_setting_connection_get_autoconnect_priority(s_con)
|
||||
== NMI_AUTOCONNECT_PRIORITY_FIRMWARE);
|
||||
|
||||
s_wired = nm_connection_get_setting_wired(c);
|
||||
g_assert(s_wired);
|
||||
mac_address = nm_setting_wired_get_mac_address(s_wired);
|
||||
g_assert(mac_address);
|
||||
g_assert(nm_utils_hwaddr_matches(mac_address, -1, expected_mac, -1));
|
||||
|
||||
if (expected_vlan_id > 0) {
|
||||
g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con),
|
||||
==,
|
||||
NM_SETTING_VLAN_SETTING_NAME);
|
||||
s_vlan = nm_connection_get_setting_vlan(c);
|
||||
g_assert(s_vlan);
|
||||
g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, expected_vlan_id);
|
||||
g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, NULL);
|
||||
} else {
|
||||
g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con),
|
||||
==,
|
||||
NM_SETTING_WIRED_SETTING_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
verify_ipv4(NMConnection *c, const char *addr, int mask, const char *gateway)
|
||||
{
|
||||
NMSettingIPConfig *s_ip4;
|
||||
NMIPAddress *ip4_addr;
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config(c);
|
||||
g_assert(s_ip4);
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4),
|
||||
==,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
|
||||
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 0);
|
||||
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1);
|
||||
ip4_addr = nm_setting_ip_config_get_address(s_ip4, 0);
|
||||
g_assert(ip4_addr);
|
||||
g_assert_cmpstr(nm_ip_address_get_address(ip4_addr), ==, addr);
|
||||
g_assert_cmpint(nm_ip_address_get_prefix(ip4_addr), ==, mask);
|
||||
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, gateway);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_ipv4_dhcp(NMConnection *c)
|
||||
{
|
||||
NMSettingIPConfig *s_ip4;
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config(c);
|
||||
g_assert(s_ip4);
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_ipv4_disabled(NMConnection *c)
|
||||
{
|
||||
NMSettingIPConfig *s_ip4;
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config(c);
|
||||
g_assert(s_ip4);
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4),
|
||||
==,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_ipv6(NMConnection *c, const char *addr, int prefix, const char *gateway)
|
||||
{
|
||||
NMSettingIPConfig *s_ip6;
|
||||
NMIPAddress *ip6_addr;
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config(c);
|
||||
g_assert(s_ip6);
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6),
|
||||
==,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
|
||||
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip6), ==, 0);
|
||||
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 1);
|
||||
ip6_addr = nm_setting_ip_config_get_address(s_ip6, 0);
|
||||
g_assert(ip6_addr);
|
||||
g_assert_cmpstr(nm_ip_address_get_address(ip6_addr), ==, addr);
|
||||
g_assert_cmpint(nm_ip_address_get_prefix(ip6_addr), ==, prefix);
|
||||
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, gateway);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_ipv6_auto(NMConnection *c)
|
||||
{
|
||||
NMSettingIPConfig *s_ip6;
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config(c);
|
||||
g_assert(s_ip6);
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_ipv6_disabled(NMConnection *c)
|
||||
{
|
||||
NMSettingIPConfig *s_ip6;
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config(c);
|
||||
g_assert(s_ip6);
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6),
|
||||
==,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_DISABLED);
|
||||
}
|
||||
|
||||
static int
|
||||
count_nm_conn(NMConnection **connections)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; connections && *connections; connections++, cnt++)
|
||||
;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static void
|
||||
free_connections(NMConnection **connections)
|
||||
{
|
||||
NMConnection **c;
|
||||
|
||||
for (c = connections; c && *c; c++)
|
||||
g_object_unref(*c);
|
||||
g_free(connections);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_nbft_ipv4_static(void)
|
||||
{
|
||||
NMConnection **nbft_connections;
|
||||
NMConnection *connection;
|
||||
const char *expected_mac_address;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
nbft_connections = nmi_nbft_reader_parse(TEST_INITRD_DIR "/nbft-ipv4-static", &hostname);
|
||||
g_assert_nonnull(hostname);
|
||||
g_assert_cmpint(count_nm_conn(nbft_connections), ==, 6);
|
||||
|
||||
/* NBFT-multi HFI 1 */
|
||||
expected_mac_address = "52:54:00:72:c5:ae";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4(connection, "192.168.122.158", 24, "192.168.122.1");
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-multi HFI 2 */
|
||||
expected_mac_address = "52:54:00:72:c5:af";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4_dhcp(connection);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-Dell.PowerEdge.R660-fw1.5.5-mpath+discovery HFI 1 */
|
||||
expected_mac_address = "00:62:0b:cb:eb:70";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4(connection, "172.18.240.1", 24, NULL);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-Dell.PowerEdge.R660-fw1.5.5-mpath+discovery HFI 2 */
|
||||
expected_mac_address = "00:62:0b:cb:eb:71";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4(connection, "172.18.230.2", 24, NULL);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-rhpoc */
|
||||
expected_mac_address = "ea:eb:d3:58:89:58";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4(connection, "192.168.101.30", 24, NULL);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-static-ipv4 */
|
||||
expected_mac_address = "52:54:00:b8:19:b9";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4(connection, "192.168.49.50", 24, NULL);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
free_connections(nbft_connections);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_nbft_ipv4_dhcp(void)
|
||||
{
|
||||
NMConnection **nbft_connections;
|
||||
NMConnection *connection;
|
||||
const char *expected_mac_address;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
nbft_connections = nmi_nbft_reader_parse(TEST_INITRD_DIR "/nbft-ipv4-dhcp", &hostname);
|
||||
g_assert_nonnull(hostname);
|
||||
g_assert_cmpint(count_nm_conn(nbft_connections), ==, 2);
|
||||
|
||||
/* NBFT-dhcp-ipv4 */
|
||||
expected_mac_address = "52:54:00:b8:19:b9";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4_dhcp(connection);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-Dell.PowerEdge.R760 */
|
||||
expected_mac_address = "b0:26:28:e8:7c:0e";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4_dhcp(connection);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
free_connections(nbft_connections);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_nbft_ipv6_static(void)
|
||||
{
|
||||
NMConnection **nbft_connections;
|
||||
NMConnection *connection;
|
||||
const char *expected_mac_address;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
nbft_connections = nmi_nbft_reader_parse(TEST_INITRD_DIR "/nbft-ipv6-static", &hostname);
|
||||
g_assert_nonnull(hostname);
|
||||
g_assert_cmpint(count_nm_conn(nbft_connections), ==, 1);
|
||||
|
||||
/* NBFT-static-ipv6 */
|
||||
expected_mac_address = "52:54:00:9e:20:1a";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv6(connection, "fd09:9a46:b5c1:1fe::10", 64, NULL);
|
||||
verify_ipv4_disabled(connection);
|
||||
|
||||
free_connections(nbft_connections);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_nbft_ipv6_auto(void)
|
||||
{
|
||||
NMConnection **nbft_connections;
|
||||
NMConnection *connection;
|
||||
const char *expected_mac_address;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
nbft_connections = nmi_nbft_reader_parse(TEST_INITRD_DIR "/nbft-ipv6-auto", &hostname);
|
||||
g_assert_nonnull(hostname);
|
||||
g_assert_cmpint(count_nm_conn(nbft_connections), ==, 3);
|
||||
|
||||
/* NBFT-auto-ipv6 */
|
||||
expected_mac_address = "52:54:00:9e:20:1a";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv6(connection, "fd09:9a46:b5c1:1ff:5054:ff:fe9e:201a", 64, NULL);
|
||||
verify_ipv4_disabled(connection);
|
||||
|
||||
/* NBFT-dhcp-ipv6 */
|
||||
expected_mac_address = "52:54:00:b8:19:b9";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv6_auto(connection);
|
||||
verify_ipv4_disabled(connection);
|
||||
|
||||
/* NBFT-ipv6-noip+disc */
|
||||
expected_mac_address = "40:a6:b7:c0:8a:c9";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv6_auto(connection);
|
||||
verify_ipv4_disabled(connection);
|
||||
|
||||
free_connections(nbft_connections);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_nbft_vlan(void)
|
||||
{
|
||||
NMConnection **nbft_connections;
|
||||
NMConnection *connection;
|
||||
const char *expected_mac_address;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
nbft_connections = nmi_nbft_reader_parse(TEST_INITRD_DIR "/nbft-vlan", &hostname);
|
||||
g_assert_cmpstr(hostname, ==, NULL);
|
||||
g_assert_cmpint(count_nm_conn(nbft_connections), ==, 4);
|
||||
|
||||
/* NBFT-qemu-vlans-incomplete HFI 1 */
|
||||
expected_mac_address = "52:54:00:72:c5:ae";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4(connection, "192.168.122.158", 24, "192.168.122.1");
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-qemu-vlans-incomplete HFI 2 */
|
||||
expected_mac_address = "52:54:00:72:c5:af";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 0);
|
||||
verify_connection(connection, expected_mac_address, 0);
|
||||
verify_ipv4_disabled(connection);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-qemu-vlans-incomplete HFI 2 VLAN 11 */
|
||||
expected_mac_address = "52:54:00:72:c5:af";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 11);
|
||||
verify_connection(connection, expected_mac_address, 11);
|
||||
verify_ipv4(connection, "192.168.124.58", 24, NULL);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
/* NBFT-qemu-vlans-incomplete HFI 2 VLAN 12 */
|
||||
expected_mac_address = "52:54:00:72:c5:af";
|
||||
connection = find_connection_for_mac(nbft_connections, expected_mac_address, 12);
|
||||
verify_connection(connection, expected_mac_address, 12);
|
||||
verify_ipv4(connection, "192.168.125.58", 24, NULL);
|
||||
verify_ipv6_disabled(connection);
|
||||
|
||||
free_connections(nbft_connections);
|
||||
}
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
g_test_add_func("/initrd/nbft/ipv4-static", test_read_nbft_ipv4_static);
|
||||
g_test_add_func("/initrd/nbft/ipv4-dhcp", test_read_nbft_ipv4_dhcp);
|
||||
g_test_add_func("/initrd/nbft/ipv6-static", test_read_nbft_ipv6_static);
|
||||
g_test_add_func("/initrd/nbft/ipv6-auto", test_read_nbft_ipv6_auto);
|
||||
g_test_add_func("/initrd/nbft/vlan", test_read_nbft_vlan);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
@ -1235,6 +1235,13 @@
|
|||
nmcli-description="The protocol used by the interface, whether it is PRP or HSR."
|
||||
format="boolean"
|
||||
values="true/yes/on, false/no/off" />
|
||||
<property name="protocol-version"
|
||||
nmcli-description="Configures the protocol version to be used for the HSR/PRP interface. "default" (-1) sets the protocol version to the default version for the protocol. "hsr-2010" (0) sets the protocol version to HSRv0 (IEC 62439-3:2010). "hsr-2012" (1) sets the protocol version to HSRv1 (IEC 62439-3:2012)."
|
||||
format="choice (NMSettingHsrProtocolVersion)"
|
||||
values="default (-1), hsr-2010 (0), hsr-2012 (1)" />
|
||||
<property name="interlink"
|
||||
nmcli-description="The optional interlink port name of the HSR interface."
|
||||
format="string" />
|
||||
</setting>
|
||||
<setting name="infiniband" >
|
||||
<property name="mac-address"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static void permission_changed(GObject *gobject, GParamSpec *pspec, NmCli *nmc);
|
|||
static NM_UTILS_LOOKUP_STR_DEFINE(nm_state_to_string,
|
||||
NMState,
|
||||
NM_UTILS_LOOKUP_DEFAULT(N_("unknown")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_STATE_ASLEEP, N_("asleep")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_STATE_DISABLED, N_("network off")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_STATE_CONNECTING, N_("connecting")),
|
||||
NM_UTILS_LOOKUP_ITEM(NM_STATE_CONNECTED_LOCAL,
|
||||
N_("connected (local only)")),
|
||||
|
|
@ -53,8 +53,8 @@ state_to_color(NMState state)
|
|||
return NM_META_COLOR_STATE_CONNECTED_GLOBAL;
|
||||
case NM_STATE_DISCONNECTING:
|
||||
return NM_META_COLOR_STATE_DISCONNECTING;
|
||||
case NM_STATE_ASLEEP:
|
||||
return NM_META_COLOR_STATE_ASLEEP;
|
||||
case NM_STATE_DISABLED:
|
||||
return NM_META_COLOR_STATE_DISABLED;
|
||||
case NM_STATE_DISCONNECTED:
|
||||
return NM_META_COLOR_STATE_DISCONNECTED;
|
||||
default:
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue