mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 20:10:10 +01:00
systemd: merge branch 'master' into systemd
The "systemd" branch is only to re-import systemd code. By itself, it doesn't even compile. Still, it's nice to not let it fall too far behind from master. Merge master back into the systemd branch.
This commit is contained in:
commit
2b2e156742
1278 changed files with 646693 additions and 516121 deletions
121
.clang-format
Normal file
121
.clang-format
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
Language: Cpp
|
||||
|
||||
TabWidth: 4
|
||||
IndentWidth: 4
|
||||
UseTab: Never
|
||||
ColumnLimit: 100
|
||||
ContinuationIndentWidth: 4
|
||||
UseCRLF: false
|
||||
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignConsecutiveMacros: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
#AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: AllDefinitions
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterControlStatement: Never
|
||||
AfterFunction: true
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakStringLiterals: true
|
||||
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
|
||||
ForEachMacros: ['c_list_for_each',
|
||||
'c_list_for_each_prev',
|
||||
'c_list_for_each_prev_safe',
|
||||
'c_list_for_each_continue',
|
||||
'c_list_for_each_entry',
|
||||
'c_list_for_each_entry_continue',
|
||||
'c_list_for_each_entry_prev',
|
||||
'c_list_for_each_entry_safe',
|
||||
'c_list_for_each_entry_safe_continue',
|
||||
'c_list_for_each_entry_safe_unlink',
|
||||
'c_list_for_each_safe',
|
||||
'c_list_for_each_safe_continue',
|
||||
'c_list_for_each_safe_unlink',
|
||||
'c_rbtree_for_each',
|
||||
'c_rbtree_for_each_entry',
|
||||
'c_rbtree_for_each_entry_postorder',
|
||||
'c_rbtree_for_each_entry_safe',
|
||||
'c_rbtree_for_each_entry_safe_postorder',
|
||||
'c_rbtree_for_each_entry_safe_postorder_unlink',
|
||||
'c_rbtree_for_each_postorder',
|
||||
'c_rbtree_for_each_safe',
|
||||
'c_rbtree_for_each_safe_postorder',
|
||||
'c_rbtree_for_each_safe_postorder_unlink',
|
||||
'json_array_foreach',
|
||||
'json_object_foreach',
|
||||
'json_object_foreach_safe',
|
||||
'ndp_msg_opt_dnssl_for_each_domain',
|
||||
'ndp_msg_opt_for_each_offset',
|
||||
'ndp_msg_opt_rdnss_for_each_addr',
|
||||
'nla_for_each_attr',
|
||||
'nla_for_each_nested',
|
||||
'nm_dedup_multi_iter_for_each',
|
||||
'nm_ip_config_iter_ip4_address_for_each',
|
||||
'nm_ip_config_iter_ip4_route_for_each',
|
||||
'nm_ip_config_iter_ip6_address_for_each',
|
||||
'nm_ip_config_iter_ip6_route_for_each',
|
||||
'nm_ip_config_iter_ip_address_for_each',
|
||||
'nm_ip_config_iter_ip_route_for_each',
|
||||
'nm_json_array_foreach',
|
||||
'nm_json_object_foreach',
|
||||
'nm_l3_config_data_iter_ip4_address_for_each',
|
||||
'nm_l3_config_data_iter_ip4_route_for_each',
|
||||
'nm_l3_config_data_iter_ip6_address_for_each',
|
||||
'nm_l3_config_data_iter_ip6_route_for_each',
|
||||
'nm_l3_config_data_iter_obj_for_each',
|
||||
'nm_manager_for_each_active_connection',
|
||||
'nm_manager_for_each_active_connection_prev',
|
||||
'nm_manager_for_each_active_connection_safe',
|
||||
'nm_manager_for_each_device',
|
||||
'nm_manager_for_each_device_safe',
|
||||
'nm_platform_iter_obj_for_each',
|
||||
'nmp_cache_iter_for_each',
|
||||
'nmp_cache_iter_for_each_link',
|
||||
]
|
||||
7
.git-blame-ignore-revs
Normal file
7
.git-blame-ignore-revs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# The commits that did automated reformatting. You can ignore them
|
||||
# during git-blame with `--ignore-rev` or `--ignore-revs-file`.
|
||||
#
|
||||
# $ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
|
||||
#
|
||||
328fb90f3e0d4e35975aff63944ac0412d7893a5
|
||||
740b092fda3d5f45102422f22884c88ea6c42858
|
||||
41
.gitignore
vendored
41
.gitignore
vendored
|
|
@ -30,6 +30,9 @@ stamp-*
|
|||
gtk-doc.make
|
||||
*.pc
|
||||
cscope.*out
|
||||
.clangd/
|
||||
compile_commands.json
|
||||
tags
|
||||
valgrind-*.log
|
||||
test-*.log
|
||||
test-*.trs
|
||||
|
|
@ -65,6 +68,8 @@ test-*.trs
|
|||
/dispatcher/tests/test-dispatcher-envp
|
||||
|
||||
/clients/cli/nmcli
|
||||
/clients/cloud-setup/nm-cloud-setup
|
||||
/clients/cloud-setup/nm-cloud-setup.service
|
||||
/clients/common/settings-docs.h
|
||||
/clients/common/tests/test-clients-common
|
||||
/clients/common/tests/test-libnm-core-aux
|
||||
|
|
@ -90,6 +95,7 @@ test-*.trs
|
|||
/docs/api/NetworkManager-*.txt
|
||||
/docs/api/NetworkManager-decl-list.txt.bak
|
||||
/docs/api/NetworkManager-decl.txt.bak
|
||||
/docs/api/NetworkManager.actions
|
||||
/docs/api/NetworkManager.args
|
||||
/docs/api/NetworkManager.hierarchy
|
||||
/docs/api/NetworkManager.interfaces
|
||||
|
|
@ -104,6 +110,7 @@ test-*.trs
|
|||
/docs/libnm/tmpl/
|
||||
/docs/libnm/xml/
|
||||
/docs/libnm/libnm-*.txt
|
||||
/docs/libnm/libnm.actions
|
||||
/docs/libnm/libnm.args
|
||||
/docs/libnm/libnm.hierarchy
|
||||
/docs/libnm/libnm.interfaces
|
||||
|
|
@ -126,7 +133,8 @@ test-*.trs
|
|||
/examples/C/qt/monitor-nm-running
|
||||
/examples/C/qt/monitor-nm-running.moc
|
||||
|
||||
/shared/nm-utils/tests/test-shared-general
|
||||
/shared/nm-glib-aux/tests/test-json-aux
|
||||
/shared/nm-glib-aux/tests/test-shared-general
|
||||
/shared/nm-version-macros.h
|
||||
|
||||
/introspection/org.freedesktop.NetworkManager*.[ch]
|
||||
|
|
@ -142,16 +150,19 @@ test-*.trs
|
|||
/libnm-core/nm-dbus-types.xml
|
||||
/libnm-core/nm-vpn-dbus-types.xml
|
||||
|
||||
/libnm/nm-settings-ifcfg-rh-docs.xml
|
||||
/libnm/nm-property-docs.xml
|
||||
/libnm/nm-settings-docs.xml
|
||||
/libnm/nm-settings-docs-overrides.xml
|
||||
/libnm/nm-settings-keyfile-docs.xml
|
||||
/libnm/nm-property-infos-dbus.xml
|
||||
/libnm/nm-property-infos-ifcfg-rh.xml
|
||||
/libnm/nm-property-infos-keyfile.xml
|
||||
/libnm/nm-property-infos-nmcli.xml
|
||||
/libnm/nm-settings-docs-gir.xml
|
||||
/libnm/tests/test-libnm
|
||||
/libnm/tests/test-nm-client
|
||||
/libnm/tests/test-remote-settings-client
|
||||
/libnm/tests/test-secret-agent
|
||||
|
||||
/clients/cli/generate-docs-nm-settings-nmcli
|
||||
/clients/cli/generate-docs-nm-settings-nmcli.xml
|
||||
|
||||
/m4/codeset.m4
|
||||
/m4/gettext.m4
|
||||
/m4/glibc2.m4
|
||||
|
|
@ -187,9 +198,12 @@ test-*.trs
|
|||
/m4/xsize.m4
|
||||
|
||||
/man/*.[1785]
|
||||
/man/nm-settings.xml
|
||||
/man/nm-settings-dbus.xml
|
||||
/man/nm-settings-docs-dbus.xml
|
||||
/man/nm-settings-docs-nmcli.xml
|
||||
/man/nm-settings-ifcfg-rh.xml
|
||||
/man/nm-settings-keyfile.xml
|
||||
/man/nm-settings-nmcli.xml
|
||||
/man/common.ent
|
||||
|
||||
/po/*.gmo
|
||||
|
|
@ -205,6 +219,7 @@ test-*.trs
|
|||
/po/remove-potcdate.sin
|
||||
|
||||
/src/NetworkManager
|
||||
/src/NetworkManager-all-sym
|
||||
/src/NetworkManager.ver
|
||||
/src/devices/bluetooth/tests/nm-bt-test
|
||||
/src/devices/tests/test-acd
|
||||
|
|
@ -234,6 +249,8 @@ test-*.trs
|
|||
/src/platform/tests/test-platform-general
|
||||
/src/platform/tests/test-route-fake
|
||||
/src/platform/tests/test-route-linux
|
||||
/src/platform/tests/test-tc-fake
|
||||
/src/platform/tests/test-tc-linux
|
||||
/src/settings/plugins/ifcfg-rh/nmdbus-ifcfg-rh.[ch]
|
||||
/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh
|
||||
/src/settings/plugins/ifupdown/tests/test-ifupdown
|
||||
|
|
@ -241,11 +258,12 @@ test-*.trs
|
|||
/src/settings/plugins/ifcfg-rh/tests/network-scripts/tmp/
|
||||
/src/supplicant/tests/test-supplicant-config
|
||||
/src/tests/config/test-config
|
||||
/src/tests/test-dcb
|
||||
/src/tests/test-core
|
||||
/src/tests/test-core-with-expect
|
||||
/src/tests/test-dcb
|
||||
/src/tests/test-ip4-config
|
||||
/src/tests/test-ip6-config
|
||||
/src/tests/test-l3cfg
|
||||
/src/tests/test-route-manager-fake
|
||||
/src/tests/test-route-manager-linux
|
||||
/src/tests/test-systemd
|
||||
|
|
@ -291,6 +309,7 @@ test-*.trs
|
|||
/docs/libnm-util/tmpl/
|
||||
/docs/libnm-util/version.xml
|
||||
/docs/libnm-util/xml/
|
||||
/man/nm-settings.xml
|
||||
/include/
|
||||
/initscript/*/[Nn]etwork[Mm]anager
|
||||
/initscript/Slackware/rc.networkmanager
|
||||
|
|
@ -318,11 +337,17 @@ test-*.trs
|
|||
/libnm/fake-typelib/typelibs.c
|
||||
/libnm/nm-ifcfg-rh-docs.xml
|
||||
/libnm/nm-keyfile-docs.xml
|
||||
/libnm/nm-property-docs.xml
|
||||
/libnm/nm-setting-docs-overrides.xml
|
||||
/libnm/nm-setting-docs.xml
|
||||
/libnm/nm-settings-docs-overrides.xml
|
||||
/libnm/nm-settings-docs.xml
|
||||
/libnm/nm-settings-ifcfg-rh-docs.xml
|
||||
/libnm/nm-settings-keyfile-docs.xml
|
||||
/libnm/tests/test-general
|
||||
/policy/org.freedesktop.NetworkManager.policy
|
||||
/policy/org.freedesktop.NetworkManager.policy.in
|
||||
/shared/nm-utils/tests/test-shared-general
|
||||
/src/devices/tests/test-arping
|
||||
/src/devices/wifi/tests/test-general
|
||||
/src/devices/wifi/tests/test-wifi-ap-utils
|
||||
|
|
|
|||
986
.gitlab-ci.yml
986
.gitlab-ci.yml
File diff suppressed because it is too large
Load diff
7
.gitlab-ci/alpine-install.sh
Executable file
7
.gitlab-ci/alpine-install.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
./contrib/alpine/REQUIRED_PACKAGES
|
||||
|
||||
ln -snf elogind/systemd /usr/include/systemd
|
||||
57
.gitlab-ci/build.sh
Executable file
57
.gitlab-ci/build.sh
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
IS_FEDORA=0
|
||||
IS_CENTOS=0
|
||||
IS_ALPINE=0
|
||||
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
|
||||
|
||||
do_clean() {
|
||||
git clean -fdx
|
||||
}
|
||||
|
||||
uname -a
|
||||
! command -v locale &>/dev/null || locale -a
|
||||
env
|
||||
meson --version
|
||||
|
||||
! command -v dpkg &>/dev/null || dpkg -l
|
||||
! command -v yum &>/dev/null || yum list installed
|
||||
! command -v apk &>/dev/null || apk -v info
|
||||
|
||||
# The formatting depends on the version of python black.
|
||||
# We have a dedicated test that checks our formatting, which
|
||||
# uses the right version. We should disable the check during
|
||||
# `make check`.
|
||||
export NMTST_SKIP_PYTHON_BLACK=1
|
||||
|
||||
# We have a unit test that check that `ci-fairy generate-template`
|
||||
# is equal to our .gitlab-ci.yml file. However, on gitlab-ci we
|
||||
# also have a dedicate test for the same thing. We don't need
|
||||
# to run that test as part of the build. Disable it.
|
||||
export NMTST_SKIP_CHECK_GITLAB_CI=1
|
||||
|
||||
do_clean; BUILD_TYPE=autotools CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh
|
||||
rm -rf /tmp/nm-docs-html;
|
||||
mv build/INST/share/gtk-doc/html /tmp/nm-docs-html
|
||||
do_clean; BUILD_TYPE=meson CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh
|
||||
do_clean; BUILD_TYPE=autotools CC=clang WITH_DOCS=0 contrib/scripts/nm-ci-run.sh
|
||||
do_clean; BUILD_TYPE=meson CC=clang WITH_DOCS=0 contrib/scripts/nm-ci-run.sh
|
||||
|
||||
do_clean; test $IS_FEDORA = 1 -o $IS_CENTOS = 1 && ./contrib/fedora/rpm/build_clean.sh -g -w crypto_gnutls -w debug -w iwd -w test -W meson
|
||||
do_clean; test $IS_FEDORA = 1 && ./contrib/fedora/rpm/build_clean.sh -g -w crypto_gnutls -w debug -w iwd -w test -w meson
|
||||
|
||||
do_clean
|
||||
if [ "$NM_BUILD_TARBALL" = 1 ]; then
|
||||
SIGN_SOURCE=0 ./contrib/fedora/rpm/build_clean.sh -r
|
||||
mv ./NetworkManager-1*.tar.xz /tmp/
|
||||
mv ./contrib/fedora/rpm/latest/SRPMS/NetworkManager-1*.src.rpm /tmp/
|
||||
do_clean
|
||||
mv /tmp/nm-docs-html ./docs-html
|
||||
mv /tmp/NetworkManager-1*.tar.xz /tmp/NetworkManager-1*.src.rpm ./
|
||||
fi
|
||||
|
||||
echo "BUILD SUCCESSFUL!!"
|
||||
229
.gitlab-ci/ci.template
Normal file
229
.gitlab-ci/ci.template
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0 filetype=yaml:
|
||||
|
||||
{# You're looking at the template here, so you can ignore the below
|
||||
warning. This is the right file to edit #}
|
||||
########################################
|
||||
# #
|
||||
# THIS FILE IS GENERATED, DO NOT EDIT #
|
||||
# #
|
||||
########################################
|
||||
|
||||
|
||||
.templates_sha: &template_sha b18e53bf67b9ed493a006d83dbadd1ecc0daa61a # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||
|
||||
include:
|
||||
{% for distro in distributions|sort(attribute="name") %}
|
||||
# {{ distro.name.capitalize() }} container builder template
|
||||
- project: 'freedesktop/ci-templates'
|
||||
ref: *template_sha
|
||||
file: '/templates/{{distro.name}}.yml'
|
||||
{% endfor %}
|
||||
|
||||
stages:
|
||||
- prep
|
||||
- test
|
||||
- deploy
|
||||
- triage
|
||||
- container_clean
|
||||
|
||||
variables:
|
||||
FDO_UPSTREAM_REPO: NetworkManager/NetworkManager
|
||||
GIT_DEPTH: 1
|
||||
# these tags should be updated each time the list of packages is updated
|
||||
# changing these will force rebuilding the associated image
|
||||
# Note: these tags have no meaning and are not tied to a particular NM version
|
||||
{% for distro in distributions %}
|
||||
{{"%-13s"| format(distro.name.upper() + '_TAG:')}}'{{distro.tag}}-{{
|
||||
(ci_fairy.hashfiles('./.gitlab-ci/config.yml',
|
||||
'./.gitlab-ci/ci.template',
|
||||
'./.gitlab-ci/' + distro.base_type + '-install.sh',
|
||||
'./contrib/' + distro.base_type + '/REQUIRED_PACKAGES'))[0:12]
|
||||
}}'
|
||||
{% endfor %}
|
||||
|
||||
{% for distro in distributions %}
|
||||
{{"%-13s"| format(distro.name.upper() + '_EXEC:')}}'bash .gitlab-ci/{{distro.base_type}}-install.sh'
|
||||
{% endfor %}
|
||||
|
||||
.nm_artifacts:
|
||||
variables:
|
||||
NM_BUILD_TARBALL: 1
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- docs-html
|
||||
- NetworkManager-1*.tar.xz
|
||||
- NetworkManager-1*.src.rpm
|
||||
|
||||
.nm_artifacts_undo:
|
||||
variables:
|
||||
NM_BUILD_TARBALL: 0
|
||||
artifacts:
|
||||
paths: []
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# containers stage #
|
||||
# #
|
||||
#################################################################
|
||||
|
||||
# Build a container for each distribution + version. The ci-templates
|
||||
# will re-use the containers if the tag doesn't change.
|
||||
{% for distro in distributions %}
|
||||
{% for version in distro.versions %}
|
||||
|
||||
{{distro.name}}:{{version}}@container-prep:
|
||||
extends:
|
||||
- .fdo.container-build@{{distro.name}}
|
||||
stage: prep
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
FDO_DISTRIBUTION_VERSION: '{{version}}'
|
||||
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
|
||||
FDO_DISTRIBUTION_EXEC: ${{distro.name.upper()}}_EXEC
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# container clean stage #
|
||||
# run during the clean stage #
|
||||
# #
|
||||
#################################################################
|
||||
|
||||
#
|
||||
# This stage will look for the container images we currently have in
|
||||
# the registry and will remove any that are not tagged with the provided
|
||||
# $container_image:$tag
|
||||
#
|
||||
# This job only runs for a scheduled pipeline.
|
||||
#
|
||||
# Go to your Profile, Settings, Access Tokens
|
||||
# Create a personal token with 'api' scope, copy the value.
|
||||
# Go to CI/CD, Schedules, schedule a monthly job.
|
||||
# Define a variable of type File named AUTHFILE. Content is that token
|
||||
# value.
|
||||
.container-clean:
|
||||
stage: container_clean
|
||||
image: golang:alpine
|
||||
before_script:
|
||||
- apk add python3 py-pip git
|
||||
- pip3 install git+http://gitlab.freedesktop.org/freedesktop/ci-templates
|
||||
script:
|
||||
- ci-fairy -v --authfile $AUTHFILE delete-image
|
||||
--repository $FDO_DISTRIBUTION_NAME/$FDO_DISTRIBUTION_VERSION
|
||||
--exclude-tag $FDO_DISTRIBUTION_TAG
|
||||
dependencies: []
|
||||
allow_failure: true
|
||||
only:
|
||||
- schedules
|
||||
|
||||
{% for distro in distributions %}
|
||||
{% for version in distro.versions %}
|
||||
{{distro.name}}:{{version}}@container-clean:
|
||||
extends:
|
||||
- .container-clean
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
CURRENT_CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/{{distro.name}}/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG
|
||||
FDO_DISTRIBUTION_VERSION: '{{version}}'
|
||||
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
|
||||
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# build stage #
|
||||
# #
|
||||
#################################################################
|
||||
|
||||
.build@template:
|
||||
stage: test
|
||||
script:
|
||||
- .gitlab-ci/build.sh
|
||||
dependencies: []
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# test stage #
|
||||
# #
|
||||
#################################################################
|
||||
|
||||
{% for distro in distributions %}
|
||||
{% for version in distro.versions %}
|
||||
|
||||
t_{{distro.name}}:{{version}}:
|
||||
extends:
|
||||
- .build@template
|
||||
- .fdo.distribution-image@{{distro.name}}
|
||||
{% if distro.name == pages_build.name and
|
||||
version == pages_build.version %}
|
||||
- .nm_artifacts
|
||||
{% endif %}
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: '{{version}}'
|
||||
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
|
||||
{# Where we have extra_variables defined, add them to the list #}
|
||||
{% if distro.build is defined and distro.build.extra_variables is defined %}
|
||||
{% for var in distro.build.extra_variables %}
|
||||
{{var}}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
needs:
|
||||
- "{{distro.name}}:{{version}}@container-prep"
|
||||
{% if not version in distro.always %}
|
||||
when: manual
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
#################################################################
|
||||
# #
|
||||
# specific jobs #
|
||||
# #
|
||||
#################################################################
|
||||
|
||||
check-patch:
|
||||
extends:
|
||||
- t_{{pages_build.name}}:{{pages_build.version}}
|
||||
- .nm_artifacts_undo
|
||||
stage: test
|
||||
script:
|
||||
- date '+%Y%m%d-%H%M%S'; NM_CHECKPATCH_FETCH_UPSTREAM=1 contrib/scripts/checkpatch-feature-branch.sh
|
||||
allow_failure: true
|
||||
|
||||
check-tree:
|
||||
extends:
|
||||
- t_{{pages_build.name}}:{{pages_build.version}}
|
||||
- .nm_artifacts_undo
|
||||
stage: test
|
||||
script:
|
||||
- date '+%Y%m%d-%H%M%S'; black --check . examples/python/gi/nm-wg-set
|
||||
- date '+%Y%m%d-%H%M%S'; git ls-files -z -- 'po/*.po' | xargs -0 -n1 msgfmt -vc
|
||||
- date '+%Y%m%d-%H%M%S'; contrib/scripts/nm-code-format.sh
|
||||
- date '+%Y%m%d-%H%M%S'; ci-fairy generate-template && git diff --exit-code
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- mv docs-html public
|
||||
artifacts:
|
||||
expire_in: 20 days
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
dependencies:
|
||||
- t_{{pages_build.name}}:{{pages_build.version}}
|
||||
needs:
|
||||
- t_{{pages_build.name}}:{{pages_build.version}}
|
||||
|
||||
triage:issues:
|
||||
stage: triage
|
||||
image: ruby:2.7
|
||||
script:
|
||||
- gem install gitlab-triage
|
||||
- gitlab-triage -d --token $API_TOKEN --source-id $SOURCE_ID
|
||||
only:
|
||||
- schedules
|
||||
67
.gitlab-ci/config.yml
Normal file
67
.gitlab-ci/config.yml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# This file contains the configuration for the gitlab ci.
|
||||
#
|
||||
# To recreate the .gitlab-ci.yml file, run
|
||||
# ci-fairy generate-template
|
||||
#
|
||||
# The ci-fairy tool is part of
|
||||
# https://gitlab.freedesktop.org/freedesktop/ci-templates
|
||||
#
|
||||
|
||||
# We're happy to rebuild all containers when one changes.
|
||||
.default_tag: &default_tag '2020-11-17.0'
|
||||
|
||||
|
||||
# The list of all distributions we want to create job for.
|
||||
# The template generates manual jobs for all these.
|
||||
distributions:
|
||||
- name: fedora
|
||||
tag: *default_tag
|
||||
base_type: fedora
|
||||
versions:
|
||||
- '28'
|
||||
- '29'
|
||||
- '30'
|
||||
- '31'
|
||||
- '32'
|
||||
- '33'
|
||||
- 'rawhide'
|
||||
always:
|
||||
- '33'
|
||||
- name: ubuntu
|
||||
tag: *default_tag
|
||||
base_type: debian
|
||||
versions:
|
||||
- '16.04'
|
||||
- '18.04'
|
||||
- '20.04'
|
||||
- 'devel'
|
||||
- 'rolling'
|
||||
- name: debian
|
||||
tag: *default_tag
|
||||
base_type: debian
|
||||
versions:
|
||||
- '9'
|
||||
- '10'
|
||||
- 'testing'
|
||||
- 'sid'
|
||||
- name: centos
|
||||
tag: *default_tag
|
||||
base_type: fedora
|
||||
versions:
|
||||
- '7.5.1804'
|
||||
- '7.6.1810'
|
||||
- '7.7.1908'
|
||||
- '7.8.2003'
|
||||
- '7.9.2009'
|
||||
- '8.1.1911'
|
||||
- '8.2.2004'
|
||||
- name: alpine
|
||||
tag: *default_tag
|
||||
base_type: alpine
|
||||
versions:
|
||||
- 'latest'
|
||||
|
||||
# specifies which of the above distros is used as source for pages
|
||||
pages_build:
|
||||
name: fedora
|
||||
version: '33'
|
||||
29
.gitlab-ci/debian-install.sh
Executable file
29
.gitlab-ci/debian-install.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
IS_UBUNTU_1604=0
|
||||
grep -q '^VERSION=.16.04.[0-9]\+ LTS' /etc/os-release && IS_UBUNTU_1604=1
|
||||
|
||||
|
||||
DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive NM_INSTALL="apt-get -qq install -y" ./contrib/debian/REQUIRED_PACKAGES
|
||||
|
||||
dbus-uuidgen --ensure
|
||||
|
||||
sed -i 's/^# \(pl_PL.UTF-8 .*\)$/\1/p' /etc/locale.gen || true
|
||||
locale-gen pl_PL.UTF-8
|
||||
|
||||
if [ $IS_UBUNTU_1604 = 1 ]; then
|
||||
pip3 install meson==0.53.2
|
||||
contrib/scripts/nm-ci-install-valgrind-in-ubuntu1604.sh
|
||||
else
|
||||
pip3 install meson
|
||||
fi
|
||||
|
||||
# iproute2 5.2.0 on debian:sid causes our unit tests to fail.
|
||||
# Downgrade to a working version. See https://www.spinics.net/lists/netdev/msg584916.html
|
||||
if dpkg -s iproute2 | grep -q '^Version[:] 5.2.0-1\(ubuntu1\)\?$' ; then
|
||||
curl 'http://ftp.debian.org/debian/pool/main/i/iproute2/iproute2_4.20.0-2_amd64.deb' --output /tmp/iproute2_4.20.0-2_amd64.deb
|
||||
dpkg -i /tmp/iproute2_4.20.0-2_amd64.deb
|
||||
fi
|
||||
56
.gitlab-ci/fedora-install.sh
Executable file
56
.gitlab-ci/fedora-install.sh
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
IS_FEDORA=0
|
||||
IS_CENTOS=0
|
||||
IS_CENTOS_7=0
|
||||
grep -q '^NAME=.*\(CentOS\)' /etc/os-release && IS_CENTOS=1
|
||||
grep -q '^NAME=.*\(Fedora\)' /etc/os-release && IS_FEDORA=1
|
||||
if [ $IS_CENTOS = 1 ]; then
|
||||
grep -q '^VERSION_ID=.*\<7\>' /etc/os-release && IS_CENTOS_7=1
|
||||
fi
|
||||
|
||||
if [ $IS_CENTOS = 1 ]; then
|
||||
if [ $IS_CENTOS_7 = 1 ]; then
|
||||
yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
|
||||
yum install -y glibc-common
|
||||
localedef -c -i pl_PL -f UTF-8 pl_PL.UTF-8
|
||||
locale -a
|
||||
yum install -y python36-dbus python36-gobject-base
|
||||
else
|
||||
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
|
||||
dnf install -y 'dnf-command(config-manager)'
|
||||
dnf config-manager --set-enabled powertools || \
|
||||
dnf config-manager --set-enabled PowerTools
|
||||
curl https://copr.fedorainfracloud.org/coprs/nmstate/nm-build-deps/repo/epel-8/nmstate-nm-build-deps-epel-8.repo > /etc/yum.repos.d/nmstate-nm-build-deps-epel-8.repo
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
NM_NO_EXTRA=1 NM_INSTALL="yum install -y" ./contrib/fedora/REQUIRED_PACKAGES
|
||||
yum install -y glibc-langpack-pl ccache clang
|
||||
|
||||
# containers have "tsflags=nodocs" in /etc/dnf/dnf.conf. We need /usr/shared/gtk-doc/html
|
||||
# to generate proper documentation.
|
||||
yum reinstall -y --setopt='tsflags=' glib2-doc
|
||||
|
||||
if command -v dnf &>/dev/null; then
|
||||
dnf install -y python3-dnf-plugins-core
|
||||
dnf debuginfo-install -y glib2
|
||||
else
|
||||
debuginfo-install -y glib2
|
||||
fi
|
||||
|
||||
contrib/scripts/nm-ci-patch-gtkdoc.sh || true
|
||||
|
||||
if [ -x /usr/bin/ninja ] && ! [ -x /usr/bin/ninja-build ]; then
|
||||
ln -s /usr/bin/ninja-build /usr/bin/ninja
|
||||
fi
|
||||
|
||||
if [ $IS_FEDORA = 1 ]; then
|
||||
TEMPLATE_SHA="$(sed -n 's/^.templates_sha: *\&template_sha *\([0-9a-f]\+\) .*/\1/p' ./.gitlab-ci/ci.template)"
|
||||
test -n "$TEMPLATE_SHA"
|
||||
dnf install -y python3-pip
|
||||
pip3 install "git+http://gitlab.freedesktop.org/freedesktop/ci-templates@$TEMPLATE_SHA"
|
||||
fi
|
||||
15
.mailmap
15
.mailmap
|
|
@ -2,13 +2,16 @@ A S Alam <aalam@users.sf.net> <amanpreet.alam@gmail.com>
|
|||
Aleksander Morgado <aleksander@aleksander.es> <aleksander@lanedo.com>
|
||||
Alfonso Sánchez-Beato <alfonso.sanchez-beato@canonical.com>
|
||||
Amitakhya Phukan <aphukan@redhat.com> <aphukan@fedoraproject.org>
|
||||
Antony Mee <eemynotna@gmail.com> <A.J.Mee@ncl.ac.uk>
|
||||
Antony Mee <antony@onlymee.co.uk> <A.J.Mee@ncl.ac.uk>
|
||||
Antony Mee <antony@onlymee.co.uk> <eemynotna@gmail.com>
|
||||
Artur Flinta <aflinta@svn.gnome.org> <aflinta@cvs.gnome.org>
|
||||
Beniamino Galvani <bgalvani@redhat.com> <b.galvani@gmail.com>
|
||||
Bryan Clark <clarkbw@cvs.gnome.org>
|
||||
Bryan Clark <clarkbw@cvs.gnome.org> <bclark@redhat.com>
|
||||
Bryan Clark <clarkbw@cvs.gnome.org> <clarkbw@gnome.org>
|
||||
Christian Kirbach <christian.kirbach@gmail.com> <Christian.Kirbach@googlemail.com>
|
||||
Christian Persch <chpe@gnome.org> <chpe@cvs.gnome.org>
|
||||
Christopher Aillon <caillon@redhat.com>
|
||||
Colin Walters <walters@verbum.org> <walters@redhat.com>
|
||||
Dan Williams <dcbw@redhat.com> <dcbw@redaht.com>
|
||||
Dan Winship <danw@redhat.com> <danw@gnome.org>
|
||||
|
|
@ -18,10 +21,11 @@ Fran Diéguez <frandieguez@gnome.org>
|
|||
Fran Diéguez <frandieguez@gnome.org> <fran.dieguez@mabishu.com>
|
||||
Francisco Javier F. Serrador <serrador@cvs.gnome.org> <serrador@openshine.com>
|
||||
Frédéric Danis <frederic.danis.oss@gmail.com> <frederic.danis.external@sigfox.com>
|
||||
Frédéric Danis <frederic.danis.oss@gmail.com> <frederic.danis@collabora.com>
|
||||
Gabor Kelemen <kelemeng@gnome.hu> <kelemeng@gnome.org>
|
||||
Gene Czarcinski <gene@czarc.net> <czar@acm.org>
|
||||
Giovanni Campagna <gcampagna@src.gnome.org> <scampa.giovanni@gmail.com>
|
||||
gunchleoc <fios@foramnagaidhlog.net> <fios@foramnagaidhlig.net>
|
||||
GunChleoc <fios@foramnagaidhlig.net> <fios@foramnagaidhlog.net>
|
||||
Hendrik Brandt <heb@gnome-de.org> <hebra@cvs.gnome.org>
|
||||
Henrique P. Machado <hpmachado@gnome.org> <zehrique@gmail.com>
|
||||
Iñaki Larrañaga Murgoitio <dooteo@euskalgnu.org>
|
||||
|
|
@ -39,6 +43,7 @@ Matej Urbančič <matej.urban@gmail.com> <mateju@svn.gnome.org>
|
|||
Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com> <mathieu-tl@ubuntu.com>
|
||||
Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com> <mathieu.tl@gmail.com>
|
||||
Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com> <mathieu@canonical.com>
|
||||
Matt Bernstein <matt@bernstein.org.uk>
|
||||
Maxim Dziumanenko <dziumanenko@gmail.com> <mvd@mylinux.com.ua>
|
||||
Maxim Dziumanenko <dziumanenko@gmail.com> <mvd@mylinux.ua>
|
||||
Michael Biebl <biebl@debian.org> <mbiebl@debian.org>
|
||||
|
|
@ -53,8 +58,9 @@ Peter Korsgaard <peter@korsgaard.com> <jacmet@sunsite.dk>
|
|||
Philip Withnall <withnall@endlessm.com> <philip@tecnocode.co.uk>
|
||||
Philip Withnall <withnall@endlessm.com> <pwithnall@svn.gnome.org>
|
||||
Priit Laes <plaes@plaes.org> <plaes at svn dot gnome dot org>
|
||||
Priit Laes <plaes@plaes.org> <plaes@svn.gnome.org>
|
||||
Priit Laes <plaes@plaes.org> <plaes@cvs.gnome.org>
|
||||
Priit Laes <plaes@plaes.org> <plaes@svn.gnome.org>
|
||||
Ray Strode <rstrode@redhat.com> <halfline@gmail.com>
|
||||
Richard Hughes <hughsient@gmail.com> <richard@hughsie.com>
|
||||
Robby Workman <rworkman@slackware.com> <rw@rlworkman.net>
|
||||
Robert Love <rml@novell.com> <rlove@rlove.org>
|
||||
|
|
@ -66,10 +72,11 @@ Scott Shambarger <devel@shambarger.net> <scott-gnome@shambarger.net>
|
|||
Simos Xenitellis <simos.bugzilla@gmail.com> <simos@gnome.org>
|
||||
Sjoerd Simons <sjoerd.simons@collabora.co.uk> <sjoerd@debian.org>
|
||||
Sjoerd Simons <sjoerd.simons@collabora.co.uk> <sjoerd@luon.net>
|
||||
Soapux <2375-Soapux@users.noreply.gitlab.freedesktop.org> <35306504+Soapux@users.noreply.github.com>
|
||||
Tambet Ingo <tambet@gmail.com> <tambet@ximian.com>
|
||||
Tomasz Dominikowski <dominikowski@gmail.com> <tdominikowski@aviary.pl>
|
||||
William Jon McCann <william.jon.mccann@gmail.com> <mccann@jhu.edu>
|
||||
Wouter Bolsterlee <wbolster@svn.gnome.org> <wbolster@gnome.org>
|
||||
Wouter Bolsterlee <wbolster@svn.gnome.org> <uws+gnome@xs4all.nl>
|
||||
Wouter Bolsterlee <wbolster@svn.gnome.org> <wbolster@gnome.org>
|
||||
Øivind Hoel <ohoel@cvs.gnome.org>
|
||||
Žygimantas Beručka <uid0@akl.lt> <zygis@gnome.org>
|
||||
|
|
|
|||
88
.travis.yml
88
.travis.yml
|
|
@ -1,88 +0,0 @@
|
|||
language: c
|
||||
dist: trusty
|
||||
sudo: required
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- autoconf
|
||||
- libtool
|
||||
- pkg-config
|
||||
- intltool
|
||||
- libdbus-1-dev
|
||||
- libiw-dev
|
||||
- libglib2.0-dev
|
||||
- libmm-glib-dev
|
||||
- ppp
|
||||
- ppp-dev
|
||||
- libpolkit-gobject-1-dev
|
||||
- libgnutls-dev
|
||||
- libgcrypt11-dev
|
||||
- uuid-dev
|
||||
- libudev-dev
|
||||
- libgirepository1.0-dev
|
||||
- gobject-introspection
|
||||
- gtk-doc-tools
|
||||
- libglib2.0-doc
|
||||
- libreadline-dev
|
||||
- libnewt-dev
|
||||
- libnss3-dev
|
||||
- iptables
|
||||
- make
|
||||
- python-software-properties
|
||||
- python-gi
|
||||
- python-dbus
|
||||
- dbus
|
||||
- dbus-x11
|
||||
- libjansson4
|
||||
- libjansson-dev
|
||||
- libndp-dev
|
||||
- automake
|
||||
- dnsmasq
|
||||
- libcurl4-gnutls-dev
|
||||
- python3-pip
|
||||
- mobile-broadband-provider-info
|
||||
coverity_scan:
|
||||
project:
|
||||
name: NetworkManager/NetworkManager
|
||||
build_command_prepend: sh autogen.sh --with-systemd-logind=no --enable-more-warnings=no --disable-ovs
|
||||
build_command: make -j4
|
||||
branch_pattern: .*coverity.*
|
||||
|
||||
before_install:
|
||||
- sudo dbus-uuidgen --ensure
|
||||
- |
|
||||
if test "$BUILD_TYPE" == 'meson'; then
|
||||
git clone https://github.com/ninja-build/ninja &&
|
||||
pushd ninja &&
|
||||
./configure.py --bootstrap &&
|
||||
sudo cp ninja /usr/bin/ &&
|
||||
popd
|
||||
|
||||
# Recent meson requires python 3.5, which isn't in Ubuntu 14.04.
|
||||
# Hence we cannot install it via `pip3 install meson`. Install the latest
|
||||
# working release.
|
||||
#
|
||||
# Wouldn't it be nice to have a build system that supports everything
|
||||
# that NetworkManager would like to support?
|
||||
wget https://github.com/mesonbuild/meson/releases/download/0.44.1/meson-0.44.1.tar.gz -O /tmp/meson.tar.gz
|
||||
tar -C /tmp -xvzf /tmp/meson.tar.gz
|
||||
pushd /tmp/meson-0.44.1
|
||||
sudo python3 setup.py install
|
||||
popd
|
||||
fi
|
||||
- sudo chmod o+x /usr/sbin/pppd
|
||||
- sudo locale-gen pl_PL.UTF-8
|
||||
|
||||
script:
|
||||
- CI=travis contrib/scripts/nm-ci-run.sh
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=autotools
|
||||
- BUILD_TYPE=meson
|
||||
global:
|
||||
secure: K36MXkcsuDZ0msuEj5zHMmHfv6O725lsXuFdP6AJ3rYWKuLYE1+iNLgIRndNWDK9ckkNQFaCxDY4Z/NCfCYQTGAS9oXR5AwNqNbhOq8XrqdaZ2GX35sob8Tp4B3IsoREkN/UbIkXQKYlA5rUhgtSifUg3EwfeOiFvnLCwHcp0rYHnvT/jaq5vodBbA1jChjezcMHsp43kvPXHpybKRkipb9EzV/V3VtDLLWh9WQBvQNawpsHnT+MXSke1yU1zfNMyD9XiD7VDzCwaTs6LzjoFBLc86QS5U/9W72s0rFe6SbecntQHftknRzSrGiJDNe64wDZN/Wxq1MHxEOFCwDi6vcSwQ+RoTdhyshhfPVY2Mm5soj2w7Dx43Cz0dDZDCMhu5xxzFAFgkieJSfwXbuxga0ds58Ph8MgtDSp3fBRewZwI+vMuzl7a1hGkcqJojrm1lfgAKbNgrNUzQRwbVYAyrpa6/vCbd6ZH4PEtITwLaRf2mz8PG71xiMQguDDDXS8WF0U7Looe+G9ybAUwDS5hqHfeP+3q6bfN5Sg5Zs5QkBIN5LZbeWbPYldOEEDTvo3VI7e84bk7U5qEoUKc0w/tqVF1B5KgNUq6nIkCkmoBx8RFnmjpOHh99IfeRG9nQTRpCaEDvAM4fcRzITzId8dIIfAW/45P3ozzfz/HYiie+o=
|
||||
67
.triage-policies.yml
Normal file
67
.triage-policies.yml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
host_url: https://gitlab.freedesktop.org
|
||||
|
||||
resource_rules:
|
||||
issues:
|
||||
rules:
|
||||
- name: Close issues with no activity for 6 months
|
||||
conditions:
|
||||
date:
|
||||
attribute: updated_at
|
||||
condition: older_than
|
||||
interval_type: months
|
||||
interval: 6
|
||||
state: opened
|
||||
actions:
|
||||
comment: |
|
||||
This issue has been inactive for 6 months, closing automatically, please reopen if you think the issue is still relevant.
|
||||
status: close
|
||||
labels:
|
||||
- auto-closed
|
||||
- name: Close RFE with no activity for 12 months
|
||||
conditions:
|
||||
date:
|
||||
attribute: updated_at
|
||||
condition: older_than
|
||||
interval_type: months
|
||||
interval: 12
|
||||
state: opened
|
||||
labels:
|
||||
- enhancement
|
||||
actions:
|
||||
comment: |
|
||||
This enhancement issue has been inactive for 12 months, closing automatically, please reopen if you think the issue is still relevant.
|
||||
status: close
|
||||
labels:
|
||||
- auto-closed
|
||||
- name: Clear auto-closed label for open issues
|
||||
conditions:
|
||||
state: opened
|
||||
labels:
|
||||
- auto-closed
|
||||
actions:
|
||||
remove_labels:
|
||||
- auto-closed
|
||||
merge_requests:
|
||||
rules:
|
||||
- name: Close MRs with no activity after 2 month
|
||||
conditions:
|
||||
date:
|
||||
attribute: updated_at
|
||||
condition: older_than
|
||||
interval_type: months
|
||||
interval: 2
|
||||
state: opened
|
||||
actions:
|
||||
comment: |
|
||||
This MR has been inactive for more than 2 months, closing automatically, please reopen if you think it is still relevant.
|
||||
status: close
|
||||
labels:
|
||||
- auto-closed
|
||||
- name: Clear auto-closed label for open MRs
|
||||
conditions:
|
||||
state: opened
|
||||
labels:
|
||||
- auto-closed
|
||||
actions:
|
||||
remove_labels:
|
||||
- auto-closed
|
||||
82
CONTRIBUTING
82
CONTRIBUTING
|
|
@ -1,38 +1,51 @@
|
|||
Guidelines for Contributing
|
||||
===========================
|
||||
|
||||
|
||||
Coding Standard
|
||||
---------------
|
||||
|
||||
Coding standards are generally GNOME coding standards, with these exceptions:
|
||||
a) 4 space tabs (_not_ 8-space tabs)
|
||||
b) REAL tabs (_not_ a mix of tabs and spaces in the initial indent)
|
||||
c) spaces used to align continuation lines past the indent point of the
|
||||
first statement line, like so:
|
||||
The formatting uses clang-format with clang 11.0. Run
|
||||
`./contrib/scripts/nm-code-format.sh -i` to reformat the code
|
||||
or call `clang-format` yourself.
|
||||
You may also call `./contrib/scripts/nm-code-format-container.sh`
|
||||
which runs a Fedora 33 container using podman.
|
||||
You are welcome to not bother and open a merge request with
|
||||
wrong formatting, but note that we then will automatically adjust
|
||||
your contribution before merging.
|
||||
|
||||
if ( some_really_really_long_variable_name
|
||||
&& another_really_really_long_variable_name) {
|
||||
...
|
||||
}
|
||||
The automatic reformatting was done by commit 328fb90f3e0d4e35975aff63944ac0412d7893a5.
|
||||
Use `--ignore-rev` option or `--ignore-revs-file .git-blame-ignore-revs` to ignore
|
||||
the reformatting commit with git-blame:
|
||||
|
||||
* Keep a space between the function name and the opening '('.
|
||||
GOOD: g_strdup (x)
|
||||
BAD: g_strdup(x)
|
||||
```
|
||||
$ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
|
||||
```
|
||||
|
||||
Since our coding style is entirely automated, the following are just
|
||||
some details of the style we use:
|
||||
|
||||
* Indent with 4 spaces. (_no_ tabs).
|
||||
|
||||
* Have no space between the function name and the opening '('.
|
||||
- GOOD: `g_strdup(x)`
|
||||
- BAD: `g_strdup (x)`
|
||||
|
||||
* C-style comments
|
||||
GOOD: f(x); /* comment */
|
||||
BAD: f(x); // comment
|
||||
- GOOD: `f(x); /* comment */`
|
||||
- BAD: `f(x); // comment`
|
||||
|
||||
* Keep assignments in the variable declaration area pretty short.
|
||||
GOOD: MyObject *object;
|
||||
BAD: MyObject *object = complex_and_long_init_function(arg1, arg2, arg3);
|
||||
- GOOD: `MyObject *object;`
|
||||
- BAD: `MyObject *object = complex_and_long_init_function(arg1, arg2, arg3);`
|
||||
|
||||
* 80-cols is a guideline, don't make the code uncomfortable in order to fit in
|
||||
less than 80 cols.
|
||||
|
||||
* Constants are CAPS_WITH_UNDERSCORES and use the preprocessor.
|
||||
GOOD: #define MY_CONSTANT 42
|
||||
BAD: static const unsigned myConstant = 42;
|
||||
- GOOD: `#define MY_CONSTANT 42`
|
||||
- BAD: `static const unsigned myConstant = 42;`
|
||||
|
||||
|
||||
Legal
|
||||
-----
|
||||
|
|
@ -46,6 +59,8 @@ Note that all new contributions to NetworkManager MUST be made under terms of
|
|||
LGPL-2.1+, that is also the case for parts that are currently licensed GPL-2.0+.
|
||||
The reason for that is that we might eventually relicense everything as LGPL and
|
||||
new contributions already must agree with that future change.
|
||||
For more details see [RELICENSE.md](RELICENSE.md).
|
||||
|
||||
|
||||
Assertions in NetworkManager code
|
||||
---------------------------------
|
||||
|
|
@ -118,3 +133,34 @@ For testing, you also want to run NetworkManager with environment variable
|
|||
G_DEBUG=fatal-warnings to crash upon G_LOG_LEVEL_CRITICAL and G_LOG_LEVEL_WARNING
|
||||
g_log() message. NetworkManager won't use these levels for regular logging
|
||||
but for assertions.
|
||||
|
||||
|
||||
Git Notes (refs/notes/bugs)
|
||||
---------------------------
|
||||
|
||||
There are special notes to annotate git commit messages with information
|
||||
about "Fixes" and "cherry picked from". Annotating the history is useful
|
||||
if it was not done initially because our scripts can make use of it.
|
||||
|
||||
The notes it are called "refs/notes/bugs".
|
||||
|
||||
So configure:
|
||||
|
||||
```
|
||||
$ git config --add 'remote.origin.fetch' 'refs/notes/bugs:refs/notes/bugs'
|
||||
$ git config --add 'notes.displayref' 'refs/notes/bugs'
|
||||
```
|
||||
|
||||
For example, set notes with
|
||||
|
||||
```
|
||||
$ git notes --ref refs/notes/bugs add -m "(cherry picked from $COMMIT_SHA)" HEAD
|
||||
```
|
||||
|
||||
You should see the notes in git-log output as well.
|
||||
|
||||
To resync our local notes use:
|
||||
|
||||
```
|
||||
$ git fetch origin refs/notes/bugs:refs/notes/bugs -f
|
||||
```
|
||||
|
|
|
|||
808
Makefile.am
808
Makefile.am
File diff suppressed because it is too large
Load diff
|
|
@ -178,8 +178,10 @@ EXTRA_DIST += \
|
|||
examples/python/gi/list-connections.py \
|
||||
examples/python/gi/nm-add-connection2.py \
|
||||
examples/python/gi/nm-connection-update-stable-id.py \
|
||||
examples/python/gi/nm-keyfile.py \
|
||||
examples/python/gi/nm-update2.py \
|
||||
examples/python/gi/nm-wg-set \
|
||||
examples/python/gi/ovs-external-ids.py \
|
||||
examples/python/gi/setting-user-data.py \
|
||||
examples/python/gi/show-wifi-networks.py \
|
||||
examples/python/gi/update-ip4-method.py \
|
||||
|
|
|
|||
173
NEWS
173
NEWS
|
|
@ -1,28 +1,187 @@
|
|||
=============================================
|
||||
NetworkManager-1.30
|
||||
Overview of changes since NetworkManager-1.28
|
||||
=============================================
|
||||
|
||||
This is a snapshot of NetworkManager 1.30 development series.
|
||||
The API is subject to change and not guaranteed to be compatible
|
||||
with the later release.
|
||||
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||
|
||||
* libnm: nm_setting_bond_add_option() no longer validates the
|
||||
option that is set. Instead, use nm_connection_verify() to validate
|
||||
the profile.
|
||||
* Increase timeout of NetworkManager-wait-online.service to 60 seconds.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.28
|
||||
Overview of changes since NetworkManager-1.26
|
||||
=============================================
|
||||
|
||||
* Introduce a new "rc-manager=auto" setting and make it the default,
|
||||
unless a different default is chosen at compile time. This mode
|
||||
tries to detect "systemd-resolved", "resolvconf", and "netconfig"
|
||||
and chooses the mode that seems most suitable depending on build
|
||||
setting and runtime detection. "resolvconf" and "netconfig" are
|
||||
only considered iff NetworkManager was built with the respective
|
||||
options enabled.
|
||||
* The long deprecated D-Bus property "Ip4Address" on
|
||||
"org.freedesktop.NetworkManager.Device" interface is now defunct and
|
||||
always returns zero.
|
||||
* Introduce a ipv4.dhcp-reject-servers connection property that
|
||||
specifies a list of DHCP server-ids from which offers should be
|
||||
rejected.
|
||||
* Add a ipv4.dhcp-vendor-class-identifier connection property to send
|
||||
a custom value for the Vendor Class Identifier DHCP option.
|
||||
* Support obtaining the system hostname through the FQDN DHCPv6
|
||||
option.
|
||||
* dbus: don't require policykit permission for GetAppliedConnection of
|
||||
a device.
|
||||
* When supported by kernel, use netlink to configure bridge settings
|
||||
instead of writing to sysfs.
|
||||
* Deprecate the "active_slave" bond option which now has the same effect
|
||||
as setting the "primary" option.
|
||||
* The initrd generator now also accepts MAC addresses to indicate
|
||||
interfaces.
|
||||
* Add a new provider for nm-cloud-setup to support automatic network
|
||||
configuration on Azure.
|
||||
* The initrd generator now supports creating Infiniband connections.
|
||||
* Fix running DHCPv6-PD over PPPoE.
|
||||
* Fix building NetworkManager with LTO (Link Time Optimization).
|
||||
* Fix failure activating Wi-Fi P2P connections.
|
||||
* Reformat code using spaces instead of tabs. Also, the entire C
|
||||
source code is now formatted with "clang-format" (version 11.0).
|
||||
* Change the behavior of nm-initrd-generator so that the 'ip=off|none' kernel
|
||||
cmdline argument actually generates a connection which disables both
|
||||
ipv4 and ipv6. Previously the generated connection would disable ipv4
|
||||
but ipv6 would be set to the 'auto' method.
|
||||
* Fix systemd-resolved DNS plugin to configure DefaultRoute option and to
|
||||
only configure wildcard DNS search domain with exclusive DNS priority.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.26
|
||||
Overview of changes since NetworkManager-1.24
|
||||
=============================================
|
||||
|
||||
* Add a new build option 'firewalld-zone'; when enabled,
|
||||
NetworkManager installs a firewalld zone for connection sharing and
|
||||
puts interfaces using IPv4 or IPv6 shared mode in this zone during
|
||||
activation. The option is enabled by default.
|
||||
Note that NetworkManager still calls to iptables to enable
|
||||
masquerading and open needed ports for DHCP and DNS. The new option
|
||||
is useful on systems using firewalld with the nftables backend,
|
||||
where the iptables rules would not be sufficient.
|
||||
* Extend the syntax for 'match' setting properties with '|', '&', '!'
|
||||
and '\\'.
|
||||
* Add MUD URL property for connection profiles (RFC 8520) and set it
|
||||
for DHCP and DHCPv6 requests.
|
||||
* Expose raw LLDP message on D-Bus and the MUD usage description URL.
|
||||
* ifcfg-rh: handle "802-1x.{,phase2-}ca-path". Otherwise setting this
|
||||
property silently fails and a profile might accidentally not perform
|
||||
any authentication (CVE-2020-10754).
|
||||
* ifcfg-rh: handle 802-1x.pin properties.
|
||||
* ethernet: reset original autonegotiation/speed/duplex settings when
|
||||
deactivating device.
|
||||
* Support ethtool coalesce and ring options.
|
||||
* Allow team connections to work without D-Bus (e.g. in the initrd).
|
||||
* Wi-Fi profiles now also autoconnect if all previous activation attempts
|
||||
failed. This means, an initial failure to autoconnect to the network will
|
||||
no longer block the automatism. A side effect is that existing Wi-Fi profiles
|
||||
which previously were blocked may now start to autoconnect.
|
||||
* NetworkManager now supports "local" type routes beside "unicast".
|
||||
* Introduce new manual pages nm-settings-dbus and nm-settings-nmcli.
|
||||
* Mark externally managed devices and profiles on D-Bus.
|
||||
* Highlight externally managed devices in nmcli.
|
||||
* Add support for a number of bridge options.
|
||||
* Add match for device path, driver and kernel command line for connection
|
||||
profiles.
|
||||
* Fix support for OVS patch interfaces.
|
||||
* Support more tc qdiscs: tbf and sfq.
|
||||
* Add new provider in nm-cloud-setup for Google Cloud Platform which
|
||||
automatically detects and configures the host to receive traffic
|
||||
from internal load balancers.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.24
|
||||
Overview of changes since NetworkManager-1.22
|
||||
=============================================
|
||||
|
||||
* Add support for virtual routing and forwarding (VRF) interfaces.
|
||||
* Add support for Opportunistic Wireless Encryption mode (OWE) for Wi-Fi networks.
|
||||
* Add support for 31-bit prefixes on IPv4 point-to-point links according to
|
||||
RFC 3021.
|
||||
* Drop dependencies for libpolkit-agent-1 and libpolkit-gobject-1.
|
||||
* nmcli:
|
||||
- support setting removal via new command
|
||||
`nmcli connection modify $CON_NAME remove $setting`.
|
||||
- support backslash escape sequences for "vpn.data", "vpn.secrets",
|
||||
"bond.options", and "ethernet.s390-options".
|
||||
* bridge: support new options "bridge.multicast-querier", "bridge.multicast-query-use-ifaddr",
|
||||
"bridge.multicast-router", "bridge.vlan-stats-enabled", "bridge.vlan-protocol",
|
||||
"bridge.group-address".
|
||||
* IPv6 SLAAC: add support for "ipv6.ra-timeout" setting
|
||||
* IPv6 DHCP: add support for "ipv6.dhcp-timeout" setting
|
||||
* WWAN: NetworkManager now detects if a PIN-protected SIM card has been
|
||||
externally unlocked and automatically tries to activate a suitable
|
||||
connection on the modem.
|
||||
* OVS:
|
||||
- add support for changing MTU of OVS interfaces.
|
||||
- remove length limitation for OVS Bridge, Patches and Interfaces
|
||||
(only Patch types) names.
|
||||
* VPN: accept empty values for VPN data items and secrets.
|
||||
* All nm-devices now expose the 'HwAddress' property via D-Bus.
|
||||
* Slave devices now do not get created/activated if master is missing.
|
||||
* Fixed multiple issues in the internal "nettools" DHCP client.
|
||||
* Export NM_CAPABILITY_OVS capability on D-Bus and in libnm to
|
||||
indicate that the OVS plugin is loaded.
|
||||
* Fixes for importing WireGuard profiles in nmcli and better handle
|
||||
configurations that enable ip4-auto-default-route with an explicit
|
||||
gateway.
|
||||
* Various bug fixes and improvements.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.22
|
||||
Overview of changes since NetworkManager-1.20
|
||||
=============================================
|
||||
|
||||
This is a snapshot of NetworkManager 1.22 development series.
|
||||
The API is subject to change and not guaranteed to be compatible
|
||||
with the later release.
|
||||
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||
This is a new stable release of NetworkManager. Notable changes include:
|
||||
|
||||
* Drop support for BlueZ 4. BlueZ 5 was released in 2012 and should
|
||||
nowadays be available everywhere.
|
||||
* DHCP: switch "internal" DHCPv4 plugin from code based on systemd to use nettools'
|
||||
n-dhcp4 library.
|
||||
* Add support for "scope" attribute for IPv4 routes.
|
||||
* Add support for specifying IAID and FQDN flags for DHCP request.
|
||||
* Add a '802-1x.optional' property to consider the wired 802.1X authentication as
|
||||
optional.
|
||||
* Use the Network Cost Wi-Fi information element to determine metered
|
||||
device state.
|
||||
* Support main.auth-polkit=root-only setting to disable PolicyKit use and
|
||||
restrict authorization to root user.
|
||||
* core: declare "startup complete" when device reaches "connected"
|
||||
state, even if IP addressing methods did not yet fully complete.
|
||||
This changes behavior for unblocking "NetworkManager-wait-online.service",
|
||||
and "network-online.target" earlier. If this causes issues in your
|
||||
setup, you may need to configure "ipv4.may-fail=no" or "ipv6.may-fail=no",
|
||||
which delays reaching "connected" state for the address family accordingly.
|
||||
* Various bug fixes and improvements.
|
||||
* libnm: hide NMObject and NMClient typedefs from header files. This prevents
|
||||
the user from subclassing these types and is an ABI change (in case somebody
|
||||
was doing so).
|
||||
the user from subclassing these types and is an ABI change (in the unlikely
|
||||
case that a user was subclassing the types, which is no longer supported).
|
||||
* libnm: retire deprecated WiMAX API NMDeviceWimax and NMWimaxNsp.
|
||||
WiMAX support was removed from NetworkManager in version 1.2 (2016) and no such
|
||||
type instances would have been created by NMClient for a while now.
|
||||
* Deprecate synchronous API for D-Bus calls in libnm. We don't remove libnm API so
|
||||
you are free to continue using it. But tells you that using it might be a bad idea.
|
||||
* libnm: heavily internal rework NMClient. This slims down libnm and makes the
|
||||
implementation more efficient. NMClient should work now well with a separate
|
||||
GMainContext.
|
||||
* Add `nmcli general reload` subcommand to reload NetworkManager configuration
|
||||
and DNS settings.
|
||||
* nm-cloud-setup: add new tool for automatically configuring NetworkManager
|
||||
in cloud. This is still experimental and currently only EC2 and IPv4 is
|
||||
supported.
|
||||
* Add new NetworkManager logo to "contrib/art/logo".
|
||||
* Various bug fixes and improvements.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.20
|
||||
|
|
|
|||
143
RELICENSE.md
Normal file
143
RELICENSE.md
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
Relicensing NetworkManager GPL Code as LGPL-2.1+
|
||||
================================================
|
||||
|
||||
This NetworkManager project consists of the daemon, client tools, and libnm.
|
||||
libnm is licensed LGPL-2.1+, while the rest is licensed under GPL-2.0+.
|
||||
|
||||
|
||||
Why Relicensing?
|
||||
================
|
||||
|
||||
Mixing two licenses in the same source tree is cumbersome:
|
||||
|
||||
1) We want to share code internally and reuse it. In particular under "shared/" directory
|
||||
there are internal static libraries that get linked both into LGPL and GPL code.
|
||||
That implies that this shared code itself must be LGPL licensed. Being unable to
|
||||
move code around within our source tree is a painful restriction. Possibly we get
|
||||
that wrong sometimes, wrongly moving GPL code as LGPL (either directly or by rewriting
|
||||
it based on GPL code).
|
||||
|
||||
2) For example keyfile and ifcfg-rh implementations are GPL licensed as they
|
||||
are historically part of core. It would be useful to add this functionality
|
||||
to libnm, so that libnm users can handle the file formats directly. That is
|
||||
not possible without relicensing.
|
||||
|
||||
3) Maybe one day we would relicense the entire source tree as LGPL-2.1+ to avoid
|
||||
this issue. This would require agreement from all copyright holders.
|
||||
|
||||
|
||||
Full relicensing (point 3) is a large effort, or maybe even impossible. However sometimes
|
||||
we may need to evaluate whether small parts can be relicensed (points 2 and 1). This
|
||||
file keeps track of copyright holders that agree or disapprove to such a license change.
|
||||
|
||||
|
||||
Which Code?
|
||||
===========
|
||||
|
||||
This applies to all GPL-2.0+ code in commit a3e75f329446a93a61ca4c458a7657bd919f4fe6 ([1]) and
|
||||
all its parent commits.
|
||||
|
||||
Since commit a3e75f329446a93a61ca4c458a7657bd919f4fe6 ([1]), the CONTRIBUTING file ([2]) makes
|
||||
it clear that all new contributions must to be provided under terms of LGPL-2.1+. So this
|
||||
approval process is only relevant for GPL-2.0+ code from before that. This was also announced on
|
||||
the mailing list on June 12 2019 ([3]). Note that the announcement was still talking about LGPL-2.0+
|
||||
but in the meantime we only request LGPL-2.1+ ([4]).
|
||||
|
||||
- [1] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/commit/a3e75f329446a93a61ca4c458a7657bd919f4fe6
|
||||
- [2] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/blob/a3e75f329446a93a61ca4c458a7657bd919f4fe6/CONTRIBUTING#L37
|
||||
- [3] https://mail.gnome.org/archives/networkmanager-list/2019-June/msg00006.html
|
||||
- [4] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/commit/3c36231706a9314f6bf03901dd13923cd32a5457
|
||||
|
||||
|
||||
Consent/Disapproval about What?
|
||||
===============================
|
||||
|
||||
Whether the copyright holder agrees to relicense the code in a3e75f329446a93a61ca4c458a7657bd919f4fe6
|
||||
and its parent commits under terms of LGPL-2.1+.
|
||||
|
||||
|
||||
How to Track Consent/Disapproval?
|
||||
=================================
|
||||
|
||||
The consent/disapproval is tracked in this file for the copyright holders
|
||||
who made their wish known. In the list below [Y] indicates consent while [N]
|
||||
indicates disapproval. [?] indicates yet unknown data.
|
||||
To express the wish either send an email to our mailing list <networkmanager-list@gnome.org>
|
||||
or open a merge request against this file, adding your name to the list. Then this
|
||||
file will be updated to track the information. The git commit messages in the history
|
||||
of this file will give details when/how an entry was added.
|
||||
|
||||
|
||||
Consent/Disapproval List
|
||||
========================
|
||||
|
||||
- [Y] Aleksander Morgado <aleksander@aleksander.es>
|
||||
- [Y] Alfonso Sánchez-Beato <alfonso.sanchez-beato@canonical.com> (Canonical, Ltd.)
|
||||
- [Y] Andrew Zaborowski <andrew.zaborowski@intel.com> (Intel Corporation)
|
||||
- [Y] Antoine Faure <antoine.faure@sigfox.com> (Sigfox)
|
||||
- [Y] Antony Mee <antony@onlymee.co.uk>
|
||||
- [Y] Atul Anand <atulhjp@gmail.com>
|
||||
- [Y] Beniamino Galvani <bgalvani@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Benjamin Berg <bberg@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Bryan Clark <clarkbw@cvs.gnome.org> (Red Hat, Inc.)
|
||||
- [Y] Christian Kellner <christian@kellner.me> (Red Hat, Inc.)
|
||||
- [Y] Colin Walters <walters@verbum.org> (Red Hat, Inc.)
|
||||
- [Y] Corentin Noël <corentin@elementary.io>
|
||||
- [Y] Dan Williams <dcbw@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Dan Winship <danw@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Daniel Drake <dsd@laptop.org> (One Laptop per Child)
|
||||
- [Y] Daniel Gnoutcheff <daniel@gnoutcheff.name>
|
||||
- [Y] David Cantrell <dcantrell@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Evan Broder <evan@ebroder.net>
|
||||
- [Y] Florian Echtler <floe@butterbrot.org>
|
||||
- [Y] Francesco Giudici <fgiudici@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Frédéric Danis <frederic.danis.oss@gmail.com> (Collabora Ltd, Sigfox)
|
||||
- [Y] Giovanni Campagna <gcampagna@src.gnome.org>
|
||||
- [Y] Ikey Doherty <michael.i.doherty@intel.com> (Intel Corporation)
|
||||
- [Y] Iñigo Martínez <inigomartinez@gmail.com>
|
||||
- [Y] Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
|
||||
- [Y] Jan Luebbe <jlu@pengutronix.de> (Pengutronix)
|
||||
- [Y] Jan Tojnar <jtojnar@gmail.com>
|
||||
- [Y] Javier Arteaga <jarteaga@jbeta.is>
|
||||
- [Y] Jiří Klimeš <blueowl@centrum.cz> (Red Hat, Inc.)
|
||||
- [Y] Kjartan Maraas <kmaraas@gnome.org>
|
||||
- [Y] Lubomir Rintel <lkundrak@v3.sk> (Red Hat, Inc.)
|
||||
- [Y] Mario Sanchez Prada <mario@endlessm.com> (Endless Mobile, Inc.)
|
||||
- [Y] Marius Vollmer <mvollmer@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Martin Pitt <martinpitt@gnome.org> (Canonical, Ltd.)
|
||||
- [Y] Michael Biebl <biebl@debian.org>
|
||||
- [Y] Pantelis Koukousoulas <pktoss@gmail.com>
|
||||
- [Y] Pavel Šimerda <pavlix@pavlix.net> (Red Hat, Inc.)
|
||||
- [Y] Przemysław Grzegorczyk <pgrzegorczyk@gmail.com>
|
||||
- [Y] Rafael Fontenelle <rafaelff@gnome.org>
|
||||
- [Y] Ray Strode <rstrode@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Robert Love <rml@novell.com> (Novell, Inc.)
|
||||
- [Y] Sebastien Fabre <sebastien.fabre@sigfox.com> (Sigfox)
|
||||
- [Y] Soapux <2375-Soapux@users.noreply.gitlab.freedesktop.org>
|
||||
- [Y] Taegil Bae <esrevinu@gmail.com>
|
||||
- [Y] Tambet Ingo <tambet@gmail.com> (Novell, Inc.)
|
||||
- [Y] Thomas Bechtold <thomasbechtold@jpberlin.de>
|
||||
- [Y] Thomas Haller <thaller@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Timothy Redaelli <tredaelli@redhat.com> (Red Hat, Inc.)
|
||||
- [Y] Yuri Chornoivan <yurchor@ukr.net>
|
||||
- [Y] Zephaniah E. Loss-Cutler-Hull <warp@aehallh.com>
|
||||
- [Y] luz.paz <luzpaz@users.noreply.github.com>
|
||||
|
||||
Copyright Held by Other Legal Entities
|
||||
======================================
|
||||
|
||||
The contributors above may have contributed the code on behalf of a company
|
||||
that holds the copyright. This list tracks such legal entities. The contributor
|
||||
list above indicates whether a contributor provided code for a legal entity here.
|
||||
|
||||
- [Y] Canonical, Ltd.
|
||||
- [Y] Endless Mobile, Inc.
|
||||
- [Y] Endless OS LLC
|
||||
- [Y] Intel Corporation
|
||||
- [Y] Novell, Inc.
|
||||
- [Y] One Laptop per Child
|
||||
- [Y] Pengutronix
|
||||
- [Y] Red Hat, Inc.
|
||||
- [Y] SUSE
|
||||
- [Y] Sigfox
|
||||
- [Y] Ximian, Inc.
|
||||
75
TODO
75
TODO
|
|
@ -1,51 +1,42 @@
|
|||
So you're interested in hacking on NetworkManager? Here's some cool
|
||||
stuff you could do...
|
||||
|
||||
* Internet Connectivity Detection Enhancements
|
||||
* Use netlink API instead of ioctl based ethtool.
|
||||
|
||||
Current connectivity checking is global, while what we really want is to check
|
||||
connectivity per-interface and update the global state based on the composite
|
||||
of each device's state. Unfortunately that requires two things:
|
||||
|
||||
1) latest libsoup and glib for using libsoup connection state signals, which
|
||||
allow us to set socket options before the actual connection is made; here
|
||||
we'd bind the socket to the specific IP address of the interface we're
|
||||
using, and possibly set SO_BINDTODEVICE as well
|
||||
2) setting /proc/sys/net/ipv4/conf/<iface>/rp_filter to "2" which tells the
|
||||
kernel to route the incoming and outgoing packet properly even though the
|
||||
interface may not have the necessary routes
|
||||
|
||||
The first is the largest obstacle, but ideally we implement this and enable it
|
||||
when we have the required glib and libsoup versions available. One other
|
||||
complication is that this checking should be done during the
|
||||
NM_DEVICE_STATE_IP_CHECK phase (along with other operations like Wi-Fi hotspot
|
||||
auto-login) while the current checks are done globally in nm-manager.c, so
|
||||
keeping both code paths might be complex.
|
||||
|
||||
But ideally, once the device has successfully gotten an IPv4 or IPv6 address, it
|
||||
should enter the state NM_DEVICE_STATE_IP_CHECK, where a connectivity check is
|
||||
started. After the check returns, the device would set a property in
|
||||
NMDevicePrivate to indicate whether Internet access was successful or not, and
|
||||
advance to the NM_DEVICE_STATE_ACTIVATED state.
|
||||
|
||||
The NMManager object, when determining the overall NM_STATE_* state in the
|
||||
nm_manager_update_state() function, would query this property and set
|
||||
NM_STATE_CONNECTED_LOCAL, NM_STATE_CONNECTED_SITE, or NM_STATE_CONNECTED_GLOBAL
|
||||
based on it and the device's state.
|
||||
NetworkManager uses ethtool API to set/obtain certain settings of network
|
||||
devices. This is an ioctl based API and implmented in "src/platform/nm-platform-utils.c".
|
||||
Recently, kernel got a netlink API for the same functionality
|
||||
(https://www.kernel.org/doc/html/latest/networking/ethtool-netlink.html).
|
||||
NetworkManager should use this API if present, and fallback to the old API
|
||||
when running on older kernels. The benefit if this is that netlink provides
|
||||
notifications when settings change. The ethtool command line tool
|
||||
also implements this API, however it is under an incompatible license,
|
||||
so better don't look and make sure not to use the code.
|
||||
|
||||
|
||||
* Implement NM_DEVICE_STATE_DISCONNECTING
|
||||
* Add 802-1x capability to nmtui.
|
||||
|
||||
To allow for "pre-down" scenarios, this state should be implemented before a
|
||||
device is taken down while it still has connectivity. If the device is
|
||||
taken down because its ethernet carrier was dropped, or because the WiFi
|
||||
connection was terminated by the supplicant, this state is pointless and should
|
||||
be skipped. But if the user requested a manual "disconnect", or NM is dropping
|
||||
connections on exit, etc, then this state should be entered. In the future
|
||||
this state should hook into a new dispatcher action in src/NetworkManagerUtils.c
|
||||
to exectue dispatcher scripts during the disconnection, and to wait a limited
|
||||
amount of time for each script to complete before allowing the device to
|
||||
proceed to the NM_DEVICE_STATE_DISCONNECTED state, fully implementing pre-down.
|
||||
Add dialogs to nmtui for 802-1x. This will be useful for ethernet (with 802-1x
|
||||
port authentication), enterprise Wi-Fi and MACSec. From the GUI and dialog design,
|
||||
possibly get inspired by nm-connection-editor.
|
||||
|
||||
|
||||
* Add Azure support to nm-cloud-setup.
|
||||
|
||||
Currently, nm-cloud-setup only works for EC2 (and only for IPv4). Add support for Azure
|
||||
cloud. See for example SUSE's cloud-netconfig which supports Azure
|
||||
(https://github.com/SUSE-Enceladus/cloud-netconfig,
|
||||
https://www.suse.com/c/multi-nic-cloud-netconfig-ec2-azure/). Note that cloud-netconfig
|
||||
is under an incompatible license, so be careful not to reuse any code. But that would
|
||||
anyway be almost impossible, because one is written in bash and the other in C.
|
||||
|
||||
|
||||
* Improve our gitlab-ci integration.
|
||||
|
||||
Currently, our .gitlab-ci starts various base containers and first installs
|
||||
the necessary dependencies. That takes time and consumes bandwidth, we should
|
||||
instead use more suitable containers. We should instead use ci-templates from
|
||||
https://gitlab.freedesktop.org/freedesktop/ci-templates.
|
||||
|
||||
|
||||
* Ethernet Network Auto-detection
|
||||
|
|
@ -119,7 +110,7 @@ connected before the drop.
|
|||
* VPN IP Methods
|
||||
|
||||
Some VPNs (openvpn with TAP for example) require that DHCP is run on a
|
||||
pseudo-ethernet device to obtain addressing information. This is not currently
|
||||
pseudo-ethernet device to obtain addressing information. Currenty, this is not
|
||||
possible, but NM already has all the code for DHCP. Thus, a new "method"
|
||||
key should be defined in include/NetworkManagerVPN.h to allow for DHCP to
|
||||
be performed if the VPN service daemon requests it in the IP4Config or IP6Config
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ AUTOPOINT='intltoolize --automake --copy' autoreconf --force --install --verbose
|
|||
|
||||
cd $olddir
|
||||
if test -z "$NOCONFIGURE"; then
|
||||
exec $srcdir/configure --enable-maintainer-mode --enable-more-warnings=error --enable-gtk-doc --enable-introspection "$@"
|
||||
exec $srcdir/configure --enable-maintainer-mode --enable-more-warnings=error --enable-gtk-doc --enable-introspection "$@"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <readline/readline.h>
|
||||
|
|
@ -16,205 +14,217 @@
|
|||
#include "utils.h"
|
||||
#include "nm-secret-agent-simple.h"
|
||||
#include "polkit-agent.h"
|
||||
#include "nm-polkit-listener.h"
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
usage(void)
|
||||
{
|
||||
g_printerr (_("Usage: nmcli agent { COMMAND | help }\n\n"
|
||||
"COMMAND := { secret | polkit | all }\n\n"
|
||||
));
|
||||
g_printerr(_("Usage: nmcli agent { COMMAND | help }\n\n"
|
||||
"COMMAND := { secret | polkit | all }\n\n"));
|
||||
}
|
||||
|
||||
static void
|
||||
usage_agent_secret (void)
|
||||
usage_agent_secret(void)
|
||||
{
|
||||
g_printerr (_("Usage: nmcli agent secret { help }\n"
|
||||
"\n"
|
||||
"Runs nmcli as NetworkManager secret agent. When NetworkManager requires\n"
|
||||
"a password it asks registered agents for it. This command keeps nmcli running\n"
|
||||
"and if a password is required asks the user for it.\n\n"));
|
||||
g_printerr(_("Usage: nmcli agent secret { help }\n"
|
||||
"\n"
|
||||
"Runs nmcli as NetworkManager secret agent. When NetworkManager requires\n"
|
||||
"a password it asks registered agents for it. This command keeps nmcli running\n"
|
||||
"and if a password is required asks the user for it.\n\n"));
|
||||
}
|
||||
|
||||
static void
|
||||
usage_agent_polkit (void)
|
||||
usage_agent_polkit(void)
|
||||
{
|
||||
g_printerr (_("Usage: nmcli agent polkit { help }\n"
|
||||
"\n"
|
||||
"Registers nmcli as a polkit action for the user session.\n"
|
||||
"When a polkit daemon requires an authorization, nmcli asks the user and gives\n"
|
||||
"the response back to polkit.\n\n"));
|
||||
g_printerr(_("Usage: nmcli agent polkit { help }\n"
|
||||
"\n"
|
||||
"Registers nmcli as a polkit action for the user session.\n"
|
||||
"When a polkit daemon requires an authorization, nmcli asks the user and gives\n"
|
||||
"the response back to polkit.\n\n"));
|
||||
}
|
||||
|
||||
static void
|
||||
usage_agent_all (void)
|
||||
usage_agent_all(void)
|
||||
{
|
||||
g_printerr (_("Usage: nmcli agent all { help }\n"
|
||||
"\n"
|
||||
"Runs nmcli as both NetworkManager secret and a polkit agent.\n\n"));
|
||||
g_printerr(_("Usage: nmcli agent all { help }\n"
|
||||
"\n"
|
||||
"Runs nmcli as both NetworkManager secret and a polkit agent.\n\n"));
|
||||
}
|
||||
|
||||
/* for pre-filling a string to readline prompt */
|
||||
static char *pre_input_deftext;
|
||||
static int
|
||||
set_deftext (void)
|
||||
set_deftext(void)
|
||||
{
|
||||
if (pre_input_deftext && rl_startup_hook) {
|
||||
rl_insert_text (pre_input_deftext);
|
||||
g_free (pre_input_deftext);
|
||||
pre_input_deftext = NULL;
|
||||
rl_startup_hook = NULL;
|
||||
}
|
||||
return 0;
|
||||
if (pre_input_deftext && rl_startup_hook) {
|
||||
rl_insert_text(pre_input_deftext);
|
||||
g_free(pre_input_deftext);
|
||||
pre_input_deftext = NULL;
|
||||
rl_startup_hook = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_secrets_from_user (const NmcConfig *nmc_config,
|
||||
const char *request_id,
|
||||
const char *title,
|
||||
const char *msg,
|
||||
GPtrArray *secrets)
|
||||
get_secrets_from_user(const NmcConfig *nmc_config,
|
||||
const char * request_id,
|
||||
const char * title,
|
||||
const char * msg,
|
||||
GPtrArray * secrets)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < secrets->len; i++) {
|
||||
NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
|
||||
char *pwd = NULL;
|
||||
for (i = 0; i < secrets->len; i++) {
|
||||
NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
|
||||
char * pwd = NULL;
|
||||
|
||||
/* Ask user for the password */
|
||||
if (msg)
|
||||
g_print ("%s\n", msg);
|
||||
if (secret->value) {
|
||||
/* Prefill the password if we have it. */
|
||||
rl_startup_hook = set_deftext;
|
||||
pre_input_deftext = g_strdup (secret->value);
|
||||
}
|
||||
if (secret->no_prompt_entry_id)
|
||||
pwd = nmc_readline (nmc_config, "%s: ", secret->pretty_name);
|
||||
else
|
||||
pwd = nmc_readline (nmc_config, "%s (%s): ", secret->pretty_name, secret->entry_id);
|
||||
/* Ask user for the password */
|
||||
if (msg)
|
||||
g_print("%s\n", msg);
|
||||
if (secret->value) {
|
||||
/* Prefill the password if we have it. */
|
||||
rl_startup_hook = set_deftext;
|
||||
pre_input_deftext = g_strdup(secret->value);
|
||||
}
|
||||
if (secret->no_prompt_entry_id)
|
||||
pwd = nmc_readline(nmc_config, "%s: ", secret->pretty_name);
|
||||
else
|
||||
pwd = nmc_readline(nmc_config, "%s (%s): ", secret->pretty_name, secret->entry_id);
|
||||
|
||||
/* No password provided, cancel the secrets. */
|
||||
if (!pwd)
|
||||
return FALSE;
|
||||
g_free (secret->value);
|
||||
secret->value = pwd;
|
||||
}
|
||||
return TRUE;
|
||||
/* No password provided, cancel the secrets. */
|
||||
if (!pwd)
|
||||
return FALSE;
|
||||
g_free(secret->value);
|
||||
secret->value = pwd;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
secrets_requested (NMSecretAgentSimple *agent,
|
||||
const char *request_id,
|
||||
const char *title,
|
||||
const char *msg,
|
||||
GPtrArray *secrets,
|
||||
gpointer user_data)
|
||||
secrets_requested(NMSecretAgentSimple *agent,
|
||||
const char * request_id,
|
||||
const char * title,
|
||||
const char * msg,
|
||||
GPtrArray * secrets,
|
||||
gpointer user_data)
|
||||
{
|
||||
NmCli *nmc = user_data;
|
||||
gboolean success;
|
||||
NmCli * nmc = user_data;
|
||||
gboolean success;
|
||||
|
||||
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
||||
nmc_terminal_erase_line ();
|
||||
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
||||
nmc_terminal_erase_line();
|
||||
|
||||
success = get_secrets_from_user (&nmc->nmc_config, request_id, title, msg, secrets);
|
||||
nm_secret_agent_simple_response (agent,
|
||||
request_id,
|
||||
success ? secrets : NULL);
|
||||
success = get_secrets_from_user(&nmc->nmc_config, request_id, title, msg, secrets);
|
||||
nm_secret_agent_simple_response(agent, request_id, success ? secrets : NULL);
|
||||
}
|
||||
|
||||
static NMCResultCode
|
||||
do_agent_secret (NmCli *nmc, int argc, char **argv)
|
||||
static void
|
||||
do_agent_secret(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
||||
{
|
||||
next_arg (nmc, &argc, &argv, NULL);
|
||||
if (nmc->complete)
|
||||
return nmc->return_value;
|
||||
next_arg(nmc, &argc, &argv, NULL);
|
||||
if (nmc->complete)
|
||||
return;
|
||||
|
||||
/* Create secret agent */
|
||||
nmc->secret_agent = nm_secret_agent_simple_new ("nmcli-agent");
|
||||
if (nmc->secret_agent) {
|
||||
/* We keep running */
|
||||
nmc->should_wait++;
|
||||
/* Create secret agent */
|
||||
nmc->secret_agent = nm_secret_agent_simple_new("nmcli-agent");
|
||||
if (nmc->secret_agent) {
|
||||
/* We keep running */
|
||||
nmc->should_wait++;
|
||||
|
||||
nm_secret_agent_simple_enable (nmc->secret_agent, NULL);
|
||||
g_signal_connect (nmc->secret_agent,
|
||||
NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS,
|
||||
G_CALLBACK (secrets_requested),
|
||||
nmc);
|
||||
g_print (_("nmcli successfully registered as a NetworkManager's secret agent.\n"));
|
||||
} else {
|
||||
g_string_printf (nmc->return_text, _("Error: secret agent initialization failed"));
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
return nmc->return_value;
|
||||
nm_secret_agent_simple_enable(nmc->secret_agent, NULL);
|
||||
g_signal_connect(nmc->secret_agent,
|
||||
NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS,
|
||||
G_CALLBACK(secrets_requested),
|
||||
nmc);
|
||||
g_print(_("nmcli successfully registered as a NetworkManager's secret agent.\n"));
|
||||
} else {
|
||||
g_string_printf(nmc->return_text, _("Error: secret agent initialization failed"));
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static NMCResultCode
|
||||
do_agent_polkit (NmCli *nmc, int argc, char **argv)
|
||||
static void
|
||||
polkit_registered(gpointer instance, gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
next_arg (nmc, &argc, &argv, NULL);
|
||||
if (nmc->complete)
|
||||
return nmc->return_value;
|
||||
|
||||
/* Initialize polkit agent */
|
||||
if (!nmc_polkit_agent_init (nmc, TRUE, &error)) {
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
g_string_printf (nmc->return_text, _("Error: polkit agent initialization failed: %s"),
|
||||
error->message);
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
g_error_free (error);
|
||||
} else {
|
||||
/* We keep running */
|
||||
nmc->should_wait++;
|
||||
|
||||
g_print (_("nmcli successfully registered as a polkit agent.\n"));
|
||||
}
|
||||
|
||||
return nmc->return_value;
|
||||
g_print(_("nmcli successfully registered as a polkit agent.\n"));
|
||||
}
|
||||
|
||||
static NMCResultCode
|
||||
do_agent_all (NmCli *nmc, int argc, char **argv)
|
||||
static void
|
||||
polkit_error(gpointer instance, const char *error, gpointer user_data)
|
||||
{
|
||||
NMCResultCode secret_res;
|
||||
|
||||
next_arg (nmc, &argc, &argv, NULL);
|
||||
if (nmc->complete)
|
||||
return nmc->return_value;
|
||||
|
||||
/* Run both secret and polkit agent */
|
||||
secret_res = do_agent_secret (nmc, argc, argv);
|
||||
if (secret_res != NMC_RESULT_SUCCESS) {
|
||||
g_printerr ("%s\n", nmc->return_text->str);
|
||||
g_string_truncate (nmc->return_text, 0);
|
||||
}
|
||||
|
||||
nmc->return_value = do_agent_polkit (nmc, argc, argv);
|
||||
if (nmc->return_value != NMC_RESULT_SUCCESS) {
|
||||
g_printerr ("%s\n", nmc->return_text->str);
|
||||
g_string_truncate (nmc->return_text, 0);
|
||||
}
|
||||
|
||||
if (nmc->return_value == NMC_RESULT_SUCCESS && secret_res != NMC_RESULT_SUCCESS)
|
||||
nmc->return_value = secret_res;
|
||||
|
||||
return nmc->return_value;
|
||||
g_main_loop_quit(loop);
|
||||
}
|
||||
|
||||
static const NMCCommand agent_cmds[] = {
|
||||
{ "secret", do_agent_secret, usage_agent_secret, TRUE, TRUE },
|
||||
{ "polkit", do_agent_polkit, usage_agent_polkit, TRUE, TRUE },
|
||||
{ "all", do_agent_all, usage_agent_all, TRUE, TRUE },
|
||||
{ NULL, do_agent_all, usage, TRUE, TRUE },
|
||||
};
|
||||
|
||||
NMCResultCode
|
||||
do_agent (NmCli *nmc, int argc, char **argv)
|
||||
static void
|
||||
do_agent_polkit(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
||||
{
|
||||
next_arg (nmc, &argc, &argv, NULL);
|
||||
nmc_do_cmd (nmc, agent_cmds, *argv, argc, argv);
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
return nmc->return_value;
|
||||
next_arg(nmc, &argc, &argv, NULL);
|
||||
if (nmc->complete)
|
||||
return;
|
||||
|
||||
if (!nmc_polkit_agent_init(nmc, TRUE, &error)) {
|
||||
g_dbus_error_strip_remote_error(error);
|
||||
g_string_printf(nmc->return_text,
|
||||
_("Error: polkit agent initialization failed: %s"),
|
||||
error->message);
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
} else {
|
||||
/* We keep running */
|
||||
nmc->should_wait++;
|
||||
g_signal_connect(nmc->pk_listener,
|
||||
NM_POLKIT_LISTENER_SIGNAL_ERROR,
|
||||
G_CALLBACK(polkit_error),
|
||||
NULL);
|
||||
g_signal_connect(nmc->pk_listener,
|
||||
NM_POLKIT_LISTENER_SIGNAL_REGISTERED,
|
||||
G_CALLBACK(polkit_registered),
|
||||
NULL);
|
||||
|
||||
/* keep running */
|
||||
nmc->should_wait++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_agent_all(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
||||
{
|
||||
NMCResultCode r;
|
||||
|
||||
next_arg(nmc, &argc, &argv, NULL);
|
||||
if (nmc->complete)
|
||||
return;
|
||||
|
||||
/* Run both secret and polkit agent */
|
||||
do_agent_secret(cmd, nmc, argc, argv);
|
||||
r = nmc->return_value;
|
||||
if (r != NMC_RESULT_SUCCESS) {
|
||||
g_printerr("%s\n", nmc->return_text->str);
|
||||
g_string_truncate(nmc->return_text, 0);
|
||||
nmc->return_value = NMC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
do_agent_polkit(cmd, nmc, argc, argv);
|
||||
if (nmc->return_value != NMC_RESULT_SUCCESS) {
|
||||
g_printerr("%s\n", nmc->return_text->str);
|
||||
g_string_truncate(nmc->return_text, 0);
|
||||
}
|
||||
|
||||
if (r != NMC_RESULT_SUCCESS)
|
||||
nmc->return_value = r;
|
||||
}
|
||||
|
||||
void
|
||||
nmc_command_func_agent(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
||||
{
|
||||
static const NMCCommand cmds[] = {
|
||||
{"secret", do_agent_secret, usage_agent_secret, TRUE, TRUE},
|
||||
{"polkit", do_agent_polkit, usage_agent_polkit, TRUE, TRUE},
|
||||
{"all", do_agent_all, usage_agent_all, TRUE, TRUE},
|
||||
{NULL, do_agent_all, usage, TRUE, TRUE},
|
||||
};
|
||||
|
||||
next_arg(nmc, &argc, &argv, NULL);
|
||||
nmc_do_cmd(nmc, cmds, *argv, argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NMC_AGENT_H__
|
||||
#define __NMC_AGENT_H__
|
||||
|
||||
#include "nmcli.h"
|
||||
|
||||
NMCResultCode do_agent (NmCli *nmc, int argc, char **argv);
|
||||
|
||||
#endif /* __NMC_AGENT_H__ */
|
||||
2028
clients/cli/common.c
2028
clients/cli/common.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2012 - 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -9,89 +9,77 @@
|
|||
#include "nmcli.h"
|
||||
#include "nm-secret-agent-simple.h"
|
||||
|
||||
gboolean print_ip_config(NMIPConfig * cfg,
|
||||
int addr_family,
|
||||
const NmcConfig *nmc_config,
|
||||
const char * one_field);
|
||||
|
||||
gboolean print_ip_config (NMIPConfig *cfg,
|
||||
int addr_family,
|
||||
const NmcConfig *nmc_config,
|
||||
const char *one_field);
|
||||
gboolean print_dhcp_config(NMDhcpConfig * dhcp,
|
||||
int addr_family,
|
||||
const NmcConfig *nmc_config,
|
||||
const char * one_field);
|
||||
|
||||
gboolean print_dhcp_config (NMDhcpConfig *dhcp,
|
||||
int addr_family,
|
||||
const NmcConfig *nmc_config,
|
||||
const char *one_field);
|
||||
NMConnection *nmc_find_connection(const GPtrArray *connections,
|
||||
const char * filter_type,
|
||||
const char * filter_val,
|
||||
GPtrArray ** out_result,
|
||||
gboolean complete);
|
||||
|
||||
NMConnection *nmc_find_connection (const GPtrArray *connections,
|
||||
const char *filter_type,
|
||||
const char *filter_val,
|
||||
GPtrArray **out_result,
|
||||
gboolean complete);
|
||||
NMActiveConnection *nmc_find_active_connection(const GPtrArray *active_cons,
|
||||
const char * filter_type,
|
||||
const char * filter_val,
|
||||
GPtrArray ** out_result,
|
||||
gboolean complete);
|
||||
|
||||
NMActiveConnection *nmc_find_active_connection (const GPtrArray *active_cons,
|
||||
const char *filter_type,
|
||||
const char *filter_val,
|
||||
GPtrArray **out_result,
|
||||
gboolean complete);
|
||||
void nmc_secrets_requested(NMSecretAgentSimple *agent,
|
||||
const char * request_id,
|
||||
const char * title,
|
||||
const char * msg,
|
||||
GPtrArray * secrets,
|
||||
gpointer user_data);
|
||||
|
||||
void nmc_secrets_requested (NMSecretAgentSimple *agent,
|
||||
const char *request_id,
|
||||
const char *title,
|
||||
const char *msg,
|
||||
GPtrArray *secrets,
|
||||
gpointer user_data);
|
||||
char *nmc_unique_connection_name(const GPtrArray *connections, const char *try_name);
|
||||
|
||||
char *nmc_unique_connection_name (const GPtrArray *connections,
|
||||
const char *try_name);
|
||||
|
||||
void nmc_cleanup_readline (void);
|
||||
char *nmc_readline (const NmcConfig *nmc_config,
|
||||
const char *prompt_fmt,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
char *nmc_readline_echo (const NmcConfig *nmc_config,
|
||||
gboolean echo_on,
|
||||
const char *prompt_fmt,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
NmcCompEntryFunc nmc_rl_compentry_func_wrap (const char *const*values);
|
||||
char *nmc_rl_gen_func_basic (const char *text, int state, const char *const*words);
|
||||
char *nmc_rl_gen_func_ifnames (const char *text, int state);
|
||||
gboolean nmc_get_in_readline (void);
|
||||
void nmc_set_in_readline (gboolean in_readline);
|
||||
void nmc_cleanup_readline(void);
|
||||
char *nmc_readline(const NmcConfig *nmc_config, const char *prompt_fmt, ...) G_GNUC_PRINTF(2, 3);
|
||||
char *nmc_readline_echo(const NmcConfig *nmc_config, gboolean echo_on, const char *prompt_fmt, ...)
|
||||
G_GNUC_PRINTF(3, 4);
|
||||
NmcCompEntryFunc nmc_rl_compentry_func_wrap(const char *const *values);
|
||||
char * nmc_rl_gen_func_basic(const char *text, int state, const char *const *words);
|
||||
char * nmc_rl_gen_func_ifnames(const char *text, int state);
|
||||
gboolean nmc_get_in_readline(void);
|
||||
void nmc_set_in_readline(gboolean in_readline);
|
||||
|
||||
/* for pre-filling a string to readline prompt */
|
||||
extern char *nmc_rl_pre_input_deftext;
|
||||
int nmc_rl_set_deftext (void);
|
||||
int nmc_rl_set_deftext(void);
|
||||
|
||||
char *nmc_parse_lldp_capabilities (guint value);
|
||||
char *nmc_parse_lldp_capabilities(guint value);
|
||||
|
||||
typedef struct {
|
||||
const char *cmd;
|
||||
NMCResultCode (*func) (NmCli *nmc, int argc, char **argv);
|
||||
void (*usage) (void);
|
||||
gboolean needs_client;
|
||||
gboolean needs_nm_running;
|
||||
} NMCCommand;
|
||||
void
|
||||
nmc_do_cmd(NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, const char *const *argv);
|
||||
|
||||
void nmc_do_cmd (NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, char **argv);
|
||||
void nmc_complete_strv(const char *prefix, gssize nargs, const char *const *args);
|
||||
|
||||
void nmc_complete_strv (const char *prefix, gssize nargs, const char *const*args);
|
||||
#define nmc_complete_strings(prefix, ...) \
|
||||
nmc_complete_strv((prefix), NM_NARG(__VA_ARGS__), (const char *const[]){__VA_ARGS__})
|
||||
|
||||
#define nmc_complete_strings(prefix, ...) nmc_complete_strv ((prefix), NM_NARG (__VA_ARGS__), (const char *const[]) { __VA_ARGS__ })
|
||||
void nmc_complete_bool(const char *prefix);
|
||||
|
||||
void nmc_complete_bool (const char *prefix);
|
||||
|
||||
const char *nmc_error_get_simple_message (GError *error);
|
||||
const char *nmc_error_get_simple_message(GError *error);
|
||||
|
||||
extern const NmcMetaGenericInfo *const metagen_ip4_config[];
|
||||
extern const NmcMetaGenericInfo *const metagen_ip6_config[];
|
||||
extern const NmcMetaGenericInfo *const metagen_dhcp_config[];
|
||||
|
||||
const char *nm_connectivity_to_string (NMConnectivityState connectivity);
|
||||
const char *nm_connectivity_to_string(NMConnectivityState connectivity);
|
||||
|
||||
GVariant *nmc_dbus_call_sync (NmCli *nmc,
|
||||
const char *object_path,
|
||||
const char *interface_name,
|
||||
const char *method_name,
|
||||
GVariant *parameters,
|
||||
const GVariantType *reply_type,
|
||||
GError **error);
|
||||
GVariant *nmc_dbus_call_sync(NmCli * nmc,
|
||||
const char * object_path,
|
||||
const char * interface_name,
|
||||
const char * method_name,
|
||||
GVariant * parameters,
|
||||
const GVariantType *reply_type,
|
||||
GError ** error);
|
||||
|
||||
#endif /* NMC_COMMON_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,20 +8,18 @@
|
|||
|
||||
#include "nmcli.h"
|
||||
|
||||
NMCResultCode do_connections (NmCli *nmc, int argc, char **argv);
|
||||
void monitor_connections(NmCli *nmc);
|
||||
|
||||
void monitor_connections (NmCli *nmc);
|
||||
gboolean nmc_process_connection_properties(NmCli * nmc,
|
||||
NMConnection * connection,
|
||||
int * argc,
|
||||
const char *const **argv,
|
||||
gboolean allow_remove_setting,
|
||||
GError ** error);
|
||||
|
||||
gboolean
|
||||
nmc_read_connection_properties (NmCli *nmc,
|
||||
NMConnection *connection,
|
||||
int *argc,
|
||||
char ***argv,
|
||||
GError **error);
|
||||
NMMetaColor nmc_active_connection_state_to_color(NMActiveConnection *ac);
|
||||
|
||||
NMMetaColor nmc_active_connection_state_to_color (NMActiveConnectionState state);
|
||||
|
||||
int nmc_active_connection_cmp (NMActiveConnection *ac_a, NMActiveConnection *ac_b);
|
||||
int nmc_active_connection_cmp(NMActiveConnection *ac_a, NMActiveConnection *ac_b);
|
||||
|
||||
extern const NmcMetaGenericInfo *const metagen_con_show[];
|
||||
extern const NmcMetaGenericInfo *const metagen_con_active_general[];
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,17 +8,15 @@
|
|||
|
||||
#include "nmcli.h"
|
||||
|
||||
NMCResultCode do_devices (NmCli *nmc, int argc, char **argv);
|
||||
void nmc_complete_device(NMClient *client, const char *prefix, gboolean wifi_only);
|
||||
|
||||
void nmc_complete_device (NMClient *client, const char *prefix, gboolean wifi_only);
|
||||
void nmc_complete_bssid(NMClient *client, const char *ifname, const char *bssid_prefix);
|
||||
|
||||
void nmc_complete_bssid (NMClient *client, const char *ifname, const char *bssid_prefix);
|
||||
void monitor_devices(NmCli *nmc);
|
||||
|
||||
void monitor_devices (NmCli *nmc);
|
||||
NMDevice **nmc_get_devices_sorted(NMClient *client);
|
||||
|
||||
NMDevice ** nmc_get_devices_sorted (NMClient *client);
|
||||
|
||||
NMMetaColor nmc_device_state_to_color (NMDeviceState state);
|
||||
NMMetaColor nmc_device_state_to_color(NMDevice *device);
|
||||
|
||||
extern const NmcMetaGenericInfo *const metagen_device_status[];
|
||||
extern const NmcMetaGenericInfo *const metagen_device_detail_general[];
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,17 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2010 - 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef NMC_GENERAL_H
|
||||
#define NMC_GENERAL_H
|
||||
|
||||
#include "nmcli.h"
|
||||
|
||||
NMCResultCode do_general (NmCli *nmc, int argc, char **argv);
|
||||
NMCResultCode do_networking (NmCli *nmc, int argc, char **argv);
|
||||
NMCResultCode do_radio (NmCli *nmc, int argc, char **argv);
|
||||
NMCResultCode do_monitor (NmCli *nmc, int argc, char **argv);
|
||||
NMCResultCode do_overview (NmCli *nmc, int argc, char **argv);
|
||||
|
||||
#endif /* NMC_GENERAL_H */
|
||||
71
clients/cli/generate-docs-nm-settings-nmcli.c
Normal file
71
clients/cli/generate-docs-nm-settings-nmcli.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-meta-setting-desc.h"
|
||||
|
||||
#define INDENT 4
|
||||
|
||||
static char *
|
||||
_xml_escape_attribute(const char *value)
|
||||
{
|
||||
gs_free char *s = NULL;
|
||||
|
||||
s = g_markup_escape_text(value, -1);
|
||||
return g_strdup_printf("\"%s\"", s);
|
||||
}
|
||||
|
||||
static const char *
|
||||
_indent_level(guint num_spaces)
|
||||
{
|
||||
static const char spaces[] = " ";
|
||||
|
||||
nm_assert(num_spaces < G_N_ELEMENTS(spaces));
|
||||
return &spaces[G_N_ELEMENTS(spaces) - num_spaces - 1];
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i_sett_infos;
|
||||
int i_property;
|
||||
|
||||
g_print("<nm-setting-docs>\n");
|
||||
for (i_sett_infos = 0; i_sett_infos < G_N_ELEMENTS(nm_meta_setting_infos_editor);
|
||||
i_sett_infos++) {
|
||||
const NMMetaSettingInfoEditor *sett_info = &nm_meta_setting_infos_editor[i_sett_infos];
|
||||
gs_free char * tmp_s1 = NULL;
|
||||
gs_free char * tmp_s2 = NULL;
|
||||
|
||||
g_print("%s<setting", _indent_level(INDENT));
|
||||
g_print(" name=%s", tmp_s1 = _xml_escape_attribute(sett_info->general->setting_name));
|
||||
if (sett_info->alias)
|
||||
g_print("\n%salias=%s",
|
||||
_indent_level(INDENT + 9),
|
||||
tmp_s2 = _xml_escape_attribute(sett_info->alias));
|
||||
g_print(" >\n");
|
||||
|
||||
for (i_property = 0; i_property < sett_info->properties_num; i_property++) {
|
||||
const NMMetaPropertyInfo *prop_info = sett_info->properties[i_property];
|
||||
gs_free char * tmp2 = NULL;
|
||||
gs_free char * tmp3 = NULL;
|
||||
gs_free char * tmp4 = NULL;
|
||||
|
||||
g_print("%s<property", _indent_level(2 * INDENT));
|
||||
g_print(" name=%s", tmp2 = _xml_escape_attribute(prop_info->property_name));
|
||||
if (prop_info->property_alias)
|
||||
g_print("\n%salias=%s",
|
||||
_indent_level(2 * INDENT + 10),
|
||||
tmp3 = _xml_escape_attribute(prop_info->property_alias));
|
||||
if (prop_info->describe_doc)
|
||||
g_print("\n%sdescription=%s",
|
||||
_indent_level(2 * INDENT + 10),
|
||||
tmp4 = _xml_escape_attribute(prop_info->describe_doc));
|
||||
g_print(" />\n");
|
||||
}
|
||||
|
||||
g_print("%s</setting>\n", _indent_level(INDENT));
|
||||
}
|
||||
g_print("</nm-setting-docs>\n");
|
||||
return 0;
|
||||
}
|
||||
1125
clients/cli/generate-docs-nm-settings-nmcli.xml.in
Normal file
1125
clients/cli/generate-docs-nm-settings-nmcli.xml.in
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,6 @@
|
|||
name = 'nmcli'
|
||||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
if enable_nmcli
|
||||
|
||||
# FIXME: nmcli-completion should be renamed to nmcli
|
||||
install_data(
|
||||
|
|
@ -6,36 +8,65 @@ install_data(
|
|||
install_dir: join_paths(nm_datadir, 'bash-completion', 'completions'),
|
||||
)
|
||||
|
||||
sources = files(
|
||||
'agent.c',
|
||||
'common.c',
|
||||
'connections.c',
|
||||
'devices.c',
|
||||
'general.c',
|
||||
'nmcli.c',
|
||||
'polkit-agent.c',
|
||||
'settings.c',
|
||||
'utils.c',
|
||||
)
|
||||
|
||||
deps = [
|
||||
libnmc_base_dep,
|
||||
libnmc_dep,
|
||||
readline_dep,
|
||||
]
|
||||
|
||||
if enable_polkit_agent
|
||||
sources += nm_polkit_listener
|
||||
|
||||
deps += polkit_agent_dep
|
||||
endif
|
||||
|
||||
executable(
|
||||
name,
|
||||
sources,
|
||||
dependencies: deps,
|
||||
c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)],
|
||||
'nmcli',
|
||||
files(
|
||||
'agent.c',
|
||||
'common.c',
|
||||
'connections.c',
|
||||
'devices.c',
|
||||
'general.c',
|
||||
'nmcli.c',
|
||||
'polkit-agent.c',
|
||||
'settings.c',
|
||||
'utils.c',
|
||||
),
|
||||
dependencies: [
|
||||
libnmc_base_dep,
|
||||
libnmc_dep,
|
||||
readline_dep,
|
||||
libnm_libnm_aux_dep,
|
||||
],
|
||||
c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format('nmcli')],
|
||||
link_args: ldflags_linker_script_binary,
|
||||
link_depends: linker_script_binary,
|
||||
install: true,
|
||||
)
|
||||
|
||||
endif
|
||||
|
||||
generate_docs_nm_settings_nmcli = executable(
|
||||
'generate-docs-nm-settings-nmcli',
|
||||
files(
|
||||
'generate-docs-nm-settings-nmcli.c',
|
||||
),
|
||||
dependencies: [
|
||||
libnmc_base_dep,
|
||||
libnmc_dep,
|
||||
libnm_libnm_aux_dep,
|
||||
],
|
||||
c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format('nmcli')],
|
||||
link_args: ldflags_linker_script_binary,
|
||||
link_depends: linker_script_binary,
|
||||
)
|
||||
|
||||
if enable_docs
|
||||
generate_docs_nm_settings_nmcli_xml = custom_target(
|
||||
'generate-docs-nm-settings-nmcli.xml',
|
||||
output: 'generate-docs-nm-settings-nmcli.xml',
|
||||
command: [ generate_docs_nm_settings_nmcli ],
|
||||
capture: true,
|
||||
)
|
||||
|
||||
test(
|
||||
'check-local-generate-docs-nm-settings-nmcli',
|
||||
find_program(join_paths(source_root, 'tools', 'check-compare-generated.sh')),
|
||||
args: [source_root, build_root, 'clients/cli/generate-docs-nm-settings-nmcli.xml'],
|
||||
)
|
||||
else
|
||||
settings_docs_source = configure_file(
|
||||
input: 'generate-docs-nm-settings-nmcli.xml.in',
|
||||
output: '@BASENAME@',
|
||||
configuration: configuration_data(),
|
||||
)
|
||||
endif
|
||||
|
|
|
|||
1577
clients/cli/nmcli.c
1577
clients/cli/nmcli.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -11,151 +11,187 @@
|
|||
|
||||
struct _NMPolkitListener;
|
||||
|
||||
typedef char *(*NmcCompEntryFunc) (const char *, int);
|
||||
typedef char *(*NmcCompEntryFunc)(const char *, int);
|
||||
|
||||
/* nmcli exit codes */
|
||||
typedef enum {
|
||||
/* Indicates successful execution */
|
||||
NMC_RESULT_SUCCESS = 0,
|
||||
/* Indicates successful execution */
|
||||
NMC_RESULT_SUCCESS = 0,
|
||||
|
||||
/* Unknown / unspecified error */
|
||||
NMC_RESULT_ERROR_UNKNOWN = 1,
|
||||
/* Unknown / unspecified error */
|
||||
NMC_RESULT_ERROR_UNKNOWN = 1,
|
||||
|
||||
/* Wrong invocation of nmcli */
|
||||
NMC_RESULT_ERROR_USER_INPUT = 2,
|
||||
/* Wrong invocation of nmcli */
|
||||
NMC_RESULT_ERROR_USER_INPUT = 2,
|
||||
|
||||
/* A timeout expired */
|
||||
NMC_RESULT_ERROR_TIMEOUT_EXPIRED = 3,
|
||||
/* A timeout expired */
|
||||
NMC_RESULT_ERROR_TIMEOUT_EXPIRED = 3,
|
||||
|
||||
/* Error in connection activation */
|
||||
NMC_RESULT_ERROR_CON_ACTIVATION = 4,
|
||||
/* Error in connection activation */
|
||||
NMC_RESULT_ERROR_CON_ACTIVATION = 4,
|
||||
|
||||
/* Error in connection deactivation */
|
||||
NMC_RESULT_ERROR_CON_DEACTIVATION = 5,
|
||||
/* Error in connection deactivation */
|
||||
NMC_RESULT_ERROR_CON_DEACTIVATION = 5,
|
||||
|
||||
/* Error in device disconnect */
|
||||
NMC_RESULT_ERROR_DEV_DISCONNECT = 6,
|
||||
/* Error in device disconnect */
|
||||
NMC_RESULT_ERROR_DEV_DISCONNECT = 6,
|
||||
|
||||
/* Error in connection deletion */
|
||||
NMC_RESULT_ERROR_CON_DEL = 7,
|
||||
/* Error in connection deletion */
|
||||
NMC_RESULT_ERROR_CON_DEL = 7,
|
||||
|
||||
/* NetworkManager is not running */
|
||||
NMC_RESULT_ERROR_NM_NOT_RUNNING = 8,
|
||||
/* NetworkManager is not running */
|
||||
NMC_RESULT_ERROR_NM_NOT_RUNNING = 8,
|
||||
|
||||
/* No more used, keep to preserve API */
|
||||
NMC_RESULT_ERROR_VERSIONS_MISMATCH = 9,
|
||||
/* No more used, keep to preserve API */
|
||||
NMC_RESULT_ERROR_VERSIONS_MISMATCH = 9,
|
||||
|
||||
/* Connection/Device/AP not found */
|
||||
NMC_RESULT_ERROR_NOT_FOUND = 10,
|
||||
/* Connection/Device/AP not found */
|
||||
NMC_RESULT_ERROR_NOT_FOUND = 10,
|
||||
|
||||
/* --complete-args signals a file name may follow */
|
||||
NMC_RESULT_COMPLETE_FILE = 65,
|
||||
/* --complete-args signals a file name may follow */
|
||||
NMC_RESULT_COMPLETE_FILE = 65,
|
||||
} NMCResultCode;
|
||||
|
||||
typedef enum {
|
||||
NMC_PRINT_TERSE = 0,
|
||||
NMC_PRINT_NORMAL = 1,
|
||||
NMC_PRINT_PRETTY = 2
|
||||
} NMCPrintOutput;
|
||||
typedef enum { NMC_PRINT_TERSE = 0, NMC_PRINT_NORMAL = 1, NMC_PRINT_PRETTY = 2 } NMCPrintOutput;
|
||||
|
||||
static inline NMMetaAccessorGetType
|
||||
nmc_print_output_to_accessor_get_type (NMCPrintOutput print_output)
|
||||
nmc_print_output_to_accessor_get_type(NMCPrintOutput print_output)
|
||||
{
|
||||
return NM_IN_SET (print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY)
|
||||
? NM_META_ACCESSOR_GET_TYPE_PRETTY
|
||||
: NM_META_ACCESSOR_GET_TYPE_PARSABLE;
|
||||
return NM_IN_SET(print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY)
|
||||
? NM_META_ACCESSOR_GET_TYPE_PRETTY
|
||||
: NM_META_ACCESSOR_GET_TYPE_PARSABLE;
|
||||
}
|
||||
|
||||
/* === Output fields === */
|
||||
|
||||
typedef enum {
|
||||
NMC_OF_FLAG_FIELD_NAMES = 0x00000001, /* Print field names instead of values */
|
||||
NMC_OF_FLAG_SECTION_PREFIX = 0x00000002, /* Use the first value as section prefix for the other field names - just in multiline */
|
||||
NMC_OF_FLAG_MAIN_HEADER_ADD = 0x00000004, /* Print main header in addition to values/field names */
|
||||
NMC_OF_FLAG_MAIN_HEADER_ONLY = 0x00000008, /* Print main header only */
|
||||
NMC_OF_FLAG_FIELD_NAMES = 0x00000001, /* Print field names instead of values */
|
||||
NMC_OF_FLAG_SECTION_PREFIX =
|
||||
0x00000002, /* Use the first value as section prefix for the other field names - just in multiline */
|
||||
NMC_OF_FLAG_MAIN_HEADER_ADD =
|
||||
0x00000004, /* Print main header in addition to values/field names */
|
||||
NMC_OF_FLAG_MAIN_HEADER_ONLY = 0x00000008, /* Print main header only */
|
||||
} NmcOfFlags;
|
||||
|
||||
typedef struct {
|
||||
const char *ansi_seq[_NM_META_COLOR_NUM];
|
||||
} NmcColorPalette;
|
||||
|
||||
extern const NMMetaType nmc_meta_type_generic_info;
|
||||
|
||||
typedef struct _NmcOutputField NmcOutputField;
|
||||
typedef struct _NmcOutputField NmcOutputField;
|
||||
typedef struct _NmcMetaGenericInfo NmcMetaGenericInfo;
|
||||
|
||||
struct _NmcOutputField {
|
||||
const NMMetaAbstractInfo *info;
|
||||
int width; /* Width in screen columns */
|
||||
void *value; /* Value of current field - char* or char** (NULL-terminated array) */
|
||||
gboolean value_is_array; /* Whether value is char** instead of char* */
|
||||
gboolean free_value; /* Whether to free the value */
|
||||
NmcOfFlags flags; /* Flags - whether and how to print values/field names/headers */
|
||||
NMMetaColor color; /* Use this color to print value */
|
||||
const NMMetaAbstractInfo *info;
|
||||
int width; /* Width in screen columns */
|
||||
void * value; /* Value of current field - char* or char** (NULL-terminated array) */
|
||||
gboolean value_is_array; /* Whether value is char** instead of char* */
|
||||
gboolean free_value; /* Whether to free the value */
|
||||
NmcOfFlags flags; /* Flags - whether and how to print values/field names/headers */
|
||||
NMMetaColor color; /* Use this color to print value */
|
||||
};
|
||||
|
||||
typedef struct _NmcConfig {
|
||||
NMCPrintOutput print_output; /* Output mode */
|
||||
bool use_colors; /* Whether to use colors for output: option '--color' */
|
||||
bool multiline_output; /* Multiline output instead of default tabular */
|
||||
bool escape_values; /* Whether to escape ':' and '\' in terse tabular mode */
|
||||
bool in_editor; /* Whether running the editor - nmcli con edit' */
|
||||
bool show_secrets; /* Whether to display secrets (both input and output): option '--show-secrets' */
|
||||
bool overview; /* Overview mode (hide default values) */
|
||||
const char *palette[_NM_META_COLOR_NUM]; /* Color palette */
|
||||
NMCPrintOutput print_output; /* Output mode */
|
||||
bool use_colors; /* Whether to use colors for output: option '--color' */
|
||||
bool multiline_output; /* Multiline output instead of default tabular */
|
||||
bool escape_values; /* Whether to escape ':' and '\' in terse tabular mode */
|
||||
bool in_editor; /* Whether running the editor - nmcli con edit' */
|
||||
bool
|
||||
show_secrets; /* Whether to display secrets (both input and output): option '--show-secrets' */
|
||||
bool overview; /* Overview mode (hide default values) */
|
||||
NmcColorPalette palette;
|
||||
} NmcConfig;
|
||||
|
||||
typedef struct {
|
||||
pid_t pid;
|
||||
} NmcPagerData;
|
||||
|
||||
typedef struct _NmcOutputData {
|
||||
GPtrArray *output_data; /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */
|
||||
GPtrArray *
|
||||
output_data; /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */
|
||||
} NmcOutputData;
|
||||
|
||||
/* NmCli - main structure */
|
||||
typedef struct _NmCli {
|
||||
NMClient *client; /* Pointer to NMClient of libnm */
|
||||
NMClient *client; /* Pointer to NMClient of libnm */
|
||||
|
||||
NMCResultCode return_value; /* Return code of nmcli */
|
||||
GString *return_text; /* Reason text */
|
||||
pid_t pager_pid; /* PID of a pager, if one was spawned */
|
||||
NMCResultCode return_value; /* Return code of nmcli */
|
||||
GString * return_text; /* Reason text */
|
||||
|
||||
int timeout; /* Operation timeout */
|
||||
NmcPagerData pager_data;
|
||||
|
||||
NMSecretAgentSimple *secret_agent; /* Secret agent */
|
||||
GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */
|
||||
struct _NMPolkitListener *pk_listener; /* polkit agent listener */
|
||||
int timeout; /* Operation timeout */
|
||||
|
||||
int should_wait; /* Semaphore indicating whether nmcli should not end or not yet */
|
||||
gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */
|
||||
gboolean mode_specified; /* Whether tabular/multiline mode was specified via '--mode' option */
|
||||
union {
|
||||
const NmcConfig nmc_config;
|
||||
NmcConfig nmc_config_mutable;
|
||||
};
|
||||
char *required_fields; /* Required fields in output: '--fields' option */
|
||||
gboolean ask; /* Ask for missing parameters: option '--ask' */
|
||||
gboolean complete; /* Autocomplete the command line */
|
||||
gboolean editor_status_line; /* Whether to display status line in connection editor */
|
||||
gboolean editor_save_confirmation; /* Whether to ask for confirmation on saving connections with 'autoconnect=yes' */
|
||||
NMSecretAgentSimple * secret_agent; /* Secret agent */
|
||||
GHashTable * pwds_hash; /* Hash table with passwords in passwd-file */
|
||||
struct _NMPolkitListener *pk_listener; /* polkit agent listener */
|
||||
|
||||
char *palette_buffer; /* Buffer with sequences for terminal-colors.d(5)-based coloring. */
|
||||
int should_wait; /* Semaphore indicating whether nmcli should not end or not yet */
|
||||
gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */
|
||||
gboolean mode_specified; /* Whether tabular/multiline mode was specified via '--mode' option */
|
||||
union {
|
||||
const NmcConfig nmc_config;
|
||||
NmcConfig nmc_config_mutable;
|
||||
};
|
||||
char * required_fields; /* Required fields in output: '--fields' option */
|
||||
gboolean ask; /* Ask for missing parameters: option '--ask' */
|
||||
gboolean complete; /* Autocomplete the command line */
|
||||
gboolean editor_status_line; /* Whether to display status line in connection editor */
|
||||
gboolean
|
||||
editor_save_confirmation; /* Whether to ask for confirmation on saving connections with 'autoconnect=yes' */
|
||||
|
||||
char *palette_buffer; /* Buffer with sequences for terminal-colors.d(5)-based coloring. */
|
||||
} NmCli;
|
||||
|
||||
extern NmCli nm_cli;
|
||||
extern const NmCli *const nm_cli_global_readline;
|
||||
|
||||
/* Error quark for GError domain */
|
||||
#define NMCLI_ERROR (nmcli_error_quark ())
|
||||
GQuark nmcli_error_quark (void);
|
||||
#define NMCLI_ERROR (nmcli_error_quark())
|
||||
GQuark nmcli_error_quark(void);
|
||||
|
||||
extern GMainLoop *loop;
|
||||
|
||||
gboolean nmc_seen_sigint (void);
|
||||
void nmc_clear_sigint (void);
|
||||
void nmc_set_sigquit_internal (void);
|
||||
void nmc_exit (void);
|
||||
gboolean nmc_seen_sigint(void);
|
||||
void nmc_clear_sigint(void);
|
||||
void nmc_set_sigquit_internal(void);
|
||||
void nmc_exit(void);
|
||||
|
||||
void nm_cli_spawn_pager (NmCli *nmc);
|
||||
void nm_cli_spawn_pager(const NmcConfig *nmc_config, NmcPagerData *pager_data);
|
||||
|
||||
void nmc_empty_output_fields (NmcOutputData *output_data);
|
||||
void nmc_empty_output_fields(NmcOutputData *output_data);
|
||||
|
||||
#define NMC_OUTPUT_DATA_DEFINE_SCOPED(out) \
|
||||
gs_unref_array GArray *out##_indices = NULL; \
|
||||
nm_auto (nmc_empty_output_fields) NmcOutputData out = { \
|
||||
.output_data = g_ptr_array_new_full (20, g_free), \
|
||||
}
|
||||
#define NMC_OUTPUT_DATA_DEFINE_SCOPED(out) \
|
||||
gs_unref_array GArray * out##_indices = NULL; \
|
||||
nm_auto(nmc_empty_output_fields) NmcOutputData out = { \
|
||||
.output_data = g_ptr_array_new_full(20, g_free), \
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMCCommand;
|
||||
|
||||
typedef struct _NMCCommand {
|
||||
const char *cmd;
|
||||
void (*func)(const struct _NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void (*usage)(void);
|
||||
bool needs_client;
|
||||
bool needs_nm_running;
|
||||
} NMCCommand;
|
||||
|
||||
void nmc_command_func_agent(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void nmc_command_func_general(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void
|
||||
nmc_command_func_networking(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void nmc_command_func_radio(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void nmc_command_func_monitor(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void
|
||||
nmc_command_func_overview(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void
|
||||
nmc_command_func_connection(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
void nmc_command_func_device(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* NMC_NMCLI_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -14,116 +14,83 @@
|
|||
#include "nm-polkit-listener.h"
|
||||
#include "common.h"
|
||||
|
||||
#if WITH_POLKIT_AGENT
|
||||
static char *
|
||||
polkit_request (NMPolkitListener *listener,
|
||||
const char *request,
|
||||
const char *action_id,
|
||||
const char *message,
|
||||
const char *icon_name,
|
||||
const char *user,
|
||||
gboolean echo_on,
|
||||
gpointer user_data)
|
||||
polkit_read_passwd(gpointer instance,
|
||||
const char *action_id,
|
||||
const char *message,
|
||||
const char *user,
|
||||
gpointer user_data)
|
||||
{
|
||||
NmCli *nmc = user_data;
|
||||
NmCli *nmc = user_data;
|
||||
|
||||
g_print ("%s\n", message);
|
||||
g_print ("(action_id: %s)\n", action_id);
|
||||
g_print("%s\n", message);
|
||||
g_print("(action_id: %s)\n", action_id);
|
||||
|
||||
/* Ask user for polkit authorization password */
|
||||
if (user) {
|
||||
gs_free char *tmp = NULL;
|
||||
char *p;
|
||||
|
||||
/* chop of ": " if present */
|
||||
tmp = g_strdup (request);
|
||||
p = strrchr (tmp, ':');
|
||||
if (p && nm_streq (p, ": "))
|
||||
*p = '\0';
|
||||
return nmc_readline_echo (&nmc->nmc_config, echo_on, "%s (%s): ", tmp, user);
|
||||
}
|
||||
|
||||
return nmc_readline_echo (&nmc->nmc_config, echo_on, "%s", request);
|
||||
/* Ask user for polkit authorization password */
|
||||
if (user) {
|
||||
return nmc_readline_echo(&nmc->nmc_config, FALSE, "password (%s): ", user);
|
||||
}
|
||||
return nmc_readline_echo(&nmc->nmc_config, FALSE, "password: ");
|
||||
}
|
||||
|
||||
static void
|
||||
polkit_show_info (NMPolkitListener *listener,
|
||||
const char *text,
|
||||
gpointer user_data)
|
||||
polkit_error(gpointer instance, const char *error, gpointer user_data)
|
||||
{
|
||||
g_print (_("Authentication message: %s\n"), text);
|
||||
g_printerr(_("Error: polkit agent failed: %s\n"), error);
|
||||
}
|
||||
|
||||
static void
|
||||
polkit_show_error (NMPolkitListener *listener,
|
||||
const char *text,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print (_("Authentication error: %s\n"), text);
|
||||
}
|
||||
|
||||
static void
|
||||
polkit_completed (NMPolkitListener *listener,
|
||||
gboolean gained_authorization,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* We don't print anything here. The outcome will be evident from
|
||||
* the operation result anyway. */
|
||||
}
|
||||
#endif
|
||||
|
||||
gboolean
|
||||
nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error)
|
||||
nmc_polkit_agent_init(NmCli *nmc, gboolean for_session, GError **error)
|
||||
{
|
||||
#if WITH_POLKIT_AGENT
|
||||
static const NMPolkitListenVtable vtable = {
|
||||
.on_request = polkit_request,
|
||||
.on_show_info = polkit_show_info,
|
||||
.on_show_error = polkit_show_error,
|
||||
.on_completed = polkit_completed,
|
||||
};
|
||||
NMPolkitListener *listener;
|
||||
NMPolkitListener *listener;
|
||||
GDBusConnection * dbus_connection = NULL;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
||||
|
||||
listener = nm_polkit_listener_new (for_session, error);
|
||||
if (!listener)
|
||||
return FALSE;
|
||||
if (nmc->client && nm_client_get_dbus_connection(nmc->client)) {
|
||||
dbus_connection = nm_client_get_dbus_connection(nmc->client);
|
||||
listener = nm_polkit_listener_new(dbus_connection, for_session);
|
||||
} else {
|
||||
dbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, error);
|
||||
|
||||
nm_polkit_listener_set_vtable (listener, &vtable, nmc);
|
||||
if (!dbus_connection) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nmc->pk_listener = listener;
|
||||
#endif
|
||||
return TRUE;
|
||||
listener = nm_polkit_listener_new(dbus_connection, for_session);
|
||||
g_object_unref(dbus_connection);
|
||||
}
|
||||
|
||||
g_signal_connect(listener,
|
||||
NM_POLKIT_LISTENER_SIGNAL_REQUEST_SYNC,
|
||||
G_CALLBACK(polkit_read_passwd),
|
||||
nmc);
|
||||
g_signal_connect(listener, NM_POLKIT_LISTENER_SIGNAL_ERROR, G_CALLBACK(polkit_error), NULL);
|
||||
|
||||
nmc->pk_listener = listener;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nmc_polkit_agent_fini (NmCli* nmc)
|
||||
nmc_polkit_agent_fini(NmCli *nmc)
|
||||
{
|
||||
#if WITH_POLKIT_AGENT
|
||||
if (nmc->pk_listener) {
|
||||
nm_polkit_listener_set_vtable (nmc->pk_listener, NULL, NULL);
|
||||
g_clear_object (&nmc->pk_listener);
|
||||
}
|
||||
#endif
|
||||
if (nmc->pk_listener) {
|
||||
g_clear_object(&nmc->pk_listener);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmc_start_polkit_agent_start_try (NmCli *nmc)
|
||||
nmc_start_polkit_agent_start_try(NmCli *nmc)
|
||||
{
|
||||
#if WITH_POLKIT_AGENT
|
||||
GError *error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
/* We don't register polkit agent at all when running non-interactively */
|
||||
if (!nmc->ask)
|
||||
return TRUE;
|
||||
/* We don't register polkit agent at all when running non-interactively */
|
||||
if (!nmc->ask)
|
||||
return TRUE;
|
||||
|
||||
if (!nmc_polkit_agent_init (nmc, FALSE, &error)) {
|
||||
g_printerr (_("Warning: polkit agent initialization failed: %s\n"),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
if (!nmc_polkit_agent_init(nmc, FALSE, &error)) {
|
||||
g_printerr(_("Warning: polkit agent initialization failed: %s\n"), error->message);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
#include "nmcli.h"
|
||||
|
||||
gboolean nmc_polkit_agent_init (NmCli *nmc, gboolean for_session, GError **error);
|
||||
void nmc_polkit_agent_fini (NmCli* nmc);
|
||||
gboolean nmc_polkit_agent_init(NmCli *nmc, gboolean for_session, GError **error);
|
||||
void nmc_polkit_agent_fini(NmCli *nmc);
|
||||
|
||||
gboolean nmc_start_polkit_agent_start_try (NmCli *nmc);
|
||||
gboolean nmc_start_polkit_agent_start_try(NmCli *nmc);
|
||||
|
||||
#endif /* __NMC_POLKIT_AGENT_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -13,28 +13,26 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nmc_setting_ip4_connect_handlers (NMSettingIPConfig *setting);
|
||||
void nmc_setting_ip6_connect_handlers (NMSettingIPConfig *setting);
|
||||
void nmc_setting_proxy_connect_handlers (NMSettingProxy *setting);
|
||||
void nmc_setting_wireless_connect_handlers (NMSettingWireless *setting);
|
||||
void nmc_setting_connection_connect_handlers (NMSettingConnection *setting, NMConnection *connection);
|
||||
void nmc_setting_ip4_connect_handlers(NMSettingIPConfig *setting);
|
||||
void nmc_setting_ip6_connect_handlers(NMSettingIPConfig *setting);
|
||||
void nmc_setting_proxy_connect_handlers(NMSettingProxy *setting);
|
||||
void nmc_setting_wireless_connect_handlers(NMSettingWireless *setting);
|
||||
void nmc_setting_connection_connect_handlers(NMSettingConnection *setting,
|
||||
NMConnection * connection);
|
||||
|
||||
char **nmc_setting_get_valid_properties (NMSetting *setting);
|
||||
char *nmc_setting_get_property_desc (NMSetting *setting, const char *prop);
|
||||
const char *const*nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop, char ***out_to_free);
|
||||
char *nmc_setting_get_property (NMSetting *setting,
|
||||
const char *prop,
|
||||
GError **error);
|
||||
char *nmc_setting_get_property_parsable (NMSetting *setting,
|
||||
const char *prop,
|
||||
GError **error);
|
||||
gboolean nmc_setting_set_property (NMClient *client,
|
||||
NMSetting *setting,
|
||||
const char *prop,
|
||||
NMMetaAccessorModifier modifier,
|
||||
const char *val,
|
||||
GError **error);
|
||||
char **nmc_setting_get_valid_properties(NMSetting *setting);
|
||||
char * nmc_setting_get_property_desc(NMSetting *setting, const char *prop);
|
||||
const char *const *
|
||||
nmc_setting_get_property_allowed_values(NMSetting *setting, const char *prop, char ***out_to_free);
|
||||
char * nmc_setting_get_property(NMSetting *setting, const char *prop, GError **error);
|
||||
char * nmc_setting_get_property_parsable(NMSetting *setting, const char *prop, GError **error);
|
||||
gboolean nmc_setting_set_property(NMClient * client,
|
||||
NMSetting * setting,
|
||||
const char * prop,
|
||||
NMMetaAccessorModifier modifier,
|
||||
const char * val,
|
||||
GError ** error);
|
||||
|
||||
gboolean setting_details (const NmcConfig *nmc_config, NMSetting *setting, const char *one_prop);
|
||||
gboolean setting_details(const NmcConfig *nmc_config, NMSetting *setting, const char *one_prop);
|
||||
|
||||
#endif /* NMC_SETTINGS_H */
|
||||
|
|
|
|||
2502
clients/cli/utils.c
2502
clients/cli/utils.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -11,331 +11,359 @@
|
|||
/* === Types === */
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
gboolean has_value;
|
||||
const char **value;
|
||||
gboolean mandatory;
|
||||
gboolean found;
|
||||
const char * name;
|
||||
gboolean has_value;
|
||||
const char **value;
|
||||
gboolean mandatory;
|
||||
gboolean found;
|
||||
} nmc_arg_t;
|
||||
|
||||
/* === Functions === */
|
||||
int next_arg (NmCli *nmc, int *argc, char ***argv, ...);
|
||||
gboolean nmc_arg_is_help (const char *arg);
|
||||
gboolean nmc_arg_is_option (const char *arg, const char *opt_name);
|
||||
gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error);
|
||||
char *ssid_to_hex (const char *str, gsize len);
|
||||
void nmc_terminal_erase_line (void);
|
||||
void nmc_terminal_show_progress (const char *str);
|
||||
pid_t nmc_terminal_spawn_pager (const NmcConfig *nmc_config);
|
||||
char *nmc_colorize (const NmcConfig *nmc_config, NMMetaColor color, const char * fmt, ...) _nm_printf (3, 4);
|
||||
void nmc_filter_out_colors_inplace (char *str);
|
||||
char *nmc_filter_out_colors (const char *str);
|
||||
char *nmc_get_user_input (const char *ask_str);
|
||||
int nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote,
|
||||
char ***argv, int *argc);
|
||||
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
|
||||
char * nmc_util_strv_for_display (const char *const*strv, gboolean brackets);
|
||||
int nmc_string_screen_width (const char *start, const char *end);
|
||||
void set_val_str (NmcOutputField fields_array[], guint32 index, char *value);
|
||||
void set_val_strc (NmcOutputField fields_array[], guint32 index, const char *value);
|
||||
void set_val_arr (NmcOutputField fields_array[], guint32 index, char **value);
|
||||
void set_val_arrc (NmcOutputField fields_array[], guint32 index, const char **value);
|
||||
void set_val_color_all (NmcOutputField fields_array[], NMMetaColor color);
|
||||
void nmc_free_output_field_values (NmcOutputField fields_array[]);
|
||||
int next_arg(NmCli *nmc, int *argc, const char *const **argv, ...);
|
||||
gboolean nmc_arg_is_help(const char *arg);
|
||||
gboolean nmc_arg_is_option(const char *arg, const char *opt_name);
|
||||
gboolean nmc_parse_args(nmc_arg_t * arg_arr,
|
||||
gboolean last,
|
||||
int * argc,
|
||||
const char *const **argv,
|
||||
GError ** error);
|
||||
char * ssid_to_hex(const char *str, gsize len);
|
||||
void nmc_terminal_erase_line(void);
|
||||
void nmc_terminal_show_progress(const char *str);
|
||||
pid_t nmc_terminal_spawn_pager(const NmcConfig *nmc_config);
|
||||
char * nmc_colorize(const NmcConfig *nmc_config, NMMetaColor color, const char *fmt, ...)
|
||||
_nm_printf(3, 4);
|
||||
void nmc_filter_out_colors_inplace(char *str);
|
||||
char * nmc_filter_out_colors(const char *str);
|
||||
char * nmc_get_user_input(const char *ask_str);
|
||||
int nmc_string_to_arg_array(const char *line,
|
||||
const char *delim,
|
||||
gboolean unquote,
|
||||
char *** argv,
|
||||
int * argc);
|
||||
const char *nmc_string_is_valid(const char *input, const char **allowed, GError **error);
|
||||
char * nmc_util_strv_for_display(const char *const *strv, gboolean brackets);
|
||||
int nmc_string_screen_width(const char *start, const char *end);
|
||||
void set_val_str(NmcOutputField fields_array[], guint32 index, char *value);
|
||||
void set_val_strc(NmcOutputField fields_array[], guint32 index, const char *value);
|
||||
void set_val_arr(NmcOutputField fields_array[], guint32 index, char **value);
|
||||
void set_val_arrc(NmcOutputField fields_array[], guint32 index, const char **value);
|
||||
void set_val_color_all(NmcOutputField fields_array[], NMMetaColor color);
|
||||
void nmc_free_output_field_values(NmcOutputField fields_array[]);
|
||||
|
||||
GArray *parse_output_fields (const char *fields_str,
|
||||
const NMMetaAbstractInfo *const* fields_array,
|
||||
gboolean parse_groups,
|
||||
GPtrArray **group_fields,
|
||||
GError **error);
|
||||
NmcOutputField *nmc_dup_fields_array (const NMMetaAbstractInfo *const*fields, NmcOfFlags flags);
|
||||
void nmc_empty_output_fields (NmcOutputData *output_data);
|
||||
void print_required_fields (const NmcConfig *nmc_config,
|
||||
NmcOfFlags of_flags,
|
||||
const GArray *indices,
|
||||
const char *header_name,
|
||||
int indent,
|
||||
const NmcOutputField *field_values);
|
||||
void print_data_prepare_width (GPtrArray *output_data);
|
||||
void print_data (const NmcConfig *nmc_config,
|
||||
const GArray *indices,
|
||||
const char *header_name,
|
||||
int indent,
|
||||
const NmcOutputData *out);
|
||||
GArray * parse_output_fields(const char * fields_str,
|
||||
const NMMetaAbstractInfo *const *fields_array,
|
||||
gboolean parse_groups,
|
||||
GPtrArray ** group_fields,
|
||||
GError ** error);
|
||||
NmcOutputField *nmc_dup_fields_array(const NMMetaAbstractInfo *const *fields, NmcOfFlags flags);
|
||||
void nmc_empty_output_fields(NmcOutputData *output_data);
|
||||
void print_required_fields(const NmcConfig * nmc_config,
|
||||
NmcPagerData * pager_data,
|
||||
NmcOfFlags of_flags,
|
||||
const GArray * indices,
|
||||
const char * header_name,
|
||||
int indent,
|
||||
const NmcOutputField *field_values);
|
||||
void print_data_prepare_width(GPtrArray *output_data);
|
||||
void print_data(const NmcConfig * nmc_config,
|
||||
NmcPagerData * pager_data,
|
||||
const GArray * indices,
|
||||
const char * header_name,
|
||||
int indent,
|
||||
const NmcOutputData *out);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern const NMMetaEnvironment *const nmc_meta_environment;
|
||||
extern NmCli *const nmc_meta_environment_arg;
|
||||
extern const NmCli *const nmc_meta_environment_arg;
|
||||
|
||||
typedef enum {
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING = 0,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX,
|
||||
_NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING = 0,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX,
|
||||
_NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION = 0,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE,
|
||||
_NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION = 0,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE,
|
||||
_NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL = 0,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_DOMAINS,
|
||||
_NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL = 0,
|
||||
NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_DOMAINS,
|
||||
_NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS,
|
||||
_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DNS,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_DOMAIN,
|
||||
NMC_GENERIC_INFO_TYPE_IP4_CONFIG_WINS,
|
||||
_NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN,
|
||||
_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DNS,
|
||||
NMC_GENERIC_INFO_TYPE_IP6_CONFIG_DOMAIN,
|
||||
_NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_OPTION = 0,
|
||||
_NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_OPTION = 0,
|
||||
_NMC_GENERIC_INFO_TYPE_DHCP_CONFIG_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_NAME = 0,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_TIMESTAMP,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_TIMESTAMP_REAL,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_AUTOCONNECT,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_AUTOCONNECT_PRIORITY,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_READONLY,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_ACTIVE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_DEVICE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_ACTIVE_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_SLAVE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_FILENAME,
|
||||
_NMC_GENERIC_INFO_TYPE_CON_SHOW_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_NAME = 0,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_TIMESTAMP,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_TIMESTAMP_REAL,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_AUTOCONNECT,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_AUTOCONNECT_PRIORITY,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_READONLY,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_ACTIVE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_DEVICE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_ACTIVE_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_SLAVE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_SHOW_FILENAME,
|
||||
_NMC_GENERIC_INFO_TYPE_CON_SHOW_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NAME = 0,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEVICES,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_IP_IFACE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT6,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_SPEC_OBJECT,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_VPN,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_CON_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_ZONE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_MASTER_PATH,
|
||||
_NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NAME = 0,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEVICES,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_IP_IFACE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DEFAULT6,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_SPEC_OBJECT,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_VPN,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_CON_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_ZONE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_MASTER_PATH,
|
||||
_NMC_GENERIC_INFO_TYPE_CON_ACTIVE_GENERAL_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE = 0,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_CFG,
|
||||
_NMC_GENERIC_INFO_TYPE_CON_ACTIVE_VPN_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_TYPE = 0,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_USERNAME,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_GATEWAY,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_BANNER,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_VPN_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_CON_VPN_CFG,
|
||||
_NMC_GENERIC_INFO_TYPE_CON_ACTIVE_VPN_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP4_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP6_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP4_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP6_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP4_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP6_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DBUS_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP4_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP6_CONNECTIVITY,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM,
|
||||
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_UP = 0,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_LOWER_UP,
|
||||
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_CARRIER,
|
||||
_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_NUM,
|
||||
|
||||
} NmcGenericInfoType;
|
||||
|
||||
#define NMC_HANDLE_COLOR(color) \
|
||||
G_STMT_START { \
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_COLOR) \
|
||||
return GINT_TO_POINTER (color); \
|
||||
} G_STMT_END
|
||||
#define NMC_HANDLE_COLOR(color) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_COLOR) \
|
||||
return GINT_TO_POINTER(color); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
struct _NmcMetaGenericInfo {
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
NmcGenericInfoType info_type;
|
||||
const char *name;
|
||||
const char *name_header;
|
||||
const NmcMetaGenericInfo *const*nested;
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
NmcGenericInfoType info_type;
|
||||
const char * name;
|
||||
const char * name_header;
|
||||
const NmcMetaGenericInfo *const *nested;
|
||||
|
||||
#define NMC_META_GENERIC_INFO_GET_FCN_ARGS \
|
||||
const NMMetaEnvironment *environment, \
|
||||
gpointer environment_user_data, \
|
||||
const NmcMetaGenericInfo *info, \
|
||||
gpointer target, \
|
||||
gpointer target_data, \
|
||||
NMMetaAccessorGetType get_type, \
|
||||
NMMetaAccessorGetFlags get_flags, \
|
||||
NMMetaAccessorGetOutFlags *out_flags, \
|
||||
gboolean *out_is_default, \
|
||||
gpointer *out_to_free
|
||||
#define NMC_META_GENERIC_INFO_GET_FCN_ARGS \
|
||||
const NMMetaEnvironment *environment, gpointer environment_user_data, \
|
||||
const NmcMetaGenericInfo *info, gpointer target, gpointer target_data, \
|
||||
NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, \
|
||||
NMMetaAccessorGetOutFlags *out_flags, gboolean *out_is_default, gpointer *out_to_free
|
||||
|
||||
gconstpointer (*get_fcn) (NMC_META_GENERIC_INFO_GET_FCN_ARGS);
|
||||
gconstpointer (*get_fcn)(NMC_META_GENERIC_INFO_GET_FCN_ARGS);
|
||||
};
|
||||
|
||||
#define NMC_META_GENERIC(n, ...) \
|
||||
(&((NmcMetaGenericInfo) { \
|
||||
.meta_type = &nmc_meta_type_generic_info, \
|
||||
.name = n, \
|
||||
__VA_ARGS__ \
|
||||
}))
|
||||
(&((NmcMetaGenericInfo){.meta_type = &nmc_meta_type_generic_info, .name = n, __VA_ARGS__}))
|
||||
|
||||
#define NMC_META_GENERIC_WITH_NESTED(n, nest, ...) \
|
||||
NMC_META_GENERIC (n, .nested = (nest), __VA_ARGS__)
|
||||
NMC_META_GENERIC(n, .nested = (nest), __VA_ARGS__)
|
||||
|
||||
#define NMC_META_GENERIC_GROUP(_group_name, _nested, _name_header) \
|
||||
((const NMMetaAbstractInfo *const*) ((const NmcMetaGenericInfo *const[]) { \
|
||||
NMC_META_GENERIC_WITH_NESTED (_group_name,_nested, .name_header = _name_header), \
|
||||
NULL, \
|
||||
}))
|
||||
#define NMC_META_GENERIC_GROUP(_group_name, _nested, _name_header) \
|
||||
((const NMMetaAbstractInfo *const *) ((const NmcMetaGenericInfo *const[]){ \
|
||||
NMC_META_GENERIC_WITH_NESTED(_group_name, _nested, .name_header = _name_header), \
|
||||
NULL, \
|
||||
}))
|
||||
|
||||
static inline const char *
|
||||
nmc_meta_generic_get_str_i18n (const char *s, NMMetaAccessorGetType get_type)
|
||||
nmc_meta_generic_get_str_i18n(const char *s, NMMetaAccessorGetType get_type)
|
||||
{
|
||||
if (!NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY,
|
||||
NM_META_ACCESSOR_GET_TYPE_PARSABLE))
|
||||
g_return_val_if_reached (NULL);
|
||||
if (!NM_IN_SET(get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, NM_META_ACCESSOR_GET_TYPE_PARSABLE))
|
||||
g_return_val_if_reached(NULL);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
return gettext (s);
|
||||
return s;
|
||||
if (!s)
|
||||
return NULL;
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
return gettext(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nmc_meta_generic_get_bool (gboolean val, NMMetaAccessorGetType get_type)
|
||||
nmc_meta_generic_get_str_i18n_null(const char *s, NMMetaAccessorGetType get_type)
|
||||
{
|
||||
return nmc_meta_generic_get_str_i18n (val ? N_("yes") : N_("no"), get_type);
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PARSABLE) {
|
||||
/* in parsable mode, return NULL. That is useful if @s is a pretty string
|
||||
* to describe a missing value (like "(unknown)"). We don't want to print
|
||||
* that for parsable mode. */
|
||||
return NULL;
|
||||
}
|
||||
return nmc_meta_generic_get_str_i18n(s, get_type);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nmc_meta_generic_get_bool_onoff (gboolean val, NMMetaAccessorGetType get_type)
|
||||
nmc_meta_generic_get_unknown(NMMetaAccessorGetType get_type)
|
||||
{
|
||||
return nmc_meta_generic_get_str_i18n (val ? N_("on") : N_("off"), get_type);
|
||||
return nmc_meta_generic_get_str_i18n_null(N_("(unknown)"), get_type);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nmc_meta_generic_get_bool(gboolean val, NMMetaAccessorGetType get_type)
|
||||
{
|
||||
return nmc_meta_generic_get_str_i18n(val ? N_("yes") : N_("no"), get_type);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nmc_meta_generic_get_bool_onoff(gboolean val, NMMetaAccessorGetType get_type)
|
||||
{
|
||||
return nmc_meta_generic_get_str_i18n(val ? N_("on") : N_("off"), get_type);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
|
||||
NMC_META_GENERIC_GET_ENUM_TYPE_DASH,
|
||||
NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
|
||||
NMC_META_GENERIC_GET_ENUM_TYPE_DASH,
|
||||
} NmcMetaGenericGetEnumType;
|
||||
|
||||
static inline char *
|
||||
nmc_meta_generic_get_enum_with_detail (NmcMetaGenericGetEnumType get_enum_type, gint64 enum_val, const char *str_val, NMMetaAccessorGetType get_type)
|
||||
nmc_meta_generic_get_enum_with_detail(NmcMetaGenericGetEnumType get_enum_type,
|
||||
gint64 enum_val,
|
||||
const char * str_val,
|
||||
NMMetaAccessorGetType get_type)
|
||||
{
|
||||
if (!NM_IN_SET (get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY,
|
||||
NM_META_ACCESSOR_GET_TYPE_PARSABLE))
|
||||
g_return_val_if_reached (NULL);
|
||||
if (!NM_IN_SET(get_type, NM_META_ACCESSOR_GET_TYPE_PRETTY, NM_META_ACCESSOR_GET_TYPE_PARSABLE))
|
||||
g_return_val_if_reached(NULL);
|
||||
|
||||
if (!str_val) {
|
||||
/* Pass %NULL for only printing the numeric value. */
|
||||
return g_strdup_printf ("%lld", (long long) enum_val);
|
||||
}
|
||||
if (!str_val) {
|
||||
/* Pass %NULL for only printing the numeric value. */
|
||||
return g_strdup_printf("%lld", (long long) enum_val);
|
||||
}
|
||||
|
||||
switch (get_enum_type) {
|
||||
case NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES:
|
||||
/* note that this function will always print "$NUM ($NICK)", also in PARSABLE
|
||||
* mode. That might not be desired, but it's done for certain properties to preserve
|
||||
* previous behavior. */
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
return g_strdup_printf (_("%lld (%s)"), (long long) enum_val, gettext (str_val));
|
||||
return g_strdup_printf ("%lld (%s)", (long long) enum_val, str_val);
|
||||
case NMC_META_GENERIC_GET_ENUM_TYPE_DASH:
|
||||
/* note that this function will always print "$NUM ($NICK)", also in PARSABLE
|
||||
* mode. That might not be desired, but it's done for certain properties to preserve
|
||||
* previous behavior. */
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
return g_strdup_printf (_("%lld - %s"), (long long) enum_val, gettext (str_val));
|
||||
return g_strdup_printf ("%lld - %s", (long long) enum_val, str_val);
|
||||
}
|
||||
g_return_val_if_reached (NULL);
|
||||
switch (get_enum_type) {
|
||||
case NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES:
|
||||
/* note that this function will always print "$NUM ($NICK)", also in PARSABLE
|
||||
* mode. That might not be desired, but it's done for certain properties to preserve
|
||||
* previous behavior. */
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
return g_strdup_printf(_("%lld (%s)"), (long long) enum_val, gettext(str_val));
|
||||
return g_strdup_printf("%lld (%s)", (long long) enum_val, str_val);
|
||||
case NMC_META_GENERIC_GET_ENUM_TYPE_DASH:
|
||||
/* note that this function will always print "$NUM ($NICK)", also in PARSABLE
|
||||
* mode. That might not be desired, but it's done for certain properties to preserve
|
||||
* previous behavior. */
|
||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
return g_strdup_printf(_("%lld - %s"), (long long) enum_val, gettext(str_val));
|
||||
return g_strdup_printf("%lld - %s", (long long) enum_val, str_val);
|
||||
}
|
||||
g_return_val_if_reached(NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nmc_print (const NmcConfig *nmc_config,
|
||||
gpointer const *targets,
|
||||
gpointer targets_data,
|
||||
const char *header_name_no_l10n,
|
||||
const NMMetaAbstractInfo *const*fields,
|
||||
const char *fields_str,
|
||||
GError **error);
|
||||
gboolean nmc_print(const NmcConfig * nmc_config,
|
||||
gpointer const * targets,
|
||||
gpointer targets_data,
|
||||
const char * header_name_no_l10n,
|
||||
const NMMetaAbstractInfo *const *fields,
|
||||
const char * fields_str,
|
||||
GError ** error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
9
clients/cloud-setup/90-nm-cloud-setup.sh
Executable file
9
clients/cloud-setup/90-nm-cloud-setup.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
case "$2" in
|
||||
up|dhcp4-change)
|
||||
if systemctl -q is-enabled nm-cloud-setup.service ; then
|
||||
exec systemctl --no-block restart nm-cloud-setup.service
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
605
clients/cloud-setup/main.c
Normal file
605
clients/cloud-setup/main.c
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-libnm-aux/nm-libnm-aux.h"
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
#include "nmcs-provider-ec2.h"
|
||||
#include "nmcs-provider-gcp.h"
|
||||
#include "nmcs-provider-azure.h"
|
||||
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainLoop * main_loop;
|
||||
GCancellable *cancellable;
|
||||
NMCSProvider *provider_result;
|
||||
guint detect_count;
|
||||
} ProviderDetectData;
|
||||
|
||||
static void
|
||||
_provider_detect_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_object NMCSProvider *provider = NMCS_PROVIDER(source);
|
||||
gs_free_error GError *error = NULL;
|
||||
ProviderDetectData * dd;
|
||||
gboolean success;
|
||||
|
||||
success = nmcs_provider_detect_finish(provider, result, &error);
|
||||
|
||||
nm_assert(success != (!!error));
|
||||
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
return;
|
||||
|
||||
dd = user_data;
|
||||
|
||||
nm_assert(dd->detect_count > 0);
|
||||
dd->detect_count--;
|
||||
|
||||
if (error) {
|
||||
_LOGI("provider %s not detected: %s", nmcs_provider_get_name(provider), error->message);
|
||||
if (dd->detect_count > 0) {
|
||||
/* wait longer. */
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGI("no provider detected");
|
||||
goto done;
|
||||
}
|
||||
|
||||
_LOGI("provider %s detected", nmcs_provider_get_name(provider));
|
||||
dd->provider_result = g_steal_pointer(&provider);
|
||||
|
||||
done:
|
||||
g_cancellable_cancel(dd->cancellable);
|
||||
g_main_loop_quit(dd->main_loop);
|
||||
}
|
||||
|
||||
static void
|
||||
_provider_detect_sigterm_cb(GCancellable *source, gpointer user_data)
|
||||
{
|
||||
ProviderDetectData *dd = user_data;
|
||||
|
||||
g_cancellable_cancel(dd->cancellable);
|
||||
g_clear_object(&dd->provider_result);
|
||||
dd->detect_count = 0;
|
||||
g_main_loop_quit(dd->main_loop);
|
||||
}
|
||||
|
||||
static NMCSProvider *
|
||||
_provider_detect(GCancellable *sigterm_cancellable)
|
||||
{
|
||||
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
|
||||
gs_unref_object GCancellable *cancellable = g_cancellable_new();
|
||||
gs_unref_object NMHttpClient *http_client = NULL;
|
||||
ProviderDetectData dd = {
|
||||
.cancellable = cancellable,
|
||||
.main_loop = main_loop,
|
||||
.detect_count = 0,
|
||||
.provider_result = NULL,
|
||||
};
|
||||
const GType gtypes[] = {
|
||||
NMCS_TYPE_PROVIDER_EC2,
|
||||
NMCS_TYPE_PROVIDER_GCP,
|
||||
NMCS_TYPE_PROVIDER_AZURE,
|
||||
};
|
||||
int i;
|
||||
gulong cancellable_signal_id;
|
||||
|
||||
cancellable_signal_id = g_cancellable_connect(sigterm_cancellable,
|
||||
G_CALLBACK(_provider_detect_sigterm_cb),
|
||||
&dd,
|
||||
NULL);
|
||||
if (!cancellable_signal_id)
|
||||
goto out;
|
||||
|
||||
http_client = nmcs_wait_for_objects_register(nm_http_client_new());
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(gtypes); i++) {
|
||||
NMCSProvider *provider;
|
||||
|
||||
provider = g_object_new(gtypes[i], NMCS_PROVIDER_HTTP_CLIENT, http_client, NULL);
|
||||
nmcs_wait_for_objects_register(provider);
|
||||
|
||||
_LOGD("start detecting %s provider...", nmcs_provider_get_name(provider));
|
||||
dd.detect_count++;
|
||||
nmcs_provider_detect(provider, cancellable, _provider_detect_cb, &dd);
|
||||
}
|
||||
|
||||
if (dd.detect_count > 0)
|
||||
g_main_loop_run(main_loop);
|
||||
|
||||
out:
|
||||
nm_clear_g_signal_handler(sigterm_cancellable, &cancellable_signal_id);
|
||||
return dd.provider_result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static char **
|
||||
_nmc_get_hwaddrs(NMClient *nmc)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *hwaddrs = NULL;
|
||||
const GPtrArray * devices;
|
||||
char ** hwaddrs_v;
|
||||
gs_free char * str = NULL;
|
||||
guint i;
|
||||
|
||||
devices = nm_client_get_devices(nmc);
|
||||
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
NMDevice * device = devices->pdata[i];
|
||||
const char *hwaddr;
|
||||
char * s;
|
||||
|
||||
if (!NM_IS_DEVICE_ETHERNET(device))
|
||||
continue;
|
||||
|
||||
if (nm_device_get_state(device) < NM_DEVICE_STATE_UNAVAILABLE)
|
||||
continue;
|
||||
|
||||
hwaddr = nm_device_ethernet_get_permanent_hw_address(NM_DEVICE_ETHERNET(device));
|
||||
if (!hwaddr)
|
||||
continue;
|
||||
|
||||
s = nmcs_utils_hwaddr_normalize(hwaddr, -1);
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
if (!hwaddrs)
|
||||
hwaddrs = g_ptr_array_new_with_free_func(g_free);
|
||||
g_ptr_array_add(hwaddrs, s);
|
||||
}
|
||||
|
||||
if (!hwaddrs) {
|
||||
_LOGD("found interfaces: none");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_ptr_array_add(hwaddrs, NULL);
|
||||
hwaddrs_v = (char **) g_ptr_array_free(g_steal_pointer(&hwaddrs), FALSE);
|
||||
|
||||
_LOGD("found interfaces: %s", (str = g_strjoinv(", ", hwaddrs_v)));
|
||||
|
||||
return hwaddrs_v;
|
||||
}
|
||||
|
||||
static NMDevice *
|
||||
_nmc_get_device_by_hwaddr(NMClient *nmc, const char *hwaddr)
|
||||
{
|
||||
const GPtrArray *devices;
|
||||
guint i;
|
||||
|
||||
devices = nm_client_get_devices(nmc);
|
||||
|
||||
for (i = 0; i < devices->len; i++) {
|
||||
NMDevice * device = devices->pdata[i];
|
||||
const char * hwaddr_dev;
|
||||
gs_free char *s = NULL;
|
||||
|
||||
if (!NM_IS_DEVICE_ETHERNET(device))
|
||||
continue;
|
||||
|
||||
hwaddr_dev = nm_device_ethernet_get_permanent_hw_address(NM_DEVICE_ETHERNET(device));
|
||||
if (!hwaddr_dev)
|
||||
continue;
|
||||
|
||||
s = nmcs_utils_hwaddr_normalize(hwaddr_dev, -1);
|
||||
if (s && nm_streq(s, hwaddr))
|
||||
return device;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainLoop * main_loop;
|
||||
GHashTable *config_dict;
|
||||
} GetConfigData;
|
||||
|
||||
static void
|
||||
_get_config_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
GetConfigData * data = user_data;
|
||||
gs_unref_hashtable GHashTable *config_dict = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
config_dict = nmcs_provider_get_config_finish(NMCS_PROVIDER(source), result, &error);
|
||||
|
||||
if (!config_dict) {
|
||||
if (!nm_utils_error_is_cancelled(error))
|
||||
_LOGI("failure to get meta data: %s", error->message);
|
||||
} else
|
||||
_LOGD("meta data received");
|
||||
|
||||
data->config_dict = g_steal_pointer(&config_dict);
|
||||
g_main_loop_quit(data->main_loop);
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
_get_config(GCancellable *sigterm_cancellable, NMCSProvider *provider, NMClient *nmc)
|
||||
{
|
||||
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
|
||||
GetConfigData data = {
|
||||
.main_loop = main_loop,
|
||||
};
|
||||
gs_strfreev char **hwaddrs = NULL;
|
||||
|
||||
hwaddrs = _nmc_get_hwaddrs(nmc);
|
||||
|
||||
nmcs_provider_get_config(provider,
|
||||
TRUE,
|
||||
(const char *const *) hwaddrs,
|
||||
sigterm_cancellable,
|
||||
_get_config_cb,
|
||||
&data);
|
||||
|
||||
g_main_loop_run(main_loop);
|
||||
|
||||
return data.config_dict;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_nmc_skip_connection(NMConnection *connection)
|
||||
{
|
||||
NMSettingUser *s_user;
|
||||
const char * v;
|
||||
|
||||
s_user = NM_SETTING_USER(nm_connection_get_setting(connection, NM_TYPE_SETTING_USER));
|
||||
if (!s_user)
|
||||
return FALSE;
|
||||
|
||||
#define USER_TAG_SKIP "org.freedesktop.nm-cloud-setup.skip"
|
||||
|
||||
nm_assert(nm_setting_user_check_key(USER_TAG_SKIP, NULL));
|
||||
|
||||
v = nm_setting_user_get_data(s_user, USER_TAG_SKIP);
|
||||
return _nm_utils_ascii_str_to_bool(v, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_nmc_mangle_connection(NMDevice * device,
|
||||
NMConnection * connection,
|
||||
const NMCSProviderGetConfigIfaceData *config_data,
|
||||
gboolean * out_changed)
|
||||
{
|
||||
NMSettingIPConfig *s_ip;
|
||||
gsize i;
|
||||
in_addr_t gateway;
|
||||
gint64 rt_metric;
|
||||
guint32 rt_table;
|
||||
NMIPRoute * route_entry;
|
||||
gboolean addrs_changed = FALSE;
|
||||
gboolean rules_changed = FALSE;
|
||||
gboolean routes_changed = FALSE;
|
||||
gs_unref_ptrarray GPtrArray *addrs_new = NULL;
|
||||
gs_unref_ptrarray GPtrArray *rules_new = NULL;
|
||||
gs_unref_ptrarray GPtrArray *routes_new = NULL;
|
||||
|
||||
if (!nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_WIRED_SETTING_NAME))
|
||||
return FALSE;
|
||||
|
||||
s_ip = nm_connection_get_setting_ip4_config(connection);
|
||||
if (!s_ip)
|
||||
return FALSE;
|
||||
|
||||
addrs_new = g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_address_unref);
|
||||
rules_new =
|
||||
g_ptr_array_new_full(config_data->ipv4s_len, (GDestroyNotify) nm_ip_routing_rule_unref);
|
||||
routes_new = g_ptr_array_new_full(config_data->iproutes_len + !!config_data->ipv4s_len,
|
||||
(GDestroyNotify) nm_ip_route_unref);
|
||||
|
||||
if (config_data->has_ipv4s && config_data->has_cidr) {
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
NMIPAddress *entry;
|
||||
|
||||
entry = nm_ip_address_new_binary(AF_INET,
|
||||
&config_data->ipv4s_arr[i],
|
||||
config_data->cidr_prefix,
|
||||
NULL);
|
||||
if (entry)
|
||||
g_ptr_array_add(addrs_new, entry);
|
||||
}
|
||||
|
||||
gateway = nm_utils_ip4_address_clear_host_address(config_data->cidr_addr,
|
||||
config_data->cidr_prefix);
|
||||
((guint8 *) &gateway)[3] += 1;
|
||||
|
||||
rt_metric = 10;
|
||||
rt_table = 30400 + config_data->iface_idx;
|
||||
|
||||
route_entry =
|
||||
nm_ip_route_new_binary(AF_INET, &nm_ip_addr_zero, 0, &gateway, rt_metric, NULL);
|
||||
nm_ip_route_set_attribute(route_entry,
|
||||
NM_IP_ROUTE_ATTRIBUTE_TABLE,
|
||||
g_variant_new_uint32(rt_table));
|
||||
g_ptr_array_add(routes_new, route_entry);
|
||||
|
||||
for (i = 0; i < config_data->ipv4s_len; i++) {
|
||||
NMIPRoutingRule *entry;
|
||||
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
|
||||
entry = nm_ip_routing_rule_new(AF_INET);
|
||||
nm_ip_routing_rule_set_priority(entry, rt_table);
|
||||
nm_ip_routing_rule_set_from(entry,
|
||||
_nm_utils_inet4_ntop(config_data->ipv4s_arr[i], sbuf),
|
||||
32);
|
||||
nm_ip_routing_rule_set_table(entry, rt_table);
|
||||
|
||||
nm_assert(nm_ip_routing_rule_validate(entry, NULL));
|
||||
|
||||
g_ptr_array_add(rules_new, entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < config_data->iproutes_len; ++i)
|
||||
g_ptr_array_add(routes_new, config_data->iproutes_arr[i]);
|
||||
|
||||
addrs_changed = nmcs_setting_ip_replace_ipv4_addresses(s_ip,
|
||||
(NMIPAddress **) addrs_new->pdata,
|
||||
addrs_new->len);
|
||||
|
||||
routes_changed = nmcs_setting_ip_replace_ipv4_routes(s_ip,
|
||||
(NMIPRoute **) routes_new->pdata,
|
||||
routes_new->len);
|
||||
|
||||
rules_changed = nmcs_setting_ip_replace_ipv4_rules(s_ip,
|
||||
(NMIPRoutingRule **) rules_new->pdata,
|
||||
rules_new->len);
|
||||
|
||||
NM_SET_OUT(out_changed, addrs_changed || routes_changed || rules_changed);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint
|
||||
_config_data_get_num_valid(GHashTable *config_dict)
|
||||
{
|
||||
const NMCSProviderGetConfigIfaceData *config_data;
|
||||
GHashTableIter h_iter;
|
||||
guint n = 0;
|
||||
|
||||
g_hash_table_iter_init(&h_iter, config_dict);
|
||||
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &config_data)) {
|
||||
if (nmcs_provider_get_config_iface_data_is_valid(config_data))
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_config_one(GCancellable * sigterm_cancellable,
|
||||
NMClient * nmc,
|
||||
gboolean is_single_nic,
|
||||
const char * hwaddr,
|
||||
const NMCSProviderGetConfigIfaceData *config_data)
|
||||
{
|
||||
gs_unref_object NMDevice *device = NULL;
|
||||
gs_unref_object NMConnection *applied_connection = NULL;
|
||||
guint64 applied_version_id;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean changed;
|
||||
gboolean version_id_changed;
|
||||
guint try_count;
|
||||
gboolean any_changes = FALSE;
|
||||
|
||||
g_main_context_iteration(NULL, FALSE);
|
||||
|
||||
if (g_cancellable_is_cancelled(sigterm_cancellable))
|
||||
return FALSE;
|
||||
|
||||
device = nm_g_object_ref(_nmc_get_device_by_hwaddr(nmc, hwaddr));
|
||||
if (!device) {
|
||||
_LOGD("config device %s: skip because device not found", hwaddr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nmcs_provider_get_config_iface_data_is_valid(config_data)) {
|
||||
_LOGD("config device %s: skip because meta data not successfully fetched", hwaddr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_LOGD("config device %s: configuring \"%s\" (%s)...",
|
||||
hwaddr,
|
||||
nm_device_get_iface(device) ?: "/unknown/",
|
||||
nm_object_get_path(NM_OBJECT(device)));
|
||||
|
||||
try_count = 0;
|
||||
|
||||
try_again:
|
||||
|
||||
applied_connection = nmcs_device_get_applied_connection(device,
|
||||
sigterm_cancellable,
|
||||
&applied_version_id,
|
||||
&error);
|
||||
if (!applied_connection) {
|
||||
if (!nm_utils_error_is_cancelled(error))
|
||||
_LOGD("config device %s: device has no applied connection (%s). Skip",
|
||||
hwaddr,
|
||||
error->message);
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
if (_nmc_skip_connection(applied_connection)) {
|
||||
_LOGD("config device %s: skip applied connection due to user data %s",
|
||||
hwaddr,
|
||||
USER_TAG_SKIP);
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
if (!_nmc_mangle_connection(device, applied_connection, config_data, &changed)) {
|
||||
_LOGD("config device %s: device has no suitable applied connection. Skip", hwaddr);
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
_LOGD("config device %s: device needs no update to applied connection \"%s\" (%s). Skip",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
_LOGD("config device %s: reapply connection \"%s\" (%s)",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
|
||||
/* we are about to call Reapply(). If if that fails, it counts as if we changed something. */
|
||||
any_changes = TRUE;
|
||||
|
||||
if (!nmcs_device_reapply(device,
|
||||
sigterm_cancellable,
|
||||
applied_connection,
|
||||
applied_version_id,
|
||||
&version_id_changed,
|
||||
&error)) {
|
||||
if (version_id_changed && try_count < 5) {
|
||||
_LOGD("config device %s: applied connection changed in the meantime. Retry...", hwaddr);
|
||||
g_clear_object(&applied_connection);
|
||||
g_clear_error(&error);
|
||||
try_count++;
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (!nm_utils_error_is_cancelled(error)) {
|
||||
_LOGD("config device %s: failure to reapply connection \"%s\" (%s): %s",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection),
|
||||
error->message);
|
||||
}
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
_LOGD("config device %s: connection \"%s\" (%s) reapplied",
|
||||
hwaddr,
|
||||
nm_connection_get_id(applied_connection),
|
||||
nm_connection_get_uuid(applied_connection));
|
||||
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_config_all(GCancellable *sigterm_cancellable, NMClient *nmc, GHashTable *config_dict)
|
||||
{
|
||||
GHashTableIter h_iter;
|
||||
const NMCSProviderGetConfigIfaceData *c_config_data;
|
||||
const char * c_hwaddr;
|
||||
gboolean is_single_nic;
|
||||
gboolean any_changes = FALSE;
|
||||
|
||||
is_single_nic = (_config_data_get_num_valid(config_dict) <= 1);
|
||||
|
||||
g_hash_table_iter_init(&h_iter, config_dict);
|
||||
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, (gpointer *) &c_config_data)) {
|
||||
if (_config_one(sigterm_cancellable, nmc, is_single_nic, c_hwaddr, c_config_data))
|
||||
any_changes = TRUE;
|
||||
}
|
||||
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
sigterm_handler(gpointer user_data)
|
||||
{
|
||||
GCancellable *sigterm_cancellable = user_data;
|
||||
|
||||
if (!g_cancellable_is_cancelled(sigterm_cancellable)) {
|
||||
_LOGD("SIGTERM received");
|
||||
g_cancellable_cancel(user_data);
|
||||
} else
|
||||
_LOGD("SIGTERM received (again)");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
main(int argc, const char *const *argv)
|
||||
{
|
||||
gs_unref_object GCancellable * sigterm_cancellable = NULL;
|
||||
nm_auto_destroy_and_unref_gsource GSource *sigterm_source = NULL;
|
||||
gs_unref_object NMCSProvider *provider = NULL;
|
||||
gs_unref_object NMClient *nmc = NULL;
|
||||
gs_unref_hashtable GHashTable *config_dict = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
_nm_logging_enabled_init(g_getenv(NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_LOG")));
|
||||
|
||||
_LOGD("nm-cloud-setup %s starting...", NM_DIST_VERSION);
|
||||
|
||||
if (argc != 1) {
|
||||
g_printerr("%s: no command line arguments supported\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sigterm_cancellable = g_cancellable_new();
|
||||
|
||||
sigterm_source = nm_g_source_attach(nm_g_unix_signal_source_new(SIGTERM,
|
||||
G_PRIORITY_DEFAULT,
|
||||
sigterm_handler,
|
||||
sigterm_cancellable,
|
||||
NULL),
|
||||
NULL);
|
||||
|
||||
provider = _provider_detect(sigterm_cancellable);
|
||||
if (!provider)
|
||||
goto done;
|
||||
|
||||
nmc_client_new_waitsync(sigterm_cancellable,
|
||||
&nmc,
|
||||
&error,
|
||||
NM_CLIENT_INSTANCE_FLAGS,
|
||||
(guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
|
||||
NULL);
|
||||
|
||||
nmcs_wait_for_objects_register(nmc);
|
||||
nmcs_wait_for_objects_register(nm_client_get_context_busy_watcher(nmc));
|
||||
|
||||
if (error) {
|
||||
if (!nm_utils_error_is_cancelled(error))
|
||||
_LOGI("failure to talk to NetworkManager: %s", error->message);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!nm_client_get_nm_running(nmc)) {
|
||||
_LOGI("NetworkManager is not running");
|
||||
goto done;
|
||||
}
|
||||
|
||||
config_dict = _get_config(sigterm_cancellable, provider, nmc);
|
||||
if (!config_dict)
|
||||
goto done;
|
||||
|
||||
if (_config_all(sigterm_cancellable, nmc, config_dict))
|
||||
_LOGI("some changes were applied for provider %s", nmcs_provider_get_name(provider));
|
||||
else
|
||||
_LOGD("no changes were applied for provider %s", nmcs_provider_get_name(provider));
|
||||
|
||||
done:
|
||||
nm_clear_pointer(&config_dict, g_hash_table_unref);
|
||||
g_clear_object(&nmc);
|
||||
g_clear_object(&provider);
|
||||
|
||||
if (!nmcs_wait_for_objects_iterate_until_done(NULL, 2000)) {
|
||||
_LOGE("shutdown: timeout waiting to application to quit. This is a bug");
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
||||
nm_clear_g_source_inst(&sigterm_source);
|
||||
g_clear_object(&sigterm_cancellable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
52
clients/cloud-setup/meson.build
Normal file
52
clients/cloud-setup/meson.build
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
name = 'nm-cloud-setup'
|
||||
|
||||
if install_systemdunitdir
|
||||
|
||||
nm_cloud_setup_service = configure_file(
|
||||
input: 'nm-cloud-setup.service.in',
|
||||
output: '@BASENAME@',
|
||||
install_dir: systemd_systemdsystemunitdir,
|
||||
configuration: data_conf,
|
||||
)
|
||||
|
||||
install_data(
|
||||
'nm-cloud-setup.timer',
|
||||
install_dir: systemd_systemdsystemunitdir,
|
||||
)
|
||||
|
||||
install_data(
|
||||
'90-nm-cloud-setup.sh',
|
||||
install_dir: join_paths(nm_pkglibdir, 'dispatcher.d', 'no-wait.d'),
|
||||
)
|
||||
|
||||
endif
|
||||
|
||||
sources = files(
|
||||
'main.c',
|
||||
'nm-cloud-setup-utils.c',
|
||||
'nm-http-client.c',
|
||||
'nmcs-provider-ec2.c',
|
||||
'nmcs-provider-gcp.c',
|
||||
'nmcs-provider-azure.c',
|
||||
'nmcs-provider.c',
|
||||
)
|
||||
|
||||
executable(
|
||||
name,
|
||||
sources,
|
||||
dependencies: [
|
||||
libnmc_base_dep,
|
||||
libnmc_dep,
|
||||
libcurl_dep,
|
||||
libnm_libnm_aux_dep,
|
||||
],
|
||||
c_args: clients_c_flags +
|
||||
['-DG_LOG_DOMAIN="@0@"'.format(name)],
|
||||
link_with: libnm_systemd_logging_stub,
|
||||
link_args: ldflags_linker_script_binary,
|
||||
link_depends: linker_script_binary,
|
||||
install: true,
|
||||
install_dir: nm_libexecdir,
|
||||
)
|
||||
832
clients/cloud-setup/nm-cloud-setup-utils.c
Normal file
832
clients/cloud-setup/nm-cloud-setup-utils.c
Normal file
|
|
@ -0,0 +1,832 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_infiniband.h>
|
||||
|
||||
#include "nm-glib-aux/nm-time-utils.h"
|
||||
#include "nm-glib-aux/nm-logging-base.h"
|
||||
#include "nm-glib-aux/nm-str-buf.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
volatile NMLogLevel _nm_logging_configured_level = LOGL_TRACE;
|
||||
|
||||
void
|
||||
_nm_logging_enabled_init(const char *level_str)
|
||||
{
|
||||
NMLogLevel level;
|
||||
|
||||
if (!_nm_log_parse_level(level_str, &level))
|
||||
level = LOGL_WARN;
|
||||
else if (level == _LOGL_KEEP)
|
||||
level = LOGL_WARN;
|
||||
|
||||
_nm_logging_configured_level = level;
|
||||
}
|
||||
|
||||
void
|
||||
_nm_log_impl_cs(NMLogLevel level, const char *fmt, ...)
|
||||
{
|
||||
gs_free char *msg = NULL;
|
||||
va_list ap;
|
||||
const char * level_str;
|
||||
gint64 ts;
|
||||
|
||||
va_start(ap, fmt);
|
||||
msg = g_strdup_vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
switch (level) {
|
||||
case LOGL_TRACE:
|
||||
level_str = "<trace>";
|
||||
break;
|
||||
case LOGL_DEBUG:
|
||||
level_str = "<debug>";
|
||||
break;
|
||||
case LOGL_INFO:
|
||||
level_str = "<info> ";
|
||||
break;
|
||||
case LOGL_WARN:
|
||||
level_str = "<warn> ";
|
||||
break;
|
||||
default:
|
||||
nm_assert(level == LOGL_ERR);
|
||||
level_str = "<error>";
|
||||
break;
|
||||
}
|
||||
|
||||
ts = nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME);
|
||||
|
||||
g_print("[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s %s\n",
|
||||
ts / NM_UTILS_NSEC_PER_SEC,
|
||||
(ts / (NM_UTILS_NSEC_PER_SEC / 10000)) % 10000,
|
||||
level_str,
|
||||
msg);
|
||||
}
|
||||
|
||||
void
|
||||
_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp,
|
||||
gint64 offset_sec,
|
||||
gboolean is_boottime)
|
||||
{}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_LOCK_DEFINE_STATIC(_wait_for_objects_lock);
|
||||
static GSList *_wait_for_objects_list;
|
||||
static GSList *_wait_for_objects_iterate_loops;
|
||||
|
||||
static void
|
||||
_wait_for_objects_maybe_quit_mainloops_with_lock(void)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
if (!_wait_for_objects_list) {
|
||||
for (iter = _wait_for_objects_iterate_loops; iter; iter = iter->next)
|
||||
g_main_loop_quit(iter->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_wait_for_objects_weak_cb(gpointer data, GObject *where_the_object_was)
|
||||
{
|
||||
G_LOCK(_wait_for_objects_lock);
|
||||
nm_assert(g_slist_find(_wait_for_objects_list, where_the_object_was));
|
||||
_wait_for_objects_list = g_slist_remove(_wait_for_objects_list, where_the_object_was);
|
||||
_wait_for_objects_maybe_quit_mainloops_with_lock();
|
||||
G_UNLOCK(_wait_for_objects_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* nmcs_wait_for_objects_register:
|
||||
* @target: a #GObject to wait for.
|
||||
*
|
||||
* Registers @target as a pointer to wait during shutdown. Using
|
||||
* nmcs_wait_for_objects_iterate_until_done() we keep waiting until
|
||||
* @target gets destroyed, which means that it gets completely unreferenced.
|
||||
*/
|
||||
gpointer
|
||||
nmcs_wait_for_objects_register(gpointer target)
|
||||
{
|
||||
g_return_val_if_fail(G_IS_OBJECT(target), NULL);
|
||||
|
||||
G_LOCK(_wait_for_objects_lock);
|
||||
_wait_for_objects_list = g_slist_prepend(_wait_for_objects_list, target);
|
||||
G_UNLOCK(_wait_for_objects_lock);
|
||||
|
||||
g_object_weak_ref(target, _wait_for_objects_weak_cb, NULL);
|
||||
return target;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GMainLoop *loop;
|
||||
gboolean got_timeout;
|
||||
} WaitForObjectsData;
|
||||
|
||||
static gboolean
|
||||
_wait_for_objects_iterate_until_done_timeout_cb(gpointer user_data)
|
||||
{
|
||||
WaitForObjectsData *data = user_data;
|
||||
|
||||
data->got_timeout = TRUE;
|
||||
g_main_loop_quit(data->loop);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_wait_for_objects_iterate_until_done_idle_cb(gpointer user_data)
|
||||
{
|
||||
/* This avoids a race where:
|
||||
*
|
||||
* - we check whether there are objects to wait for.
|
||||
* - the last object to wait for gets removed (issuing g_main_loop_quit()).
|
||||
* - we run the mainloop (and missed our signal).
|
||||
*
|
||||
* It's really a missing feature of GMainLoop where the "is-running" flag is always set to
|
||||
* TRUE by g_main_loop_run(). That means, you cannot catch a g_main_loop_quit() in a race
|
||||
* free way while not iterating the loop.
|
||||
*
|
||||
* Avoid this, by checking once again after we start running the mainloop.
|
||||
*/
|
||||
|
||||
G_LOCK(_wait_for_objects_lock);
|
||||
_wait_for_objects_maybe_quit_mainloops_with_lock();
|
||||
G_UNLOCK(_wait_for_objects_lock);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nmcs_wait_for_objects_iterate_until_done:
|
||||
* @context: the #GMainContext to iterate.
|
||||
* @timeout_msec: timeout or -1 for no timeout.
|
||||
*
|
||||
* Iterates the provided @context until all objects that we wait for
|
||||
* are destroyed.
|
||||
*
|
||||
* The purpose of this is to cleanup all objects that we have on exit. That
|
||||
* is especially because objects have asynchronous operations pending that
|
||||
* should be cancelled and properly completed during exit.
|
||||
*
|
||||
* Returns: %FALSE on timeout or %TRUE if all objects destroyed before timeout.
|
||||
*/
|
||||
gboolean
|
||||
nmcs_wait_for_objects_iterate_until_done(GMainContext *context, int timeout_msec)
|
||||
{
|
||||
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(context, FALSE);
|
||||
nm_auto_destroy_and_unref_gsource GSource *timeout_source = NULL;
|
||||
WaitForObjectsData data;
|
||||
gboolean has_more_objects;
|
||||
|
||||
G_LOCK(_wait_for_objects_lock);
|
||||
if (!_wait_for_objects_list) {
|
||||
G_UNLOCK(_wait_for_objects_lock);
|
||||
return TRUE;
|
||||
}
|
||||
_wait_for_objects_iterate_loops = g_slist_prepend(_wait_for_objects_iterate_loops, loop);
|
||||
G_UNLOCK(_wait_for_objects_lock);
|
||||
|
||||
data = (WaitForObjectsData){
|
||||
.loop = loop,
|
||||
.got_timeout = FALSE,
|
||||
};
|
||||
|
||||
if (timeout_msec >= 0) {
|
||||
timeout_source = nm_g_source_attach(
|
||||
nm_g_timeout_source_new(timeout_msec,
|
||||
G_PRIORITY_DEFAULT,
|
||||
_wait_for_objects_iterate_until_done_timeout_cb,
|
||||
&data,
|
||||
NULL),
|
||||
context);
|
||||
}
|
||||
|
||||
has_more_objects = TRUE;
|
||||
while (has_more_objects && !data.got_timeout) {
|
||||
nm_auto_destroy_and_unref_gsource GSource *idle_source = NULL;
|
||||
|
||||
idle_source =
|
||||
nm_g_source_attach(nm_g_idle_source_new(G_PRIORITY_DEFAULT,
|
||||
_wait_for_objects_iterate_until_done_idle_cb,
|
||||
&data,
|
||||
NULL),
|
||||
context);
|
||||
|
||||
g_main_loop_run(loop);
|
||||
|
||||
G_LOCK(_wait_for_objects_lock);
|
||||
has_more_objects = (!!_wait_for_objects_list);
|
||||
if (data.got_timeout || !has_more_objects)
|
||||
_wait_for_objects_iterate_loops = g_slist_remove(_wait_for_objects_iterate_loops, loop);
|
||||
G_UNLOCK(_wait_for_objects_lock);
|
||||
}
|
||||
|
||||
return !data.got_timeout;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GTask * task;
|
||||
GSource * source_timeout;
|
||||
GSource * source_next_poll;
|
||||
GMainContext * context;
|
||||
GCancellable * internal_cancellable;
|
||||
NMCSUtilsPollProbeStartFcn probe_start_fcn;
|
||||
NMCSUtilsPollProbeFinishFcn probe_finish_fcn;
|
||||
gpointer probe_user_data;
|
||||
gulong cancellable_id;
|
||||
gint64 last_poll_start_ms;
|
||||
int sleep_timeout_ms;
|
||||
int ratelimit_timeout_ms;
|
||||
bool completed : 1;
|
||||
} PollTaskData;
|
||||
|
||||
static void
|
||||
_poll_task_data_free(gpointer data)
|
||||
{
|
||||
PollTaskData *poll_task_data = data;
|
||||
|
||||
nm_assert(G_IS_TASK(poll_task_data->task));
|
||||
nm_assert(!poll_task_data->source_next_poll);
|
||||
nm_assert(!poll_task_data->source_timeout);
|
||||
nm_assert(poll_task_data->cancellable_id == 0);
|
||||
|
||||
g_main_context_unref(poll_task_data->context);
|
||||
|
||||
nm_g_slice_free(poll_task_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_poll_return(PollTaskData *poll_task_data, GError *error_take)
|
||||
{
|
||||
nm_clear_g_source_inst(&poll_task_data->source_next_poll);
|
||||
nm_clear_g_source_inst(&poll_task_data->source_timeout);
|
||||
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(poll_task_data->task),
|
||||
&poll_task_data->cancellable_id);
|
||||
|
||||
nm_clear_g_cancellable(&poll_task_data->internal_cancellable);
|
||||
|
||||
if (error_take)
|
||||
g_task_return_error(poll_task_data->task, g_steal_pointer(&error_take));
|
||||
else
|
||||
g_task_return_boolean(poll_task_data->task, TRUE);
|
||||
|
||||
g_object_unref(poll_task_data->task);
|
||||
}
|
||||
|
||||
static gboolean _poll_start_cb(gpointer user_data);
|
||||
|
||||
static void
|
||||
_poll_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
PollTaskData * poll_task_data = user_data;
|
||||
_nm_unused gs_unref_object GTask *task =
|
||||
poll_task_data->task; /* balance ref from _poll_start_cb() */
|
||||
gs_free_error GError *error = NULL;
|
||||
gint64 now_ms;
|
||||
gint64 wait_ms;
|
||||
gboolean is_finished;
|
||||
|
||||
is_finished =
|
||||
poll_task_data->probe_finish_fcn(source, result, poll_task_data->probe_user_data, &error);
|
||||
|
||||
if (nm_utils_error_is_cancelled(error)) {
|
||||
/* we already handle this differently. Nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (error || is_finished) {
|
||||
_poll_return(poll_task_data, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
now_ms = nm_utils_get_monotonic_timestamp_msec();
|
||||
if (poll_task_data->ratelimit_timeout_ms > 0)
|
||||
wait_ms =
|
||||
(poll_task_data->last_poll_start_ms + poll_task_data->ratelimit_timeout_ms) - now_ms;
|
||||
else
|
||||
wait_ms = 0;
|
||||
if (poll_task_data->sleep_timeout_ms > 0)
|
||||
wait_ms = MAX(wait_ms, poll_task_data->sleep_timeout_ms);
|
||||
|
||||
poll_task_data->source_next_poll =
|
||||
nm_g_source_attach(nm_g_timeout_source_new(MAX(1, wait_ms),
|
||||
G_PRIORITY_DEFAULT,
|
||||
_poll_start_cb,
|
||||
poll_task_data,
|
||||
NULL),
|
||||
poll_task_data->context);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_poll_start_cb(gpointer user_data)
|
||||
{
|
||||
PollTaskData *poll_task_data = user_data;
|
||||
|
||||
nm_clear_g_source_inst(&poll_task_data->source_next_poll);
|
||||
|
||||
poll_task_data->last_poll_start_ms = nm_utils_get_monotonic_timestamp_msec();
|
||||
|
||||
g_object_ref(poll_task_data->task); /* balanced by _poll_done_cb() */
|
||||
|
||||
poll_task_data->probe_start_fcn(poll_task_data->internal_cancellable,
|
||||
poll_task_data->probe_user_data,
|
||||
_poll_done_cb,
|
||||
poll_task_data);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_poll_timeout_cb(gpointer user_data)
|
||||
{
|
||||
PollTaskData *poll_task_data = user_data;
|
||||
|
||||
_poll_return(poll_task_data, nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "timeout expired"));
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_poll_cancelled_cb(GObject *object, gpointer user_data)
|
||||
{
|
||||
PollTaskData *poll_task_data = user_data;
|
||||
GError * error = NULL;
|
||||
|
||||
nm_clear_g_signal_handler(g_task_get_cancellable(poll_task_data->task),
|
||||
&poll_task_data->cancellable_id);
|
||||
nm_utils_error_set_cancelled(&error, FALSE, NULL);
|
||||
_poll_return(poll_task_data, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* nmcs_utils_poll:
|
||||
* @poll_timeout_ms: if >= 0, then this is the overall timeout for how long we poll.
|
||||
* When this timeout expires, the request completes with failure (and error set).
|
||||
* @ratelimit_timeout_ms: if > 0, we ratelimit the starts from one prope_start_fcn
|
||||
* call to the next.
|
||||
* @sleep_timeout_ms: if > 0, then we wait after a probe finished this timeout
|
||||
* before the next. Together with @ratelimit_timeout_ms this determines how
|
||||
* frequently we probe.
|
||||
* @probe_start_fcn: used to start a (asynchronous) probe. A probe must be completed
|
||||
* by calling the provided callback. While a probe is in progress, we will not
|
||||
* start another. This function is already invoked the first time synchronously,
|
||||
* during nmcs_utils_poll().
|
||||
* @probe_finish_fcn: will be called from the callback of @probe_start_fcn. If the
|
||||
* function returns %TRUE (polling done) or an error, polling stops. Otherwise,
|
||||
* another poll will be started.
|
||||
* @probe_user_data: user_data for the probe functions.
|
||||
* @cancellable: cancellable for polling.
|
||||
* @callback: when polling completes.
|
||||
* @user_data: for @callback.
|
||||
*
|
||||
* This uses the current g_main_context_get_thread_default() for scheduling
|
||||
* actions.
|
||||
*/
|
||||
void
|
||||
nmcs_utils_poll(int poll_timeout_ms,
|
||||
int ratelimit_timeout_ms,
|
||||
int sleep_timeout_ms,
|
||||
NMCSUtilsPollProbeStartFcn probe_start_fcn,
|
||||
NMCSUtilsPollProbeFinishFcn probe_finish_fcn,
|
||||
gpointer probe_user_data,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
PollTaskData *poll_task_data;
|
||||
|
||||
poll_task_data = g_slice_new(PollTaskData);
|
||||
*poll_task_data = (PollTaskData){
|
||||
.task = nm_g_task_new(NULL, cancellable, nmcs_utils_poll, callback, user_data),
|
||||
.probe_start_fcn = probe_start_fcn,
|
||||
.probe_finish_fcn = probe_finish_fcn,
|
||||
.probe_user_data = probe_user_data,
|
||||
.completed = FALSE,
|
||||
.context = g_main_context_ref_thread_default(),
|
||||
.sleep_timeout_ms = sleep_timeout_ms,
|
||||
.ratelimit_timeout_ms = ratelimit_timeout_ms,
|
||||
.internal_cancellable = g_cancellable_new(),
|
||||
};
|
||||
|
||||
nmcs_wait_for_objects_register(poll_task_data->task);
|
||||
|
||||
g_task_set_task_data(poll_task_data->task, poll_task_data, _poll_task_data_free);
|
||||
|
||||
if (poll_timeout_ms >= 0) {
|
||||
poll_task_data->source_timeout =
|
||||
nm_g_source_attach(nm_g_timeout_source_new(poll_timeout_ms,
|
||||
G_PRIORITY_DEFAULT,
|
||||
_poll_timeout_cb,
|
||||
poll_task_data,
|
||||
NULL),
|
||||
poll_task_data->context);
|
||||
}
|
||||
|
||||
poll_task_data->source_next_poll = nm_g_source_attach(
|
||||
nm_g_idle_source_new(G_PRIORITY_DEFAULT, _poll_start_cb, poll_task_data, NULL),
|
||||
poll_task_data->context);
|
||||
|
||||
if (cancellable) {
|
||||
gulong signal_id;
|
||||
|
||||
signal_id = g_cancellable_connect(cancellable,
|
||||
G_CALLBACK(_poll_cancelled_cb),
|
||||
poll_task_data,
|
||||
NULL);
|
||||
if (signal_id == 0) {
|
||||
/* the request is already cancelled. Return. */
|
||||
return;
|
||||
}
|
||||
poll_task_data->cancellable_id = signal_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nmcs_utils_poll_finish:
|
||||
* @result: the GAsyncResult from the GAsyncReadyCallback callback.
|
||||
* @probe_user_data: the user data provided to nmcs_utils_poll().
|
||||
* @error: the failure code.
|
||||
*
|
||||
* Returns: %TRUE if the polling completed with success. In that case,
|
||||
* the error won't be set.
|
||||
* If the request was cancelled, this is indicated by @error and
|
||||
* %FALSE will be returned.
|
||||
* If the probe returned a failure, this returns %FALSE and the error
|
||||
* provided by @probe_finish_fcn.
|
||||
* If the request times out, this returns %FALSE with error set.
|
||||
* Error is always set if (and only if) the function returns %FALSE.
|
||||
*/
|
||||
gboolean
|
||||
nmcs_utils_poll_finish(GAsyncResult *result, gpointer *probe_user_data, GError **error)
|
||||
{
|
||||
GTask * task;
|
||||
PollTaskData *poll_task_data;
|
||||
|
||||
g_return_val_if_fail(nm_g_task_is_valid(result, NULL, nmcs_utils_poll), FALSE);
|
||||
g_return_val_if_fail(!error || !*error, FALSE);
|
||||
|
||||
task = G_TASK(result);
|
||||
|
||||
if (probe_user_data) {
|
||||
poll_task_data = g_task_get_task_data(task);
|
||||
NM_SET_OUT(probe_user_data, poll_task_data->probe_user_data);
|
||||
}
|
||||
|
||||
return g_task_propagate_boolean(task, error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *
|
||||
nmcs_utils_hwaddr_normalize(const char *hwaddr, gssize len)
|
||||
{
|
||||
gs_free char *hwaddr_clone = NULL;
|
||||
guint8 buf[ETH_ALEN];
|
||||
|
||||
nm_assert(len >= -1);
|
||||
|
||||
if (len < 0) {
|
||||
if (!hwaddr)
|
||||
return NULL;
|
||||
} else {
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
nm_assert(hwaddr);
|
||||
hwaddr = nm_strndup_a(300, hwaddr, len, &hwaddr_clone);
|
||||
}
|
||||
/* we cannot use _nm_utils_hwaddr_aton() because that requires a delimiter.
|
||||
* Azure exposes MAC addresses without delimiter, so accept that too. */
|
||||
if (!nm_utils_hexstr2bin_full(hwaddr,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
":-",
|
||||
sizeof(buf),
|
||||
buf,
|
||||
sizeof(buf),
|
||||
NULL))
|
||||
return NULL;
|
||||
|
||||
return nm_utils_hwaddr_ntoa(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
nmcs_utils_parse_memmem(GBytes *mem, const char *needle)
|
||||
{
|
||||
const char *mem_data;
|
||||
gsize mem_size;
|
||||
|
||||
g_return_val_if_fail(mem, NULL);
|
||||
g_return_val_if_fail(needle, NULL);
|
||||
|
||||
mem_data = g_bytes_get_data(mem, &mem_size);
|
||||
return memmem(mem_data, mem_size, needle, strlen(needle));
|
||||
}
|
||||
|
||||
const char *
|
||||
nmcs_utils_parse_get_full_line(GBytes *mem, const char *needle)
|
||||
{
|
||||
const char *mem_data;
|
||||
gsize mem_size;
|
||||
gsize c;
|
||||
gsize l;
|
||||
|
||||
const char *line;
|
||||
|
||||
line = nmcs_utils_parse_memmem(mem, needle);
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
mem_data = g_bytes_get_data(mem, &mem_size);
|
||||
|
||||
if (line != mem_data && line[-1] != '\n') {
|
||||
/* the line must be preceeded either by the begin of the data or
|
||||
* by a newline. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c = mem_size - (line - mem_data);
|
||||
l = strlen(needle);
|
||||
|
||||
if (c != l && line[l] != '\n') {
|
||||
/* the end of the needle must be either a newline or the end of the buffer. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *
|
||||
nmcs_utils_uri_build_concat_v(const char *base, const char **components, gsize n_components)
|
||||
{
|
||||
NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
|
||||
|
||||
nm_assert(base);
|
||||
nm_assert(base[0]);
|
||||
nm_assert(!NM_STR_HAS_SUFFIX(base, "/"));
|
||||
|
||||
nm_str_buf_append(&strbuf, base);
|
||||
|
||||
if (n_components > 0 && components[0] && components[0][0] == '/') {
|
||||
/* the first component starts with a slash. We allow that, and don't add a duplicate
|
||||
* slash. Otherwise, we add a separator after base.
|
||||
*
|
||||
* We only do that for the first component. */
|
||||
} else
|
||||
nm_str_buf_append_c(&strbuf, '/');
|
||||
|
||||
while (n_components > 0) {
|
||||
if (!components[0]) {
|
||||
/* we allow NULL, to indicate nothing to append */
|
||||
} else
|
||||
nm_str_buf_append(&strbuf, components[0]);
|
||||
components++;
|
||||
n_components--;
|
||||
}
|
||||
|
||||
return nm_str_buf_finalize(&strbuf, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nmcs_setting_ip_replace_ipv4_addresses(NMSettingIPConfig *s_ip,
|
||||
NMIPAddress ** entries_arr,
|
||||
guint entries_len)
|
||||
{
|
||||
gboolean any_changes = FALSE;
|
||||
guint i_next;
|
||||
guint num;
|
||||
guint i;
|
||||
|
||||
num = nm_setting_ip_config_get_num_addresses(s_ip);
|
||||
|
||||
i_next = 0;
|
||||
|
||||
for (i = 0; i < entries_len; i++) {
|
||||
NMIPAddress *entry = entries_arr[i];
|
||||
|
||||
if (!any_changes) {
|
||||
if (i_next < num) {
|
||||
if (nm_ip_address_cmp_full(entry,
|
||||
nm_setting_ip_config_get_address(s_ip, i_next),
|
||||
NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS)
|
||||
== 0) {
|
||||
i_next++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (i_next < num)
|
||||
nm_setting_ip_config_remove_address(s_ip, --num);
|
||||
any_changes = TRUE;
|
||||
}
|
||||
|
||||
if (!nm_setting_ip_config_add_address(s_ip, entry))
|
||||
continue;
|
||||
|
||||
i_next++;
|
||||
}
|
||||
if (any_changes) {
|
||||
while (i_next < num) {
|
||||
nm_setting_ip_config_remove_address(s_ip, --num);
|
||||
any_changes = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmcs_setting_ip_replace_ipv4_routes(NMSettingIPConfig *s_ip,
|
||||
NMIPRoute ** entries_arr,
|
||||
guint entries_len)
|
||||
{
|
||||
gboolean any_changes = FALSE;
|
||||
guint i_next;
|
||||
guint num;
|
||||
guint i;
|
||||
|
||||
num = nm_setting_ip_config_get_num_routes(s_ip);
|
||||
|
||||
i_next = 0;
|
||||
|
||||
for (i = 0; i < entries_len; i++) {
|
||||
NMIPRoute *entry = entries_arr[i];
|
||||
|
||||
if (!any_changes) {
|
||||
if (i_next < num) {
|
||||
if (nm_ip_route_equal_full(entry,
|
||||
nm_setting_ip_config_get_route(s_ip, i_next),
|
||||
NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) {
|
||||
i_next++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (i_next < num)
|
||||
nm_setting_ip_config_remove_route(s_ip, --num);
|
||||
any_changes = TRUE;
|
||||
}
|
||||
|
||||
if (!nm_setting_ip_config_add_route(s_ip, entry))
|
||||
continue;
|
||||
|
||||
i_next++;
|
||||
}
|
||||
if (!any_changes) {
|
||||
while (i_next < num) {
|
||||
nm_setting_ip_config_remove_route(s_ip, --num);
|
||||
any_changes = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmcs_setting_ip_replace_ipv4_rules(NMSettingIPConfig *s_ip,
|
||||
NMIPRoutingRule ** entries_arr,
|
||||
guint entries_len)
|
||||
{
|
||||
gboolean any_changes = FALSE;
|
||||
guint i_next;
|
||||
guint num;
|
||||
guint i;
|
||||
|
||||
num = nm_setting_ip_config_get_num_routing_rules(s_ip);
|
||||
|
||||
i_next = 0;
|
||||
|
||||
for (i = 0; i < entries_len; i++) {
|
||||
NMIPRoutingRule *entry = entries_arr[i];
|
||||
|
||||
if (!any_changes) {
|
||||
if (i_next < num) {
|
||||
if (nm_ip_routing_rule_cmp(entry,
|
||||
nm_setting_ip_config_get_routing_rule(s_ip, i_next))
|
||||
== 0) {
|
||||
i_next++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (i_next < num)
|
||||
nm_setting_ip_config_remove_routing_rule(s_ip, --num);
|
||||
any_changes = TRUE;
|
||||
}
|
||||
|
||||
nm_setting_ip_config_add_routing_rule(s_ip, entry);
|
||||
i_next++;
|
||||
}
|
||||
if (!any_changes) {
|
||||
while (i_next < num) {
|
||||
nm_setting_ip_config_remove_routing_rule(s_ip, --num);
|
||||
any_changes = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return any_changes;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainLoop * main_loop;
|
||||
NMConnection *connection;
|
||||
GError * error;
|
||||
guint64 version_id;
|
||||
} DeviceGetAppliedConnectionData;
|
||||
|
||||
static void
|
||||
_nmcs_device_get_applied_connection_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
DeviceGetAppliedConnectionData *data = user_data;
|
||||
|
||||
data->connection = nm_device_get_applied_connection_finish(NM_DEVICE(source),
|
||||
result,
|
||||
&data->version_id,
|
||||
&data->error);
|
||||
g_main_loop_quit(data->main_loop);
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
nmcs_device_get_applied_connection(NMDevice * device,
|
||||
GCancellable *cancellable,
|
||||
guint64 * version_id,
|
||||
GError ** error)
|
||||
{
|
||||
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
|
||||
DeviceGetAppliedConnectionData data = {
|
||||
.main_loop = main_loop,
|
||||
};
|
||||
|
||||
nm_device_get_applied_connection_async(device,
|
||||
0,
|
||||
cancellable,
|
||||
_nmcs_device_get_applied_connection_cb,
|
||||
&data);
|
||||
|
||||
g_main_loop_run(main_loop);
|
||||
|
||||
if (data.error)
|
||||
g_propagate_error(error, data.error);
|
||||
NM_SET_OUT(version_id, data.version_id);
|
||||
return data.connection;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainLoop *main_loop;
|
||||
GError * error;
|
||||
} DeviceReapplyData;
|
||||
|
||||
static void
|
||||
_nmcs_device_reapply_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
DeviceReapplyData *data = user_data;
|
||||
|
||||
nm_device_reapply_finish(NM_DEVICE(source), result, &data->error);
|
||||
g_main_loop_quit(data->main_loop);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmcs_device_reapply(NMDevice * device,
|
||||
GCancellable *sigterm_cancellable,
|
||||
NMConnection *connection,
|
||||
guint64 version_id,
|
||||
gboolean * out_version_id_changed,
|
||||
GError ** error)
|
||||
{
|
||||
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
|
||||
DeviceReapplyData data = {
|
||||
.main_loop = main_loop,
|
||||
};
|
||||
|
||||
nm_device_reapply_async(device,
|
||||
connection,
|
||||
version_id,
|
||||
0,
|
||||
sigterm_cancellable,
|
||||
_nmcs_device_reapply_cb,
|
||||
&data);
|
||||
|
||||
g_main_loop_run(main_loop);
|
||||
|
||||
if (data.error) {
|
||||
NM_SET_OUT(
|
||||
out_version_id_changed,
|
||||
g_error_matches(data.error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_VERSION_ID_MISMATCH));
|
||||
g_propagate_error(error, data.error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_SET_OUT(out_version_id_changed, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
122
clients/cloud-setup/nm-cloud-setup-utils.h
Normal file
122
clients/cloud-setup/nm-cloud-setup-utils.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#ifndef __NM_CLOUD_SETUP_UTILS_H__
|
||||
#define __NM_CLOUD_SETUP_UTILS_H__
|
||||
|
||||
#include "nm-glib-aux/nm-logging-fwd.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* mark names for variables that can be used as configuration. Search
|
||||
* for NMCS_ENV_VARIABLE() to find all honored environment variables. */
|
||||
#define NMCS_ENV_VARIABLE(var) "" var ""
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern volatile NMLogLevel _nm_logging_configured_level;
|
||||
|
||||
static inline gboolean
|
||||
nm_logging_enabled(NMLogLevel level)
|
||||
{
|
||||
return level >= _nm_logging_configured_level;
|
||||
}
|
||||
|
||||
void _nm_logging_enabled_init(const char *level_str);
|
||||
|
||||
void _nm_log_impl_cs(NMLogLevel level, const char *fmt, ...) _nm_printf(2, 3);
|
||||
|
||||
#define _nm_log(level, ...) _nm_log_impl_cs((level), __VA_ARGS__);
|
||||
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMLogLevel _level = (level); \
|
||||
\
|
||||
if (nm_logging_enabled(_level)) { \
|
||||
_nm_log(_level, __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef NM_DIST_VERSION
|
||||
#define NM_DIST_VERSION VERSION
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gpointer nmcs_wait_for_objects_register(gpointer target);
|
||||
|
||||
gboolean nmcs_wait_for_objects_iterate_until_done(GMainContext *context, int timeout_msec);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef void (*NMCSUtilsPollProbeStartFcn)(GCancellable * cancellable,
|
||||
gpointer probe_user_data,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
typedef gboolean (*NMCSUtilsPollProbeFinishFcn)(GObject * source,
|
||||
GAsyncResult *result,
|
||||
gpointer probe_user_data,
|
||||
GError ** error);
|
||||
|
||||
void nmcs_utils_poll(int poll_timeout_ms,
|
||||
int ratelimit_timeout_ms,
|
||||
int sleep_timeout_ms,
|
||||
NMCSUtilsPollProbeStartFcn probe_start_fcn,
|
||||
NMCSUtilsPollProbeFinishFcn probe_finish_fcn,
|
||||
gpointer probe_user_data,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nmcs_utils_poll_finish(GAsyncResult *result, gpointer *probe_user_data, GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *nmcs_utils_hwaddr_normalize(const char *hwaddr, gssize len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *nmcs_utils_parse_memmem(GBytes *mem, const char *needle);
|
||||
|
||||
const char *nmcs_utils_parse_get_full_line(GBytes *mem, const char *needle);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *nmcs_utils_uri_build_concat_v(const char *base, const char **components, gsize n_components);
|
||||
|
||||
#define nmcs_utils_uri_build_concat(base, ...) \
|
||||
nmcs_utils_uri_build_concat_v(base, ((const char *[]){__VA_ARGS__}), NM_NARG(__VA_ARGS__))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nmcs_setting_ip_replace_ipv4_addresses(NMSettingIPConfig *s_ip,
|
||||
NMIPAddress ** entries_arr,
|
||||
guint entries_len);
|
||||
|
||||
gboolean nmcs_setting_ip_replace_ipv4_routes(NMSettingIPConfig *s_ip,
|
||||
NMIPRoute ** entries_arr,
|
||||
guint entries_len);
|
||||
|
||||
gboolean nmcs_setting_ip_replace_ipv4_rules(NMSettingIPConfig *s_ip,
|
||||
NMIPRoutingRule ** entries_arr,
|
||||
guint entries_len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMConnection *nmcs_device_get_applied_connection(NMDevice * device,
|
||||
GCancellable *cancellable,
|
||||
guint64 * version_id,
|
||||
GError ** error);
|
||||
|
||||
gboolean nmcs_device_reapply(NMDevice * device,
|
||||
GCancellable *sigterm_cancellable,
|
||||
NMConnection *connection,
|
||||
guint64 version_id,
|
||||
gboolean * out_version_id_changed,
|
||||
GError ** error);
|
||||
|
||||
#endif /* __NM_CLOUD_SETUP_UTILS_H__ */
|
||||
38
clients/cloud-setup/nm-cloud-setup.service.in
Normal file
38
clients/cloud-setup/nm-cloud-setup.service.in
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
[Unit]
|
||||
Description=Automatically configure NetworkManager in cloud
|
||||
After=NetworkManager.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=@libexecdir@/nm-cloud-setup
|
||||
|
||||
#Environment=NM_CLOUD_SETUP_LOG=TRACE
|
||||
|
||||
# Cloud providers are disabled by default. You need to
|
||||
# Opt-in by setting the right environment variable for
|
||||
# the provider.
|
||||
#Environment=NM_CLOUD_SETUP_EC2=yes
|
||||
#Environment=NM_CLOUD_SETUP_GCP=yes
|
||||
#Environment=NM_CLOUD_SETUP_AZURE=yes
|
||||
|
||||
CapabilityBoundingSet=
|
||||
LockPersonality=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
NoNewPrivileges=yes
|
||||
PrivateDevices=yes
|
||||
PrivateTmp=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectHome=yes
|
||||
ProtectHostname=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectSystem=strict
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictSUIDSGID=yes
|
||||
SystemCallFilter=@system-service
|
||||
|
||||
[Install]
|
||||
WantedBy=NetworkManager.service
|
||||
9
clients/cloud-setup/nm-cloud-setup.timer
Normal file
9
clients/cloud-setup/nm-cloud-setup.timer
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=Periodically run nm-cloud-setup
|
||||
|
||||
[Timer]
|
||||
OnBootSec=5min
|
||||
OnUnitActiveSec=5min
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
801
clients/cloud-setup/nm-http-client.c
Normal file
801
clients/cloud-setup/nm-http-client.c
Normal file
|
|
@ -0,0 +1,801 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-http-client.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
#include "nm-glib-aux/nm-str-buf.h"
|
||||
|
||||
#define NM_CURL_DEBUG 0
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GMainContext *context;
|
||||
CURLM * mhandle;
|
||||
GSource * mhandle_source_timeout;
|
||||
GHashTable * source_sockets_hashtable;
|
||||
} NMHttpClientPrivate;
|
||||
|
||||
struct _NMHttpClient {
|
||||
GObject parent;
|
||||
NMHttpClientPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMHttpClientClass {
|
||||
GObjectClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMHttpClient, nm_http_client, G_TYPE_OBJECT);
|
||||
|
||||
#define NM_HTTP_CLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMHttpClient, NM_IS_HTTP_CLIENT)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG2(level, edata, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
EHandleData *_edata = (edata); \
|
||||
\
|
||||
_NMLOG(level, \
|
||||
"http-request[" NM_HASH_OBFUSCATE_PTR_FMT \
|
||||
", \"%s\"]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
NM_HASH_OBFUSCATE_PTR(_edata), \
|
||||
(_edata)->url _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_LOCK_DEFINE_STATIC(_my_curl_initalized_lock);
|
||||
static bool _my_curl_initialized = FALSE;
|
||||
|
||||
__attribute__((destructor)) static void
|
||||
_my_curl_global_cleanup(void)
|
||||
{
|
||||
G_LOCK(_my_curl_initalized_lock);
|
||||
if (_my_curl_initialized) {
|
||||
_my_curl_initialized = FALSE;
|
||||
curl_global_cleanup();
|
||||
}
|
||||
G_UNLOCK(_my_curl_initalized_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_http_client_curl_global_init(void)
|
||||
{
|
||||
G_LOCK(_my_curl_initalized_lock);
|
||||
if (!_my_curl_initialized) {
|
||||
_my_curl_initialized = TRUE;
|
||||
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
|
||||
/* Even if this fails, we are partly initialized. WTF. */
|
||||
_LOGE("curl: curl_global_init() failed!");
|
||||
}
|
||||
}
|
||||
G_UNLOCK(_my_curl_initalized_lock);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GMainContext *
|
||||
nm_http_client_get_main_context(NMHttpClient *self)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_HTTP_CLIENT(self), NULL);
|
||||
|
||||
return NM_HTTP_CLIENT_GET_PRIVATE(self)->context;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static GSource *
|
||||
_source_attach(NMHttpClient *self, GSource *source)
|
||||
{
|
||||
return nm_g_source_attach(source, NM_HTTP_CLIENT_GET_PRIVATE(self)->context);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
long response_code;
|
||||
GBytes *response_data;
|
||||
} GetResult;
|
||||
|
||||
static void
|
||||
_get_result_free(gpointer data)
|
||||
{
|
||||
GetResult *get_result = data;
|
||||
|
||||
g_bytes_unref(get_result->response_data);
|
||||
nm_g_slice_free(get_result);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GTask * task;
|
||||
GSource * timeout_source;
|
||||
CURLcode ehandle_result;
|
||||
CURL * ehandle;
|
||||
char * url;
|
||||
NMStrBuf recv_data;
|
||||
struct curl_slist *headers;
|
||||
gssize max_data;
|
||||
gulong cancellable_id;
|
||||
} EHandleData;
|
||||
|
||||
static void
|
||||
_ehandle_free_ehandle(EHandleData *edata)
|
||||
{
|
||||
if (edata->ehandle) {
|
||||
NMHttpClient * self = g_task_get_source_object(edata->task);
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
curl_multi_remove_handle(priv->mhandle, edata->ehandle);
|
||||
curl_easy_cleanup(g_steal_pointer(&edata->ehandle));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_ehandle_free(EHandleData *edata)
|
||||
{
|
||||
nm_assert(!edata->ehandle);
|
||||
nm_assert(!edata->timeout_source);
|
||||
|
||||
g_object_unref(edata->task);
|
||||
|
||||
nm_str_buf_destroy(&edata->recv_data);
|
||||
if (edata->headers)
|
||||
curl_slist_free_all(edata->headers);
|
||||
g_free(edata->url);
|
||||
nm_g_slice_free(edata);
|
||||
}
|
||||
|
||||
static void
|
||||
_ehandle_complete(EHandleData *edata, GError *error_take)
|
||||
{
|
||||
GetResult * get_result;
|
||||
gs_free char *str_tmp_1 = NULL;
|
||||
long response_code = -1;
|
||||
|
||||
nm_clear_pointer(&edata->timeout_source, nm_g_source_destroy_and_unref);
|
||||
|
||||
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(edata->task), &edata->cancellable_id);
|
||||
|
||||
if (error_take) {
|
||||
if (nm_utils_error_is_cancelled(error_take))
|
||||
_LOG2T(edata, "cancelled");
|
||||
else
|
||||
_LOG2D(edata, "failed with %s", error_take->message);
|
||||
} else if (edata->ehandle_result != CURLE_OK) {
|
||||
_LOG2D(edata, "failed with curl error \"%s\"", curl_easy_strerror(edata->ehandle_result));
|
||||
nm_utils_error_set(&error_take,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"failed with curl error \"%s\"",
|
||||
curl_easy_strerror(edata->ehandle_result));
|
||||
}
|
||||
|
||||
if (error_take) {
|
||||
_ehandle_free_ehandle(edata);
|
||||
g_task_return_error(edata->task, error_take);
|
||||
_ehandle_free(edata);
|
||||
return;
|
||||
}
|
||||
|
||||
if (curl_easy_getinfo(edata->ehandle, CURLINFO_RESPONSE_CODE, &response_code) != CURLE_OK)
|
||||
_LOG2E(edata, "failed to get response code from curl easy handle");
|
||||
|
||||
_LOG2D(edata,
|
||||
"success getting %" G_GSIZE_FORMAT " bytes (response code %ld)",
|
||||
edata->recv_data.len,
|
||||
response_code);
|
||||
|
||||
_LOG2T(edata,
|
||||
"received %" G_GSIZE_FORMAT " bytes: [[%s]]",
|
||||
edata->recv_data.len,
|
||||
nm_utils_buf_utf8safe_escape(nm_str_buf_get_str(&edata->recv_data),
|
||||
edata->recv_data.len,
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL,
|
||||
&str_tmp_1));
|
||||
|
||||
_ehandle_free_ehandle(edata);
|
||||
|
||||
get_result = g_slice_new(GetResult);
|
||||
*get_result = (GetResult){
|
||||
.response_code = response_code,
|
||||
/* This ensures that response_data is always NUL terminated. This is an important guarantee
|
||||
* that NMHttpClient makes. */
|
||||
.response_data = nm_str_buf_finalize_to_gbytes(&edata->recv_data),
|
||||
};
|
||||
|
||||
g_task_return_pointer(edata->task, get_result, _get_result_free);
|
||||
|
||||
_ehandle_free(edata);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static size_t
|
||||
_get_writefunction_cb(char *ptr, size_t size, size_t nmemb, void *user_data)
|
||||
{
|
||||
EHandleData *edata = user_data;
|
||||
gsize nconsume;
|
||||
|
||||
/* size should always be 1, but still. Multiply them to be sure. */
|
||||
nmemb *= size;
|
||||
|
||||
if (edata->max_data >= 0) {
|
||||
nm_assert(edata->recv_data.len <= edata->max_data);
|
||||
nconsume = (((gsize) edata->max_data) - edata->recv_data.len);
|
||||
if (nconsume > nmemb)
|
||||
nconsume = nmemb;
|
||||
} else
|
||||
nconsume = nmemb;
|
||||
|
||||
nm_str_buf_append_len(&edata->recv_data, ptr, nconsume);
|
||||
return nconsume;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_get_timeout_cb(gpointer user_data)
|
||||
{
|
||||
_ehandle_complete(
|
||||
user_data,
|
||||
g_error_new_literal(NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "HTTP request timed out"));
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
_get_cancelled_cb(GObject *object, gpointer user_data)
|
||||
{
|
||||
EHandleData *edata = user_data;
|
||||
GError * error = NULL;
|
||||
|
||||
nm_clear_g_signal_handler(g_task_get_cancellable(edata->task), &edata->cancellable_id);
|
||||
nm_utils_error_set_cancelled(&error, FALSE, NULL);
|
||||
_ehandle_complete(edata, error);
|
||||
}
|
||||
|
||||
void
|
||||
nm_http_client_get(NMHttpClient * self,
|
||||
const char * url,
|
||||
int timeout_msec,
|
||||
gssize max_data,
|
||||
const char *const * http_headers,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMHttpClientPrivate *priv;
|
||||
EHandleData * edata;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail(NM_IS_HTTP_CLIENT(self));
|
||||
g_return_if_fail(url);
|
||||
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
||||
g_return_if_fail(timeout_msec >= 0);
|
||||
g_return_if_fail(max_data >= -1);
|
||||
|
||||
priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
edata = g_slice_new(EHandleData);
|
||||
*edata = (EHandleData){
|
||||
.task = nm_g_task_new(self, cancellable, nm_http_client_get, callback, user_data),
|
||||
.recv_data = NM_STR_BUF_INIT(0, FALSE),
|
||||
.max_data = max_data,
|
||||
.url = g_strdup(url),
|
||||
.headers = NULL,
|
||||
};
|
||||
|
||||
nmcs_wait_for_objects_register(edata->task);
|
||||
|
||||
_LOG2D(edata, "start get ...");
|
||||
|
||||
edata->ehandle = curl_easy_init();
|
||||
if (!edata->ehandle) {
|
||||
_ehandle_complete(edata,
|
||||
g_error_new_literal(NM_UTILS_ERROR,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"HTTP request failed to create curl handle"));
|
||||
return;
|
||||
}
|
||||
|
||||
curl_easy_setopt(edata->ehandle, CURLOPT_URL, url);
|
||||
|
||||
curl_easy_setopt(edata->ehandle, CURLOPT_WRITEFUNCTION, _get_writefunction_cb);
|
||||
curl_easy_setopt(edata->ehandle, CURLOPT_WRITEDATA, edata);
|
||||
curl_easy_setopt(edata->ehandle, CURLOPT_PRIVATE, edata);
|
||||
|
||||
if (http_headers) {
|
||||
for (i = 0; http_headers[i]; ++i) {
|
||||
struct curl_slist *tmp;
|
||||
|
||||
tmp = curl_slist_append(edata->headers, http_headers[i]);
|
||||
if (!tmp) {
|
||||
curl_slist_free_all(tmp);
|
||||
_LOGE("curl: curl_slist_append() failed adding %s", http_headers[i]);
|
||||
continue;
|
||||
}
|
||||
edata->headers = tmp;
|
||||
}
|
||||
|
||||
curl_easy_setopt(edata->ehandle, CURLOPT_HTTPHEADER, edata->headers);
|
||||
}
|
||||
|
||||
if (timeout_msec > 0) {
|
||||
edata->timeout_source = _source_attach(self,
|
||||
nm_g_timeout_source_new(timeout_msec,
|
||||
G_PRIORITY_DEFAULT,
|
||||
_get_timeout_cb,
|
||||
edata,
|
||||
NULL));
|
||||
}
|
||||
|
||||
curl_multi_add_handle(priv->mhandle, edata->ehandle);
|
||||
|
||||
if (cancellable) {
|
||||
gulong signal_id;
|
||||
|
||||
signal_id = g_cancellable_connect(cancellable, G_CALLBACK(_get_cancelled_cb), edata, NULL);
|
||||
if (signal_id == 0) {
|
||||
/* the request is already cancelled. Return. */
|
||||
return;
|
||||
}
|
||||
edata->cancellable_id = signal_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_http_client_get_finish:
|
||||
* @self: the #NMHttpClient instance
|
||||
* @result: the #GAsyncResult which to complete.
|
||||
* @out_response_code: (allow-none) (out): the HTTP response code or -1 on other error.
|
||||
* @out_response_data: (allow-none) (transfer full): the HTTP response data, if any.
|
||||
* The GBytes buffer is guaranteed to have a trailing NUL character *after* the
|
||||
* returned buffer size. That means, you can always trust that the buffer is NUL terminated
|
||||
* and that there is one additional hidden byte after the data.
|
||||
* Also, the returned buffer is allocated just for you. While GBytes is immutable, you are
|
||||
* allowed to modify the buffer as it's not used by anybody else.
|
||||
* @error: the error
|
||||
*
|
||||
* Returns: %TRUE on success or %FALSE with an error code.
|
||||
*/
|
||||
gboolean
|
||||
nm_http_client_get_finish(NMHttpClient *self,
|
||||
GAsyncResult *result,
|
||||
long * out_response_code,
|
||||
GBytes ** out_response_data,
|
||||
GError ** error)
|
||||
{
|
||||
GetResult *get_result;
|
||||
|
||||
g_return_val_if_fail(NM_IS_HTTP_CLIENT(self), FALSE);
|
||||
g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_get), FALSE);
|
||||
|
||||
get_result = g_task_propagate_pointer(G_TASK(result), error);
|
||||
|
||||
nm_assert(!error || (!!get_result) == (!*error));
|
||||
|
||||
if (!get_result) {
|
||||
NM_SET_OUT(out_response_code, -1);
|
||||
NM_SET_OUT(out_response_data, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_SET_OUT(out_response_code, get_result->response_code);
|
||||
|
||||
/* response_data is binary, but is also guaranteed to be NUL terminated! */
|
||||
NM_SET_OUT(out_response_data, g_steal_pointer(&get_result->response_data));
|
||||
|
||||
_get_result_free(get_result);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
GTask * task;
|
||||
char * uri;
|
||||
const char *const * http_headers;
|
||||
NMHttpClientPollGetCheckFcn check_fcn;
|
||||
gpointer check_user_data;
|
||||
GBytes * response_data;
|
||||
gsize request_max_data;
|
||||
long response_code;
|
||||
int request_timeout_ms;
|
||||
} PollGetData;
|
||||
|
||||
static void
|
||||
_poll_get_data_free(gpointer data)
|
||||
{
|
||||
PollGetData *poll_get_data = data;
|
||||
|
||||
g_free(poll_get_data->uri);
|
||||
|
||||
nm_clear_pointer(&poll_get_data->response_data, g_bytes_unref);
|
||||
g_strfreev((char **) poll_get_data->http_headers);
|
||||
|
||||
nm_g_slice_free(poll_get_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_poll_get_probe_start_fcn(GCancellable * cancellable,
|
||||
gpointer probe_user_data,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
PollGetData *poll_get_data = probe_user_data;
|
||||
|
||||
/* balanced by _poll_get_probe_finish_fcn() */
|
||||
g_object_ref(poll_get_data->task);
|
||||
|
||||
nm_http_client_get(g_task_get_source_object(poll_get_data->task),
|
||||
poll_get_data->uri,
|
||||
poll_get_data->request_timeout_ms,
|
||||
poll_get_data->request_max_data,
|
||||
poll_get_data->http_headers,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_poll_get_probe_finish_fcn(GObject * source,
|
||||
GAsyncResult *result,
|
||||
gpointer probe_user_data,
|
||||
GError ** error)
|
||||
{
|
||||
PollGetData * poll_get_data = probe_user_data;
|
||||
_nm_unused gs_unref_object GTask *task =
|
||||
poll_get_data->task; /* balance ref from _poll_get_probe_start_fcn() */
|
||||
gboolean success;
|
||||
gs_free_error GError *local_error = NULL;
|
||||
gs_unref_bytes GBytes *response_data = NULL;
|
||||
long response_code = -1;
|
||||
|
||||
success = nm_http_client_get_finish(g_task_get_source_object(poll_get_data->task),
|
||||
result,
|
||||
&response_code,
|
||||
&response_data,
|
||||
&local_error);
|
||||
|
||||
nm_assert((!!success) == (!local_error));
|
||||
|
||||
if (local_error) {
|
||||
if (nm_utils_error_is_cancelled(local_error)) {
|
||||
g_propagate_error(error, g_steal_pointer(&local_error));
|
||||
return TRUE;
|
||||
}
|
||||
/* any other error. Continue polling. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (poll_get_data->check_fcn) {
|
||||
success = poll_get_data->check_fcn(response_code,
|
||||
response_data,
|
||||
poll_get_data->check_user_data,
|
||||
&local_error);
|
||||
} else
|
||||
success = (response_code == 200);
|
||||
|
||||
if (local_error) {
|
||||
g_propagate_error(error, g_steal_pointer(&local_error));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
/* Not yet ready. Continue polling. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
poll_get_data->response_code = response_code;
|
||||
poll_get_data->response_data = g_steal_pointer(&response_data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_poll_get_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
PollGetData * poll_get_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean success;
|
||||
|
||||
success = nmcs_utils_poll_finish(result, NULL, &error);
|
||||
|
||||
nm_assert((!!success) == (!error));
|
||||
|
||||
if (error)
|
||||
g_task_return_error(poll_get_data->task, g_steal_pointer(&error));
|
||||
else
|
||||
g_task_return_boolean(poll_get_data->task, TRUE);
|
||||
|
||||
g_object_unref(poll_get_data->task);
|
||||
}
|
||||
|
||||
void
|
||||
nm_http_client_poll_get(NMHttpClient * self,
|
||||
const char * uri,
|
||||
int request_timeout_ms,
|
||||
gssize request_max_data,
|
||||
int poll_timeout_ms,
|
||||
int ratelimit_timeout_ms,
|
||||
const char *const * http_headers,
|
||||
GCancellable * cancellable,
|
||||
NMHttpClientPollGetCheckFcn check_fcn,
|
||||
gpointer check_user_data,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
nm_auto_pop_gmaincontext GMainContext *context = NULL;
|
||||
PollGetData * poll_get_data;
|
||||
|
||||
g_return_if_fail(NM_IS_HTTP_CLIENT(self));
|
||||
g_return_if_fail(uri && uri[0]);
|
||||
g_return_if_fail(request_timeout_ms >= -1);
|
||||
g_return_if_fail(request_max_data >= -1);
|
||||
g_return_if_fail(poll_timeout_ms >= -1);
|
||||
g_return_if_fail(ratelimit_timeout_ms >= -1);
|
||||
g_return_if_fail(!cancellable || G_CANCELLABLE(cancellable));
|
||||
|
||||
poll_get_data = g_slice_new(PollGetData);
|
||||
*poll_get_data = (PollGetData){
|
||||
.task = nm_g_task_new(self, cancellable, nm_http_client_poll_get, callback, user_data),
|
||||
.uri = g_strdup(uri),
|
||||
.request_timeout_ms = request_timeout_ms,
|
||||
.request_max_data = request_max_data,
|
||||
.check_fcn = check_fcn,
|
||||
.check_user_data = check_user_data,
|
||||
.response_code = -1,
|
||||
.http_headers = NM_CAST_STRV_CC(g_strdupv((char **) http_headers)),
|
||||
};
|
||||
|
||||
nmcs_wait_for_objects_register(poll_get_data->task);
|
||||
|
||||
g_task_set_task_data(poll_get_data->task, poll_get_data, _poll_get_data_free);
|
||||
|
||||
context =
|
||||
nm_g_main_context_push_thread_default_if_necessary(nm_http_client_get_main_context(self));
|
||||
|
||||
nmcs_utils_poll(poll_timeout_ms,
|
||||
ratelimit_timeout_ms,
|
||||
0,
|
||||
_poll_get_probe_start_fcn,
|
||||
_poll_get_probe_finish_fcn,
|
||||
poll_get_data,
|
||||
cancellable,
|
||||
_poll_get_done_cb,
|
||||
poll_get_data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_http_client_poll_get_finish(NMHttpClient *self,
|
||||
GAsyncResult *result,
|
||||
long * out_response_code,
|
||||
GBytes ** out_response_data,
|
||||
GError ** error)
|
||||
{
|
||||
PollGetData * poll_get_data;
|
||||
GTask * task;
|
||||
gboolean success;
|
||||
gs_free_error GError *local_error = NULL;
|
||||
|
||||
g_return_val_if_fail(NM_HTTP_CLIENT(self), FALSE);
|
||||
g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_poll_get), FALSE);
|
||||
|
||||
task = G_TASK(result);
|
||||
|
||||
success = g_task_propagate_boolean(task, &local_error);
|
||||
|
||||
nm_assert((!!success) == (!local_error));
|
||||
|
||||
if (local_error) {
|
||||
g_propagate_error(error, g_steal_pointer(&local_error));
|
||||
NM_SET_OUT(out_response_code, -1);
|
||||
NM_SET_OUT(out_response_data, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
poll_get_data = g_task_get_task_data(task);
|
||||
|
||||
NM_SET_OUT(out_response_code, poll_get_data->response_code);
|
||||
NM_SET_OUT(out_response_data, g_steal_pointer(&poll_get_data->response_data));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_mhandle_action(NMHttpClient *self, int sockfd, int ev_bitmask)
|
||||
{
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
EHandleData * edata;
|
||||
CURLMsg * msg;
|
||||
CURLcode eret;
|
||||
int m_left;
|
||||
CURLMcode ret;
|
||||
int running_handles;
|
||||
|
||||
ret = curl_multi_socket_action(priv->mhandle, sockfd, ev_bitmask, &running_handles);
|
||||
if (ret != CURLM_OK) {
|
||||
_LOGE("curl: curl_multi_socket_action() failed: (%d) %s", ret, curl_multi_strerror(ret));
|
||||
/* really unexpected. Not clear how to handle this. */
|
||||
}
|
||||
|
||||
while ((msg = curl_multi_info_read(priv->mhandle, &m_left))) {
|
||||
if (msg->msg != CURLMSG_DONE)
|
||||
continue;
|
||||
|
||||
eret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char **) &edata);
|
||||
|
||||
nm_assert(eret == CURLE_OK);
|
||||
nm_assert(edata);
|
||||
|
||||
edata->ehandle_result = msg->data.result;
|
||||
_ehandle_complete(edata, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_mhandle_socket_cb(int fd, GIOCondition condition, gpointer user_data)
|
||||
{
|
||||
int ev_bitmask = 0;
|
||||
|
||||
if (condition & G_IO_IN)
|
||||
ev_bitmask |= CURL_CSELECT_IN;
|
||||
if (condition & G_IO_OUT)
|
||||
ev_bitmask |= CURL_CSELECT_OUT;
|
||||
if (condition & G_IO_ERR)
|
||||
ev_bitmask |= CURL_CSELECT_ERR;
|
||||
|
||||
_mhandle_action(user_data, fd, ev_bitmask);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
_mhandle_socketfunction_cb(CURL * e_handle,
|
||||
curl_socket_t fd,
|
||||
int what,
|
||||
void * user_data,
|
||||
void * socketp)
|
||||
{
|
||||
GSource * source_socket;
|
||||
NMHttpClient * self = user_data;
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
(void) _NM_ENSURE_TYPE(int, fd);
|
||||
|
||||
g_hash_table_remove(priv->source_sockets_hashtable, GINT_TO_POINTER(fd));
|
||||
|
||||
if (what != CURL_POLL_REMOVE) {
|
||||
GIOCondition condition = 0;
|
||||
|
||||
if (what == CURL_POLL_IN)
|
||||
condition = G_IO_IN;
|
||||
else if (what == CURL_POLL_OUT)
|
||||
condition = G_IO_OUT;
|
||||
else if (what == CURL_POLL_INOUT)
|
||||
condition = G_IO_IN | G_IO_OUT;
|
||||
else
|
||||
condition = 0;
|
||||
|
||||
if (condition) {
|
||||
source_socket = nm_g_unix_fd_source_new(fd,
|
||||
condition,
|
||||
G_PRIORITY_DEFAULT,
|
||||
_mhandle_socket_cb,
|
||||
self,
|
||||
NULL);
|
||||
g_source_attach(source_socket, priv->context);
|
||||
|
||||
g_hash_table_insert(priv->source_sockets_hashtable, GINT_TO_POINTER(fd), source_socket);
|
||||
}
|
||||
}
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_mhandle_timeout_cb(gpointer user_data)
|
||||
{
|
||||
_mhandle_action(user_data, CURL_SOCKET_TIMEOUT, 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static int
|
||||
_mhandle_timerfunction_cb(CURLM *multi, long timeout_msec, void *user_data)
|
||||
{
|
||||
NMHttpClient * self = user_data;
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
nm_clear_pointer(&priv->mhandle_source_timeout, nm_g_source_destroy_and_unref);
|
||||
if (timeout_msec >= 0) {
|
||||
priv->mhandle_source_timeout =
|
||||
_source_attach(self,
|
||||
nm_g_timeout_source_new(NM_MIN(timeout_msec, G_MAXINT),
|
||||
G_PRIORITY_DEFAULT,
|
||||
_mhandle_timeout_cb,
|
||||
self,
|
||||
NULL));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_http_client_init(NMHttpClient *self)
|
||||
{
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
priv->source_sockets_hashtable =
|
||||
g_hash_table_new_full(nm_direct_hash,
|
||||
NULL,
|
||||
NULL,
|
||||
(GDestroyNotify) nm_g_source_destroy_and_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
constructed(GObject *object)
|
||||
{
|
||||
NMHttpClient * self = NM_HTTP_CLIENT(object);
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
priv->context = g_main_context_ref_thread_default();
|
||||
|
||||
priv->mhandle = curl_multi_init();
|
||||
if (!priv->mhandle)
|
||||
_LOGE("curl: failed to create multi-handle");
|
||||
else {
|
||||
curl_multi_setopt(priv->mhandle, CURLMOPT_SOCKETFUNCTION, _mhandle_socketfunction_cb);
|
||||
curl_multi_setopt(priv->mhandle, CURLMOPT_SOCKETDATA, self);
|
||||
curl_multi_setopt(priv->mhandle, CURLMOPT_TIMERFUNCTION, _mhandle_timerfunction_cb);
|
||||
curl_multi_setopt(priv->mhandle, CURLMOPT_TIMERDATA, self);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS(nm_http_client_parent_class)->constructed(object);
|
||||
}
|
||||
|
||||
NMHttpClient *
|
||||
nm_http_client_new(void)
|
||||
{
|
||||
return g_object_new(NM_TYPE_HTTP_CLIENT, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dispose(GObject *object)
|
||||
{
|
||||
NMHttpClient * self = NM_HTTP_CLIENT(object);
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
nm_clear_pointer(&priv->mhandle, curl_multi_cleanup);
|
||||
nm_clear_pointer(&priv->source_sockets_hashtable, g_hash_table_unref);
|
||||
|
||||
nm_clear_g_source_inst(&priv->mhandle_source_timeout);
|
||||
|
||||
G_OBJECT_CLASS(nm_http_client_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize(GObject *object)
|
||||
{
|
||||
NMHttpClient * self = NM_HTTP_CLIENT(object);
|
||||
NMHttpClientPrivate *priv = NM_HTTP_CLIENT_GET_PRIVATE(self);
|
||||
|
||||
G_OBJECT_CLASS(nm_http_client_parent_class)->finalize(object);
|
||||
|
||||
g_main_context_unref(priv->context);
|
||||
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
static void
|
||||
nm_http_client_class_init(NMHttpClientClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
nm_http_client_curl_global_init();
|
||||
}
|
||||
71
clients/cloud-setup/nm-http-client.h
Normal file
71
clients/cloud-setup/nm-http-client.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#ifndef __NM_HTTP_CLIENT_C__
|
||||
#define __NM_HTTP_CLIENT_C__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMHttpClient NMHttpClient;
|
||||
typedef struct _NMHttpClientClass NMHttpClientClass;
|
||||
|
||||
#define NM_TYPE_HTTP_CLIENT (nm_http_client_get_type())
|
||||
#define NM_HTTP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_HTTP_CLIENT, NMHttpClient))
|
||||
#define NM_HTTP_CLIENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_HTTP_CLIENT, NMHttpClientClass))
|
||||
#define NM_IS_HTTP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_HTTP_CLIENT))
|
||||
#define NM_IS_HTTP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_HTTP_CLIENT))
|
||||
#define NM_HTTP_CLIENT_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_HTTP_CLIENT, NMHttpClientClass))
|
||||
|
||||
GType nm_http_client_get_type(void);
|
||||
|
||||
NMHttpClient *nm_http_client_new(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GMainContext *nm_http_client_get_main_context(NMHttpClient *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_http_client_get(NMHttpClient * self,
|
||||
const char * uri,
|
||||
int timeout_msec,
|
||||
gssize max_data,
|
||||
const char *const * http_headers,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nm_http_client_get_finish(NMHttpClient *self,
|
||||
GAsyncResult *result,
|
||||
long * out_response_code,
|
||||
GBytes ** out_response_data,
|
||||
GError ** error);
|
||||
|
||||
typedef gboolean (*NMHttpClientPollGetCheckFcn)(long response_code,
|
||||
GBytes * response_data,
|
||||
gpointer check_user_data,
|
||||
GError **error);
|
||||
|
||||
void nm_http_client_poll_get(NMHttpClient * self,
|
||||
const char * uri,
|
||||
int request_timeout_ms,
|
||||
gssize request_max_data,
|
||||
int poll_timeout_ms,
|
||||
int ratelimit_timeout_ms,
|
||||
const char *const * http_headers,
|
||||
GCancellable * cancellable,
|
||||
NMHttpClientPollGetCheckFcn check_fcn,
|
||||
gpointer check_user_data,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nm_http_client_poll_get_finish(NMHttpClient *self,
|
||||
GAsyncResult *result,
|
||||
long * out_response_code,
|
||||
GBytes ** out_response_data,
|
||||
GError ** error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_HTTP_CLIENT_C__ */
|
||||
530
clients/cloud-setup/nmcs-provider-azure.c
Normal file
530
clients/cloud-setup/nmcs-provider-azure.c
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nmcs-provider-azure.h"
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define HTTP_TIMEOUT_MS 3000
|
||||
|
||||
#define NM_AZURE_METADATA_HEADER "Metadata:true"
|
||||
#define NM_AZURE_HOST "169.254.169.254"
|
||||
#define NM_AZURE_BASE "http://" NM_AZURE_HOST
|
||||
#define NM_AZURE_API_VERSION "?format=text&api-version=2017-04-02"
|
||||
#define NM_AZURE_METADATA_URL_BASE /* $NM_AZURE_BASE/$NM_AZURE_API_VERSION */ \
|
||||
"/metadata/instance/network/interface/"
|
||||
|
||||
#define _azure_uri_concat(...) \
|
||||
nmcs_utils_uri_build_concat(NM_AZURE_BASE, __VA_ARGS__, NM_AZURE_API_VERSION)
|
||||
#define _azure_uri_interfaces(...) _azure_uri_concat(NM_AZURE_METADATA_URL_BASE, ##__VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMCSProviderAzure {
|
||||
NMCSProvider parent;
|
||||
};
|
||||
|
||||
struct _NMCSProviderAzureClass {
|
||||
NMCSProviderClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMCSProviderAzure, nmcs_provider_azure, NMCS_TYPE_PROVIDER);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_object GTask *task = user_data;
|
||||
gs_free_error GError *get_error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean success;
|
||||
|
||||
success =
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
|
||||
|
||||
if (nm_utils_error_is_cancelled(get_error)) {
|
||||
g_task_return_error(task, g_steal_pointer(&get_error));
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_error) {
|
||||
nm_utils_error_set(&error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"failure to get Azure metadata: %s",
|
||||
get_error->message);
|
||||
g_task_return_error(task, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "failure to detect azure metadata");
|
||||
g_task_return_error(task, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean(task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
detect(NMCSProvider *provider, GTask *task)
|
||||
{
|
||||
NMHttpClient *http_client;
|
||||
gs_free char *uri = NULL;
|
||||
|
||||
http_client = nmcs_provider_get_http_client(provider);
|
||||
|
||||
nm_http_client_poll_get(http_client,
|
||||
(uri = _azure_uri_concat("/metadata/instance")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
256 * 1024,
|
||||
7000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
|
||||
g_task_get_cancellable(task),
|
||||
NULL,
|
||||
NULL,
|
||||
_detect_get_meta_data_done_cb,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMCSProviderGetConfigTaskData *config_data;
|
||||
guint n_ifaces_pending;
|
||||
GError * error;
|
||||
} AzureData;
|
||||
|
||||
typedef struct {
|
||||
NMCSProviderGetConfigIfaceData *iface_get_config;
|
||||
AzureData * azure_data;
|
||||
gssize iface_idx;
|
||||
guint n_ips_prefix_pending;
|
||||
char * hwaddr;
|
||||
} AzureIfaceData;
|
||||
|
||||
static void
|
||||
_azure_iface_data_free(AzureIfaceData *iface_data)
|
||||
{
|
||||
g_free(iface_data->hwaddr);
|
||||
nm_g_slice_free(iface_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_maybe_task_return(AzureData *azure_data, GError *error_take)
|
||||
{
|
||||
NMCSProviderGetConfigTaskData *config_data = azure_data->config_data;
|
||||
|
||||
if (error_take) {
|
||||
if (!azure_data->error)
|
||||
azure_data->error = error_take;
|
||||
else if (!nm_utils_error_is_cancelled(azure_data->error)
|
||||
&& nm_utils_error_is_cancelled(error_take)) {
|
||||
nm_clear_error(&azure_data->error);
|
||||
azure_data->error = error_take;
|
||||
} else
|
||||
g_error_free(error_take);
|
||||
}
|
||||
|
||||
if (azure_data->n_ifaces_pending > 0)
|
||||
return;
|
||||
|
||||
if (azure_data->error) {
|
||||
if (nm_utils_error_is_cancelled(azure_data->error))
|
||||
_LOGD("get-config: cancelled");
|
||||
else
|
||||
_LOGD("get-config: failed: %s", azure_data->error->message);
|
||||
g_task_return_error(config_data->task, g_steal_pointer(&azure_data->error));
|
||||
} else {
|
||||
_LOGD("get-config: success");
|
||||
g_task_return_pointer(config_data->task,
|
||||
g_hash_table_ref(config_data->result_dict),
|
||||
(GDestroyNotify) g_hash_table_unref);
|
||||
}
|
||||
|
||||
nm_g_slice_free(azure_data);
|
||||
g_object_unref(config_data->task);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb(NMHttpClient *http_client,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data,
|
||||
gboolean is_ipv4)
|
||||
{
|
||||
NMCSProviderGetConfigIfaceData *iface_get_config;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
AzureIfaceData * iface_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char * fip_str = NULL;
|
||||
AzureData * azure_data;
|
||||
|
||||
azure_data = iface_data->azure_data;
|
||||
|
||||
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
|
||||
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
if (!error) {
|
||||
in_addr_t tmp_addr;
|
||||
int tmp_prefix;
|
||||
|
||||
fip_str = g_bytes_get_data(response, NULL);
|
||||
iface_data->iface_get_config =
|
||||
g_hash_table_lookup(azure_data->config_data->result_dict, iface_data->hwaddr);
|
||||
iface_get_config = iface_data->iface_get_config;
|
||||
iface_get_config->iface_idx = iface_data->iface_idx;
|
||||
|
||||
if (is_ipv4) {
|
||||
if (!nm_utils_parse_inaddr_bin(AF_INET, fip_str, NULL, &tmp_addr)) {
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
||||
"ip is not a valid private ip address");
|
||||
goto done;
|
||||
}
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: adding private ip %s",
|
||||
iface_data->iface_idx,
|
||||
fip_str);
|
||||
iface_get_config->ipv4s_arr[iface_get_config->ipv4s_len] = tmp_addr;
|
||||
iface_get_config->has_ipv4s = TRUE;
|
||||
iface_get_config->ipv4s_len++;
|
||||
} else {
|
||||
tmp_prefix = (_nm_utils_ascii_str_to_int64(fip_str, 10, 0, 32, -1));
|
||||
|
||||
if (tmp_prefix == -1) {
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: invalid prefix %d",
|
||||
iface_data->iface_idx,
|
||||
tmp_prefix);
|
||||
goto done;
|
||||
}
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: adding prefix %d",
|
||||
iface_data->iface_idx,
|
||||
tmp_prefix);
|
||||
iface_get_config->cidr_prefix = tmp_prefix;
|
||||
iface_get_config->has_cidr = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
--iface_data->n_ips_prefix_pending;
|
||||
if (iface_data->n_ips_prefix_pending == 0) {
|
||||
_azure_iface_data_free(iface_data);
|
||||
--azure_data->n_ifaces_pending;
|
||||
_get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb_private_ipv4s(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb_subnet_cidr_prefix(GObject * source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
AzureIfaceData * iface_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char * response_str = NULL;
|
||||
gsize response_len;
|
||||
AzureData * azure_data;
|
||||
const char * line;
|
||||
gsize line_len;
|
||||
|
||||
azure_data = iface_data->azure_data;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
response_str = g_bytes_get_data(response, &response_len);
|
||||
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
|
||||
nm_assert(response_str[response_len] == 0);
|
||||
|
||||
nm_assert(!iface_data->iface_get_config->has_ipv4s);
|
||||
nm_assert(!iface_data->iface_get_config->ipv4s_arr);
|
||||
nm_assert(!iface_data->iface_get_config->has_cidr);
|
||||
|
||||
while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) {
|
||||
gint64 ips_prefix_idx;
|
||||
|
||||
if (line_len == 0)
|
||||
continue;
|
||||
/* Truncate the string. It's safe to do, because we own @response_data an it has an
|
||||
* extra NULL character after the buffer. */
|
||||
((char *) line)[line_len] = '\0';
|
||||
|
||||
if (line[line_len - 1] == '/')
|
||||
((char *) line)[--line_len] = '\0';
|
||||
|
||||
ips_prefix_idx = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXINT64, -1);
|
||||
|
||||
if (ips_prefix_idx < 0)
|
||||
continue;
|
||||
|
||||
{
|
||||
gs_free const char *uri = NULL;
|
||||
char buf[100];
|
||||
|
||||
iface_data->n_ips_prefix_pending++;
|
||||
|
||||
nm_http_client_poll_get(
|
||||
NM_HTTP_CLIENT(source),
|
||||
(uri = _azure_uri_interfaces(nm_sprintf_buf(
|
||||
buf,
|
||||
"%" G_GSSIZE_FORMAT "/ipv4/ipAddress/%" G_GINT64_FORMAT "/privateIpAddress",
|
||||
iface_data->iface_idx,
|
||||
ips_prefix_idx))),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
|
||||
g_task_get_cancellable(azure_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_private_ipv4s,
|
||||
iface_data);
|
||||
}
|
||||
}
|
||||
|
||||
iface_data->iface_get_config->ipv4s_len = 0;
|
||||
iface_data->iface_get_config->ipv4s_arr = g_new(in_addr_t, iface_data->n_ips_prefix_pending);
|
||||
|
||||
{
|
||||
gs_free const char *uri = NULL;
|
||||
char buf[30];
|
||||
|
||||
iface_data->n_ips_prefix_pending++;
|
||||
nm_http_client_poll_get(
|
||||
NM_HTTP_CLIENT(source),
|
||||
(uri = _azure_uri_interfaces(
|
||||
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT, iface_data->iface_idx),
|
||||
"/ipv4/subnet/0/prefix/")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
|
||||
g_task_get_cancellable(azure_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_subnet_cidr_prefix,
|
||||
iface_data);
|
||||
}
|
||||
return;
|
||||
|
||||
done:
|
||||
_azure_iface_data_free(iface_data);
|
||||
--azure_data->n_ifaces_pending;
|
||||
_get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
AzureIfaceData * iface_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free const char * uri = NULL;
|
||||
char buf[100];
|
||||
AzureData * azure_data;
|
||||
|
||||
azure_data = iface_data->azure_data;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
iface_data->hwaddr = nmcs_utils_hwaddr_normalize(g_bytes_get_data(response, NULL), -1);
|
||||
|
||||
if (!iface_data->hwaddr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
iface_data->iface_get_config =
|
||||
g_hash_table_lookup(azure_data->config_data->result_dict, iface_data->hwaddr);
|
||||
|
||||
if (!iface_data->iface_get_config) {
|
||||
if (!iface_data->azure_data->config_data->any) {
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: ignore hwaddr %s",
|
||||
iface_data->iface_idx,
|
||||
iface_data->hwaddr);
|
||||
goto done;
|
||||
}
|
||||
iface_data->iface_get_config = nmcs_provider_get_config_iface_data_new(FALSE);
|
||||
g_hash_table_insert(azure_data->config_data->result_dict,
|
||||
g_strdup(iface_data->hwaddr),
|
||||
iface_data->iface_get_config);
|
||||
}
|
||||
|
||||
_LOGD("interface[%" G_GSSIZE_FORMAT "]: found a matching device with hwaddr %s",
|
||||
iface_data->iface_idx,
|
||||
iface_data->hwaddr);
|
||||
|
||||
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/ipv4/ipAddress/", iface_data->iface_idx);
|
||||
|
||||
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
|
||||
(uri = _azure_uri_interfaces(buf)),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
|
||||
g_task_get_cancellable(azure_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_ips_prefix_list_cb,
|
||||
iface_data);
|
||||
return;
|
||||
|
||||
done:
|
||||
nm_g_slice_free(iface_data);
|
||||
--azure_data->n_ifaces_pending;
|
||||
_get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
static void
|
||||
_get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *ifaces_arr = NULL;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
AzureData * azure_data = user_data;
|
||||
const char * response_str;
|
||||
gsize response_len;
|
||||
const char * line;
|
||||
gsize line_len;
|
||||
guint i;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
|
||||
if (error) {
|
||||
_get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
response_str = g_bytes_get_data(response, &response_len);
|
||||
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
|
||||
nm_assert(response_str[response_len] == 0);
|
||||
|
||||
ifaces_arr = g_ptr_array_new();
|
||||
|
||||
while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) {
|
||||
AzureIfaceData *iface_data;
|
||||
gssize iface_idx;
|
||||
|
||||
if (line_len == 0)
|
||||
continue;
|
||||
|
||||
/* Truncate the string. It's safe to do, because we own @response_data an it has an
|
||||
* extra NULL character after the buffer. */
|
||||
((char *) line)[line_len] = '\0';
|
||||
|
||||
if (line[line_len - 1] == '/' && line_len != 0)
|
||||
((char *) line)[--line_len] = '\0';
|
||||
|
||||
iface_idx = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXSSIZE, -1);
|
||||
if (iface_idx < 0)
|
||||
continue;
|
||||
|
||||
iface_data = g_slice_new(AzureIfaceData);
|
||||
*iface_data = (AzureIfaceData){
|
||||
.iface_get_config = NULL,
|
||||
.azure_data = azure_data,
|
||||
.iface_idx = iface_idx,
|
||||
.n_ips_prefix_pending = 0,
|
||||
.hwaddr = NULL,
|
||||
};
|
||||
g_ptr_array_add(ifaces_arr, iface_data);
|
||||
}
|
||||
|
||||
_LOGD("found azure interfaces: %u", ifaces_arr->len);
|
||||
|
||||
if (ifaces_arr->len == 0) {
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "no Azure interfaces found");
|
||||
_get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ifaces_arr->len; ++i) {
|
||||
AzureIfaceData * data = ifaces_arr->pdata[i];
|
||||
gs_free const char *uri = NULL;
|
||||
char buf[100];
|
||||
|
||||
_LOGD("azure interface[%" G_GSSIZE_FORMAT "]: retrieving configuration", data->iface_idx);
|
||||
|
||||
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/macAddress", data->iface_idx);
|
||||
|
||||
azure_data->n_ifaces_pending++;
|
||||
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
|
||||
(uri = _azure_uri_interfaces(buf)),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
|
||||
g_task_get_cancellable(azure_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_iface_cb,
|
||||
data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
|
||||
{
|
||||
gs_free const char *uri = NULL;
|
||||
AzureData * azure_data;
|
||||
|
||||
azure_data = g_slice_new(AzureData);
|
||||
*azure_data = (AzureData){
|
||||
.config_data = get_config_data,
|
||||
.n_ifaces_pending = 0,
|
||||
};
|
||||
|
||||
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
|
||||
(uri = _azure_uri_interfaces()),
|
||||
HTTP_TIMEOUT_MS,
|
||||
256 * 1024,
|
||||
15000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
|
||||
g_task_get_cancellable(get_config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_net_ifaces_list_cb,
|
||||
azure_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nmcs_provider_azure_init(NMCSProviderAzure *self)
|
||||
{}
|
||||
|
||||
static void
|
||||
nmcs_provider_azure_class_init(NMCSProviderAzureClass *klass)
|
||||
{
|
||||
NMCSProviderClass *provider_class = NMCS_PROVIDER_CLASS(klass);
|
||||
|
||||
provider_class->_name = "azure";
|
||||
provider_class->_env_provider_enabled = NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_AZURE");
|
||||
provider_class->detect = detect;
|
||||
provider_class->get_config = get_config;
|
||||
}
|
||||
28
clients/cloud-setup/nmcs-provider-azure.h
Normal file
28
clients/cloud-setup/nmcs-provider-azure.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#ifndef __NMCS_PROVIDER_AZURE_H__
|
||||
#define __NMCS_PROVIDER_AZURE_H__
|
||||
|
||||
#include "nmcs-provider.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMCSProviderAzure NMCSProviderAzure;
|
||||
typedef struct _NMCSProviderAzureClass NMCSProviderAzureClass;
|
||||
|
||||
#define NMCS_TYPE_PROVIDER_AZURE (nmcs_provider_azure_get_type())
|
||||
#define NMCS_PROVIDER_AZURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMCS_TYPE_PROVIDER_AZURE, NMCSProviderAzure))
|
||||
#define NMCS_PROVIDER_AZURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMCS_TYPE_PROVIDER_AZURE, NMCSProviderAzureClass))
|
||||
#define NMCS_IS_PROVIDER_AZURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMCS_TYPE_PROVIDER_AZURE))
|
||||
#define NMCS_IS_PROVIDER_AZURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NMCS_TYPE_PROVIDER_AZURE))
|
||||
#define NMCS_PROVIDER_AZURE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMCS_TYPE_PROVIDER_AZURE, NMCSProviderAzureClass))
|
||||
|
||||
GType nmcs_provider_azure_get_type(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NMCS_PROVIDER_AZURE_H__ */
|
||||
525
clients/cloud-setup/nmcs-provider-ec2.c
Normal file
525
clients/cloud-setup/nmcs-provider-ec2.c
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nmcs-provider-ec2.h"
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define HTTP_TIMEOUT_MS 3000
|
||||
|
||||
#define NM_EC2_HOST "169.254.169.254"
|
||||
#define NM_EC2_BASE "http://" NM_EC2_HOST
|
||||
#define NM_EC2_API_VERSION "2018-09-24"
|
||||
#define NM_EC2_METADATA_URL_BASE /* $NM_EC2_BASE/$NM_EC2_API_VERSION */ \
|
||||
"/meta-data/network/interfaces/macs/"
|
||||
|
||||
static const char *
|
||||
_ec2_base(void)
|
||||
{
|
||||
static const char *base_cached = NULL;
|
||||
const char * base;
|
||||
|
||||
again:
|
||||
base = g_atomic_pointer_get(&base_cached);
|
||||
if (G_UNLIKELY(!base)) {
|
||||
/* The base URI can be set via environment variable.
|
||||
* This is mainly for testing, it's not usually supposed to be configured.
|
||||
* Consider this private API! */
|
||||
base = g_getenv(NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_EC2_HOST"));
|
||||
|
||||
if (base && base[0] && !strchr(base, '/')) {
|
||||
if (NM_STR_HAS_PREFIX(base, "http://") || NM_STR_HAS_PREFIX(base, "https://"))
|
||||
base = g_intern_string(base);
|
||||
else {
|
||||
gs_free char *s = NULL;
|
||||
|
||||
s = g_strconcat("http://", base, NULL);
|
||||
base = g_intern_string(s);
|
||||
}
|
||||
}
|
||||
if (!base)
|
||||
base = NM_EC2_BASE;
|
||||
|
||||
nm_assert(!NM_STR_HAS_SUFFIX(base, "/"));
|
||||
|
||||
if (!g_atomic_pointer_compare_and_exchange(&base_cached, NULL, base))
|
||||
goto again;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
#define _ec2_uri_concat(...) nmcs_utils_uri_build_concat(_ec2_base(), __VA_ARGS__)
|
||||
#define _ec2_uri_interfaces(...) \
|
||||
_ec2_uri_concat(NM_EC2_API_VERSION, NM_EC2_METADATA_URL_BASE, ##__VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMCSProviderEC2 {
|
||||
NMCSProvider parent;
|
||||
};
|
||||
|
||||
struct _NMCSProviderEC2Class {
|
||||
NMCSProviderClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMCSProviderEC2, nmcs_provider_ec2, NMCS_TYPE_PROVIDER);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_detect_get_meta_data_check_cb(long response_code,
|
||||
GBytes * response_data,
|
||||
gpointer check_user_data,
|
||||
GError **error)
|
||||
{
|
||||
return response_code == 200 && nmcs_utils_parse_get_full_line(response_data, "ami-id");
|
||||
}
|
||||
|
||||
static void
|
||||
_detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_object GTask *task = user_data;
|
||||
gs_free_error GError *get_error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
|
||||
|
||||
if (nm_utils_error_is_cancelled(get_error)) {
|
||||
g_task_return_error(task, g_steal_pointer(&get_error));
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_error) {
|
||||
nm_utils_error_set(&error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"failure to get EC2 metadata: %s",
|
||||
get_error->message);
|
||||
g_task_return_error(task, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean(task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
detect(NMCSProvider *provider, GTask *task)
|
||||
{
|
||||
NMHttpClient *http_client;
|
||||
gs_free char *uri = NULL;
|
||||
|
||||
http_client = nmcs_provider_get_http_client(provider);
|
||||
|
||||
nm_http_client_poll_get(http_client,
|
||||
(uri = _ec2_uri_concat("latest/meta-data/")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
256 * 1024,
|
||||
7000,
|
||||
1000,
|
||||
NULL,
|
||||
g_task_get_cancellable(task),
|
||||
_detect_get_meta_data_check_cb,
|
||||
NULL,
|
||||
_detect_get_meta_data_done_cb,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMCSProviderGetConfigTaskData *get_config_data;
|
||||
GError * error;
|
||||
GCancellable * cancellable;
|
||||
gulong cancelled_id;
|
||||
guint n_pending;
|
||||
} GetConfigIfaceData;
|
||||
|
||||
static void
|
||||
_get_config_task_maybe_return(GetConfigIfaceData *iface_data, GError *error_take)
|
||||
{
|
||||
NMCSProviderGetConfigTaskData *get_config_data = iface_data->get_config_data;
|
||||
|
||||
if (error_take) {
|
||||
if (!iface_data->error)
|
||||
iface_data->error = error_take;
|
||||
else if (!nm_utils_error_is_cancelled(iface_data->error)
|
||||
&& nm_utils_error_is_cancelled(error_take)) {
|
||||
nm_clear_error(&iface_data->error);
|
||||
iface_data->error = error_take;
|
||||
} else
|
||||
g_error_free(error_take);
|
||||
|
||||
nm_clear_g_cancellable(&iface_data->cancellable);
|
||||
}
|
||||
|
||||
if (iface_data->n_pending > 0)
|
||||
return;
|
||||
|
||||
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(get_config_data->task),
|
||||
&iface_data->cancelled_id);
|
||||
|
||||
nm_clear_g_cancellable(&iface_data->cancellable);
|
||||
|
||||
if (iface_data->error) {
|
||||
if (nm_utils_error_is_cancelled(iface_data->error))
|
||||
_LOGD("get-config: cancelled");
|
||||
else
|
||||
_LOGD("get-config: failed: %s", iface_data->error->message);
|
||||
g_task_return_error(get_config_data->task, g_steal_pointer(&iface_data->error));
|
||||
} else {
|
||||
_LOGD("get-config: success");
|
||||
g_task_return_pointer(get_config_data->task,
|
||||
g_hash_table_ref(get_config_data->result_dict),
|
||||
(GDestroyNotify) g_hash_table_unref);
|
||||
}
|
||||
|
||||
nm_g_slice_free(iface_data);
|
||||
g_object_unref(get_config_data->task);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb(NMHttpClient *http_client,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data,
|
||||
gboolean is_local_ipv4)
|
||||
{
|
||||
GetConfigIfaceData *iface_data;
|
||||
const char * hwaddr = NULL;
|
||||
gs_unref_bytes GBytes *response_data = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_utils_user_data_unpack(user_data, &iface_data, &hwaddr);
|
||||
|
||||
nm_http_client_poll_get_finish(http_client, result, NULL, &response_data, &error);
|
||||
|
||||
if (!error) {
|
||||
NMCSProviderGetConfigIfaceData *config_iface_data;
|
||||
in_addr_t tmp_addr;
|
||||
int tmp_prefix;
|
||||
|
||||
config_iface_data = g_hash_table_lookup(iface_data->get_config_data->result_dict, hwaddr);
|
||||
|
||||
if (is_local_ipv4) {
|
||||
gs_free const char **s_addrs = NULL;
|
||||
gsize i, len;
|
||||
|
||||
s_addrs = nm_utils_strsplit_set_full(g_bytes_get_data(response_data, NULL),
|
||||
"\n",
|
||||
NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
|
||||
len = NM_PTRARRAY_LEN(s_addrs);
|
||||
|
||||
nm_assert(!config_iface_data->has_ipv4s);
|
||||
nm_assert(!config_iface_data->ipv4s_arr);
|
||||
config_iface_data->has_ipv4s = TRUE;
|
||||
config_iface_data->ipv4s_len = 0;
|
||||
if (len > 0) {
|
||||
config_iface_data->ipv4s_arr = g_new(in_addr_t, len);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (nm_utils_parse_inaddr_bin(AF_INET, s_addrs[i], NULL, &tmp_addr))
|
||||
config_iface_data->ipv4s_arr[config_iface_data->ipv4s_len++] = tmp_addr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nm_utils_parse_inaddr_prefix_bin(AF_INET,
|
||||
g_bytes_get_data(response_data, NULL),
|
||||
NULL,
|
||||
&tmp_addr,
|
||||
&tmp_prefix)) {
|
||||
nm_assert(!config_iface_data->has_cidr);
|
||||
config_iface_data->has_cidr = TRUE;
|
||||
config_iface_data->cidr_prefix = tmp_prefix;
|
||||
config_iface_data->cidr_addr = tmp_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If nm_utils_error_is_cancelled(error), then our internal iface_data->cancellable
|
||||
* was cancelled, because the overall request failed. From point of view of the
|
||||
* caller, this does not mean that a cancellation happened. It also means, our
|
||||
* request overall is already about to fail. */
|
||||
nm_assert(!nm_utils_error_is_cancelled(error) || iface_data->error);
|
||||
|
||||
iface_data->n_pending--;
|
||||
_get_config_task_maybe_return(iface_data,
|
||||
nm_utils_error_is_cancelled(error) ? NULL
|
||||
: g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb_subnet_ipv4_cidr_block(GObject * source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_done_cb_local_ipv4s(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fetch_cancelled_cb(GObject *object, gpointer user_data)
|
||||
{
|
||||
GetConfigIfaceData *iface_data = user_data;
|
||||
|
||||
nm_clear_g_signal_handler(g_task_get_cancellable(iface_data->get_config_data->task),
|
||||
&iface_data->cancelled_id);
|
||||
_get_config_task_maybe_return(iface_data, nm_utils_error_new_cancelled(FALSE, NULL));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
NMCSProviderGetConfigTaskData *get_config_data;
|
||||
GHashTable * response_parsed;
|
||||
} GetConfigMetadataData;
|
||||
|
||||
typedef struct {
|
||||
gssize iface_idx;
|
||||
char path[0];
|
||||
} GetConfigMetadataMac;
|
||||
|
||||
static void
|
||||
_get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
GetConfigMetadataData * metadata_data = user_data;
|
||||
GetConfigIfaceData * iface_data;
|
||||
NMCSProviderGetConfigTaskData *get_config_data = metadata_data->get_config_data;
|
||||
gs_unref_hashtable GHashTable *response_parsed =
|
||||
g_steal_pointer(&metadata_data->response_parsed);
|
||||
gs_free_error GError *error = NULL;
|
||||
GCancellable * cancellable;
|
||||
GetConfigMetadataMac *v_mac_data;
|
||||
const char * v_hwaddr;
|
||||
GHashTableIter h_iter;
|
||||
NMHttpClient * http_client;
|
||||
|
||||
nm_g_slice_free(metadata_data);
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &error);
|
||||
|
||||
iface_data = g_slice_new(GetConfigIfaceData);
|
||||
*iface_data = (GetConfigIfaceData){
|
||||
.get_config_data = get_config_data,
|
||||
.n_pending = 0,
|
||||
};
|
||||
|
||||
if (nm_utils_error_is_cancelled(error)) {
|
||||
_get_config_task_maybe_return(iface_data, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We ignore errors. Only if we got no response at all, it's a problem.
|
||||
* Otherwise, we proceed with whatever we could fetch. */
|
||||
if (!response_parsed) {
|
||||
_get_config_task_maybe_return(
|
||||
iface_data,
|
||||
nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "meta data for interfaces not found"));
|
||||
return;
|
||||
}
|
||||
|
||||
cancellable = g_task_get_cancellable(get_config_data->task);
|
||||
if (cancellable) {
|
||||
gulong cancelled_id;
|
||||
|
||||
cancelled_id = g_cancellable_connect(cancellable,
|
||||
G_CALLBACK(_get_config_fetch_cancelled_cb),
|
||||
iface_data,
|
||||
NULL);
|
||||
if (cancelled_id == 0) {
|
||||
/* the callback was already invoked synchronously and the task already returned. */
|
||||
return;
|
||||
}
|
||||
|
||||
iface_data->cancelled_id = cancelled_id;
|
||||
}
|
||||
|
||||
iface_data->cancellable = g_cancellable_new();
|
||||
|
||||
http_client = nmcs_provider_get_http_client(g_task_get_source_object(get_config_data->task));
|
||||
|
||||
g_hash_table_iter_init(&h_iter, response_parsed);
|
||||
while (g_hash_table_iter_next(&h_iter, (gpointer *) &v_hwaddr, (gpointer *) &v_mac_data)) {
|
||||
NMCSProviderGetConfigIfaceData *config_iface_data;
|
||||
gs_free char * uri1 = NULL;
|
||||
gs_free char * uri2 = NULL;
|
||||
const char * hwaddr;
|
||||
|
||||
if (!g_hash_table_lookup_extended(get_config_data->result_dict,
|
||||
v_hwaddr,
|
||||
(gpointer *) &hwaddr,
|
||||
(gpointer *) &config_iface_data)) {
|
||||
if (!get_config_data->any) {
|
||||
_LOGD("get-config: skip fetching meta data for %s (%s)",
|
||||
v_hwaddr,
|
||||
v_mac_data->path);
|
||||
continue;
|
||||
}
|
||||
config_iface_data = nmcs_provider_get_config_iface_data_new(FALSE);
|
||||
g_hash_table_insert(get_config_data->result_dict,
|
||||
(char *) (hwaddr = g_strdup(v_hwaddr)),
|
||||
config_iface_data);
|
||||
}
|
||||
|
||||
nm_assert(config_iface_data->iface_idx == -1);
|
||||
config_iface_data->iface_idx = v_mac_data->iface_idx;
|
||||
|
||||
_LOGD("get-config: start fetching meta data for #%" G_GSSIZE_FORMAT ", %s (%s)",
|
||||
config_iface_data->iface_idx,
|
||||
hwaddr,
|
||||
v_mac_data->path);
|
||||
|
||||
iface_data->n_pending++;
|
||||
nm_http_client_poll_get(
|
||||
http_client,
|
||||
(uri1 = _ec2_uri_interfaces(v_mac_data->path,
|
||||
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
|
||||
"subnet-ipv4-cidr-block")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NULL,
|
||||
iface_data->cancellable,
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_subnet_ipv4_cidr_block,
|
||||
nm_utils_user_data_pack(iface_data, hwaddr));
|
||||
|
||||
iface_data->n_pending++;
|
||||
nm_http_client_poll_get(
|
||||
http_client,
|
||||
(uri2 = _ec2_uri_interfaces(v_mac_data->path,
|
||||
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
|
||||
"local-ipv4s")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
512 * 1024,
|
||||
10000,
|
||||
1000,
|
||||
NULL,
|
||||
iface_data->cancellable,
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_fetch_done_cb_local_ipv4s,
|
||||
nm_utils_user_data_pack(iface_data, hwaddr));
|
||||
}
|
||||
|
||||
_get_config_task_maybe_return(iface_data, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_get_config_metadata_ready_check(long response_code,
|
||||
GBytes * response_data,
|
||||
gpointer check_user_data,
|
||||
GError **error)
|
||||
{
|
||||
GetConfigMetadataData *metadata_data = check_user_data;
|
||||
gs_unref_hashtable GHashTable *response_parsed = NULL;
|
||||
const guint8 * r_data;
|
||||
const char * cur_line;
|
||||
gsize r_len;
|
||||
gsize cur_line_len;
|
||||
GHashTableIter h_iter;
|
||||
gboolean has_all;
|
||||
const char * c_hwaddr;
|
||||
gssize iface_idx_counter = 0;
|
||||
|
||||
if (response_code != 200 || !response_data) {
|
||||
/* we wait longer. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r_data = g_bytes_get_data(response_data, &r_len);
|
||||
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
|
||||
nm_assert(r_data[r_len] == 0);
|
||||
|
||||
while (nm_utils_parse_next_line((const char **) &r_data, &r_len, &cur_line, &cur_line_len)) {
|
||||
GetConfigMetadataMac *mac_data;
|
||||
char * hwaddr;
|
||||
|
||||
if (cur_line_len == 0)
|
||||
continue;
|
||||
|
||||
/* Truncate the string. It's safe to do, because we own @response_data an it has an
|
||||
* extra NUL character after the buffer. */
|
||||
((char *) cur_line)[cur_line_len] = '\0';
|
||||
|
||||
hwaddr = nmcs_utils_hwaddr_normalize(
|
||||
cur_line,
|
||||
cur_line[cur_line_len - 1u] == '/' ? (gssize)(cur_line_len - 1u) : -1);
|
||||
if (!hwaddr)
|
||||
continue;
|
||||
|
||||
if (!response_parsed)
|
||||
response_parsed = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
mac_data = g_malloc(sizeof(GetConfigMetadataMac) + 1u + cur_line_len);
|
||||
mac_data->iface_idx = iface_idx_counter++;
|
||||
memcpy(mac_data->path, cur_line, cur_line_len + 1u);
|
||||
|
||||
g_hash_table_insert(response_parsed, hwaddr, mac_data);
|
||||
}
|
||||
|
||||
has_all = TRUE;
|
||||
g_hash_table_iter_init(&h_iter, metadata_data->get_config_data->result_dict);
|
||||
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, NULL)) {
|
||||
if (!response_parsed || !g_hash_table_contains(response_parsed, c_hwaddr)) {
|
||||
has_all = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nm_clear_pointer(&metadata_data->response_parsed, g_hash_table_unref);
|
||||
metadata_data->response_parsed = g_steal_pointer(&response_parsed);
|
||||
return has_all;
|
||||
}
|
||||
|
||||
static void
|
||||
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
|
||||
{
|
||||
gs_free char * uri = NULL;
|
||||
GetConfigMetadataData *metadata_data;
|
||||
|
||||
metadata_data = g_slice_new(GetConfigMetadataData);
|
||||
*metadata_data = (GetConfigMetadataData){
|
||||
.get_config_data = get_config_data,
|
||||
};
|
||||
|
||||
/* First we fetch the "macs/". If the caller requested some particular
|
||||
* MAC addresses, then we poll until we see them. They might not yet be
|
||||
* around from the start...
|
||||
*/
|
||||
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
|
||||
(uri = _ec2_uri_interfaces()),
|
||||
HTTP_TIMEOUT_MS,
|
||||
256 * 1024,
|
||||
15000,
|
||||
1000,
|
||||
NULL,
|
||||
g_task_get_cancellable(get_config_data->task),
|
||||
_get_config_metadata_ready_check,
|
||||
metadata_data,
|
||||
_get_config_metadata_ready_cb,
|
||||
metadata_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nmcs_provider_ec2_init(NMCSProviderEC2 *self)
|
||||
{}
|
||||
|
||||
static void
|
||||
nmcs_provider_ec2_class_init(NMCSProviderEC2Class *klass)
|
||||
{
|
||||
NMCSProviderClass *provider_class = NMCS_PROVIDER_CLASS(klass);
|
||||
|
||||
provider_class->_name = "ec2";
|
||||
provider_class->_env_provider_enabled = NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_EC2");
|
||||
provider_class->detect = detect;
|
||||
provider_class->get_config = get_config;
|
||||
}
|
||||
27
clients/cloud-setup/nmcs-provider-ec2.h
Normal file
27
clients/cloud-setup/nmcs-provider-ec2.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#ifndef __NMCS_PROVIDER_EC2_H__
|
||||
#define __NMCS_PROVIDER_EC2_H__
|
||||
|
||||
#include "nmcs-provider.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMCSProviderEC2 NMCSProviderEC2;
|
||||
typedef struct _NMCSProviderEC2Class NMCSProviderEC2Class;
|
||||
|
||||
#define NMCS_TYPE_PROVIDER_EC2 (nmcs_provider_ec2_get_type())
|
||||
#define NMCS_PROVIDER_EC2(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMCS_TYPE_PROVIDER_EC2, NMCSProviderEC2))
|
||||
#define NMCS_PROVIDER_EC2_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMCS_TYPE_PROVIDER_EC2, NMCSProviderEC2Class))
|
||||
#define NMCS_IS_PROVIDER_EC2(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMCS_TYPE_PROVIDER_EC2))
|
||||
#define NMCS_IS_PROVIDER_EC2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMCS_TYPE_PROVIDER_EC2))
|
||||
#define NMCS_PROVIDER_EC2_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMCS_TYPE_PROVIDER_EC2, NMCSProviderEC2Class))
|
||||
|
||||
GType nmcs_provider_ec2_get_type(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NMCS_PROVIDER_EC2_H__ */
|
||||
454
clients/cloud-setup/nmcs-provider-gcp.c
Normal file
454
clients/cloud-setup/nmcs-provider-gcp.c
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nmcs-provider-gcp.h"
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define HTTP_TIMEOUT_MS 3000
|
||||
#define HTTP_REQ_MAX_DATA 512 * 1024
|
||||
#define HTTP_POLL_TIMEOUT_MS 10000
|
||||
#define HTTP_RATE_LIMIT_MS 1000
|
||||
|
||||
#define NM_GCP_HOST "metadata.google.internal"
|
||||
#define NM_GCP_BASE "http://" NM_GCP_HOST
|
||||
#define NM_GCP_API_VERSION "/v1"
|
||||
#define NM_GCP_METADATA_URL_BASE NM_GCP_BASE "/computeMetadata" NM_GCP_API_VERSION "/instance"
|
||||
#define NM_GCP_METADATA_URL_NET "/network-interfaces/"
|
||||
|
||||
#define NM_GCP_METADATA_HEADER "Metadata-Flavor: Google"
|
||||
|
||||
#define _gcp_uri_concat(...) nmcs_utils_uri_build_concat(NM_GCP_METADATA_URL_BASE, __VA_ARGS__)
|
||||
#define _gcp_uri_interfaces(...) _gcp_uri_concat(NM_GCP_METADATA_URL_NET, ##__VA_ARGS__)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMCSProviderGCP {
|
||||
NMCSProvider parent;
|
||||
};
|
||||
|
||||
struct _NMCSProviderGCPClass {
|
||||
NMCSProviderClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMCSProviderGCP, nmcs_provider_gcp, NMCS_TYPE_PROVIDER);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_object GTask *task = user_data;
|
||||
gs_free_error GError *get_error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
|
||||
|
||||
if (nm_utils_error_is_cancelled(get_error)) {
|
||||
g_task_return_error(task, g_steal_pointer(&get_error));
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_error) {
|
||||
nm_utils_error_set(&error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"failure to get GCP metadata: %s",
|
||||
get_error->message);
|
||||
g_task_return_error(task, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean(task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
detect(NMCSProvider *provider, GTask *task)
|
||||
{
|
||||
NMHttpClient *http_client;
|
||||
gs_free char *uri = NULL;
|
||||
|
||||
http_client = nmcs_provider_get_http_client(provider);
|
||||
|
||||
nm_http_client_poll_get(http_client,
|
||||
(uri = _gcp_uri_concat("id")),
|
||||
HTTP_TIMEOUT_MS,
|
||||
256 * 1024,
|
||||
7000,
|
||||
1000,
|
||||
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
|
||||
g_task_get_cancellable(task),
|
||||
NULL,
|
||||
NULL,
|
||||
_detect_get_meta_data_done_cb,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMCSProviderGetConfigTaskData *config_data;
|
||||
guint n_ifaces_pending;
|
||||
GError * error;
|
||||
} GCPData;
|
||||
|
||||
typedef struct {
|
||||
NMCSProviderGetConfigIfaceData *iface_get_config;
|
||||
GCPData * gcp_data;
|
||||
gssize iface_idx;
|
||||
guint n_fips_pending;
|
||||
} GCPIfaceData;
|
||||
|
||||
static void
|
||||
_get_config_maybe_task_return(GCPData *gcp_data, GError *error_take)
|
||||
{
|
||||
NMCSProviderGetConfigTaskData *config_data = gcp_data->config_data;
|
||||
|
||||
if (error_take) {
|
||||
if (!gcp_data->error)
|
||||
gcp_data->error = error_take;
|
||||
else if (!nm_utils_error_is_cancelled(gcp_data->error)
|
||||
&& nm_utils_error_is_cancelled(error_take)) {
|
||||
nm_clear_error(&gcp_data->error);
|
||||
gcp_data->error = error_take;
|
||||
} else
|
||||
g_error_free(error_take);
|
||||
}
|
||||
|
||||
if (gcp_data->n_ifaces_pending > 0)
|
||||
return;
|
||||
|
||||
if (gcp_data->error) {
|
||||
if (nm_utils_error_is_cancelled(gcp_data->error))
|
||||
_LOGD("get-config: cancelled");
|
||||
else
|
||||
_LOGD("get-config: failed: %s", gcp_data->error->message);
|
||||
g_task_return_error(config_data->task, g_steal_pointer(&gcp_data->error));
|
||||
} else {
|
||||
_LOGD("get-config: success");
|
||||
g_task_return_pointer(config_data->task,
|
||||
g_hash_table_ref(config_data->result_dict),
|
||||
(GDestroyNotify) g_hash_table_unref);
|
||||
}
|
||||
|
||||
nm_g_slice_free(gcp_data);
|
||||
g_object_unref(config_data->task);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_fip_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
NMCSProviderGetConfigIfaceData *iface_get_config;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
GCPIfaceData * iface_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char * fip_str = NULL;
|
||||
NMIPRoute ** routes_arr;
|
||||
NMIPRoute * route_new;
|
||||
GCPData * gcp_data;
|
||||
|
||||
gcp_data = iface_data->gcp_data;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
|
||||
if (error)
|
||||
goto iface_done;
|
||||
|
||||
fip_str = g_bytes_get_data(response, NULL);
|
||||
if (!nm_utils_ipaddr_valid(AF_INET, fip_str)) {
|
||||
error =
|
||||
nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "forwarded-ip is not a valid ip address");
|
||||
goto iface_done;
|
||||
}
|
||||
|
||||
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: adding forwarded-ip %s",
|
||||
iface_data->iface_idx,
|
||||
fip_str);
|
||||
|
||||
iface_get_config = iface_data->iface_get_config;
|
||||
iface_get_config->iface_idx = iface_data->iface_idx;
|
||||
routes_arr = iface_get_config->iproutes_arr;
|
||||
|
||||
route_new = nm_ip_route_new(AF_INET, fip_str, 32, NULL, 100, &error);
|
||||
if (error)
|
||||
goto iface_done;
|
||||
|
||||
nm_ip_route_set_attribute(route_new, NM_IP_ROUTE_ATTRIBUTE_TYPE, g_variant_new_string("local"));
|
||||
routes_arr[iface_get_config->iproutes_len] = route_new;
|
||||
++iface_get_config->iproutes_len;
|
||||
|
||||
iface_done:
|
||||
--iface_data->n_fips_pending;
|
||||
if (iface_data->n_fips_pending == 0) {
|
||||
nm_g_slice_free(iface_data);
|
||||
--gcp_data->n_ifaces_pending;
|
||||
}
|
||||
|
||||
_get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *uri_arr = NULL;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
GCPIfaceData * iface_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
const char * response_str = NULL;
|
||||
gsize response_len;
|
||||
GCPData * gcp_data;
|
||||
const char * line;
|
||||
gsize line_len;
|
||||
guint i;
|
||||
|
||||
gcp_data = iface_data->gcp_data;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
|
||||
if (error)
|
||||
goto fips_error;
|
||||
|
||||
response_str = g_bytes_get_data(response, &response_len);
|
||||
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
|
||||
nm_assert(response_str[response_len] == 0);
|
||||
|
||||
uri_arr = g_ptr_array_new_with_free_func(g_free);
|
||||
while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) {
|
||||
gint64 fip_index;
|
||||
|
||||
/* Truncate the string. It's safe to do, because we own @response_data an it has an
|
||||
* extra NUL character after the buffer. */
|
||||
((char *) line)[line_len] = '\0';
|
||||
|
||||
fip_index = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXINT64, -1);
|
||||
if (fip_index < 0)
|
||||
continue;
|
||||
|
||||
g_ptr_array_add(uri_arr,
|
||||
g_strdup_printf("%" G_GSSIZE_FORMAT "/forwarded-ips/%" G_GINT64_FORMAT,
|
||||
iface_data->iface_idx,
|
||||
fip_index));
|
||||
}
|
||||
|
||||
iface_data->n_fips_pending = uri_arr->len;
|
||||
|
||||
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: found %u forwarded ips",
|
||||
iface_data->iface_idx,
|
||||
iface_data->n_fips_pending);
|
||||
|
||||
if (iface_data->n_fips_pending == 0) {
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "found no forwarded ip");
|
||||
goto fips_error;
|
||||
}
|
||||
|
||||
iface_data->iface_get_config->iproutes_arr = g_new(NMIPRoute *, iface_data->n_fips_pending);
|
||||
|
||||
for (i = 0; i < uri_arr->len; ++i) {
|
||||
const char * str = uri_arr->pdata[i];
|
||||
gs_free const char *uri = NULL;
|
||||
|
||||
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
|
||||
(uri = _gcp_uri_interfaces(str)),
|
||||
HTTP_TIMEOUT_MS,
|
||||
HTTP_REQ_MAX_DATA,
|
||||
HTTP_POLL_TIMEOUT_MS,
|
||||
HTTP_RATE_LIMIT_MS,
|
||||
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
|
||||
g_task_get_cancellable(gcp_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_fip_cb,
|
||||
iface_data);
|
||||
}
|
||||
return;
|
||||
|
||||
fips_error:
|
||||
nm_g_slice_free(iface_data);
|
||||
--gcp_data->n_ifaces_pending;
|
||||
_get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
GCPIfaceData * iface_data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free const char * hwaddr = NULL;
|
||||
gs_free const char * uri = NULL;
|
||||
char sbuf[100];
|
||||
GCPData * gcp_data;
|
||||
|
||||
gcp_data = iface_data->gcp_data;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
|
||||
if (error)
|
||||
goto iface_error;
|
||||
|
||||
hwaddr = nmcs_utils_hwaddr_normalize(g_bytes_get_data(response, NULL), -1);
|
||||
iface_data->iface_get_config = g_hash_table_lookup(gcp_data->config_data->result_dict, hwaddr);
|
||||
if (!iface_data->iface_get_config) {
|
||||
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: did not find a matching device",
|
||||
iface_data->iface_idx);
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
|
||||
"no matching hwaddr found for GCP interface");
|
||||
goto iface_error;
|
||||
}
|
||||
|
||||
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: found a matching device with hwaddr %s",
|
||||
iface_data->iface_idx,
|
||||
hwaddr);
|
||||
|
||||
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/forwarded-ips/", iface_data->iface_idx);
|
||||
|
||||
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
|
||||
(uri = _gcp_uri_interfaces(sbuf)),
|
||||
HTTP_TIMEOUT_MS,
|
||||
HTTP_REQ_MAX_DATA,
|
||||
HTTP_POLL_TIMEOUT_MS,
|
||||
HTTP_RATE_LIMIT_MS,
|
||||
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
|
||||
g_task_get_cancellable(gcp_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_ips_list_cb,
|
||||
iface_data);
|
||||
return;
|
||||
|
||||
iface_error:
|
||||
nm_g_slice_free(iface_data);
|
||||
--gcp_data->n_ifaces_pending;
|
||||
_get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
|
||||
}
|
||||
|
||||
static void
|
||||
_get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *ifaces_arr = NULL;
|
||||
gs_unref_bytes GBytes *response = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
GCPData * gcp_data = user_data;
|
||||
const char * response_str;
|
||||
gsize response_len;
|
||||
const char * line;
|
||||
gsize line_len;
|
||||
guint i;
|
||||
|
||||
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
|
||||
|
||||
if (error) {
|
||||
_get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
response_str = g_bytes_get_data(response, &response_len);
|
||||
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
|
||||
nm_assert(response_str[response_len] == 0);
|
||||
|
||||
ifaces_arr = g_ptr_array_new();
|
||||
|
||||
while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) {
|
||||
GCPIfaceData *iface_data;
|
||||
gssize iface_idx;
|
||||
|
||||
if (line_len == 0)
|
||||
continue;
|
||||
|
||||
/* Truncate the string. It's safe to do, because we own @response_data an it has an
|
||||
* extra NUL character after the buffer. */
|
||||
((char *) line)[line_len] = '\0';
|
||||
if (line[line_len - 1] == '/')
|
||||
((char *) line)[--line_len] = '\0';
|
||||
|
||||
iface_idx = _nm_utils_ascii_str_to_int64(line, 10, 0, G_MAXSSIZE, -1);
|
||||
if (iface_idx < 0)
|
||||
continue;
|
||||
|
||||
iface_data = g_slice_new(GCPIfaceData);
|
||||
*iface_data = (GCPIfaceData){
|
||||
.iface_get_config = NULL,
|
||||
.gcp_data = gcp_data,
|
||||
.iface_idx = iface_idx,
|
||||
.n_fips_pending = 0,
|
||||
};
|
||||
g_ptr_array_add(ifaces_arr, iface_data);
|
||||
}
|
||||
|
||||
gcp_data->n_ifaces_pending = ifaces_arr->len;
|
||||
_LOGI("found GCP interfaces: %u", ifaces_arr->len);
|
||||
|
||||
for (i = 0; i < ifaces_arr->len; ++i) {
|
||||
GCPIfaceData * data = ifaces_arr->pdata[i];
|
||||
gs_free const char *uri = NULL;
|
||||
char sbuf[100];
|
||||
|
||||
_LOGD("GCP interface[%" G_GSSIZE_FORMAT "]: retrieving configuration", data->iface_idx);
|
||||
|
||||
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/mac", data->iface_idx);
|
||||
|
||||
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
|
||||
(uri = _gcp_uri_interfaces(sbuf)),
|
||||
HTTP_TIMEOUT_MS,
|
||||
HTTP_REQ_MAX_DATA,
|
||||
HTTP_POLL_TIMEOUT_MS,
|
||||
HTTP_RATE_LIMIT_MS,
|
||||
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
|
||||
g_task_get_cancellable(gcp_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_config_iface_cb,
|
||||
data);
|
||||
}
|
||||
|
||||
if (ifaces_arr->len == 0) {
|
||||
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "no GCP interfaces found");
|
||||
_get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
|
||||
{
|
||||
gs_free const char *uri = NULL;
|
||||
GCPData * gcp_data;
|
||||
|
||||
gcp_data = g_slice_new(GCPData);
|
||||
*gcp_data = (GCPData){
|
||||
.config_data = get_config_data,
|
||||
.n_ifaces_pending = 0,
|
||||
.error = NULL,
|
||||
};
|
||||
|
||||
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
|
||||
(uri = _gcp_uri_interfaces()),
|
||||
HTTP_TIMEOUT_MS,
|
||||
HTTP_REQ_MAX_DATA,
|
||||
HTTP_POLL_TIMEOUT_MS,
|
||||
HTTP_RATE_LIMIT_MS,
|
||||
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
|
||||
g_task_get_cancellable(gcp_data->config_data->task),
|
||||
NULL,
|
||||
NULL,
|
||||
_get_net_ifaces_list_cb,
|
||||
gcp_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nmcs_provider_gcp_init(NMCSProviderGCP *self)
|
||||
{}
|
||||
|
||||
static void
|
||||
nmcs_provider_gcp_class_init(NMCSProviderGCPClass *klass)
|
||||
{
|
||||
NMCSProviderClass *provider_class = NMCS_PROVIDER_CLASS(klass);
|
||||
|
||||
provider_class->_name = "GCP";
|
||||
provider_class->_env_provider_enabled = NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_GCP");
|
||||
provider_class->detect = detect;
|
||||
provider_class->get_config = get_config;
|
||||
}
|
||||
27
clients/cloud-setup/nmcs-provider-gcp.h
Normal file
27
clients/cloud-setup/nmcs-provider-gcp.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#ifndef __NMCS_PROVIDER_GCP_H__
|
||||
#define __NMCS_PROVIDER_GCP_H__
|
||||
|
||||
#include "nmcs-provider.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMCSProviderGCP NMCSProviderGCP;
|
||||
typedef struct _NMCSProviderGCPClass NMCSProviderGCPClass;
|
||||
|
||||
#define NMCS_TYPE_PROVIDER_GCP (nmcs_provider_gcp_get_type())
|
||||
#define NMCS_PROVIDER_GCP(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMCS_TYPE_PROVIDER_GCP, NMCSProviderGCP))
|
||||
#define NMCS_PROVIDER_GCP_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMCS_TYPE_PROVIDER_GCP, NMCSProviderGCPClass))
|
||||
#define NMCS_IS_PROVIDER_GCP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMCS_TYPE_PROVIDER_GCP))
|
||||
#define NMCS_IS_PROVIDER_GCP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMCS_TYPE_PROVIDER_GCP))
|
||||
#define NMCS_PROVIDER_GCP_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMCS_TYPE_PROVIDER_GCP, NMCSProviderGCPClass))
|
||||
|
||||
GType nmcs_provider_gcp_get_type(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NMCS_PROVIDER_GCP_H__ */
|
||||
232
clients/cloud-setup/nmcs-provider.c
Normal file
232
clients/cloud-setup/nmcs-provider.c
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nmcs-provider.h"
|
||||
|
||||
#include "nm-cloud-setup-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_HTTP_CLIENT, );
|
||||
|
||||
typedef struct _NMCSProviderPrivate {
|
||||
NMHttpClient *http_client;
|
||||
} NMCSProviderPrivate;
|
||||
|
||||
G_DEFINE_TYPE(NMCSProvider, nmcs_provider, G_TYPE_OBJECT);
|
||||
|
||||
#define NMCS_PROVIDER_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMCSProvider, NMCS_IS_PROVIDER)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
nmcs_provider_get_name(NMCSProvider *self)
|
||||
{
|
||||
NMCSProviderClass *klass;
|
||||
|
||||
g_return_val_if_fail(NMCS_IS_PROVIDER(self), NULL);
|
||||
|
||||
klass = NMCS_PROVIDER_GET_CLASS(self);
|
||||
nm_assert(klass->_name);
|
||||
return klass->_name;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMHttpClient *
|
||||
nmcs_provider_get_http_client(NMCSProvider *self)
|
||||
{
|
||||
g_return_val_if_fail(NMCS_IS_PROVIDER(self), NULL);
|
||||
|
||||
return NMCS_PROVIDER_GET_PRIVATE(self)->http_client;
|
||||
}
|
||||
|
||||
GMainContext *
|
||||
nmcs_provider_get_main_context(NMCSProvider *self)
|
||||
{
|
||||
g_return_val_if_fail(NMCS_IS_PROVIDER(self), NULL);
|
||||
|
||||
return nm_http_client_get_main_context(NMCS_PROVIDER_GET_PRIVATE(self)->http_client);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nmcs_provider_detect(NMCSProvider * self,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
gs_unref_object GTask *task = NULL;
|
||||
const char * env;
|
||||
|
||||
g_return_if_fail(NMCS_IS_PROVIDER(self));
|
||||
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
||||
|
||||
task = nm_g_task_new(self, cancellable, nmcs_provider_detect, callback, user_data);
|
||||
|
||||
nmcs_wait_for_objects_register(task);
|
||||
|
||||
env = g_getenv(NMCS_PROVIDER_GET_CLASS(self)->_env_provider_enabled);
|
||||
if (!_nm_utils_ascii_str_to_bool(env, FALSE)) {
|
||||
g_task_return_error(task,
|
||||
nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "provider is disabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
NMCS_PROVIDER_GET_CLASS(self)->detect(self, g_steal_pointer(&task));
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmcs_provider_detect_finish(NMCSProvider *self, GAsyncResult *result, GError **error)
|
||||
{
|
||||
g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE);
|
||||
g_return_val_if_fail(nm_g_task_is_valid(result, self, nmcs_provider_detect), FALSE);
|
||||
|
||||
return g_task_propagate_boolean(G_TASK(result), error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMCSProviderGetConfigIfaceData *
|
||||
nmcs_provider_get_config_iface_data_new(gboolean was_requested)
|
||||
{
|
||||
NMCSProviderGetConfigIfaceData *iface_data;
|
||||
|
||||
iface_data = g_slice_new(NMCSProviderGetConfigIfaceData);
|
||||
*iface_data = (NMCSProviderGetConfigIfaceData){
|
||||
.iface_idx = -1,
|
||||
.was_requested = was_requested,
|
||||
};
|
||||
return iface_data;
|
||||
}
|
||||
|
||||
static void
|
||||
_iface_data_free(gpointer data)
|
||||
{
|
||||
NMCSProviderGetConfigIfaceData *iface_data = data;
|
||||
|
||||
g_free(iface_data->ipv4s_arr);
|
||||
g_free(iface_data->iproutes_arr);
|
||||
|
||||
nm_g_slice_free(iface_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_get_config_data_free(gpointer data)
|
||||
{
|
||||
NMCSProviderGetConfigTaskData *get_config_data = data;
|
||||
|
||||
if (get_config_data->extra_destroy)
|
||||
get_config_data->extra_destroy(get_config_data->extra_data);
|
||||
|
||||
nm_clear_pointer(&get_config_data->result_dict, g_hash_table_unref);
|
||||
|
||||
nm_g_slice_free(get_config_data);
|
||||
}
|
||||
|
||||
void
|
||||
nmcs_provider_get_config(NMCSProvider * self,
|
||||
gboolean any,
|
||||
const char *const * hwaddrs,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMCSProviderGetConfigTaskData *get_config_data;
|
||||
|
||||
g_return_if_fail(NMCS_IS_PROVIDER(self));
|
||||
g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
|
||||
|
||||
get_config_data = g_slice_new(NMCSProviderGetConfigTaskData);
|
||||
*get_config_data = (NMCSProviderGetConfigTaskData){
|
||||
.task = nm_g_task_new(self, cancellable, nmcs_provider_get_config, callback, user_data),
|
||||
.any = any,
|
||||
.result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _iface_data_free),
|
||||
};
|
||||
|
||||
g_task_set_task_data(get_config_data->task, get_config_data, _get_config_data_free);
|
||||
|
||||
nmcs_wait_for_objects_register(get_config_data->task);
|
||||
|
||||
for (; hwaddrs && hwaddrs[0]; hwaddrs++) {
|
||||
g_hash_table_insert(get_config_data->result_dict,
|
||||
g_strdup(hwaddrs[0]),
|
||||
nmcs_provider_get_config_iface_data_new(TRUE));
|
||||
}
|
||||
|
||||
_LOGD("get-config: starting");
|
||||
|
||||
NMCS_PROVIDER_GET_CLASS(self)->get_config(self, get_config_data);
|
||||
}
|
||||
|
||||
GHashTable *
|
||||
nmcs_provider_get_config_finish(NMCSProvider *self, GAsyncResult *result, GError **error)
|
||||
{
|
||||
g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE);
|
||||
g_return_val_if_fail(nm_g_task_is_valid(result, self, nmcs_provider_get_config), FALSE);
|
||||
|
||||
return g_task_propagate_pointer(G_TASK(result), error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMCSProviderPrivate *priv = NMCS_PROVIDER_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HTTP_CLIENT:
|
||||
priv->http_client = g_value_dup_object(value);
|
||||
g_return_if_fail(NM_IS_HTTP_CLIENT(priv->http_client));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nmcs_provider_init(NMCSProvider *self)
|
||||
{
|
||||
NMCSProviderPrivate *priv;
|
||||
|
||||
priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NMCS_TYPE_PROVIDER, NMCSProviderPrivate);
|
||||
|
||||
self->_priv = priv;
|
||||
}
|
||||
|
||||
static void
|
||||
dispose(GObject *object)
|
||||
{
|
||||
NMCSProvider * self = NMCS_PROVIDER(object);
|
||||
NMCSProviderPrivate *priv = NMCS_PROVIDER_GET_PRIVATE(self);
|
||||
|
||||
g_clear_object(&priv->http_client);
|
||||
|
||||
G_OBJECT_CLASS(nmcs_provider_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void
|
||||
nmcs_provider_class_init(NMCSProviderClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(NMCSProviderPrivate));
|
||||
|
||||
object_class->set_property = set_property;
|
||||
object_class->dispose = dispose;
|
||||
|
||||
obj_properties[PROP_HTTP_CLIENT] =
|
||||
g_param_spec_object(NMCS_PROVIDER_HTTP_CLIENT,
|
||||
"",
|
||||
"",
|
||||
NM_TYPE_HTTP_CLIENT,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
}
|
||||
106
clients/cloud-setup/nmcs-provider.h
Normal file
106
clients/cloud-setup/nmcs-provider.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#ifndef __NMCS_PROVIDER_H__
|
||||
#define __NMCS_PROVIDER_H__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "nm-http-client.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
in_addr_t *ipv4s_arr;
|
||||
gsize ipv4s_len;
|
||||
gssize iface_idx;
|
||||
in_addr_t cidr_addr;
|
||||
guint8 cidr_prefix;
|
||||
bool has_ipv4s : 1;
|
||||
bool has_cidr : 1;
|
||||
|
||||
NMIPRoute **iproutes_arr;
|
||||
gsize iproutes_len;
|
||||
|
||||
/* TRUE, if the configuration was requested via hwaddrs argument to
|
||||
* nmcs_provider_get_config(). */
|
||||
bool was_requested : 1;
|
||||
|
||||
} NMCSProviderGetConfigIfaceData;
|
||||
|
||||
static inline gboolean
|
||||
nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceData *config_data)
|
||||
{
|
||||
return config_data && config_data->iface_idx >= 0
|
||||
&& ((config_data->has_ipv4s && config_data->has_cidr) || config_data->iproutes_len);
|
||||
}
|
||||
|
||||
NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_new(gboolean was_requested);
|
||||
|
||||
typedef struct {
|
||||
GTask * task;
|
||||
GHashTable * result_dict;
|
||||
gpointer extra_data;
|
||||
GDestroyNotify extra_destroy;
|
||||
bool any : 1;
|
||||
} NMCSProviderGetConfigTaskData;
|
||||
|
||||
#define NMCS_TYPE_PROVIDER (nmcs_provider_get_type())
|
||||
#define NMCS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMCS_TYPE_PROVIDER, NMCSProvider))
|
||||
#define NMCS_PROVIDER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMCS_TYPE_PROVIDER, NMCSProviderClass))
|
||||
#define NMCS_IS_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMCS_TYPE_PROVIDER))
|
||||
#define NMCS_IS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMCS_TYPE_PROVIDER))
|
||||
#define NMCS_PROVIDER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMCS_TYPE_PROVIDER, NMCSProviderClass))
|
||||
|
||||
#define NMCS_PROVIDER_HTTP_CLIENT "http-client"
|
||||
|
||||
struct _NMCSProviderPrivate;
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
struct _NMCSProviderPrivate *_priv;
|
||||
} NMCSProvider;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
const char * _name;
|
||||
const char * _env_provider_enabled;
|
||||
|
||||
void (*detect)(NMCSProvider *self, GTask *task);
|
||||
|
||||
void (*get_config)(NMCSProvider *self, NMCSProviderGetConfigTaskData *get_config_data);
|
||||
|
||||
} NMCSProviderClass;
|
||||
|
||||
GType nmcs_provider_get_type(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *nmcs_provider_get_name(NMCSProvider *provider);
|
||||
|
||||
NMHttpClient *nmcs_provider_get_http_client(NMCSProvider *provider);
|
||||
GMainContext *nmcs_provider_get_main_context(NMCSProvider *provider);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nmcs_provider_detect(NMCSProvider * provider,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nmcs_provider_detect_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nmcs_provider_get_config(NMCSProvider * provider,
|
||||
gboolean any,
|
||||
const char *const * hwaddrs,
|
||||
GCancellable * cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GHashTable *
|
||||
nmcs_provider_get_config_finish(NMCSProvider *provider, GAsyncResult *result, GError **error);
|
||||
|
||||
#endif /* __NMCS_PROVIDER_H__ */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
common_inc = include_directories('.')
|
||||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
nm_polkit_listener = files('nm-polkit-listener.c')
|
||||
common_inc = include_directories('.')
|
||||
|
||||
common_deps = [
|
||||
libnm_dep,
|
||||
|
|
@ -13,6 +13,7 @@ sources = files(
|
|||
'nm-client-utils.c',
|
||||
'nm-secret-agent-simple.c',
|
||||
'nm-vpn-helpers.c',
|
||||
'nm-polkit-listener.c',
|
||||
)
|
||||
|
||||
libnmc_base = static_library(
|
||||
|
|
@ -30,17 +31,17 @@ libnmc_base_dep = declare_dependency(
|
|||
|
||||
settings_docs = 'settings-docs.h'
|
||||
|
||||
if enable_introspection
|
||||
if enable_docs
|
||||
settings_docs_source = custom_target(
|
||||
settings_docs,
|
||||
input: nm_property_docs,
|
||||
input: nm_settings_docs_xml_gir,
|
||||
output: settings_docs,
|
||||
command: [xsltproc, '--output', '@OUTPUT@', join_paths(meson.current_source_dir(), 'settings-docs.xsl'), '@INPUT@'],
|
||||
)
|
||||
|
||||
test(
|
||||
'check-settings-docs',
|
||||
find_program(join_paths(source_root, 'tools', 'check-settings-docs.sh')),
|
||||
find_program(join_paths(source_root, 'tools', 'check-compare-generated.sh')),
|
||||
args: [source_root, build_root, 'clients/common/' + settings_docs],
|
||||
)
|
||||
else
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2017 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -11,36 +11,43 @@
|
|||
#include "nm-device.h"
|
||||
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
|
||||
|
||||
const NMObject **nmc_objects_sort_by_path (const NMObject *const*objs, gssize len);
|
||||
const NMObject **nmc_objects_sort_by_path(const NMObject *const *objs, gssize len);
|
||||
|
||||
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
|
||||
const char *nmc_string_is_valid(const char *input, const char **allowed, GError **error);
|
||||
|
||||
gboolean nmc_string_to_uint (const char *str,
|
||||
gboolean range_check,
|
||||
unsigned long int min,
|
||||
unsigned long int max,
|
||||
unsigned long int *value);
|
||||
gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
|
||||
gboolean nmc_string_to_ternary (const char *str, NMTernary *val, GError **error);
|
||||
gboolean nmc_string_to_uint(const char * str,
|
||||
gboolean range_check,
|
||||
unsigned long int min,
|
||||
unsigned long int max,
|
||||
unsigned long int *value);
|
||||
gboolean nmc_string_to_bool(const char *str, gboolean *val_bool, GError **error);
|
||||
gboolean nmc_string_to_ternary(const char *str, NMTernary *val, GError **error);
|
||||
|
||||
gboolean matches (const char *cmd, const char *pattern);
|
||||
gboolean matches(const char *cmd, const char *pattern);
|
||||
|
||||
/* FIXME: don't expose this function on its own, at least not from this file. */
|
||||
const char *nmc_bond_validate_mode (const char *mode, GError **error);
|
||||
const char *nmc_bond_validate_mode(const char *mode, GError **error);
|
||||
|
||||
const char *nm_active_connection_state_reason_to_string (NMActiveConnectionStateReason reason);
|
||||
const char *nmc_device_state_to_string (NMDeviceState state);
|
||||
const char *nmc_device_reason_to_string (NMDeviceStateReason reason);
|
||||
const char *nmc_device_metered_to_string (NMMetered value);
|
||||
const char *nmc_device_state_to_string_with_external(NMDevice *device);
|
||||
|
||||
NMActiveConnectionState nmc_activation_get_effective_state (NMActiveConnection *active,
|
||||
NMDevice *device,
|
||||
const char **reason);
|
||||
const char *nm_active_connection_state_reason_to_string(NMActiveConnectionStateReason reason);
|
||||
const char *nmc_device_state_to_string(NMDeviceState state);
|
||||
const char *nmc_device_reason_to_string(NMDeviceStateReason reason);
|
||||
const char *nmc_device_metered_to_string(NMMetered value);
|
||||
|
||||
const char *nmc_wifi_strength_bars (guint8 strength);
|
||||
NMActiveConnectionState nmc_activation_get_effective_state(NMActiveConnection *active,
|
||||
NMDevice * device,
|
||||
const char ** reason);
|
||||
|
||||
const char *nmc_password_subst_char (void);
|
||||
const char *nmc_wifi_strength_bars(guint8 strength);
|
||||
|
||||
void nmc_print_qrcode (const char *str);
|
||||
const char *nmc_password_subst_char(void);
|
||||
|
||||
void nmc_print_qrcode(const char *str);
|
||||
|
||||
GHashTable *nmc_utils_parse_passwd_file(char *contents, gssize *out_error_line, GError **error);
|
||||
|
||||
GHashTable *
|
||||
nmc_utils_read_passwd_file(const char *passwd_file, gssize *out_error_line, GError **error);
|
||||
|
||||
#endif /* __NM_CLIENT_UTILS_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2017 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -11,81 +11,90 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMSetting *nm_meta_setting_info_editor_new_setting (const NMMetaSettingInfoEditor *setting_info,
|
||||
NMMetaAccessorSettingInitType init_type);
|
||||
NMSetting *nm_meta_setting_info_editor_new_setting(const NMMetaSettingInfoEditor *setting_info,
|
||||
NMMetaAccessorSettingInitType init_type);
|
||||
|
||||
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias);
|
||||
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_gtype (GType gtype);
|
||||
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_setting (NMSetting *setting);
|
||||
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_name(const char *setting_name,
|
||||
gboolean use_alias);
|
||||
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_gtype(GType gtype);
|
||||
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_setting(NMSetting *setting);
|
||||
|
||||
const NMMetaPropertyInfo *nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info,
|
||||
const char *property_name);
|
||||
const NMMetaPropertyInfo *nm_meta_property_info_find_by_name (const char *setting_name,
|
||||
const char *property_name);
|
||||
const NMMetaPropertyInfo *nm_meta_property_info_find_by_setting (NMSetting *setting,
|
||||
const char *property_name);
|
||||
const NMMetaPropertyInfo *
|
||||
nm_meta_setting_info_editor_get_property_info(const NMMetaSettingInfoEditor *setting_info,
|
||||
const char * property_name);
|
||||
const NMMetaPropertyInfo *nm_meta_property_info_find_by_name(const char *setting_name,
|
||||
const char *property_name);
|
||||
const NMMetaPropertyInfo *nm_meta_property_info_find_by_setting(NMSetting * setting,
|
||||
const char *property_name);
|
||||
|
||||
gboolean nm_meta_setting_info_editor_has_secrets (const NMMetaSettingInfoEditor *setting_info);
|
||||
gboolean nm_meta_setting_info_editor_has_secrets(const NMMetaSettingInfoEditor *setting_info);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMMetaSettingInfoEditor *const*nm_meta_setting_infos_editor_p (void);
|
||||
const NMMetaSettingInfoEditor *const *nm_meta_setting_infos_editor_p(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *nm_meta_abstract_info_get_name (const NMMetaAbstractInfo *abstract_info, gboolean for_header);
|
||||
const char *nm_meta_abstract_info_get_name(const NMMetaAbstractInfo *abstract_info,
|
||||
gboolean for_header);
|
||||
|
||||
const NMMetaAbstractInfo *const*nm_meta_abstract_info_get_nested (const NMMetaAbstractInfo *abstract_info,
|
||||
guint *out_len,
|
||||
gpointer *nested_to_free);
|
||||
const NMMetaAbstractInfo *const *
|
||||
nm_meta_abstract_info_get_nested(const NMMetaAbstractInfo *abstract_info,
|
||||
guint * out_len,
|
||||
gpointer * nested_to_free);
|
||||
|
||||
gconstpointer nm_meta_abstract_info_get (const NMMetaAbstractInfo *abstract_info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
gpointer target,
|
||||
gpointer target_data,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gboolean *out_is_default,
|
||||
gpointer *out_to_free);
|
||||
gconstpointer nm_meta_abstract_info_get(const NMMetaAbstractInfo * abstract_info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
gpointer target,
|
||||
gpointer target_data,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gboolean * out_is_default,
|
||||
gpointer * out_to_free);
|
||||
|
||||
const char *const*nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abstract_info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
const char *const *nm_meta_abstract_info_complete(const NMMetaAbstractInfo *abstract_info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
const NMMetaOperationContext *operation_context,
|
||||
const char *text,
|
||||
const char * text,
|
||||
gboolean *out_complete_filename,
|
||||
char ***out_to_free);
|
||||
char *** out_to_free);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *nm_meta_abstract_info_get_nested_names_str (const NMMetaAbstractInfo *abstract_info, const char *name_prefix);
|
||||
char *nm_meta_abstract_infos_get_names_str (const NMMetaAbstractInfo *const*fields_array, const char *name_prefix);
|
||||
char *nm_meta_abstract_info_get_nested_names_str(const NMMetaAbstractInfo *abstract_info,
|
||||
const char * name_prefix);
|
||||
char *nm_meta_abstract_infos_get_names_str(const NMMetaAbstractInfo *const *fields_array,
|
||||
const char * name_prefix);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const NMMetaAbstractInfo *info;
|
||||
const char *self_selection;
|
||||
const char *sub_selection;
|
||||
guint idx;
|
||||
const NMMetaAbstractInfo *info;
|
||||
const char * self_selection;
|
||||
const char * sub_selection;
|
||||
guint idx;
|
||||
} NMMetaSelectionItem;
|
||||
|
||||
typedef struct {
|
||||
const guint num;
|
||||
const NMMetaSelectionItem items[];
|
||||
const guint num;
|
||||
const NMMetaSelectionItem items[];
|
||||
} NMMetaSelectionResultList;
|
||||
|
||||
NMMetaSelectionResultList *nm_meta_selection_create_all (const NMMetaAbstractInfo *const* fields_array);
|
||||
NMMetaSelectionResultList *nm_meta_selection_create_parse_one (const NMMetaAbstractInfo *const* fields_array,
|
||||
const char *fields_prefix,
|
||||
const char *fields_str,
|
||||
gboolean validate_nested,
|
||||
GError **error);
|
||||
NMMetaSelectionResultList *nm_meta_selection_create_parse_list (const NMMetaAbstractInfo *const* fields_array,
|
||||
const char *fields_str,
|
||||
gboolean validate_nested,
|
||||
GError **error);
|
||||
NMMetaSelectionResultList *
|
||||
nm_meta_selection_create_all(const NMMetaAbstractInfo *const *fields_array);
|
||||
NMMetaSelectionResultList *
|
||||
nm_meta_selection_create_parse_one(const NMMetaAbstractInfo *const *fields_array,
|
||||
const char * fields_prefix,
|
||||
const char * fields_str,
|
||||
gboolean validate_nested,
|
||||
GError ** error);
|
||||
NMMetaSelectionResultList *
|
||||
nm_meta_selection_create_parse_list(const NMMetaAbstractInfo *const *fields_array,
|
||||
const char * fields_str,
|
||||
gboolean validate_nested,
|
||||
GError ** error);
|
||||
|
||||
#endif /* _NM_META_SETTING_ACCESS_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2010 - 2018 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -15,155 +15,170 @@ struct _NMDevice;
|
|||
#define NM_META_TEXT_HIDDEN N_("<hidden>")
|
||||
|
||||
#define NM_META_TEXT_PROMPT_ADSL_PROTO N_("Protocol")
|
||||
#define NM_META_TEXT_PROMPT_ADSL_PROTO_CHOICES "(" NM_SETTING_ADSL_PROTOCOL_PPPOA "/" NM_SETTING_ADSL_PROTOCOL_PPPOE "/" NM_SETTING_ADSL_PROTOCOL_IPOATM ")"
|
||||
#define NM_META_TEXT_PROMPT_ADSL_PROTO_CHOICES \
|
||||
"(" NM_SETTING_ADSL_PROTOCOL_PPPOA "/" NM_SETTING_ADSL_PROTOCOL_PPPOE \
|
||||
"/" NM_SETTING_ADSL_PROTOCOL_IPOATM ")"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_ADSL_ENCAP N_("ADSL encapsulation")
|
||||
#define NM_META_TEXT_PROMPT_ADSL_ENCAP_CHOICES "(" NM_SETTING_ADSL_ENCAPSULATION_VCMUX "/" NM_SETTING_ADSL_ENCAPSULATION_LLC ") [none]"
|
||||
#define NM_META_TEXT_PROMPT_ADSL_ENCAP_CHOICES \
|
||||
"(" NM_SETTING_ADSL_ENCAPSULATION_VCMUX "/" NM_SETTING_ADSL_ENCAPSULATION_LLC ") [none]"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_CON_TYPE N_("Connection type")
|
||||
#define NM_META_TEXT_PROMPT_IFNAME N_("Interface name [*]")
|
||||
#define NM_META_TEXT_PROMPT_VPN_TYPE N_("VPN type")
|
||||
#define NM_META_TEXT_PROMPT_MASTER N_("Master")
|
||||
#define NM_META_TEXT_PROMPT_CON_TYPE N_("Connection type")
|
||||
#define NM_META_TEXT_PROMPT_IFNAME N_("Interface name [*]")
|
||||
#define NM_META_TEXT_PROMPT_VPN_TYPE N_("VPN type")
|
||||
#define NM_META_TEXT_PROMPT_MASTER N_("Master")
|
||||
|
||||
#define NM_META_TEXT_PROMPT_IB_MODE N_("Transport mode")
|
||||
#define NM_META_TEXT_PROMPT_IB_MODE N_("Transport mode")
|
||||
#define NM_META_TEXT_WORD_DATAGRAM "datagram"
|
||||
#define NM_META_TEXT_WORD_CONNECTED "connected"
|
||||
#define NM_META_TEXT_PROMPT_IB_MODE_CHOICES "(" NM_META_TEXT_WORD_DATAGRAM "/" NM_META_TEXT_WORD_CONNECTED ") [" NM_META_TEXT_WORD_DATAGRAM "]"
|
||||
#define NM_META_TEXT_PROMPT_IB_MODE_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_DATAGRAM "/" NM_META_TEXT_WORD_CONNECTED \
|
||||
") [" NM_META_TEXT_WORD_DATAGRAM "]"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_BT_TYPE N_("Bluetooth type")
|
||||
#define NM_META_TEXT_WORD_PANU "panu"
|
||||
#define NM_META_TEXT_WORD_NAP "nap"
|
||||
#define NM_META_TEXT_WORD_DUN_GSM "dun-gsm"
|
||||
#define NM_META_TEXT_WORD_DUN_CDMA "dun-cdma"
|
||||
#define NM_META_TEXT_PROMPT_BT_TYPE_CHOICES "(" NM_META_TEXT_WORD_PANU "/" NM_META_TEXT_WORD_NAP "/" NM_META_TEXT_WORD_DUN_GSM "/" NM_META_TEXT_WORD_DUN_CDMA ") [" NM_META_TEXT_WORD_PANU "]"
|
||||
#define NM_META_TEXT_PROMPT_BT_TYPE_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_PANU "/" NM_META_TEXT_WORD_NAP "/" NM_META_TEXT_WORD_DUN_GSM \
|
||||
"/" NM_META_TEXT_WORD_DUN_CDMA ") [" NM_META_TEXT_WORD_PANU "]"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_BOND_MODE N_("Bonding mode")
|
||||
|
||||
#define NM_META_TEXT_PROMPT_BOND_MON_MODE N_("Bonding monitoring mode")
|
||||
#define NM_META_TEXT_WORD_MIIMON "miimon"
|
||||
#define NM_META_TEXT_WORD_ARP "arp"
|
||||
#define NM_META_TEXT_PROMPT_BOND_MON_MODE_CHOICES "(" NM_META_TEXT_WORD_MIIMON "/" NM_META_TEXT_WORD_ARP ") [" NM_META_TEXT_WORD_MIIMON "]"
|
||||
#define NM_META_TEXT_WORD_MIIMON "miimon"
|
||||
#define NM_META_TEXT_WORD_ARP "arp"
|
||||
#define NM_META_TEXT_PROMPT_BOND_MON_MODE_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_MIIMON "/" NM_META_TEXT_WORD_ARP ") [" NM_META_TEXT_WORD_MIIMON "]"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_WIFI_MODE N_("Wi-Fi mode")
|
||||
#define NM_META_TEXT_WORD_INFRA "infrastructure"
|
||||
#define NM_META_TEXT_WORD_AP "ap"
|
||||
#define NM_META_TEXT_WORD_ADHOC "adhoc"
|
||||
#define NM_META_TEXT_WORD_MESH "mesh"
|
||||
#define NM_META_TEXT_PROMPT_WIFI_MODE_CHOICES "(" NM_META_TEXT_WORD_INFRA "/" NM_META_TEXT_WORD_AP "/" NM_META_TEXT_WORD_ADHOC "/" NM_META_TEXT_WORD_MESH ") [" NM_META_TEXT_WORD_INFRA "]"
|
||||
#define NM_META_TEXT_WORD_INFRA "infrastructure"
|
||||
#define NM_META_TEXT_WORD_AP "ap"
|
||||
#define NM_META_TEXT_WORD_ADHOC "adhoc"
|
||||
#define NM_META_TEXT_WORD_MESH "mesh"
|
||||
#define NM_META_TEXT_PROMPT_WIFI_MODE_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_INFRA "/" NM_META_TEXT_WORD_AP "/" NM_META_TEXT_WORD_ADHOC \
|
||||
"/" NM_META_TEXT_WORD_MESH ") [" NM_META_TEXT_WORD_INFRA "]"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_TUN_MODE N_("Tun mode")
|
||||
#define NM_META_TEXT_WORD_TUN "tun"
|
||||
#define NM_META_TEXT_WORD_TAP "tap"
|
||||
#define NM_META_TEXT_PROMPT_TUN_MODE_CHOICES "(" NM_META_TEXT_WORD_TUN "/" NM_META_TEXT_WORD_TAP ") [" NM_META_TEXT_WORD_TUN "]"
|
||||
#define NM_META_TEXT_WORD_TUN "tun"
|
||||
#define NM_META_TEXT_WORD_TAP "tap"
|
||||
#define NM_META_TEXT_PROMPT_TUN_MODE_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_TUN "/" NM_META_TEXT_WORD_TAP ") [" NM_META_TEXT_WORD_TUN "]"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_IP_TUNNEL_MODE N_("IP Tunnel mode")
|
||||
|
||||
#define NM_META_TEXT_PROMPT_MACVLAN_MODE N_("MACVLAN mode")
|
||||
|
||||
#define NM_META_TEXT_PROMPT_MACSEC_MODE N_("MACsec mode")
|
||||
#define NM_META_TEXT_WORD_PSK "psk"
|
||||
#define NM_META_TEXT_WORD_EAP "eap"
|
||||
#define NM_META_TEXT_PROMPT_MACSEC_MODE_CHOICES "(" NM_META_TEXT_WORD_PSK "/" NM_META_TEXT_WORD_EAP ")"
|
||||
#define NM_META_TEXT_WORD_PSK "psk"
|
||||
#define NM_META_TEXT_WORD_EAP "eap"
|
||||
#define NM_META_TEXT_PROMPT_MACSEC_MODE_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_PSK "/" NM_META_TEXT_WORD_EAP ")"
|
||||
|
||||
#define NM_META_TEXT_PROMPT_PROXY_METHOD N_("Proxy method")
|
||||
#define NM_META_TEXT_WORD_NONE "none"
|
||||
#define NM_META_TEXT_WORD_AUTO "auto"
|
||||
#define NM_META_TEXT_PROMPT_PROXY_METHOD_CHOICES "(" NM_META_TEXT_WORD_NONE "/" NM_META_TEXT_WORD_AUTO ") [" NM_META_TEXT_WORD_NONE "]"
|
||||
#define NM_META_TEXT_WORD_NONE "none"
|
||||
#define NM_META_TEXT_WORD_AUTO "auto"
|
||||
#define NM_META_TEXT_PROMPT_PROXY_METHOD_CHOICES \
|
||||
"(" NM_META_TEXT_WORD_NONE "/" NM_META_TEXT_WORD_AUTO ") [" NM_META_TEXT_WORD_NONE "]"
|
||||
|
||||
typedef enum {
|
||||
NM_META_COLOR_NONE = 0,
|
||||
NM_META_COLOR_CONNECTION_ACTIVATED,
|
||||
NM_META_COLOR_CONNECTION_ACTIVATING,
|
||||
NM_META_COLOR_CONNECTION_DISCONNECTING,
|
||||
NM_META_COLOR_CONNECTION_INVISIBLE,
|
||||
NM_META_COLOR_CONNECTION_UNKNOWN,
|
||||
NM_META_COLOR_CONNECTIVITY_FULL,
|
||||
NM_META_COLOR_CONNECTIVITY_LIMITED,
|
||||
NM_META_COLOR_CONNECTIVITY_NONE,
|
||||
NM_META_COLOR_CONNECTIVITY_PORTAL,
|
||||
NM_META_COLOR_CONNECTIVITY_UNKNOWN,
|
||||
NM_META_COLOR_DEVICE_ACTIVATED,
|
||||
NM_META_COLOR_DEVICE_ACTIVATING,
|
||||
NM_META_COLOR_DEVICE_DISCONNECTED,
|
||||
NM_META_COLOR_DEVICE_FIRMWARE_MISSING,
|
||||
NM_META_COLOR_DEVICE_PLUGIN_MISSING,
|
||||
NM_META_COLOR_DEVICE_UNAVAILABLE,
|
||||
NM_META_COLOR_DEVICE_DISABLED,
|
||||
NM_META_COLOR_DEVICE_UNKNOWN,
|
||||
NM_META_COLOR_MANAGER_RUNNING,
|
||||
NM_META_COLOR_MANAGER_STARTING,
|
||||
NM_META_COLOR_MANAGER_STOPPED,
|
||||
NM_META_COLOR_PERMISSION_AUTH,
|
||||
NM_META_COLOR_PERMISSION_NO,
|
||||
NM_META_COLOR_PERMISSION_UNKNOWN,
|
||||
NM_META_COLOR_PERMISSION_YES,
|
||||
NM_META_COLOR_PROMPT,
|
||||
NM_META_COLOR_STATE_ASLEEP,
|
||||
NM_META_COLOR_STATE_CONNECTED_GLOBAL,
|
||||
NM_META_COLOR_STATE_CONNECTED_LOCAL,
|
||||
NM_META_COLOR_STATE_CONNECTED_SITE,
|
||||
NM_META_COLOR_STATE_CONNECTING,
|
||||
NM_META_COLOR_STATE_DISCONNECTED,
|
||||
NM_META_COLOR_STATE_DISCONNECTING,
|
||||
NM_META_COLOR_STATE_UNKNOWN,
|
||||
NM_META_COLOR_WIFI_SIGNAL_EXCELLENT,
|
||||
NM_META_COLOR_WIFI_SIGNAL_FAIR,
|
||||
NM_META_COLOR_WIFI_SIGNAL_GOOD,
|
||||
NM_META_COLOR_WIFI_SIGNAL_POOR,
|
||||
NM_META_COLOR_WIFI_SIGNAL_UNKNOWN,
|
||||
NM_META_COLOR_DISABLED,
|
||||
NM_META_COLOR_ENABLED,
|
||||
_NM_META_COLOR_NUM
|
||||
NM_META_COLOR_NONE = 0,
|
||||
NM_META_COLOR_CONNECTION_ACTIVATED,
|
||||
NM_META_COLOR_CONNECTION_ACTIVATING,
|
||||
NM_META_COLOR_CONNECTION_DISCONNECTING,
|
||||
NM_META_COLOR_CONNECTION_INVISIBLE,
|
||||
NM_META_COLOR_CONNECTION_EXTERNAL,
|
||||
NM_META_COLOR_CONNECTION_UNKNOWN,
|
||||
NM_META_COLOR_CONNECTIVITY_FULL,
|
||||
NM_META_COLOR_CONNECTIVITY_LIMITED,
|
||||
NM_META_COLOR_CONNECTIVITY_NONE,
|
||||
NM_META_COLOR_CONNECTIVITY_PORTAL,
|
||||
NM_META_COLOR_CONNECTIVITY_UNKNOWN,
|
||||
NM_META_COLOR_DEVICE_ACTIVATED,
|
||||
NM_META_COLOR_DEVICE_ACTIVATING,
|
||||
NM_META_COLOR_DEVICE_DISCONNECTED,
|
||||
NM_META_COLOR_DEVICE_FIRMWARE_MISSING,
|
||||
NM_META_COLOR_DEVICE_PLUGIN_MISSING,
|
||||
NM_META_COLOR_DEVICE_UNAVAILABLE,
|
||||
NM_META_COLOR_DEVICE_DISABLED,
|
||||
NM_META_COLOR_DEVICE_EXTERNAL,
|
||||
NM_META_COLOR_DEVICE_UNKNOWN,
|
||||
NM_META_COLOR_MANAGER_RUNNING,
|
||||
NM_META_COLOR_MANAGER_STARTING,
|
||||
NM_META_COLOR_MANAGER_STOPPED,
|
||||
NM_META_COLOR_PERMISSION_AUTH,
|
||||
NM_META_COLOR_PERMISSION_NO,
|
||||
NM_META_COLOR_PERMISSION_UNKNOWN,
|
||||
NM_META_COLOR_PERMISSION_YES,
|
||||
NM_META_COLOR_PROMPT,
|
||||
NM_META_COLOR_STATE_ASLEEP,
|
||||
NM_META_COLOR_STATE_CONNECTED_GLOBAL,
|
||||
NM_META_COLOR_STATE_CONNECTED_LOCAL,
|
||||
NM_META_COLOR_STATE_CONNECTED_SITE,
|
||||
NM_META_COLOR_STATE_CONNECTING,
|
||||
NM_META_COLOR_STATE_DISCONNECTED,
|
||||
NM_META_COLOR_STATE_DISCONNECTING,
|
||||
NM_META_COLOR_STATE_UNKNOWN,
|
||||
NM_META_COLOR_WIFI_SIGNAL_EXCELLENT,
|
||||
NM_META_COLOR_WIFI_SIGNAL_FAIR,
|
||||
NM_META_COLOR_WIFI_SIGNAL_GOOD,
|
||||
NM_META_COLOR_WIFI_SIGNAL_POOR,
|
||||
NM_META_COLOR_WIFI_SIGNAL_UNKNOWN,
|
||||
NM_META_COLOR_DISABLED,
|
||||
NM_META_COLOR_ENABLED,
|
||||
_NM_META_COLOR_NUM
|
||||
} NMMetaColor;
|
||||
|
||||
typedef enum {
|
||||
NM_META_ACCESSOR_MODIFIER_SET,
|
||||
NM_META_ACCESSOR_MODIFIER_ADD,
|
||||
NM_META_ACCESSOR_MODIFIER_DEL,
|
||||
NM_META_ACCESSOR_MODIFIER_SET,
|
||||
NM_META_ACCESSOR_MODIFIER_ADD,
|
||||
NM_META_ACCESSOR_MODIFIER_DEL,
|
||||
} NMMetaAccessorModifier;
|
||||
|
||||
typedef enum {
|
||||
NM_META_ACCESSOR_GET_TYPE_PRETTY,
|
||||
NM_META_ACCESSOR_GET_TYPE_PARSABLE,
|
||||
NM_META_ACCESSOR_GET_TYPE_COLOR,
|
||||
NM_META_ACCESSOR_GET_TYPE_PRETTY,
|
||||
NM_META_ACCESSOR_GET_TYPE_PARSABLE,
|
||||
NM_META_ACCESSOR_GET_TYPE_COLOR,
|
||||
} NMMetaAccessorGetType;
|
||||
|
||||
typedef enum {
|
||||
NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT,
|
||||
NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI,
|
||||
NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT,
|
||||
NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI,
|
||||
} NMMetaAccessorSettingInitType;
|
||||
|
||||
typedef enum {
|
||||
NM_META_ACCESSOR_GET_FLAGS_NONE = 0,
|
||||
NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV = (1LL << 0),
|
||||
NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS = (1LL << 1),
|
||||
NM_META_ACCESSOR_GET_FLAGS_NONE = 0,
|
||||
NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV = (1LL << 0),
|
||||
NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS = (1LL << 1),
|
||||
} NMMetaAccessorGetFlags;
|
||||
|
||||
typedef enum {
|
||||
NM_META_ACCESSOR_GET_OUT_FLAGS_NONE = 0,
|
||||
NM_META_ACCESSOR_GET_OUT_FLAGS_STRV = (1LL << 0),
|
||||
NM_META_ACCESSOR_GET_OUT_FLAGS_NONE = 0,
|
||||
NM_META_ACCESSOR_GET_OUT_FLAGS_STRV = (1LL << 0),
|
||||
|
||||
/* the property allows to be hidden, if and only if, it's value is set to the
|
||||
* default. This should only be set by new properties, to preserve behavior
|
||||
* of old properties, which were always printed. */
|
||||
NM_META_ACCESSOR_GET_OUT_FLAGS_HIDE = (1LL << 1),
|
||||
/* the property allows to be hidden, if and only if, it's value is set to the
|
||||
* default. This should only be set by new properties, to preserve behavior
|
||||
* of old properties, which were always printed. */
|
||||
NM_META_ACCESSOR_GET_OUT_FLAGS_HIDE = (1LL << 1),
|
||||
} NMMetaAccessorGetOutFlags;
|
||||
|
||||
typedef enum {
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC = (1LL << 0),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX = (1LL << 1),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT = (1LL << 2),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT_L10N = (1LL << 3),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC = (1LL << 4),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC_HEX = (1LL << 5),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT = (1LL << 6),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC = (1LL << 0),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX = (1LL << 1),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT = (1LL << 2),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT_L10N = (1LL << 3),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC = (1LL << 4),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC_HEX = (1LL << 5),
|
||||
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT = (1LL << 6),
|
||||
} NMMetaPropertyTypFlags;
|
||||
|
||||
typedef enum {
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_WPAN,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND,
|
||||
NM_META_PROPERTY_TYPE_MAC_MODE_WPAN,
|
||||
} NMMetaPropertyTypeMacMode;
|
||||
|
||||
typedef struct _NMMetaEnvironment NMMetaEnvironment;
|
||||
|
|
@ -181,280 +196,274 @@ typedef struct _NMMetaPropertyTypDataNested NMMetaPropertyTypDataNested;
|
|||
* This command actually violates layering, and should be considered
|
||||
* a hack. In the future, try to replace its use. */
|
||||
struct _NMMetaOperationContext {
|
||||
NMConnection *connection;
|
||||
NMConnection *connection;
|
||||
};
|
||||
|
||||
struct _NMMetaPropertyType {
|
||||
/* should return a translated string */
|
||||
const char *(*describe_fcn)(const NMMetaPropertyInfo *property_info, char **out_to_free);
|
||||
|
||||
/* should return a translated string */
|
||||
const char *(*describe_fcn) (const NMMetaPropertyInfo *property_info,
|
||||
char **out_to_free);
|
||||
gconstpointer (*get_fcn)(const NMMetaPropertyInfo * property_info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
NMSetting * setting,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gboolean * out_is_default,
|
||||
gpointer * out_to_free);
|
||||
gboolean (*set_fcn)(const NMMetaPropertyInfo *property_info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
NMSetting * setting,
|
||||
NMMetaAccessorModifier modifier,
|
||||
const char * value,
|
||||
GError ** error);
|
||||
|
||||
gconstpointer (*get_fcn) (const NMMetaPropertyInfo *property_info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
NMSetting *setting,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gboolean *out_is_default,
|
||||
gpointer *out_to_free);
|
||||
gboolean (*set_fcn) (const NMMetaPropertyInfo *property_info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
NMSetting *setting,
|
||||
NMMetaAccessorModifier modifier,
|
||||
const char *value,
|
||||
GError **error);
|
||||
const char *const *(*values_fcn)(const NMMetaPropertyInfo *property_info, char ***out_to_free);
|
||||
|
||||
const char *const*(*values_fcn) (const NMMetaPropertyInfo *property_info,
|
||||
char ***out_to_free);
|
||||
const char *const *(*complete_fcn)(const NMMetaPropertyInfo * property_info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
const NMMetaOperationContext *operation_context,
|
||||
const char * text,
|
||||
gboolean * out_complete_filename,
|
||||
char *** out_to_free);
|
||||
|
||||
const char *const*(*complete_fcn) (const NMMetaPropertyInfo *property_info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
const NMMetaOperationContext *operation_context,
|
||||
const char *text,
|
||||
gboolean *out_complete_filename,
|
||||
char ***out_to_free);
|
||||
|
||||
/* Whether set_fcn() supports the '-' modifier. That is, whether the property
|
||||
* is a list type. */
|
||||
bool set_supports_remove:1;
|
||||
/* Whether set_fcn() supports the '-' modifier. That is, whether the property
|
||||
* is a list type. */
|
||||
bool set_supports_remove : 1;
|
||||
};
|
||||
|
||||
struct _NMUtilsEnumValueInfo;
|
||||
|
||||
typedef union {
|
||||
gint64 i64;
|
||||
guint64 u64;
|
||||
gint64 i64;
|
||||
guint64 u64;
|
||||
} NMMetaSignUnsignInt64;
|
||||
|
||||
typedef struct {
|
||||
const char *nick;
|
||||
NMMetaSignUnsignInt64 value;
|
||||
const char * nick;
|
||||
NMMetaSignUnsignInt64 value;
|
||||
} NMMetaUtilsIntValueInfo;
|
||||
|
||||
struct _NMMetaPropertyTypData {
|
||||
union {
|
||||
struct {
|
||||
GType (*get_gtype) (void);
|
||||
int min;
|
||||
int max;
|
||||
const struct _NMUtilsEnumValueInfo *value_infos_get; /* nicks for get function */
|
||||
const struct _NMUtilsEnumValueInfo *value_infos; /* nicks for set function */
|
||||
void (*pre_set_notify) (const NMMetaPropertyInfo *property_info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
NMSetting *setting,
|
||||
int value);
|
||||
} gobject_enum;
|
||||
struct {
|
||||
NMMetaSignUnsignInt64 min;
|
||||
NMMetaSignUnsignInt64 max;
|
||||
guint base;
|
||||
const NMMetaUtilsIntValueInfo *value_infos;
|
||||
} gobject_int;
|
||||
struct {
|
||||
const char *(*validate_fcn) (const char *value, char **out_to_free, GError **error);
|
||||
} gobject_string;
|
||||
struct {
|
||||
bool legacy_format:1;
|
||||
} gobject_bytes;
|
||||
struct {
|
||||
guint32 (*get_num_fcn_u32) (NMSetting *setting);
|
||||
guint (*get_num_fcn_u) (NMSetting *setting);
|
||||
void (*clear_all_fcn) (NMSetting *setting);
|
||||
union {
|
||||
struct {
|
||||
GType (*get_gtype)(void);
|
||||
int min;
|
||||
int max;
|
||||
const struct _NMUtilsEnumValueInfo *value_infos_get; /* nicks for get function */
|
||||
const struct _NMUtilsEnumValueInfo *value_infos; /* nicks for set function */
|
||||
void (*pre_set_notify)(const NMMetaPropertyInfo *property_info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
NMSetting * setting,
|
||||
int value);
|
||||
} gobject_enum;
|
||||
struct {
|
||||
NMMetaSignUnsignInt64 min;
|
||||
NMMetaSignUnsignInt64 max;
|
||||
guint base;
|
||||
const NMMetaUtilsIntValueInfo *value_infos;
|
||||
} gobject_int;
|
||||
struct {
|
||||
const char *(*validate_fcn)(const char *value, char **out_to_free, GError **error);
|
||||
bool handle_emptyunset : 1;
|
||||
} gobject_string;
|
||||
struct {
|
||||
bool legacy_format : 1;
|
||||
} gobject_bytes;
|
||||
struct {
|
||||
guint32 (*get_num_fcn_u32)(NMSetting *setting);
|
||||
guint (*get_num_fcn_u)(NMSetting *setting);
|
||||
void (*clear_all_fcn)(NMSetting *setting);
|
||||
|
||||
/* some multilist properties distinguish between an empty list and
|
||||
* and unset. If this function pointer is set, certain behaviors come
|
||||
* into action to handle that. */
|
||||
void (*clear_emptyunset_fcn) (NMSetting *setting,
|
||||
gboolean is_set /* or else set default */);
|
||||
/* some multilist properties distinguish between an empty list and
|
||||
* and unset. If this function pointer is set, certain behaviors come
|
||||
* into action to handle that. */
|
||||
void (*clear_emptyunset_fcn)(NMSetting *setting,
|
||||
gboolean is_set /* or else set default */);
|
||||
|
||||
gboolean (*add_fcn) (NMSetting *setting,
|
||||
const char *item);
|
||||
void (*add2_fcn) (NMSetting *setting,
|
||||
const char *item);
|
||||
const char *(*validate_fcn) (const char *item, GError **error);
|
||||
const char *(*validate2_fcn) (NMSetting *setting, const char *item, GError **error);
|
||||
void (*remove_by_idx_fcn_u32) (NMSetting *setting, guint32 idx);
|
||||
void (*remove_by_idx_fcn_u) (NMSetting *setting, guint idx);
|
||||
void (*remove_by_idx_fcn_s) (NMSetting *setting, int idx);
|
||||
gboolean (*remove_by_value_fcn) (NMSetting *setting, const char *item);
|
||||
bool strsplit_plain:1;
|
||||
bool strsplit_with_spaces:1;
|
||||
} multilist;
|
||||
struct {
|
||||
guint (*get_num_fcn) (NMSetting *setting);
|
||||
void (*obj_to_str_fcn) (NMMetaAccessorGetType get_type,
|
||||
NMSetting *setting,
|
||||
guint idx,
|
||||
GString *str);
|
||||
gboolean (*set_fcn) (NMSetting *setting,
|
||||
gboolean do_add /* or else remove. */,
|
||||
const char *value,
|
||||
GError **error);
|
||||
void (*clear_all_fcn) (NMSetting *setting);
|
||||
void (*remove_by_idx_fcn_u) (NMSetting *setting, guint idx);
|
||||
void (*remove_by_idx_fcn_s) (NMSetting *setting, int idx);
|
||||
bool delimit_pretty_with_semicolon:1;
|
||||
bool strsplit_plain:1;
|
||||
} objlist;
|
||||
struct {
|
||||
gboolean (*set_fcn) (NMSetting *setting,
|
||||
const char *option,
|
||||
const char *value,
|
||||
GError **error);
|
||||
bool no_empty_value:1;
|
||||
} optionlist;
|
||||
struct {
|
||||
guint32 (*get_fcn) (NMSetting *setting);
|
||||
} mtu;
|
||||
struct {
|
||||
NMSetting8021xSchemeType scheme_type;
|
||||
} cert_8021x;
|
||||
struct {
|
||||
NMMetaPropertyTypeMacMode mode;
|
||||
} mac;
|
||||
struct {
|
||||
guint (*get_fcn) (NMSettingDcb *setting,
|
||||
guint user_priority);
|
||||
void (*set_fcn) (NMSettingDcb *setting,
|
||||
guint id,
|
||||
guint value);
|
||||
guint max;
|
||||
guint other;
|
||||
bool is_percent:1;
|
||||
} dcb;
|
||||
struct {
|
||||
gboolean (*get_fcn) (NMSettingDcb *s_dcb,
|
||||
guint priority);
|
||||
void (*set_fcn) (NMSettingDcb *setting,
|
||||
guint user_priority,
|
||||
gboolean enabled);
|
||||
bool with_flow_control_flags:1;
|
||||
} dcb_bool;
|
||||
struct {
|
||||
NMEthtoolID ethtool_id;
|
||||
} ethtool;
|
||||
} subtype;
|
||||
gboolean (*is_default_fcn) (NMSetting *setting);
|
||||
const char *const*values_static;
|
||||
const NMMetaPropertyTypDataNested *nested;
|
||||
NMMetaPropertyTypFlags typ_flags;
|
||||
gboolean (*add_fcn)(NMSetting *setting, const char *item);
|
||||
void (*add2_fcn)(NMSetting *setting, const char *item);
|
||||
const char *(*validate_fcn)(const char *item, GError **error);
|
||||
const char *(*validate2_fcn)(NMSetting *setting, const char *item, GError **error);
|
||||
void (*remove_by_idx_fcn_u32)(NMSetting *setting, guint32 idx);
|
||||
void (*remove_by_idx_fcn_u)(NMSetting *setting, guint idx);
|
||||
void (*remove_by_idx_fcn_s)(NMSetting *setting, int idx);
|
||||
gboolean (*remove_by_value_fcn)(NMSetting *setting, const char *item);
|
||||
bool strsplit_plain : 1;
|
||||
bool strsplit_with_spaces : 1;
|
||||
} multilist;
|
||||
struct {
|
||||
guint (*get_num_fcn)(NMSetting *setting);
|
||||
void (*obj_to_str_fcn)(NMMetaAccessorGetType get_type,
|
||||
NMSetting * setting,
|
||||
guint idx,
|
||||
GString * str);
|
||||
gboolean (*set_fcn)(NMSetting * setting,
|
||||
gboolean do_add /* or else remove. */,
|
||||
const char *value,
|
||||
GError ** error);
|
||||
void (*clear_all_fcn)(NMSetting *setting);
|
||||
void (*remove_by_idx_fcn_u)(NMSetting *setting, guint idx);
|
||||
void (*remove_by_idx_fcn_s)(NMSetting *setting, int idx);
|
||||
bool delimit_pretty_with_semicolon : 1;
|
||||
bool strsplit_plain : 1;
|
||||
} objlist;
|
||||
struct {
|
||||
gboolean (*set_fcn)(NMSetting * setting,
|
||||
const char *option,
|
||||
const char *value,
|
||||
GError ** error);
|
||||
bool no_empty_value : 1;
|
||||
} optionlist;
|
||||
struct {
|
||||
guint32 (*get_fcn)(NMSetting *setting);
|
||||
} mtu;
|
||||
struct {
|
||||
NMSetting8021xSchemeType scheme_type;
|
||||
} cert_8021x;
|
||||
struct {
|
||||
NMMetaPropertyTypeMacMode mode;
|
||||
} mac;
|
||||
struct {
|
||||
guint (*get_fcn)(NMSettingDcb *setting, guint user_priority);
|
||||
void (*set_fcn)(NMSettingDcb *setting, guint id, guint value);
|
||||
guint max;
|
||||
guint other;
|
||||
bool is_percent : 1;
|
||||
} dcb;
|
||||
struct {
|
||||
gboolean (*get_fcn)(NMSettingDcb *s_dcb, guint priority);
|
||||
void (*set_fcn)(NMSettingDcb *setting, guint user_priority, gboolean enabled);
|
||||
bool with_flow_control_flags : 1;
|
||||
} dcb_bool;
|
||||
struct {
|
||||
NMEthtoolID ethtool_id;
|
||||
} ethtool;
|
||||
} subtype;
|
||||
gboolean (*is_default_fcn)(NMSetting *setting);
|
||||
const char *const * values_static;
|
||||
const NMMetaPropertyTypDataNested *nested;
|
||||
NMMetaPropertyTypFlags typ_flags;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NM_META_PROPERTY_INF_FLAG_NONE = 0x00,
|
||||
NM_META_PROPERTY_INF_FLAG_REQD = 0x01, /* Don't ask to ask. */
|
||||
NM_META_PROPERTY_INF_FLAG_DONT_ASK = 0x02, /* Don't ask interactively by default */
|
||||
NM_META_PROPERTY_INF_FLAG_MULTI = 0x04, /* Ask multiple times, do an append instead of set. */
|
||||
NM_META_PROPERTY_INF_FLAG_NONE = 0x00,
|
||||
NM_META_PROPERTY_INF_FLAG_REQD = 0x01, /* Don't ask to ask. */
|
||||
NM_META_PROPERTY_INF_FLAG_DONT_ASK = 0x02, /* Don't ask interactively by default */
|
||||
NM_META_PROPERTY_INF_FLAG_MULTI = 0x04, /* Ask multiple times, do an append instead of set. */
|
||||
} NMMetaPropertyInfFlags;
|
||||
|
||||
enum {
|
||||
_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE = 0,
|
||||
_NM_META_PROPERTY_TYPE_CONNECTION_TYPE = 3,
|
||||
_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE = 0,
|
||||
_NM_META_PROPERTY_TYPE_CONNECTION_TYPE = 3,
|
||||
};
|
||||
|
||||
#define nm_meta_property_info_connection_type (nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION].properties[_NM_META_PROPERTY_TYPE_CONNECTION_TYPE])
|
||||
#define nm_meta_property_info_vpn_service_type (nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_VPN].properties[_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE])
|
||||
#define nm_meta_property_info_connection_type \
|
||||
(nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION] \
|
||||
.properties[_NM_META_PROPERTY_TYPE_CONNECTION_TYPE])
|
||||
#define nm_meta_property_info_vpn_service_type \
|
||||
(nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_VPN] \
|
||||
.properties[_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE])
|
||||
|
||||
struct _NMMetaPropertyInfo {
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
|
||||
const NMMetaSettingInfoEditor *setting_info;
|
||||
const NMMetaSettingInfoEditor *setting_info;
|
||||
|
||||
const char *property_name;
|
||||
const char *property_name;
|
||||
|
||||
const char *property_alias;
|
||||
const char *property_alias;
|
||||
|
||||
NMMetaPropertyInfFlags inf_flags;
|
||||
bool is_secret:1;
|
||||
NMMetaPropertyInfFlags inf_flags;
|
||||
bool is_secret : 1;
|
||||
|
||||
bool is_cli_option:1;
|
||||
bool is_cli_option : 1;
|
||||
bool hide_if_default : 1;
|
||||
|
||||
const char *prompt;
|
||||
const char *prompt;
|
||||
|
||||
const char *def_hint;
|
||||
const char *def_hint;
|
||||
|
||||
const char *describe_doc;
|
||||
const char *describe_doc;
|
||||
|
||||
/* a non-translated but translatable static description (marked with N_()). */
|
||||
const char *describe_message;
|
||||
/* a non-translated but translatable static description (marked with N_()). */
|
||||
const char *describe_message;
|
||||
|
||||
const NMMetaPropertyType *property_type;
|
||||
const NMMetaPropertyTypData *property_typ_data;
|
||||
const NMMetaPropertyType * property_type;
|
||||
const NMMetaPropertyTypData *property_typ_data;
|
||||
};
|
||||
|
||||
typedef struct _NMMetaSettingValidPartItem {
|
||||
const NMMetaSettingInfoEditor *setting_info;
|
||||
bool mandatory;
|
||||
const NMMetaSettingInfoEditor *setting_info;
|
||||
bool mandatory;
|
||||
} NMMetaSettingValidPartItem;
|
||||
|
||||
struct _NMMetaSettingInfoEditor {
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
const NMMetaSettingInfo *general;
|
||||
const char *alias;
|
||||
const char *pretty_name;
|
||||
const NMMetaPropertyInfo *const*properties;
|
||||
guint properties_num;
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
const NMMetaSettingInfo * general;
|
||||
const char * alias;
|
||||
const char * pretty_name;
|
||||
const NMMetaPropertyInfo *const *properties;
|
||||
guint properties_num;
|
||||
|
||||
/* a NMConnection has a main type (connection.type), which is a
|
||||
* main NMSetting instance. Depending on the type, a connection
|
||||
* may have a list of other allowed settings.
|
||||
*
|
||||
* For example, a connection of type "vlan" may have settings
|
||||
* of type "connection", "vlan", and "wired".
|
||||
*
|
||||
* Some setting types a not a main type (NMSettingProxy). They
|
||||
* don't have valid_settings but are usually referenced by other
|
||||
* settings to be valid for them. */
|
||||
const NMMetaSettingValidPartItem *const*valid_parts;
|
||||
/* a NMConnection has a main type (connection.type), which is a
|
||||
* main NMSetting instance. Depending on the type, a connection
|
||||
* may have a list of other allowed settings.
|
||||
*
|
||||
* For example, a connection of type "vlan" may have settings
|
||||
* of type "connection", "vlan", and "wired".
|
||||
*
|
||||
* Some setting types a not a main type (NMSettingProxy). They
|
||||
* don't have valid_settings but are usually referenced by other
|
||||
* settings to be valid for them. */
|
||||
const NMMetaSettingValidPartItem *const *valid_parts;
|
||||
|
||||
void (*setting_init_fcn) (const NMMetaSettingInfoEditor *setting_info,
|
||||
NMSetting *setting,
|
||||
NMMetaAccessorSettingInitType init_type);
|
||||
void (*setting_init_fcn)(const NMMetaSettingInfoEditor *setting_info,
|
||||
NMSetting * setting,
|
||||
NMMetaAccessorSettingInitType init_type);
|
||||
};
|
||||
|
||||
struct _NMMetaType {
|
||||
NMObjBaseClass parent;
|
||||
const char *type_name;
|
||||
const char *(*get_name) (const NMMetaAbstractInfo *abstract_info,
|
||||
gboolean for_header);
|
||||
const NMMetaAbstractInfo *const*(*get_nested) (const NMMetaAbstractInfo *abstract_info,
|
||||
guint *out_len,
|
||||
gpointer *out_to_free);
|
||||
gconstpointer (*get_fcn) (const NMMetaAbstractInfo *info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
gpointer target,
|
||||
gpointer target_data,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gboolean *out_is_default,
|
||||
gpointer *out_to_free);
|
||||
const char *const*(*complete_fcn) (const NMMetaAbstractInfo *info,
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
const NMMetaOperationContext *operation_context,
|
||||
const char *text,
|
||||
gboolean *out_complete_filename,
|
||||
char ***out_to_free);
|
||||
NMObjBaseClass parent;
|
||||
const char * type_name;
|
||||
const char *(*get_name)(const NMMetaAbstractInfo *abstract_info, gboolean for_header);
|
||||
const NMMetaAbstractInfo *const *(*get_nested)(const NMMetaAbstractInfo *abstract_info,
|
||||
guint * out_len,
|
||||
gpointer * out_to_free);
|
||||
gconstpointer (*get_fcn)(const NMMetaAbstractInfo * info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
gpointer target,
|
||||
gpointer target_data,
|
||||
NMMetaAccessorGetType get_type,
|
||||
NMMetaAccessorGetFlags get_flags,
|
||||
NMMetaAccessorGetOutFlags *out_flags,
|
||||
gboolean * out_is_default,
|
||||
gpointer * out_to_free);
|
||||
const char *const *(*complete_fcn)(const NMMetaAbstractInfo * info,
|
||||
const NMMetaEnvironment * environment,
|
||||
gpointer environment_user_data,
|
||||
const NMMetaOperationContext *operation_context,
|
||||
const char * text,
|
||||
gboolean * out_complete_filename,
|
||||
char *** out_to_free);
|
||||
};
|
||||
|
||||
struct _NMMetaAbstractInfo {
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
union {
|
||||
NMObjBaseInst parent;
|
||||
const NMMetaType *meta_type;
|
||||
};
|
||||
};
|
||||
|
||||
extern const NMMetaType nm_meta_type_setting_info_editor;
|
||||
|
|
@ -464,13 +473,15 @@ extern const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[_NM_META_SETTI
|
|||
|
||||
extern const NMMetaSettingValidPartItem *const nm_meta_setting_info_valid_parts_default[];
|
||||
|
||||
const NMMetaSettingValidPartItem *const*nm_meta_setting_info_valid_parts_for_slave_type (const char *slave_type, const char **out_slave_name);
|
||||
const NMMetaSettingValidPartItem *const *
|
||||
nm_meta_setting_info_valid_parts_for_slave_type(const char * slave_type,
|
||||
const char **out_slave_name);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
NM_META_ENV_WARN_LEVEL_INFO,
|
||||
NM_META_ENV_WARN_LEVEL_WARN,
|
||||
NM_META_ENV_WARN_LEVEL_INFO,
|
||||
NM_META_ENV_WARN_LEVEL_WARN,
|
||||
} NMMetaEnvWarnLevel;
|
||||
|
||||
/* the settings-meta data is supposed to be independent of an actual client
|
||||
|
|
@ -478,21 +489,21 @@ typedef enum {
|
|||
* The meta-data handlers may call back to the environment with certain
|
||||
* actions. */
|
||||
struct _NMMetaEnvironment {
|
||||
void (*warn_fcn)(
|
||||
const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
NMMetaEnvWarnLevel warn_level,
|
||||
const char *
|
||||
fmt_l10n, /* the untranslated format string, but it is marked for translation using N_(). */
|
||||
va_list ap);
|
||||
|
||||
void (*warn_fcn) (const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
NMMetaEnvWarnLevel warn_level,
|
||||
const char *fmt_l10n, /* the untranslated format string, but it is marked for translation using N_(). */
|
||||
va_list ap);
|
||||
|
||||
struct _NMDevice *const*(*get_nm_devices) (const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
guint *out_len);
|
||||
|
||||
struct _NMRemoteConnection *const*(*get_nm_connections) (const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
guint *out_len);
|
||||
struct _NMDevice *const *(*get_nm_devices)(const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
guint * out_len);
|
||||
|
||||
struct _NMRemoteConnection *const *(*get_nm_connections)(const NMMetaEnvironment *environment,
|
||||
gpointer environment_user_data,
|
||||
guint * out_len);
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -503,20 +514,27 @@ struct _NMMetaEnvironment {
|
|||
|
||||
extern const NMMetaType nm_meta_type_nested_property_info;
|
||||
|
||||
struct _NMMetaNestedPropertyInfo {
|
||||
union {
|
||||
const NMMetaType *meta_type;
|
||||
NMMetaPropertyInfo base;
|
||||
};
|
||||
const NMMetaPropertyInfo *parent_info;
|
||||
struct _NMMetaNestedPropertyInfo {
|
||||
union {
|
||||
const NMMetaType * meta_type;
|
||||
NMMetaPropertyInfo base;
|
||||
};
|
||||
const NMMetaPropertyInfo *parent_info;
|
||||
};
|
||||
|
||||
struct _NMMetaPropertyTypDataNested {
|
||||
const NMMetaNestedPropertyInfo *nested;
|
||||
guint nested_len;
|
||||
struct _NMMetaPropertyTypDataNested {
|
||||
const NMMetaNestedPropertyInfo *nested;
|
||||
guint nested_len;
|
||||
};
|
||||
|
||||
const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond;
|
||||
extern const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean _nm_meta_setting_bond_add_option(NMSetting * setting,
|
||||
const char *name,
|
||||
const char *value,
|
||||
GError ** error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -6,133 +6,28 @@
|
|||
#ifndef __NM_POLKIT_LISTENER_H__
|
||||
#define __NM_POLKIT_LISTENER_H__
|
||||
|
||||
#if WITH_POLKIT_AGENT
|
||||
#define NM_POLKIT_LISTENER_SIGNAL_REGISTERED "registered"
|
||||
#define NM_POLKIT_LISTENER_SIGNAL_REQUEST_SYNC "request-sync"
|
||||
#define NM_POLKIT_LISTENER_SIGNAL_AUTH_SUCCESS "auth-success"
|
||||
#define NM_POLKIT_LISTENER_SIGNAL_AUTH_FAILURE "auth-failure"
|
||||
#define NM_POLKIT_LISTENER_SIGNAL_ERROR "error"
|
||||
|
||||
typedef struct _NMPolkitListener NMPolkitListener;
|
||||
typedef struct _NMPolkitListener NMPolkitListener;
|
||||
typedef struct _NMPolkitListenerClass NMPolkitListenerClass;
|
||||
|
||||
typedef struct {
|
||||
#define NM_TYPE_POLKIT_LISTENER (nm_polkit_listener_get_type())
|
||||
#define NM_POLKIT_LISTENER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListener))
|
||||
#define NM_POLKIT_LISTENER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass))
|
||||
#define NM_IS_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_POLKIT_LISTENER))
|
||||
#define NM_IS_POLKIT_LISTENER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_POLKIT_LISTENER))
|
||||
#define NM_POLKIT_LISTENER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass))
|
||||
|
||||
/*
|
||||
* @request: the request asked by polkit agent
|
||||
* @action_id: the action_id of the polkit request
|
||||
* @message: the message of the polkit request
|
||||
* @icon_name: the icon name of the polkit request
|
||||
* @user: user name
|
||||
* @echo_on: whether the response to the request should be echoed to the screen
|
||||
* @user_data: user data for the callback
|
||||
*
|
||||
* Called as a result of a request by polkit. The function should obtain response
|
||||
* to the request from user, i.e. get the password required.
|
||||
*/
|
||||
char *(*on_request) (NMPolkitListener *self,
|
||||
const char *request,
|
||||
const char *action_id,
|
||||
const char *message,
|
||||
const char *icon_name,
|
||||
const char *user,
|
||||
gboolean echo_on,
|
||||
gpointer user_data);
|
||||
GType nm_polkit_listener_get_type(void);
|
||||
|
||||
/*
|
||||
* @text: the info text from polkit
|
||||
*
|
||||
* Called as a result of show-info signal by polkit.
|
||||
*/
|
||||
void (*on_show_info) (NMPolkitListener *self,
|
||||
const char *text,
|
||||
gpointer user_data);
|
||||
|
||||
/*
|
||||
* @text: the error text from polkit
|
||||
*
|
||||
* Called as a result of show-error signal by polkit.
|
||||
*/
|
||||
void (*on_show_error) (NMPolkitListener *self,
|
||||
const char *text,
|
||||
gpointer user_data);
|
||||
|
||||
/*
|
||||
* @gained_authorization: whether the authorization was successful
|
||||
*
|
||||
* Called as a result of completed signal by polkit.
|
||||
*/
|
||||
void (*on_completed) (NMPolkitListener *self,
|
||||
gboolean gained_authorization,
|
||||
gpointer user_data);
|
||||
} NMPolkitListenVtable;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <polkitagent/polkitagent.h>
|
||||
|
||||
#define NM_TYPE_POLKIT_LISTENER (nm_polkit_listener_get_type ())
|
||||
#define NM_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListener))
|
||||
#define NM_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass))
|
||||
#define NM_IS_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_POLKIT_LISTENER))
|
||||
#define NM_IS_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_POLKIT_LISTENER))
|
||||
#define NM_POLKIT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass))
|
||||
|
||||
/**
|
||||
* NMPolkitListenerOnRequestFunc:
|
||||
* @request: the request asked by polkit agent
|
||||
* @action_id: the action_id of the polkit request
|
||||
* @message: the message of the polkit request
|
||||
* @icon_name: the icon name of the polkit request
|
||||
* @user: user name
|
||||
* @echo_on: whether the response to the request should be echoed to the screen
|
||||
* @user_data: user data for the callback
|
||||
*
|
||||
* Called as a result of a request by polkit. The function should obtain response
|
||||
* to the request from user, i.e. get the password required.
|
||||
*/
|
||||
typedef char * (*NMPolkitListenerOnRequestFunc) (const char *request,
|
||||
const char *action_id,
|
||||
const char *message,
|
||||
const char *icon_name,
|
||||
const char *user,
|
||||
gboolean echo_on,
|
||||
gpointer user_data);
|
||||
/**
|
||||
* NMPolkitListenerOnShowInfoFunc:
|
||||
* @text: the info text from polkit
|
||||
*
|
||||
* Called as a result of show-info signal by polkit.
|
||||
*/
|
||||
typedef void (*NMPolkitListenerOnShowInfoFunc) (const char *text);
|
||||
/**
|
||||
* NMPolkitListenerOnShowErrorFunc:
|
||||
* @text: the error text from polkit
|
||||
*
|
||||
* Called as a result of show-error signal by polkit.
|
||||
*/
|
||||
typedef void (*NMPolkitListenerOnShowErrorFunc) (const char *text);
|
||||
/**
|
||||
* NMPolkitListenerCompletedFunc:
|
||||
* @gained_authorization: whether the authorization was successful
|
||||
*
|
||||
* Called as a result of completed signal by polkit.
|
||||
*/
|
||||
typedef void (*NMPolkitListenerOnCompletedFunc) (gboolean gained_authorization);
|
||||
|
||||
struct _NMPolkitListener {
|
||||
PolkitAgentListener parent;
|
||||
};
|
||||
|
||||
struct _NMPolkitListenerClass {
|
||||
PolkitAgentListenerClass parent;
|
||||
};
|
||||
|
||||
GType nm_polkit_listener_get_type (void);
|
||||
|
||||
NMPolkitListener *nm_polkit_listener_new (gboolean for_session,
|
||||
GError **error);
|
||||
|
||||
void nm_polkit_listener_set_vtable (NMPolkitListener *self,
|
||||
const NMPolkitListenVtable *vtable,
|
||||
gpointer user_data);
|
||||
|
||||
#endif
|
||||
NMPolkitListener *nm_polkit_listener_new(GDBusConnection *dbus_connection, gboolean session_agent);
|
||||
|
||||
#endif /* __NM_POLKIT_LISTENER_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 - 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -9,49 +9,53 @@
|
|||
#include "nm-secret-agent-old.h"
|
||||
|
||||
typedef enum {
|
||||
NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_SECRET,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_PROPERTY,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_SECRET,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET,
|
||||
NM_SECRET_AGENT_SECRET_TYPE_WIREGUARD_PEER_PSK,
|
||||
} NMSecretAgentSecretType;
|
||||
|
||||
typedef struct {
|
||||
NMSecretAgentSecretType secret_type;
|
||||
const char *pretty_name;
|
||||
const char *entry_id;
|
||||
char *value;
|
||||
const char *vpn_type;
|
||||
bool is_secret:1;
|
||||
bool no_prompt_entry_id:1;
|
||||
NMSecretAgentSecretType secret_type;
|
||||
const char * pretty_name;
|
||||
const char * entry_id;
|
||||
char * value;
|
||||
const char * vpn_type;
|
||||
bool is_secret : 1;
|
||||
bool no_prompt_entry_id : 1;
|
||||
} NMSecretAgentSimpleSecret;
|
||||
|
||||
#define NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS "vpn.secrets."
|
||||
|
||||
#define NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT NM_DBUS_INTERFACE".openconnect"
|
||||
#define NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT NM_DBUS_INTERFACE ".openconnect"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_SECRET_AGENT_SIMPLE (nm_secret_agent_simple_get_type ())
|
||||
#define NM_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimple))
|
||||
#define NM_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass))
|
||||
#define NM_IS_SECRET_AGENT_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SECRET_AGENT_SIMPLE))
|
||||
#define NM_IS_SECRET_AGENT_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT_SIMPLE))
|
||||
#define NM_SECRET_AGENT_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass))
|
||||
#define NM_TYPE_SECRET_AGENT_SIMPLE (nm_secret_agent_simple_get_type())
|
||||
#define NM_SECRET_AGENT_SIMPLE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimple))
|
||||
#define NM_SECRET_AGENT_SIMPLE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass))
|
||||
#define NM_IS_SECRET_AGENT_SIMPLE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SECRET_AGENT_SIMPLE))
|
||||
#define NM_IS_SECRET_AGENT_SIMPLE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SECRET_AGENT_SIMPLE))
|
||||
#define NM_SECRET_AGENT_SIMPLE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SECRET_AGENT_SIMPLE, NMSecretAgentSimpleClass))
|
||||
|
||||
#define NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS "request-secrets"
|
||||
#define NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS "request-secrets"
|
||||
|
||||
typedef struct _NMSecretAgentSimple NMSecretAgentSimple;
|
||||
typedef struct _NMSecretAgentSimpleClass NMSecretAgentSimpleClass;
|
||||
|
||||
GType nm_secret_agent_simple_get_type (void);
|
||||
GType nm_secret_agent_simple_get_type(void);
|
||||
|
||||
NMSecretAgentSimple *nm_secret_agent_simple_new (const char *name);
|
||||
NMSecretAgentSimple *nm_secret_agent_simple_new(const char *name);
|
||||
|
||||
void nm_secret_agent_simple_response (NMSecretAgentSimple *self,
|
||||
const char *request_id,
|
||||
GPtrArray *secrets);
|
||||
void nm_secret_agent_simple_response(NMSecretAgentSimple *self,
|
||||
const char * request_id,
|
||||
GPtrArray * secrets);
|
||||
|
||||
void nm_secret_agent_simple_enable (NMSecretAgentSimple *self,
|
||||
const char *path);
|
||||
void nm_secret_agent_simple_enable(NMSecretAgentSimple *self, const char *path);
|
||||
|
||||
#endif /* __NM_SECRET_AGENT_SIMPLE_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 - 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -7,26 +7,25 @@
|
|||
#define __NM_VPN_HELPERS_H__
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *ui_name;
|
||||
} VpnPasswordName;
|
||||
const char *name;
|
||||
const char *ui_name;
|
||||
} NmcVpnPasswordName;
|
||||
|
||||
GSList *nm_vpn_get_plugin_infos (void);
|
||||
GSList *nm_vpn_get_plugin_infos(void);
|
||||
|
||||
NMVpnEditorPlugin *nm_vpn_get_editor_plugin (const char *service_type, GError **error);
|
||||
NMVpnEditorPlugin *nm_vpn_get_editor_plugin(const char *service_type, GError **error);
|
||||
|
||||
gboolean nm_vpn_supports_ipv6 (NMConnection *connection);
|
||||
gboolean nm_vpn_supports_ipv6(NMConnection *connection);
|
||||
|
||||
const VpnPasswordName * nm_vpn_get_secret_names (const char *service_type);
|
||||
const NmcVpnPasswordName *nm_vpn_get_secret_names(const char *service_type);
|
||||
|
||||
gboolean nm_vpn_openconnect_authenticate_helper (const char *host,
|
||||
char **cookie,
|
||||
char **gateway,
|
||||
char **gwcert,
|
||||
int *status,
|
||||
GError **error);
|
||||
gboolean nm_vpn_openconnect_authenticate_helper(const char *host,
|
||||
char ** cookie,
|
||||
char ** gateway,
|
||||
char ** gwcert,
|
||||
int * status,
|
||||
GError ** error);
|
||||
|
||||
NMConnection *nm_vpn_wireguard_import (const char *filename,
|
||||
GError **error);
|
||||
NMConnection *nm_vpn_wireguard_import(const char *filename, GError **error);
|
||||
|
||||
#endif /* __NM_VPN_HELPERS_H__ */
|
||||
#endif /* __NM_VPN_HELPERS_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,12 +27,10 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This library creates QR Code symbols, which is a type of two-dimension barcode.
|
||||
* Invented by Denso Wave and described in the ISO/IEC 18004 standard.
|
||||
|
|
@ -48,53 +46,49 @@ extern "C" {
|
|||
* (Note that all ways require supplying the desired error correction level and various byte buffers.)
|
||||
*/
|
||||
|
||||
|
||||
/*---- Enum and struct types----*/
|
||||
|
||||
/*
|
||||
* The error correction level in a QR Code symbol.
|
||||
*/
|
||||
enum qrcodegen_Ecc {
|
||||
// Must be declared in ascending order of error protection
|
||||
// so that an internal qrcodegen function works properly
|
||||
qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords
|
||||
qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords
|
||||
qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
|
||||
qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords
|
||||
// Must be declared in ascending order of error protection
|
||||
// so that an internal qrcodegen function works properly
|
||||
qrcodegen_Ecc_LOW = 0, // The QR Code can tolerate about 7% erroneous codewords
|
||||
qrcodegen_Ecc_MEDIUM, // The QR Code can tolerate about 15% erroneous codewords
|
||||
qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
|
||||
qrcodegen_Ecc_HIGH, // The QR Code can tolerate about 30% erroneous codewords
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The mask pattern used in a QR Code symbol.
|
||||
*/
|
||||
enum qrcodegen_Mask {
|
||||
// A special value to tell the QR Code encoder to
|
||||
// automatically select an appropriate mask pattern
|
||||
qrcodegen_Mask_AUTO = -1,
|
||||
// The eight actual mask patterns
|
||||
qrcodegen_Mask_0 = 0,
|
||||
qrcodegen_Mask_1,
|
||||
qrcodegen_Mask_2,
|
||||
qrcodegen_Mask_3,
|
||||
qrcodegen_Mask_4,
|
||||
qrcodegen_Mask_5,
|
||||
qrcodegen_Mask_6,
|
||||
qrcodegen_Mask_7,
|
||||
// A special value to tell the QR Code encoder to
|
||||
// automatically select an appropriate mask pattern
|
||||
qrcodegen_Mask_AUTO = -1,
|
||||
// The eight actual mask patterns
|
||||
qrcodegen_Mask_0 = 0,
|
||||
qrcodegen_Mask_1,
|
||||
qrcodegen_Mask_2,
|
||||
qrcodegen_Mask_3,
|
||||
qrcodegen_Mask_4,
|
||||
qrcodegen_Mask_5,
|
||||
qrcodegen_Mask_6,
|
||||
qrcodegen_Mask_7,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Describes how a segment's data bits are interpreted.
|
||||
*/
|
||||
enum qrcodegen_Mode {
|
||||
qrcodegen_Mode_NUMERIC = 0x1,
|
||||
qrcodegen_Mode_ALPHANUMERIC = 0x2,
|
||||
qrcodegen_Mode_BYTE = 0x4,
|
||||
qrcodegen_Mode_KANJI = 0x8,
|
||||
qrcodegen_Mode_ECI = 0x7,
|
||||
qrcodegen_Mode_NUMERIC = 0x1,
|
||||
qrcodegen_Mode_ALPHANUMERIC = 0x2,
|
||||
qrcodegen_Mode_BYTE = 0x4,
|
||||
qrcodegen_Mode_KANJI = 0x8,
|
||||
qrcodegen_Mode_ECI = 0x7,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A segment of character/binary/control data in a QR Code symbol.
|
||||
* The mid-level way to create a segment is to take the payload data
|
||||
|
|
@ -107,43 +101,41 @@ enum qrcodegen_Mode {
|
|||
* the largest QR Code (version 40) has 31329 modules.
|
||||
*/
|
||||
struct qrcodegen_Segment {
|
||||
// The mode indicator of this segment.
|
||||
enum qrcodegen_Mode mode;
|
||||
// The mode indicator of this segment.
|
||||
enum qrcodegen_Mode mode;
|
||||
|
||||
// The length of this segment's unencoded data. Measured in characters for
|
||||
// numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
|
||||
// Always zero or positive. Not the same as the data's bit length.
|
||||
int numChars;
|
||||
// The length of this segment's unencoded data. Measured in characters for
|
||||
// numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
|
||||
// Always zero or positive. Not the same as the data's bit length.
|
||||
int numChars;
|
||||
|
||||
// The data bits of this segment, packed in bitwise big endian.
|
||||
// Can be null if the bit length is zero.
|
||||
uint8_t *data;
|
||||
// The data bits of this segment, packed in bitwise big endian.
|
||||
// Can be null if the bit length is zero.
|
||||
uint8_t *data;
|
||||
|
||||
// The number of valid data bits used in the buffer. Requires
|
||||
// 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8.
|
||||
// The character count (numChars) must agree with the mode and the bit buffer length.
|
||||
int bitLength;
|
||||
// The number of valid data bits used in the buffer. Requires
|
||||
// 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8.
|
||||
// The character count (numChars) must agree with the mode and the bit buffer length.
|
||||
int bitLength;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*---- Macro constants and functions ----*/
|
||||
|
||||
#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard
|
||||
#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard
|
||||
#define qrcodegen_VERSION_MIN \
|
||||
1 // The minimum version number supported in the QR Code Model 2 standard
|
||||
#define qrcodegen_VERSION_MAX \
|
||||
40 // The maximum version number supported in the QR Code Model 2 standard
|
||||
|
||||
// Calculates the number of bytes needed to store any QR Code up to and including the given version number,
|
||||
// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];'
|
||||
// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16).
|
||||
// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX.
|
||||
#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1)
|
||||
#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) *4 + 17) * ((n) *4 + 17) + 7) / 8 + 1)
|
||||
|
||||
// The worst-case number of bytes needed to store one QR Code, up to and including
|
||||
// version 40. This value equals 3918, which is just under 4 kilobytes.
|
||||
// Use this more convenient value to avoid calculating tighter memory bounds for buffers.
|
||||
#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)
|
||||
|
||||
|
||||
#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)
|
||||
|
||||
/*---- Functions (high level) to generate QR Codes ----*/
|
||||
|
||||
|
|
@ -166,9 +158,14 @@ struct qrcodegen_Segment {
|
|||
* - Please consult the QR Code specification for information on
|
||||
* data capacities per version, ECC level, and text encoding mode.
|
||||
*/
|
||||
bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[],
|
||||
enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
|
||||
|
||||
bool qrcodegen_encodeText(const char * text,
|
||||
uint8_t tempBuffer[],
|
||||
uint8_t qrcode[],
|
||||
enum qrcodegen_Ecc ecl,
|
||||
int minVersion,
|
||||
int maxVersion,
|
||||
enum qrcodegen_Mask mask,
|
||||
bool boostEcl);
|
||||
|
||||
/*
|
||||
* Encodes the given binary data to a QR Code, returning true if encoding succeeded.
|
||||
|
|
@ -188,9 +185,14 @@ bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode
|
|||
* - Please consult the QR Code specification for information on
|
||||
* data capacities per version, ECC level, and text encoding mode.
|
||||
*/
|
||||
bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[],
|
||||
enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
|
||||
|
||||
bool qrcodegen_encodeBinary(uint8_t dataAndTemp[],
|
||||
size_t dataLen,
|
||||
uint8_t qrcode[],
|
||||
enum qrcodegen_Ecc ecl,
|
||||
int minVersion,
|
||||
int maxVersion,
|
||||
enum qrcodegen_Mask mask,
|
||||
bool boostEcl);
|
||||
|
||||
/*---- Functions (low level) to generate QR Codes ----*/
|
||||
|
||||
|
|
@ -206,9 +208,11 @@ bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcod
|
|||
* result in them being clobbered, but the QR Code output will still be correct.
|
||||
* But the qrcode array must not overlap tempBuffer or any segment's data buffer.
|
||||
*/
|
||||
bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len,
|
||||
enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]);
|
||||
|
||||
bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[],
|
||||
size_t len,
|
||||
enum qrcodegen_Ecc ecl,
|
||||
uint8_t tempBuffer[],
|
||||
uint8_t qrcode[]);
|
||||
|
||||
/*
|
||||
* Renders a QR Code representing the given segments with the given encoding parameters.
|
||||
|
|
@ -225,9 +229,15 @@ bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len,
|
|||
* result in them being clobbered, but the QR Code output will still be correct.
|
||||
* But the qrcode array must not overlap tempBuffer or any segment's data buffer.
|
||||
*/
|
||||
bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl,
|
||||
int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]);
|
||||
|
||||
bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[],
|
||||
size_t len,
|
||||
enum qrcodegen_Ecc ecl,
|
||||
int minVersion,
|
||||
int maxVersion,
|
||||
int mask,
|
||||
bool boostEcl,
|
||||
uint8_t tempBuffer[],
|
||||
uint8_t qrcode[]);
|
||||
|
||||
/*
|
||||
* Tests whether the given string can be encoded as a segment in alphanumeric mode.
|
||||
|
|
@ -236,14 +246,12 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz
|
|||
*/
|
||||
bool qrcodegen_isAlphanumeric(const char *text);
|
||||
|
||||
|
||||
/*
|
||||
* Tests whether the given string can be encoded as a segment in numeric mode.
|
||||
* A string is encodable iff each character is in the range 0 to 9.
|
||||
*/
|
||||
bool qrcodegen_isNumeric(const char *text);
|
||||
|
||||
|
||||
/*
|
||||
* Returns the number of bytes (uint8_t) needed for the data buffer of a segment
|
||||
* containing the given number of characters using the given mode. Notes:
|
||||
|
|
@ -257,7 +265,6 @@ bool qrcodegen_isNumeric(const char *text);
|
|||
*/
|
||||
size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars);
|
||||
|
||||
|
||||
/*
|
||||
* Returns a segment representing the given binary data encoded in
|
||||
* byte mode. All input byte arrays are acceptable. Any text string
|
||||
|
|
@ -265,13 +272,11 @@ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars
|
|||
*/
|
||||
struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]);
|
||||
|
||||
|
||||
/*
|
||||
* Returns a segment representing the given string of decimal digits encoded in numeric mode.
|
||||
*/
|
||||
struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]);
|
||||
|
||||
|
||||
/*
|
||||
* Returns a segment representing the given text string encoded in alphanumeric mode.
|
||||
* The characters allowed are: 0 to 9, A to Z (uppercase only), space,
|
||||
|
|
@ -279,14 +284,12 @@ struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]
|
|||
*/
|
||||
struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]);
|
||||
|
||||
|
||||
/*
|
||||
* Returns a segment representing an Extended Channel Interpretation
|
||||
* (ECI) designator with the given assignment value.
|
||||
*/
|
||||
struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]);
|
||||
|
||||
|
||||
/*---- Functions to extract raw data from QR Codes ----*/
|
||||
|
||||
/*
|
||||
|
|
@ -297,7 +300,6 @@ struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]);
|
|||
*/
|
||||
int qrcodegen_getSize(const uint8_t qrcode[]);
|
||||
|
||||
|
||||
/*
|
||||
* Returns the color of the module (pixel) at the given coordinates, which is false
|
||||
* for white or true for black. The top left corner has the coordinates (x=0, y=0).
|
||||
|
|
@ -305,7 +307,6 @@ int qrcodegen_getSize(const uint8_t qrcode[]);
|
|||
*/
|
||||
bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_CHANNEL N_("Channel on which the mesh network to join is located.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS N_("Anycast DHCP MAC address used when requesting an IP address via DHCP. The specific anycast address used determines which DHCP server class answers the request.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OLPC_MESH_SSID N_("SSID of the mesh network to join.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_AP_ISOLATION N_("Configures AP isolation, which prevents communication between wireless devices connected to this AP. This property can be set to a value different from NM_TERNARY_DEFAULT (-1) only when the interface is configured in AP mode. If set to NM_TERNARY_TRUE (1), devices are not able to communicate with each other. This increases security because it protects devices against attacks from other clients in the network. At the same time, it prevents devices to access resources on the same wireless networks as file shares, printers, etc. If set to NM_TERNARY_FALSE (0), devices can talk to each other. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_FALSE (0).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BAND N_("802.11 frequency band of the network. One of \"a\" for 5GHz 802.11a or \"bg\" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible. This setting depends on specific driver capability and may not work with all drivers.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_BSSID N_("If specified, directs the device to only associate with the given access point. This capability is highly driver dependent and not supported by all devices. Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CHANNEL N_("Wireless channel to use for the Wi-Fi connection. The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. Because channel numbers overlap between bands, this property also requires the \"band\" property to be set.")
|
||||
|
|
@ -24,7 +25,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_AUTH_ALG N_("When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the 802.11 authentication algorithm required by the AP here. One of \"open\" for Open System, \"shared\" for Shared Key, or \"leap\" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\") the \"leap-username\" and \"leap-password\" properties must be specified.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_FILS N_("Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_GROUP N_("A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection. One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-psk\" (infrastructure WPA-PSK), \"sae\" (SAE) or \"wpa-eap\" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_KEY_MGMT N_("Key management used for the connection. One of \"none\" (WEP), \"ieee8021x\" (Dynamic WEP), \"wpa-psk\" (infrastructure WPA-PSK), \"sae\" (SAE), \"owe\" (Opportunistic Wireless Encryption), \"wpa-eap\" (WPA-Enterprise) or \"wpa-eap-suite-b-192\" (WPA3-Enterprise Suite B). This property must be set for any Wi-Fi connection that uses security.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD N_("The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS N_("Flags indicating how to handle the \"leap-password\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME N_("The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" and auth-alg = \"leap\").")
|
||||
|
|
@ -44,14 +45,15 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_802_1X_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_ANONYMOUS_IDENTITY N_("Anonymous identity string for EAP authentication methods. Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_AUTH_TIMEOUT N_("A timeout for the authentication. Zero means the global default; if the global default is not set, the authentication timeout is 25 seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT N_("Contains the CA certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT N_("Contains the CA certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; three are currently supported: blob, path and pkcs#11 URL. When using the blob scheme this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended. Note that enabling NMSetting8021x:system-ca-certs will override this setting to use the built-in path, if the built-in path is not a directory.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT_PASSWORD N_("The password used to access the CA certificate stored in \"ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"ca-cert-password\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"ca-cert\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"ca-cert\" property. If NMSetting8021x:system-ca-certs is enabled and the built-in CA path is an existing directory, then this setting is ignored.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT N_("Contains the client certificate if used by the EAP method specified in the \"eap\" property. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD N_("The password used to access the client certificate stored in \"client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"client-cert-password\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_MATCH N_("Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a \";\" delimited list.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a \";\" delimited list.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_EAP N_("The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: \"leap\", \"md5\", \"tls\", \"peap\", \"ttls\", \"pwd\", and \"fast\". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_IDENTITY N_("Identity string for EAP authentication methods. Often the user's user or login name.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_OPTIONAL N_("Whether the 802.1X authentication is optional. If TRUE, the activation will continue even after a timeout or an authentication failure. Setting the property to TRUE is currently allowed only for Ethernet connections. If set to FALSE, the activation can continue only after a successful authentication.")
|
||||
|
|
@ -67,14 +69,15 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If the list is empty, no verification of the server certificate's altSubjectName is performed.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_AUTH N_("Specifies the allowed \"phase 2\" inner non-EAP authentication method when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property. Recognized non-EAP \"phase 2\" methods are \"pap\", \"chap\", \"mschap\", \"mschapv2\", \"gtc\", \"otp\", \"md5\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_AUTHEAP N_("Specifies the allowed \"phase 2\" inner EAP-based authentication method when an EAP method that uses an inner TLS tunnel is specified in the \"eap\" property. Recognized EAP-based \"phase 2\" methods are \"md5\", \"mschapv2\", \"otp\", \"gtc\", and \"tls\". Each \"phase 2\" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT N_("Contains the \"phase 2\" CA certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT N_("Contains the \"phase 2\" CA certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; three are currently supported: blob, path and pkcs#11 URL. When using the blob scheme this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended. Note that enabling NMSetting8021x:system-ca-certs will override this setting to use the built-in path, if the built-in path is not a directory.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD N_("The password used to access the \"phase2\" CA certificate stored in \"phase2-ca-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-ca-cert-password\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"phase2-ca-cert\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CA_PATH N_("UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the \"phase2-ca-cert\" property. If NMSetting8021x:system-ca-certs is enabled and the built-in CA path is an existing directory, then this setting is ignored.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT N_("Contains the \"phase 2\" client certificate if used by the EAP method specified in the \"phase2-auth\" or \"phase2-autheap\" properties. Certificate data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string \"file://\" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD N_("The password used to access the \"phase2\" client certificate stored in \"phase2-client-cert\" property. Only makes sense if the certificate is stored on a PKCS#11 token that requires a login.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-client-cert-password\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH N_("Constraint for server domain name. If set, this list of FQDNs is used as a match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using the same comparison. Multiple valid FQDNs can be passed as a \";\" delimited list.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH N_("Constraint for server domain name. If set, this FQDN is used as a suffix match requirement for dNSName element(s) of the certificate presented by the authentication server during the inner \"phase 2\" authentication. If a matching dNSName is found, this constraint is met. If no dNSName values are present, this constraint is matched against SubjectName CN using same suffix match comparison. Since version 1.24, multiple valid FQDNs can be passed as a \";\" delimited list.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY N_("Contains the \"phase 2\" inner private key when the \"phase2-auth\" or \"phase2-autheap\" property is set to \"tls\". Key data is specified using a \"scheme\"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the \"phase2-private-key-password\" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string \"file://\" and ending with a terminating NUL byte, and as with the blob scheme the \"phase2-private-key-password\" property must be set to the password used to decode the PKCS#12 private key and certificate.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD N_("The password used to decrypt the \"phase 2\" private key specified in the \"phase2-private-key\" property when the private key either uses the path scheme, or is a PKCS#12 format key.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS N_("Flags indicating how to handle the \"phase2-private-key-password\" property.")
|
||||
|
|
@ -112,15 +115,30 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS N_("Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_AGEING_TIME N_("The Ethernet MAC address aging time, in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_FORWARD_DELAY N_("The Spanning Tree Protocol (STP) forwarding delay, in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_ADDRESS N_("If specified, The MAC address of the multicast group this bridge uses for STP. The address must be a link-local address in standard Ethernet MAC address format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If not specified the default value is 01:80:C2:00:00:00.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_FORWARD_MASK N_("A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_HASH_MAX N_("Set maximum size of multicast hash table (value must be a power of 2).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT N_("Set the number of queries the bridge will send before stopping forwarding a multicast group after a \"leave\" message has been received.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL N_("Set interval (in deciseconds) between queries to find remaining members of a group, after a \"leave\" message is received.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL N_("Set delay (in deciseconds) after which the bridge will leave a group, if no membership reports for this group are received.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERIER N_("Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL N_("If no queries are seen after this delay (in deciseconds) has passed, the bridge will start to send its own queries.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL N_("Interval (in deciseconds) between queries sent by the bridge after the end of the startup phase.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL N_("Set the Max Response Time/Max Response Delay (in deciseconds) for IGMP/MLD queries sent by the bridge.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR N_("If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_ROUTER N_("Sets bridge's multicast router. Multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled' to which kernel assigns the numbers 1, 0, and 2, respectively. If not specified the default value is 'auto' (1).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT N_("Set the number of IGMP queries to send during startup phase.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL N_("Sets the time (in deciseconds) between queries sent out at startup to determine membership information.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID N_("The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_FILTERING N_("Control whether VLAN filtering is enabled on the bridge.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_PROTOCOL N_("If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_STATS_ENABLED N_("Controls whether per-VLAN stats accounting is enabled.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.")
|
||||
|
|
@ -131,7 +149,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD N_("The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD_FLAGS N_("Flags indicating how to handle the \"password\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CDMA_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_CONNECTION_AUTH_RETRIES N_("The number of retries for the authentication. Zero means to try indefinitely; -1 means to use a global default. If the global default is not set, the authentication retries for 3 times before failing the connection. Currently this only applies to 802-1x authentication.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTH_RETRIES N_("The number of retries for the authentication. Zero means to try indefinitely; -1 means to use a global default. If the global default is not set, the authentication retries for 3 times before failing the connection. Currently, this only applies to 802-1x authentication.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT N_("Whether or not the connection should be automatically connected by NetworkManager when the resources for the connection are available. TRUE to automatically activate the connection, FALSE to require manual intervention to activate the connection. Note that autoconnect is not implemented for VPN profiles. See \"secondaries\" as an alternative to automatically connect VPN profiles.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY N_("The autoconnect priority. If the connection is set to autoconnect, connections with higher priority will be preferred. Defaults to 0. The higher number means higher priority.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES N_("The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.")
|
||||
|
|
@ -140,20 +158,21 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_ID N_("A human readable unique identifier for the connection, like \"Work Wi-Fi\" or \"T-Mobile 3G\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_INTERFACE_NAME N_("The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_LLDP N_("Whether LLDP is enabled for the connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_LLMNR N_("Whether Link-Local Multicast Name Resolution (LLMNR) is enabled for the connection. LLMNR is a protocol based on the Domain Name System (DNS) packet format that allows both IPv4 and IPv6 hosts to perform name resolution for hosts on the same local link. The permitted values are: yes: register hostname and resolving for the connection, no: disable LLMNR for the interface, resolve: do not register hostname but allow resolving of LLMNR host names. This feature requires a plugin which supports LLMNR. One such plugin is dns-systemd-resolved.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_LLMNR N_("Whether Link-Local Multicast Name Resolution (LLMNR) is enabled for the connection. LLMNR is a protocol based on the Domain Name System (DNS) packet format that allows both IPv4 and IPv6 hosts to perform name resolution for hosts on the same local link. The permitted values are: \"yes\" (2) register hostname and resolving for the connection, \"no\" (0) disable LLMNR for the interface, \"resolve\" (1) do not register hostname but allow resolving of LLMNR host names If unspecified, \"default\" ultimately depends on the DNS plugin (which for systemd-resolved currently means \"yes\"). This feature requires a plugin which supports LLMNR. Otherwise, the setting has no effect. One such plugin is dns-systemd-resolved.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MASTER N_("Interface name of the master device or UUID of the master connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MDNS N_("Whether mDNS is enabled for the connection. The permitted values are: yes: register hostname and resolving for the connection, no: disable mDNS for the interface, resolve: do not register hostname but allow resolving of mDNS host names. This feature requires a plugin which supports mDNS. One such plugin is dns-systemd-resolved.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MDNS N_("Whether mDNS is enabled for the connection. The permitted values are: \"yes\" (2) register hostname and resolving for the connection, \"no\" (0) disable mDNS for the interface, \"resolve\" (1) do not register hostname but allow resolving of mDNS host names and \"default\" (-1) to allow lookup of a global default in NetworkManager.conf. If unspecified, \"default\" ultimately depends on the DNS plugin (which for systemd-resolved currently means \"no\"). This feature requires a plugin which supports mDNS. Otherwise, the setting has no effect. One such plugin is dns-systemd-resolved.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_METERED N_("Whether the connection is metered. When updating this property on a currently activated connection, the change takes effect immediately.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MUD_URL N_("If configured, set to a Manufacturer Usage Description (MUD) URL that points to manufacturer-recommended network policies for IoT devices. It is transmitted as a DHCPv4 or DHCPv6 option. The value must be a valid URL starting with \"https://\". The special value \"none\" is allowed to indicate that no MUD URL is used. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the ultimate default is \"none\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_MULTI_CONNECT N_("Specifies whether the profile can be active multiple times at a particular moment. The value is of type NMConnectionMultiConnect.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_PERMISSIONS N_("An array of strings defining what access a given user has to this connection. If this is NULL or empty, all users are allowed to access this connection; otherwise users are allowed if and only if they are in this list. When this is not empty, the connection can be active only when one of the specified users is logged into an active session. Each entry is of the form \"[type]:[id]:[reserved]\"; for example, \"user:dcbw:blah\". At this time only the \"user\" [type] is allowed. Any other values are ignored and reserved for future use. [id] is the username that this permission refers to, which may not contain the \":\" character. Any [reserved] information present must be ignored and is reserved for future use. All of [type], [id], and [reserved] must be valid UTF-8.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently, only VPN connections are supported.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds to the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret-key. The '$' character is treated special to perform dynamic substitutions at runtime. Currently, supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that \"${DEVICE}\" corresponds to the interface name of the device and \"${MAC}\" is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to \"${CONNECTION}\" and uses a unique, fixed ID for the connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT N_("Timeout in milliseconds to wait for device at startup. During boot, devices may take a while to be detected by the driver. This property will cause to delay NetworkManager-wait-online.service and nm-online to give the device a chance to appear. Note that this property only works together with NMSettingConnection:interface-name to identify the device that will be waited for. The value 0 means no wait time. The default value is -1, which currently has the same meaning as no wait time.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT N_("Timeout in milliseconds to wait for device at startup. During boot, devices may take a while to be detected by the driver. This property will cause to delay NetworkManager-wait-online.service and nm-online to give the device a chance to appear. This works by waiting for the given timeout until a compatible device for the profile is available and managed. The value 0 means no wait time. The default value is -1, which currently has the same meaning as no wait time.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_ZONE N_("The trust level of a the connection. Free form case-insensitive string (for example \"Home\", \"Work\", \"Public\"). NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall. When updating this property on a currently activated connection, the change takes effect immediately.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FCoE application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_MODE N_("The FCoE controller mode; either \"fabric\" (default) or \"vn2vn\".")
|
||||
|
|
@ -184,13 +203,17 @@
|
|||
#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_HOSTNAME_FROM_DHCP N_("Whether the system hostname can be determined from DHCP on this connection. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP N_("Whether the system hostname can be determined from reverse DNS lookup of addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT N_("If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has the default route for the given address family (IPv4/IPv6). If set to NM_TERNARY_FALSE (0), the hostname can be set from this device even if it doesn't have the default route. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_PRIORITY N_("The relative priority of this connection to determine the system hostname. A lower numerical value is better (higher priority). A connection with higher priority is considered before connections with lower priority. If the value is zero, it can be overridden by a global value from NetworkManager configuration. If the property doesn't have a value in the global configuration, the value is assumed to be 100. Negative values have the special effect of excluding other connections with a greater numerical priority value; so in presence of at least one negative priority, only connections with the lowest priority value will be used to determine the hostname.")
|
||||
#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.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_P_KEY N_("The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka \"the P_Key at index 0\"). Otherwise it is a 16-bit unsigned integer, whose high bit is set if it is a \"full membership\" P_Key.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_P_KEY N_("The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka \"the P_Key at index 0\"). Otherwise, it is a 16-bit unsigned integer, whose high bit is set if it is a \"full membership\" P_Key.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_PARENT N_("The interface name of the parent device of this device. Normally NULL, but if the \"p_key\" property is set, then you must specify the base device by setting either this property or \"mac-address\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_TRANSPORT_MODE N_("The IP-over-InfiniBand transport mode. Either \"datagram\" or \"connected\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT N_("How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLAGS N_("Tunnel flags. Currently the following values are supported: NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT (0x1), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS (0x2), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL (0x4), NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV (0x8), NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY (0x10), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). They are valid only for IPv6 tunnels.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLAGS N_("Tunnel flags. Currently, the following values are supported: NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT (0x1), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS (0x2), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL (0x4), NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV (0x8), NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY (0x10), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). They are valid only for IPv6 tunnels.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLOW_LABEL N_("The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_INPUT_KEY N_("The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_LOCAL N_("The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.")
|
||||
|
|
@ -207,15 +230,18 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID N_("A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options. When the property is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which case the first byte is assumed to be the 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC address). If the property is not a hex string it is considered as a non-hardware-address client ID and the 'type' field is set to 0. The special values \"mac\" and \"perm-mac\" are supported, which use the current or permanent MAC address of the device to generate a client identifier with type ethernet (01). Currently, these options only work for ethernet type of links. The special value \"duid\" generates a RFC4361-compliant client identifier based on a hash of the interface name as IAID and /etc/machine-id. The special value \"stable\" is supported to generate a type 0 client identifier based on the stable-id (see connection.stable-id) and a per-host key. If you set the stable-id, you may want to include the \"${DEVICE}\" or \"${MAC}\" specifier to get a per-device key. If unset, a globally configured default is used. If still unset, the default depends on the DHCP plugin.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_FQDN N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-hostname\" are mutually exclusive and cannot be set at the same time.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME_FLAGS N_("Flags for the DHCP hostname and FQDN. Currently, this property only includes flags to control the FQDN flags set in the DHCP FQDN option. Supported FQDN flags are NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) and NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the DHCP FQDN option will contain no flag. Otherwise, if no FQDN flag is set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the standard FQDN flags are set in the request: NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) for IPv4 and NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. When this property is set to the default value NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is looked up in NetworkManager configuration. If that value is unset or also NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags described above are sent in the DHCP requests.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_IAID N_("A string containing the \"Identity Association Identifier\" (IAID) used by the DHCP client. The property is a 32-bit decimal value or a special value among \"mac\", \"perm-mac\", \"ifname\" and \"stable\". When set to \"mac\" (or \"perm-mac\"), the last 4 bytes of the current (or permanent) MAC address are used as IAID. When set to \"ifname\", the IAID is computed by hashing the interface name. The special value \"stable\" can be used to generate an IAID based on the stable-id (see connection.stable-id), a per-host key and the interface name. When the property is unset, the value from global configuration is used; if no global default is set then the IAID is assumed to be \"ifname\". Note that at the moment this property is ignored for IPv6 by dhclient, which always derives the IAID from the MAC address.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. Since 1.28")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"ndots\", \"no-check-names\", \"no-ip6-dotint\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\". The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower numerical value is better (higher priority). Negative values have the special effect of excluding other configurations with a greater numerical priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. To avoid all DNS leaks, set the priority of the profile that should be used to the most negative value of all active connections profiles. Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. Note that commonly the resolver tries name servers in /etc/resolv.conf in the order listed, proceeding with the next server in the list on failure. See for example the \"rotate\" option of the dns-options setting. If there are any negative DNS priorities, then only name servers from the devices with that lowest priority will be considered. When using a DNS resolver that supports Conditional Forwarding or Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection is used to query domains in its search list. The search domains determine which name servers to ask, and the DNS priority is used to prioritize name servers based on the domain. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the best priority (lowest numerical value) wins. If a sub domain is configured on another interface it will be accepted regardless the priority, unless parent domain on the other interface has a negative priority, which causes the sub domain to be shadowed. With Split DNS one can avoid undesired DNS leaks by properly configuring DNS priorities and the search domains, so that only name servers of the desired interface are configured.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names. When using a DNS plugin that supports Conditional Forwarding or Split DNS, then the search domains specify which name servers to query. This makes the behavior different from running with plain /etc/resolv.conf. For more information see also the dns-priority setting.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set. The gateway's main purpose is to control the next hop of the standard default route on the device. Hence, the gateway property conflicts with \"never-default\" and will be automatically dropped if the IP configuration is set to never-default. As an alternative to set the gateway, configure a static default route with /0 as prefix length.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration. The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.")
|
||||
|
|
@ -228,20 +254,23 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DAD_TIMEOUT N_("Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_DUID N_("A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in the Client Identifier option. If the property is a hex string ('aa:bb:cc') it is interpreted as a binary DUID and filled as an opaque value in the Client Identifier option. The special value \"lease\" will retrieve the DUID previously used from the lease file belonging to the connection. If no DUID is found and \"dhclient\" is the configured dhcp client, the DUID is searched in the system-wide dhclient lease file. If still no DUID is found, or another dhcp client is used, a global and permanent DUID-UUID (RFC 6355) will be generated based on the machine-id. The special values \"llt\" and \"ll\" will generate a DUID of type LLT or LL (see RFC 3315) based on the current MAC address of the device. In order to try providing a stable DUID-LLT, the time field will contain a constant timestamp that is used globally (for all profiles) and persisted to disk. The special values \"stable-llt\", \"stable-ll\" and \"stable-uuid\" will generate a DUID of the corresponding type, derived from the connection's stable-id and a per-host unique key. You may want to include the \"${DEVICE}\" or \"${MAC}\" specifier in the stable-id, in case this profile gets activated on multiple devices. So, the link-layer address of \"stable-ll\" and \"stable-llt\" will be a generated address derived from the stable id. The DUID-LLT time value in the \"stable-llt\" option will be picked among a static timespan of three years (the upper bound of the interval is the same constant timestamp used in \"llt\"). When the property is unset, the global value provided for \"ipv6.dhcp-duid\" is used. If no global value is provided, the default \"lease\" value is assumed.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME N_("If the \"dhcp-send-hostname\" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease. This property and \"dhcp-fqdn\" are mutually exclusive and cannot be set at the same time.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME_FLAGS N_("Flags for the DHCP hostname and FQDN. Currently, this property only includes flags to control the FQDN flags set in the DHCP FQDN option. Supported FQDN flags are NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) and NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the DHCP FQDN option will contain no flag. Otherwise, if no FQDN flag is set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the standard FQDN flags are set in the request: NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) for IPv4 and NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. When this property is set to the default value NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is looked up in NetworkManager configuration. If that value is unset or also NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags described above are sent in the DHCP requests.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_IAID N_("A string containing the \"Identity Association Identifier\" (IAID) used by the DHCP client. The property is a 32-bit decimal value or a special value among \"mac\", \"perm-mac\", \"ifname\" and \"stable\". When set to \"mac\" (or \"perm-mac\"), the last 4 bytes of the current (or permanent) MAC address are used as IAID. When set to \"ifname\", the IAID is computed by hashing the interface name. The special value \"stable\" can be used to generate an IAID based on the stable-id (see connection.stable-id), a per-host key and the interface name. When the property is unset, the value from global configuration is used; if no global default is set then the IAID is assumed to be \"ifname\". Note that at the moment this property is ignored for IPv6 by dhclient, which always derives the IAID from the MAC address.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS N_("Array of IP addresses of DNS servers.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower value is better (higher priority). Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. When multiple devices have configurations with the same priority, the one with an active default route will be preferred. Negative values have the special effect of excluding other configurations with a greater priority value; so in presence of at least a negative priority, only DNS servers from connections with the lowest priority value will be used. When using a DNS resolver that supports Conditional Forwarding as dns=dnsmasq or dns=systemd-resolved, each connection is used to query domains in its search list. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the highest priority (lowest numerical value) wins. If a connection specifies a domain which is subdomain of another domain with a negative DNS priority value, the subdomain is ignored.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"ndots\", \"no-check-names\", \"no-ip6-dotint\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\". The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower numerical value is better (higher priority). Negative values have the special effect of excluding other configurations with a greater numerical priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. To avoid all DNS leaks, set the priority of the profile that should be used to the most negative value of all active connections profiles. Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. Note that commonly the resolver tries name servers in /etc/resolv.conf in the order listed, proceeding with the next server in the list on failure. See for example the \"rotate\" option of the dns-options setting. If there are any negative DNS priorities, then only name servers from the devices with that lowest priority will be considered. When using a DNS resolver that supports Conditional Forwarding or Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection is used to query domains in its search list. The search domains determine which name servers to ask, and the DNS priority is used to prioritize name servers based on the domain. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the best priority (lowest numerical value) wins. If a sub domain is configured on another interface it will be accepted regardless the priority, unless parent domain on the other interface has a negative priority, which causes the sub domain to be shadowed. With Split DNS one can avoid undesired DNS leaks by properly configuring DNS priorities and the search domains, so that only name servers of the desired interface are configured.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH N_("Array of DNS search domains. Domains starting with a tilde ('~') are considered 'routing' domains and are used only to decide the interface over which a query must be forwarded; they are not used to complete unqualified host names. When using a DNS plugin that supports Conditional Forwarding or Split DNS, then the search domains specify which name servers to query. This makes the behavior different from running with plain /etc/resolv.conf. For more information see also the dns-priority setting.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set. The gateway's main purpose is to control the next hop of the standard default route on the device. Hence, the gateway property conflicts with \"never-default\" and will be automatically dropped if the IP configuration is set to never-default. As an alternative to set the gateway, configure a static default route with /0 as prefix length.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IP6_PRIVACY N_("Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64. This enhances privacy, but could cause problems in some applications, on the other hand. The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses). Having a per-connection setting set to \"-1\" (unknown) means fallback to global configuration \"ipv6.ip6-privacy\". If also global configuration is unspecified or set to \"-1\", fallback to read \"/proc/sys/net/ipv6/conf/default/use_tempaddr\". Note that this setting is distinct from the Stable Privacy addresses that can be enabled with the \"addr-gen-mode\" property's \"stable-privacy\" setting as another way of avoiding host tracking with IPv6 addresses.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration. The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_RA_TIMEOUT N_("A timeout for waiting Router Advertisements in seconds. If zero (the default), a globally configured default is used. If still unspecified, the timeout depends on the sysctl settings of the device. Set to 2147483647 (MAXINT32) for infinity.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.")
|
||||
|
|
@ -259,15 +288,19 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created. If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_PROMISCUOUS N_("Whether the interface should be put in promiscuous mode.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MACVLAN_TAP N_("Whether the interface should be a MACVTAP.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_INTERFACE_NAME N_("A list of interface names to match. Each element is a shell wildcard pattern. When an element is prefixed with exclamation mark (!) the condition is inverted. A candidate interface name is considered matching when both these conditions are satisfied: (a) any of the elements not prefixed with '!' matches or there aren't such elements; (b) none of the elements prefixed with '!' match.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_DRIVER N_("A list of driver names to match. Each element is a shell wildcard pattern. See NMSettingMatch:interface-name for how special characters '|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_INTERFACE_NAME N_("A list of interface names to match. Each element is a shell wildcard pattern. An element can be prefixed with a pipe symbol (|) or an ampersand (&). The former means that the element is optional and the latter means that it is mandatory. If there are any optional elements, than the match evaluates to true if at least one of the optional element matches (logical OR). If there are any mandatory elements, then they all must match (logical AND). By default, an element is optional. This means that an element \"foo\" behaves the same as \"|foo\". An element can also be inverted with exclamation mark (!) between the pipe symbol (or the ampersand) and before the pattern. Note that \"!foo\" is a shortcut for the mandatory match \"&!foo\". Finally, a backslash can be used at the beginning of the element (after the optional special characters) to escape the start of the pattern. For example, \"&\\!a\" is an mandatory match for literally \"!a\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_KERNEL_COMMAND_LINE N_("A list of kernel command line arguments to match. This may be used to check whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). The argument must either be a single word, or an assignment (i.e. two words, separated \"=\"). In the former case the kernel command line is searched for the word appearing as is, or as left hand side of an assignment. In the latter case, the exact assignment is looked for with right and left hand side matching. See NMSettingMatch:interface-name for how special characters '|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_MATCH_PATH N_("A list of paths to match against the ID_PATH udev property of devices. ID_PATH represents the topological persistent path of a device. It typically contains a subsystem string (pci, usb, platform, etc.) and a subsystem-specific identifier. For PCI devices the path has the form \"pci-$domain:$bus:$device.$function\", where each variable is an hexadecimal value; for example \"pci-0000:0a:00.0\". The path of a device can be obtained with \"udevadm info /sys/class/net/$dev | grep ID_PATH=\" or by looking at the \"path\" property exported by NetworkManager (\"nmcli -f general.path device show $dev\"). Each element of the list is a shell wildcard pattern. See NMSettingMatch:interface-name for how special characters '|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE N_("The data path type. One of \"system\", \"netdev\" or empty.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_FAIL_MODE N_("The bridge failure mode. One of \"secure\", \"standalone\" or empty.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE N_("Enable or disable multicast snooping.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_RSTP_ENABLE N_("Enable or disable RSTP.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_STP_ENABLE N_("Enable or disable STP.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_DPDK_DEVARGS N_("Open vSwitch DPDK device arguments.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_EXTERNAL_IDS_DATA N_("A dictionary of key/value pairs with exernal-ids for OVS.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_INTERFACE_TYPE N_("The interface type. Either \"internal\", \"system\", \"patch\", \"dpdk\", or empty.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_PEER N_("Specifies the unicast destination IP address of a remote Open vSwitch bridge port to connect to.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PATCH_PEER N_("Specifies the name of the interface for the other side of the patch. The patch on the other side must also set this interface as peer.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_DOWNDELAY N_("The time port must be inactive in order to be considered down.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_MODE N_("Bonding mode. One of \"active-backup\", \"balance-slb\", or \"balance-tcp\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_OVS_PORT_BOND_UPDELAY N_("The time port must be active before it starts forwarding traffic.")
|
||||
|
|
@ -307,8 +340,8 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in \"8n1\" for example.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_SRIOV_AUTOPROBE_DRIVERS N_("Whether to autoprobe virtual functions by a compatible driver. If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no network interfaces will be created for them. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_TRUE (1).")
|
||||
#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface also when it is zero. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". Multiple VFs can be specified using a comma as separator. Currently the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The \"vlans\" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". Multiple VFs can be specified using a comma as separator. Currently, the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The \"vlans\" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_QDISCS N_("Array of TC queueing disciplines.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_TFILTERS N_("Array of TC traffic filters.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TEAM_CONFIG N_("The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details.")
|
||||
|
|
@ -341,6 +374,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_TUN_PI N_("If TRUE the interface will prepend a 4 byte header describing the physical interface to the packets.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_TUN_VNET_HDR N_("If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network header.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_USER_DATA N_("A dictionary of key/value pairs with user data. This data is ignored by NetworkManager and can be used at the users discretion. The keys only support a strict ascii format, but the values can be arbitrary UTF8 strings up to a certain length.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VETH_PEER N_("This property specifies the peer interface name of the veth. This property is mandatory.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VLAN_EGRESS_PRIORITY_MAP N_("For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities. The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VLAN_FLAGS N_("One or more flags which control the behavior and features of the VLAN interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, but it used to be 0. To preserve backward compatibility, the default-value in the D-Bus API continues to be 0 and a missing property on D-Bus is still considered as 0.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VLAN_ID N_("The VLAN identifier that the interface created by this connection should be assigned. The valid range is from 0 to 4094, without the reserved id 4095.")
|
||||
|
|
@ -352,6 +386,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_VPN_SERVICE_TYPE N_("D-Bus service name of the VPN plugin that this setting uses to connect to its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VPN_TIMEOUT N_("Timeout for the VPN service to establish the connection. Some services may take quite a long time to connect. Value of 0 means a default timeout, which is 60 seconds (unless overridden by vpn.timeout in configuration file). Values greater than zero mean timeout in seconds.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VPN_USER_NAME N_("If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VRF_TABLE N_("The routing table for this VRF.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VXLAN_AGEING N_("Specifies the lifetime in seconds of FDB entries learnt by the kernel.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VXLAN_DESTINATION_PORT N_("Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VXLAN_ID N_("Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use.")
|
||||
|
|
@ -368,17 +403,17 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_VXLAN_SOURCE_PORT_MIN N_("Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VXLAN_TOS N_("Specifies the TOS value to use in outgoing packets.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_VXLAN_TTL N_("Specifies the time-to-live value to use in outgoing packets.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_PEER N_("The P2P device that should be connected to. Currently this is the only way to create or join a group.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_PEER N_("The P2P device that should be connected to. Currently, this is the only way to create or join a group.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WFD_IES N_("The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display requires a protocol specific information element to be set in certain Wi-Fi frames. These can be specified here for the purpose of establishing a connection. This setting is only useful when implementing a Wi-Fi Display client.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIFI_P2P_WPS_METHOD N_("Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIMAX_MAC_ADDRESS N_("If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIMAX_NETWORK_NAME N_("Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets. Note that \"ip4-auto-default-route\" or \"ip6-auto-default-route\" enabled, implies to automatically choose a fwmark.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE N_("Whether to enable special handling of the IPv4 default route. If enabled, the IPv4 default route will be placed to a dedicated routing-table and two policy routing rules will be added. The fwmark number is also used as routing-table for the default-route, and if fwmark is zero, a unused fwmark/table is chosen automatically. This corresponds to what wg-quick does with Table=auto. Leaving this at the default will enable this option automatically if ipv4.never-default is not set and there are any peers that use a default-route as allowed-ips.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_FWMARK N_("The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. Note that \"ip4-auto-default-route\" or \"ip6-auto-default-route\" enabled, implies to automatically choose a fwmark.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_IP4_AUTO_DEFAULT_ROUTE N_("Whether to enable special handling of the IPv4 default route. If enabled, the IPv4 default route from wireguard.peer-routes will be placed to a dedicated routing-table and two policy routing rules will be added. The fwmark number is also used as routing-table for the default-route, and if fwmark is zero, an unused fwmark/table is chosen automatically. This corresponds to what wg-quick does with Table=auto and what WireGuard calls \"Improved Rule-based Routing\". Note that for this automatism to work, you usually don't want to set ipv4.gateway, because that will result in a conflicting default route. Leaving this at the default will enable this option automatically if ipv4.never-default is not set and there are any peers that use a default-route as allowed-ips.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_IP6_AUTO_DEFAULT_ROUTE N_("Like ip4-auto-default-route, but for the IPv6 default route.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_LISTEN_PORT N_("The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments. If zero a default MTU is used. Note that contrary to wg-quick's MTU setting, this does not take into account the current routes at the time of activation.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PEER_ROUTES N_("Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PEER_ROUTES N_("Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. Usually you want this automatism enabled. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively. Note that if the peer's AllowedIPs is \"0.0.0.0/0\" or \"::/0\" and the profile's ipv4.never-default or ipv6.never-default setting is enabled, the peer route for this peer won't be added automatically.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY N_("The 256 bit private-key in base64 encoding.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS N_("Flags indicating how to handle the \"private-key\" property.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_WPAN_CHANNEL N_("IEEE 802.15.4 channel. A positive integer or -1, meaning \"do not set, use whatever the device is already set to\".")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
common_c_flags = clients_c_flags + ['-DNETWORKMANAGER_COMPILATION_TEST']
|
||||
|
||||
test_name = 'test-clients-common'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -7,234 +7,360 @@
|
|||
|
||||
#include "nm-meta-setting-access.h"
|
||||
#include "nm-vpn-helpers.h"
|
||||
#include "nm-client-utils.h"
|
||||
|
||||
#include "nm-utils/nm-test-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_client_meta_check (void)
|
||||
test_client_meta_check(void)
|
||||
{
|
||||
const NMMetaSettingInfoEditor *const*infos_p;
|
||||
NMMetaSettingType m;
|
||||
guint p;
|
||||
const NMMetaSettingInfoEditor *const *infos_p;
|
||||
NMMetaSettingType m;
|
||||
guint p;
|
||||
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMMetaAbstractInfo, meta_type) == G_STRUCT_OFFSET (NMMetaSettingInfoEditor, meta_type));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMMetaAbstractInfo, meta_type) == G_STRUCT_OFFSET (NMMetaPropertyInfo, meta_type));
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(NMMetaAbstractInfo, meta_type)
|
||||
== G_STRUCT_OFFSET(NMMetaSettingInfoEditor, meta_type));
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(NMMetaAbstractInfo, meta_type)
|
||||
== G_STRUCT_OFFSET(NMMetaPropertyInfo, meta_type));
|
||||
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
|
||||
const NMMetaSettingInfo *info = &nm_meta_setting_infos[m];
|
||||
GType gtype;
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
|
||||
const NMMetaSettingInfo *info = &nm_meta_setting_infos[m];
|
||||
GType gtype;
|
||||
|
||||
g_assert (info);
|
||||
g_assert (info->meta_type == m);
|
||||
g_assert (info->setting_name);
|
||||
g_assert (info->get_setting_gtype);
|
||||
g_assert(info);
|
||||
g_assert(info->meta_type == m);
|
||||
g_assert(info->setting_name);
|
||||
g_assert(info->get_setting_gtype);
|
||||
|
||||
gtype = info->get_setting_gtype ();
|
||||
g_assert (gtype != NM_TYPE_SETTING);
|
||||
gtype = info->get_setting_gtype();
|
||||
g_assert(gtype != NM_TYPE_SETTING);
|
||||
|
||||
{
|
||||
nm_auto_unref_gtypeclass GTypeClass *gclass = g_type_class_ref (gtype);
|
||||
{
|
||||
nm_auto_unref_gtypeclass GTypeClass *gclass = g_type_class_ref(gtype);
|
||||
|
||||
g_assert (G_TYPE_CHECK_CLASS_TYPE (gclass, gtype));
|
||||
}
|
||||
{
|
||||
gs_unref_object NMSetting *setting = g_object_new (gtype, NULL);
|
||||
g_assert(G_TYPE_CHECK_CLASS_TYPE(gclass, gtype));
|
||||
}
|
||||
{
|
||||
gs_unref_object NMSetting *setting = g_object_new(gtype, NULL);
|
||||
|
||||
g_assert (NM_IS_SETTING (setting));
|
||||
g_assert (G_TYPE_CHECK_INSTANCE_TYPE (setting, gtype));
|
||||
g_assert_cmpstr (nm_setting_get_name (setting), ==, info->setting_name);
|
||||
}
|
||||
}
|
||||
g_assert(NM_IS_SETTING(setting));
|
||||
g_assert(G_TYPE_CHECK_INSTANCE_TYPE(setting, gtype));
|
||||
g_assert_cmpstr(nm_setting_get_name(setting), ==, info->setting_name);
|
||||
}
|
||||
}
|
||||
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
|
||||
const NMMetaSettingInfoEditor *info = &nm_meta_setting_infos_editor[m];
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
|
||||
const NMMetaSettingInfoEditor *info = &nm_meta_setting_infos_editor[m];
|
||||
GType gtype;
|
||||
NMSettingPriority base_priority;
|
||||
gboolean is_base_type;
|
||||
|
||||
g_assert (info);
|
||||
g_assert (info->meta_type == &nm_meta_type_setting_info_editor);
|
||||
g_assert (info->general);
|
||||
g_assert (info->general == &nm_meta_setting_infos[m]);
|
||||
g_assert(info);
|
||||
g_assert(info->meta_type == &nm_meta_type_setting_info_editor);
|
||||
g_assert(info->general);
|
||||
g_assert(info->general == &nm_meta_setting_infos[m]);
|
||||
|
||||
g_assert_cmpstr (info->general->setting_name, ==, info->meta_type->get_name ((const NMMetaAbstractInfo *) info, FALSE));
|
||||
g_assert_cmpstr ("name", ==, info->meta_type->get_name ((const NMMetaAbstractInfo *) info, TRUE));
|
||||
g_assert_cmpstr(info->general->setting_name,
|
||||
==,
|
||||
info->meta_type->get_name((const NMMetaAbstractInfo *) info, FALSE));
|
||||
g_assert_cmpstr("name",
|
||||
==,
|
||||
info->meta_type->get_name((const NMMetaAbstractInfo *) info, TRUE));
|
||||
|
||||
g_assert (info->properties_num == NM_PTRARRAY_LEN (info->properties));
|
||||
g_assert(info->properties_num == NM_PTRARRAY_LEN(info->properties));
|
||||
|
||||
if (info->properties_num) {
|
||||
gs_unref_hashtable GHashTable *property_names = g_hash_table_new (nm_str_hash, g_str_equal);
|
||||
if (info->properties_num) {
|
||||
gs_unref_hashtable GHashTable *property_names =
|
||||
g_hash_table_new(nm_str_hash, g_str_equal);
|
||||
|
||||
g_assert (info->properties);
|
||||
for (p = 0; p < info->properties_num; p++) {
|
||||
const NMMetaPropertyInfo *pi = info->properties[p];
|
||||
g_assert(info->properties);
|
||||
for (p = 0; p < info->properties_num; p++) {
|
||||
const NMMetaPropertyInfo *pi = info->properties[p];
|
||||
|
||||
g_assert (pi);
|
||||
g_assert (pi->meta_type == &nm_meta_type_property_info);
|
||||
g_assert (pi->setting_info == info);
|
||||
g_assert (pi->property_name);
|
||||
g_assert(pi);
|
||||
g_assert(pi->meta_type == &nm_meta_type_property_info);
|
||||
g_assert(pi->setting_info == info);
|
||||
g_assert(pi->property_name);
|
||||
|
||||
g_assert (g_hash_table_add (property_names, (gpointer) pi->property_name));
|
||||
g_assert(g_hash_table_add(property_names, (gpointer) pi->property_name));
|
||||
|
||||
g_assert_cmpstr (pi->property_name, ==, pi->meta_type->get_name ((const NMMetaAbstractInfo *) pi, FALSE));
|
||||
g_assert_cmpstr (pi->property_name, ==, pi->meta_type->get_name ((const NMMetaAbstractInfo *) pi, TRUE));
|
||||
g_assert_cmpstr(pi->property_name,
|
||||
==,
|
||||
pi->meta_type->get_name((const NMMetaAbstractInfo *) pi, FALSE));
|
||||
g_assert_cmpstr(pi->property_name,
|
||||
==,
|
||||
pi->meta_type->get_name((const NMMetaAbstractInfo *) pi, TRUE));
|
||||
|
||||
g_assert (pi->property_type);
|
||||
g_assert (pi->property_type->get_fcn);
|
||||
}
|
||||
g_assert (!info->properties[info->properties_num]);
|
||||
} else
|
||||
g_assert (!info->properties);
|
||||
g_assert(pi->property_type);
|
||||
g_assert(pi->property_type->get_fcn);
|
||||
}
|
||||
g_assert(!info->properties[info->properties_num]);
|
||||
} else
|
||||
g_assert(!info->properties);
|
||||
|
||||
if (info->valid_parts) {
|
||||
gsize i, l;
|
||||
gs_unref_hashtable GHashTable *dup = g_hash_table_new (nm_direct_hash, NULL);
|
||||
gtype = info->general->get_setting_gtype();
|
||||
base_priority = _nm_setting_type_get_base_type_priority(gtype);
|
||||
is_base_type = (base_priority != NM_SETTING_PRIORITY_INVALID);
|
||||
g_assert((!!info->valid_parts) == is_base_type);
|
||||
|
||||
l = NM_PTRARRAY_LEN (info->valid_parts);
|
||||
g_assert (l >= 2);
|
||||
if (info->valid_parts) {
|
||||
gsize i, l;
|
||||
gs_unref_hashtable GHashTable *dup = g_hash_table_new(nm_direct_hash, NULL);
|
||||
|
||||
for (i = 0; info->valid_parts[i]; i++) {
|
||||
g_assert (info->valid_parts[i]->setting_info);
|
||||
g_assert (g_hash_table_add (dup, (gpointer) info->valid_parts[i]->setting_info));
|
||||
l = NM_PTRARRAY_LEN(info->valid_parts);
|
||||
g_assert(l >= 2);
|
||||
|
||||
if (i == 0) {
|
||||
g_assert (info->valid_parts[i]->setting_info == &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION]);
|
||||
g_assert (info->valid_parts[i]->mandatory);
|
||||
}
|
||||
if (i == 1) {
|
||||
g_assert (info->valid_parts[i]->setting_info == &nm_meta_setting_infos_editor[m]);
|
||||
g_assert (info->valid_parts[i]->mandatory);
|
||||
}
|
||||
}
|
||||
g_assert (i == l);
|
||||
}
|
||||
}
|
||||
for (i = 0; info->valid_parts[i]; i++) {
|
||||
g_assert(info->valid_parts[i]->setting_info);
|
||||
g_assert(g_hash_table_add(dup, (gpointer) info->valid_parts[i]->setting_info));
|
||||
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
|
||||
const NMMetaSettingInfoEditor *info = &nm_meta_setting_infos_editor[m];
|
||||
if (i == 0) {
|
||||
g_assert(info->valid_parts[i]->setting_info
|
||||
== &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION]);
|
||||
g_assert(info->valid_parts[i]->mandatory);
|
||||
}
|
||||
if (i == 1) {
|
||||
g_assert(info->valid_parts[i]->setting_info
|
||||
== &nm_meta_setting_infos_editor[m]);
|
||||
g_assert(info->valid_parts[i]->mandatory);
|
||||
}
|
||||
}
|
||||
g_assert(i == l);
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (nm_meta_setting_info_editor_find_by_name (info->general->setting_name, FALSE) == info);
|
||||
g_assert (nm_meta_setting_info_editor_find_by_gtype (info->general->get_setting_gtype ()) == info);
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++) {
|
||||
const NMMetaSettingInfoEditor *info = &nm_meta_setting_infos_editor[m];
|
||||
|
||||
for (p = 0; p < info->properties_num; p++) {
|
||||
const NMMetaPropertyInfo *pi = info->properties[p];
|
||||
g_assert(nm_meta_setting_info_editor_find_by_name(info->general->setting_name, FALSE)
|
||||
== info);
|
||||
g_assert(nm_meta_setting_info_editor_find_by_gtype(info->general->get_setting_gtype())
|
||||
== info);
|
||||
|
||||
g_assert (nm_meta_setting_info_editor_get_property_info (info, pi->property_name) == pi);
|
||||
g_assert (nm_meta_property_info_find_by_name (info->general->setting_name, pi->property_name) == pi);
|
||||
}
|
||||
}
|
||||
for (p = 0; p < info->properties_num; p++) {
|
||||
const NMMetaPropertyInfo *pi = info->properties[p];
|
||||
|
||||
infos_p = nm_meta_setting_infos_editor_p ();
|
||||
g_assert (infos_p);
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++)
|
||||
g_assert (infos_p[m] == &nm_meta_setting_infos_editor[m]);
|
||||
g_assert (!infos_p[m]);
|
||||
g_assert(nm_meta_setting_info_editor_get_property_info(info, pi->property_name) == pi);
|
||||
g_assert(
|
||||
nm_meta_property_info_find_by_name(info->general->setting_name, pi->property_name)
|
||||
== pi);
|
||||
}
|
||||
}
|
||||
|
||||
infos_p = nm_meta_setting_infos_editor_p();
|
||||
g_assert(infos_p);
|
||||
for (m = 0; m < _NM_META_SETTING_TYPE_NUM; m++)
|
||||
g_assert(infos_p[m] == &nm_meta_setting_infos_editor[m]);
|
||||
g_assert(!infos_p[m]);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_client_import_wireguard_test0 (void)
|
||||
test_client_import_wireguard_test0(void)
|
||||
{
|
||||
gs_unref_object NMConnection *connection;
|
||||
NMSettingWireGuard *s_wg;
|
||||
NMWireGuardPeer *peer;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_object NMConnection *connection;
|
||||
NMSettingWireGuard * s_wg;
|
||||
NMSettingIPConfig * s_ip4;
|
||||
NMSettingIPConfig * s_ip6;
|
||||
NMWireGuardPeer * peer;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
connection = nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test0.conf",
|
||||
&error);
|
||||
connection =
|
||||
nm_vpn_wireguard_import(NM_BUILD_SRCDIR "/clients/common/tests/wg-test0.conf", &error);
|
||||
|
||||
g_assert_no_error (error);
|
||||
g_assert_no_error(error);
|
||||
|
||||
g_assert_cmpstr (nm_connection_get_id (connection), ==, "wg-test0");
|
||||
g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "wg-test0");
|
||||
g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_WIREGUARD_SETTING_NAME);
|
||||
g_assert_cmpstr(nm_connection_get_id(connection), ==, "wg-test0");
|
||||
g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "wg-test0");
|
||||
g_assert_cmpstr(nm_connection_get_connection_type(connection),
|
||||
==,
|
||||
NM_SETTING_WIREGUARD_SETTING_NAME);
|
||||
|
||||
s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD));
|
||||
s_wg = NM_SETTING_WIREGUARD(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIREGUARD));
|
||||
|
||||
g_assert_cmpint (nm_setting_wireguard_get_listen_port (s_wg), ==, 51820);
|
||||
g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg), ==, "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=");
|
||||
g_assert_cmpint(nm_setting_wireguard_get_listen_port(s_wg), ==, 51820);
|
||||
g_assert_cmpstr(nm_setting_wireguard_get_private_key(s_wg),
|
||||
==,
|
||||
"yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=");
|
||||
|
||||
g_assert_cmpint (nm_setting_wireguard_get_peers_len (s_wg), ==, 3);
|
||||
g_assert_cmpint(nm_setting_wireguard_get_peers_len(s_wg), ==, 3);
|
||||
|
||||
peer = nm_setting_wireguard_get_peer (s_wg, 0);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_public_key (peer), ==, "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=");
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_endpoint (peer), ==, "192.95.5.67:1234");
|
||||
g_assert_cmpint (nm_wireguard_peer_get_allowed_ips_len (peer), ==, 2);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 0, NULL), ==, "10.192.122.3/32");
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 1, NULL), ==, "10.192.124.1/24");
|
||||
peer = nm_setting_wireguard_get_peer(s_wg, 0);
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_public_key(peer),
|
||||
==,
|
||||
"xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=");
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_endpoint(peer), ==, "192.95.5.67:1234");
|
||||
g_assert_cmpint(nm_wireguard_peer_get_allowed_ips_len(peer), ==, 2);
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_allowed_ip(peer, 0, NULL), ==, "10.192.122.3/32");
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_allowed_ip(peer, 1, NULL), ==, "10.192.124.1/24");
|
||||
|
||||
peer = nm_setting_wireguard_get_peer (s_wg, 1);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_public_key (peer), ==, "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=");
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_endpoint (peer), ==, "[2607:5300:60:6b0::c05f:543]:2468");
|
||||
g_assert_cmpint (nm_wireguard_peer_get_allowed_ips_len (peer), ==, 2);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 0, NULL), ==, "10.192.122.4/32");
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 1, NULL), ==, "192.168.0.0/16");
|
||||
peer = nm_setting_wireguard_get_peer(s_wg, 1);
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_public_key(peer),
|
||||
==,
|
||||
"TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=");
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_endpoint(peer), ==, "[2607:5300:60:6b0::c05f:543]:2468");
|
||||
g_assert_cmpint(nm_wireguard_peer_get_allowed_ips_len(peer), ==, 2);
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_allowed_ip(peer, 0, NULL), ==, "10.192.122.4/32");
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_allowed_ip(peer, 1, NULL), ==, "192.168.0.0/16");
|
||||
|
||||
peer = nm_setting_wireguard_get_peer (s_wg, 2);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_public_key (peer), ==, "gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=");
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_endpoint (peer), ==, "test.wireguard.com:18981");
|
||||
g_assert_cmpint (nm_wireguard_peer_get_allowed_ips_len (peer), ==, 1);
|
||||
g_assert_cmpstr (nm_wireguard_peer_get_allowed_ip (peer, 0, NULL), ==, "10.10.10.230/32");
|
||||
peer = nm_setting_wireguard_get_peer(s_wg, 2);
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_public_key(peer),
|
||||
==,
|
||||
"gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=");
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_endpoint(peer), ==, "test.wireguard.com:18981");
|
||||
g_assert_cmpint(nm_wireguard_peer_get_allowed_ips_len(peer), ==, 1);
|
||||
g_assert_cmpstr(nm_wireguard_peer_get_allowed_ip(peer, 0, NULL), ==, "10.10.10.230/32");
|
||||
|
||||
s_ip4 = nm_connection_get_setting_ip4_config(connection);
|
||||
s_ip6 = nm_connection_get_setting_ip6_config(connection);
|
||||
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 1);
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 0);
|
||||
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_dns_searches(s_ip4), ==, 1);
|
||||
g_assert_cmpint(nm_setting_ip_config_get_num_dns_searches(s_ip6), ==, 0);
|
||||
|
||||
g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip4, 0), ==, "~");
|
||||
}
|
||||
|
||||
static void
|
||||
test_client_import_wireguard_test1 (void)
|
||||
test_client_import_wireguard_test1(void)
|
||||
{
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test1.conf", &error);
|
||||
g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT);
|
||||
g_assert (g_str_has_prefix (error->message, "invalid secret 'PrivateKey'"));
|
||||
g_assert (g_str_has_suffix (error->message, "wg-test1.conf:2"));
|
||||
nm_vpn_wireguard_import(NM_BUILD_SRCDIR "/clients/common/tests/wg-test1.conf", &error);
|
||||
g_assert_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT);
|
||||
g_assert(g_str_has_prefix(error->message, "invalid secret 'PrivateKey'"));
|
||||
g_assert(g_str_has_suffix(error->message, "wg-test1.conf:2"));
|
||||
}
|
||||
|
||||
static void
|
||||
test_client_import_wireguard_test2 (void)
|
||||
test_client_import_wireguard_test2(void)
|
||||
{
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test2.conf", &error);
|
||||
nm_vpn_wireguard_import(NM_BUILD_SRCDIR "/clients/common/tests/wg-test2.conf", &error);
|
||||
|
||||
g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT);
|
||||
g_assert (g_str_has_prefix (error->message, "unrecognized line at"));
|
||||
g_assert (g_str_has_suffix (error->message, "wg-test2.conf:5"));
|
||||
g_assert_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT);
|
||||
g_assert(g_str_has_prefix(error->message, "unrecognized line at"));
|
||||
g_assert(g_str_has_suffix(error->message, "wg-test2.conf:5"));
|
||||
}
|
||||
|
||||
static void
|
||||
test_client_import_wireguard_test3 (void)
|
||||
test_client_import_wireguard_test3(void)
|
||||
{
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-test3.conf", &error);
|
||||
g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT);
|
||||
g_assert (g_str_has_prefix (error->message, "invalid value for 'ListenPort'"));
|
||||
g_assert (g_str_has_suffix (error->message, "wg-test3.conf:3"));
|
||||
nm_vpn_wireguard_import(NM_BUILD_SRCDIR "/clients/common/tests/wg-test3.conf", &error);
|
||||
g_assert_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT);
|
||||
g_assert(g_str_has_prefix(error->message, "invalid value for 'ListenPort'"));
|
||||
g_assert(g_str_has_suffix(error->message, "wg-test3.conf:3"));
|
||||
}
|
||||
|
||||
static void
|
||||
test_client_import_wireguard_missing (void)
|
||||
test_client_import_wireguard_missing(void)
|
||||
{
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_vpn_wireguard_import (NM_BUILD_SRCDIR"/clients/common/tests/wg-missing.conf", &error);
|
||||
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
|
||||
nm_vpn_wireguard_import(NM_BUILD_SRCDIR "/clients/common/tests/wg-missing.conf", &error);
|
||||
g_assert_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
#define _do_test_parse_passwd_file(contents, success, exp_error_line, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
static const NMUtilsNamedValue _values[] = {__VA_ARGS__}; \
|
||||
gs_free char * _contents = g_strndup(contents, NM_STRLEN(contents)); \
|
||||
gs_unref_hashtable GHashTable *_secrets = NULL; \
|
||||
gs_free_error GError *_local = NULL; \
|
||||
gssize _error_line; \
|
||||
GError ** _p_local = nmtst_get_rand_bool() ? &_local : NULL; \
|
||||
gssize * _p_error_line = nmtst_get_rand_bool() ? &_error_line : NULL; \
|
||||
gboolean _success = !!(success); \
|
||||
gssize _exp_error_line = (exp_error_line); \
|
||||
int _i; \
|
||||
\
|
||||
g_assert(_success || (G_N_ELEMENTS(_values) == 0)); \
|
||||
\
|
||||
_secrets = nmc_utils_parse_passwd_file(_contents, _p_error_line, _p_local); \
|
||||
\
|
||||
g_assert(_success == (!!_secrets)); \
|
||||
if (!_success) { \
|
||||
if (_p_error_line) \
|
||||
g_assert_cmpint(_exp_error_line, ==, *_p_error_line); \
|
||||
if (_p_local) \
|
||||
g_assert(_local); \
|
||||
} else { \
|
||||
if (_p_error_line) \
|
||||
g_assert_cmpint(-1, ==, *_p_error_line); \
|
||||
g_assert(!_local); \
|
||||
\
|
||||
for (_i = 0; _i < G_N_ELEMENTS(_values); _i++) { \
|
||||
const NMUtilsNamedValue *_n = &_values[_i]; \
|
||||
const char * _v; \
|
||||
\
|
||||
_v = g_hash_table_lookup(_secrets, _n->name); \
|
||||
if (!_v) \
|
||||
g_error("cannot find key \"%s\"", _n->name); \
|
||||
g_assert_cmpstr(_v, ==, _n->value_str); \
|
||||
} \
|
||||
\
|
||||
g_assert_cmpint(g_hash_table_size(_secrets), ==, G_N_ELEMENTS(_values)); \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
#define _do_test_parse_passwd_file_bad(contents, exp_error_line) \
|
||||
_do_test_parse_passwd_file(contents, FALSE, exp_error_line)
|
||||
#define _do_test_parse_passwd_file_good(contents, ...) \
|
||||
_do_test_parse_passwd_file(contents, TRUE, -1, __VA_ARGS__)
|
||||
|
||||
static void
|
||||
test_nmc_utils_parse_passwd_file(void)
|
||||
{
|
||||
_do_test_parse_passwd_file_good("");
|
||||
_do_test_parse_passwd_file_bad("x", 1);
|
||||
_do_test_parse_passwd_file_bad("\r\rx", 3);
|
||||
_do_test_parse_passwd_file_good(
|
||||
"wifi.psk=abc",
|
||||
NM_UTILS_NAMED_VALUE_INIT("802-11-wireless-security.psk", "abc"));
|
||||
_do_test_parse_passwd_file_good(
|
||||
"wifi.psk:ABC\r"
|
||||
"wifi-sec.psk = abc ",
|
||||
NM_UTILS_NAMED_VALUE_INIT("802-11-wireless-security.psk", "abc"));
|
||||
_do_test_parse_passwd_file_good(
|
||||
"wifi.psk: abc\r"
|
||||
"wifi-sec.psk2 = d\\145f\r\n"
|
||||
" wifi.psk3 = e\\ \n"
|
||||
" #wifi-sec.psk2 = \r\n"
|
||||
" wifi-sec.psk4:",
|
||||
NM_UTILS_NAMED_VALUE_INIT("802-11-wireless-security.psk", "abc"),
|
||||
NM_UTILS_NAMED_VALUE_INIT("802-11-wireless-security.psk2", "def"),
|
||||
NM_UTILS_NAMED_VALUE_INIT("802-11-wireless-security.psk3", "e "),
|
||||
NM_UTILS_NAMED_VALUE_INIT("802-11-wireless-security.psk4", ""));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
nmtst_init (&argc, &argv, TRUE);
|
||||
nmtst_init(&argc, &argv, TRUE);
|
||||
|
||||
g_test_add_func ("/client/meta/check", test_client_meta_check);
|
||||
g_test_add_func ("/client/import/wireguard/test0", test_client_import_wireguard_test0);
|
||||
g_test_add_func ("/client/import/wireguard/test1", test_client_import_wireguard_test1);
|
||||
g_test_add_func ("/client/import/wireguard/test2", test_client_import_wireguard_test2);
|
||||
g_test_add_func ("/client/import/wireguard/test3", test_client_import_wireguard_test3);
|
||||
g_test_add_func ("/client/import/wireguard/missing", test_client_import_wireguard_missing);
|
||||
g_test_add_func("/client/meta/check", test_client_meta_check);
|
||||
g_test_add_func("/client/import/wireguard/test0", test_client_import_wireguard_test0);
|
||||
g_test_add_func("/client/import/wireguard/test1", test_client_import_wireguard_test1);
|
||||
g_test_add_func("/client/import/wireguard/test2", test_client_import_wireguard_test2);
|
||||
g_test_add_func("/client/import/wireguard/test3", test_client_import_wireguard_test3);
|
||||
g_test_add_func("/client/import/wireguard/missing", test_client_import_wireguard_missing);
|
||||
g_test_add_func("/client/test_nmc_utils_parse_passwd_file", test_nmc_utils_parse_passwd_file);
|
||||
|
||||
return g_test_run ();
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -13,224 +13,238 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
static NMTeamLinkWatcher *
|
||||
_team_link_watcher_from_string_impl (const char *str, gsize nextra, const char *const*vextra)
|
||||
_team_link_watcher_from_string_impl(const char *str, gsize nextra, const char *const *vextra)
|
||||
{
|
||||
NMTeamLinkWatcher *watcher;
|
||||
gs_free char *str1_free = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gsize i;
|
||||
NMTeamLinkWatcher *watcher;
|
||||
gs_free char * str1_free = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gsize i;
|
||||
|
||||
g_assert (str);
|
||||
g_assert(str);
|
||||
|
||||
watcher = nm_utils_team_link_watcher_from_string (str, &error);
|
||||
nmtst_assert_success (watcher, error);
|
||||
watcher = nm_utils_team_link_watcher_from_string(str, &error);
|
||||
nmtst_assert_success(watcher, error);
|
||||
|
||||
for (i = 0; i < 1 + nextra; i++) {
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher1 = NULL;
|
||||
const char *str1;
|
||||
for (i = 0; i < 1 + nextra; i++) {
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *watcher1 = NULL;
|
||||
const char * str1;
|
||||
|
||||
if (i == 0) {
|
||||
str1_free = nm_utils_team_link_watcher_to_string (watcher);
|
||||
g_assert (str1_free);
|
||||
str1 = str1_free;
|
||||
g_assert_cmpstr (str, ==, str1);
|
||||
} else
|
||||
str1 = vextra[i - 1];
|
||||
if (i == 0) {
|
||||
str1_free = nm_utils_team_link_watcher_to_string(watcher);
|
||||
g_assert(str1_free);
|
||||
str1 = str1_free;
|
||||
g_assert_cmpstr(str, ==, str1);
|
||||
} else
|
||||
str1 = vextra[i - 1];
|
||||
|
||||
watcher1 = nm_utils_team_link_watcher_from_string (str1, &error);
|
||||
nmtst_assert_success (watcher1, error);
|
||||
if (!nm_team_link_watcher_equal (watcher, watcher1)) {
|
||||
gs_free char *ss1 = NULL;
|
||||
gs_free char *ss2 = NULL;
|
||||
watcher1 = nm_utils_team_link_watcher_from_string(str1, &error);
|
||||
nmtst_assert_success(watcher1, error);
|
||||
if (!nm_team_link_watcher_equal(watcher, watcher1)) {
|
||||
gs_free char *ss1 = NULL;
|
||||
gs_free char *ss2 = NULL;
|
||||
|
||||
g_print (">>> watcher differs: \"%s\" vs. \"%s\"",
|
||||
(ss1 = nm_utils_team_link_watcher_to_string (watcher)),
|
||||
(ss2 = nm_utils_team_link_watcher_to_string (watcher1)));
|
||||
g_print (">>> ORIG: \"%s\" vs. \"%s\"", str, str1);
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
g_assert (nm_team_link_watcher_equal (watcher1, watcher));
|
||||
}
|
||||
g_print(">>> watcher differs: \"%s\" vs. \"%s\"",
|
||||
(ss1 = nm_utils_team_link_watcher_to_string(watcher)),
|
||||
(ss2 = nm_utils_team_link_watcher_to_string(watcher1)));
|
||||
g_print(">>> ORIG: \"%s\" vs. \"%s\"", str, str1);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
g_assert(nm_team_link_watcher_equal(watcher1, watcher));
|
||||
}
|
||||
|
||||
return watcher;
|
||||
return watcher;
|
||||
}
|
||||
#define _team_link_watcher_from_string(str, ...) \
|
||||
_team_link_watcher_from_string_impl ((str), NM_NARG (__VA_ARGS__), NM_MAKE_STRV (__VA_ARGS__))
|
||||
_team_link_watcher_from_string_impl((str), NM_NARG(__VA_ARGS__), NM_MAKE_STRV(__VA_ARGS__))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_team_link_watcher_tofro_string (void)
|
||||
test_team_link_watcher_tofro_string(void)
|
||||
{
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *w = NULL;
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *w = NULL;
|
||||
|
||||
#define _team_link_watcher_cmp(watcher, \
|
||||
name, \
|
||||
delay_down, \
|
||||
delay_up, \
|
||||
init_wait, \
|
||||
interval, \
|
||||
missed_max, \
|
||||
target_host, \
|
||||
source_host, \
|
||||
vlanid, \
|
||||
arping_flags) \
|
||||
G_STMT_START { \
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *_w = g_steal_pointer (watcher); \
|
||||
\
|
||||
g_assert_cmpstr ((name), ==, nm_team_link_watcher_get_name (_w)); \
|
||||
g_assert_cmpint ((delay_down), ==, nm_team_link_watcher_get_delay_down (_w)); \
|
||||
g_assert_cmpint ((delay_up), ==, nm_team_link_watcher_get_delay_up (_w)); \
|
||||
g_assert_cmpint ((init_wait), ==, nm_team_link_watcher_get_init_wait (_w)); \
|
||||
g_assert_cmpint ((interval), ==, nm_team_link_watcher_get_interval (_w)); \
|
||||
g_assert_cmpint ((missed_max), ==, nm_team_link_watcher_get_missed_max (_w)); \
|
||||
g_assert_cmpstr ((target_host), ==, nm_team_link_watcher_get_target_host (_w)); \
|
||||
g_assert_cmpstr ((source_host), ==, nm_team_link_watcher_get_source_host (_w)); \
|
||||
g_assert_cmpint ((vlanid), ==, nm_team_link_watcher_get_vlanid (_w)); \
|
||||
g_assert_cmpint ((arping_flags), ==, nm_team_link_watcher_get_flags (_w)); \
|
||||
} G_STMT_END
|
||||
#define _team_link_watcher_cmp(watcher, \
|
||||
name, \
|
||||
delay_down, \
|
||||
delay_up, \
|
||||
init_wait, \
|
||||
interval, \
|
||||
missed_max, \
|
||||
target_host, \
|
||||
source_host, \
|
||||
vlanid, \
|
||||
arping_flags) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
nm_auto_unref_team_link_watcher NMTeamLinkWatcher *_w = g_steal_pointer(watcher); \
|
||||
\
|
||||
g_assert_cmpstr((name), ==, nm_team_link_watcher_get_name(_w)); \
|
||||
g_assert_cmpint((delay_down), ==, nm_team_link_watcher_get_delay_down(_w)); \
|
||||
g_assert_cmpint((delay_up), ==, nm_team_link_watcher_get_delay_up(_w)); \
|
||||
g_assert_cmpint((init_wait), ==, nm_team_link_watcher_get_init_wait(_w)); \
|
||||
g_assert_cmpint((interval), ==, nm_team_link_watcher_get_interval(_w)); \
|
||||
g_assert_cmpint((missed_max), ==, nm_team_link_watcher_get_missed_max(_w)); \
|
||||
g_assert_cmpstr((target_host), ==, nm_team_link_watcher_get_target_host(_w)); \
|
||||
g_assert_cmpstr((source_host), ==, nm_team_link_watcher_get_source_host(_w)); \
|
||||
g_assert_cmpint((vlanid), ==, nm_team_link_watcher_get_vlanid(_w)); \
|
||||
g_assert_cmpint((arping_flags), ==, nm_team_link_watcher_get_flags(_w)); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
w = _team_link_watcher_from_string ("name=ethtool",
|
||||
"delay-up=0 name=ethtool",
|
||||
" delay-down=0 name=ethtool ");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"ethtool",
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string("name=ethtool",
|
||||
"delay-up=0 name=ethtool",
|
||||
" delay-down=0 name=ethtool ");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"ethtool",
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=ethtool delay-up=10",
|
||||
" delay-down=0 delay-up=10 name=ethtool");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"ethtool",
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string("name=ethtool delay-up=10",
|
||||
" delay-down=0 delay-up=10 name=ethtool");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"ethtool",
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=ethtool delay-up=10 delay-down=11",
|
||||
" delay-down=11 delay-up=10 name=ethtool");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"ethtool",
|
||||
11,
|
||||
10,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string("name=ethtool delay-up=10 delay-down=11",
|
||||
" delay-down=11 delay-up=10 name=ethtool");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"ethtool",
|
||||
11,
|
||||
10,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=nsna_ping target-host=xxx",
|
||||
"name=nsna_ping target-host=xxx",
|
||||
" missed-max=3 target-host=xxx name=nsna_ping ");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"nsna_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string(
|
||||
"name=nsna_ping target-host=xxx",
|
||||
"name=nsna_ping target-host=xxx",
|
||||
" missed-max=3 target-host=xxx name=nsna_ping ");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"nsna_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
NULL,
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=arp_ping target-host=xxx source-host=yzd",
|
||||
" source-host=yzd target-host=xxx name=arp_ping ");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
"yzd",
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string("name=arp_ping target-host=xxx source-host=yzd",
|
||||
" source-host=yzd target-host=xxx name=arp_ping ");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
"yzd",
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=arp_ping missed-max=0 target-host=xxx vlanid=0 source-host=yzd");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"xxx",
|
||||
"yzd",
|
||||
0,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string(
|
||||
"name=arp_ping missed-max=0 target-host=xxx vlanid=0 source-host=yzd");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"xxx",
|
||||
"yzd",
|
||||
0,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=arp_ping target-host=xxx source-host=yzd validate-active=true",
|
||||
"source-host=yzd send-always=false name=arp_ping validate-active=true validate-inactive=false target-host=xxx",
|
||||
" source-host=yzd target-host=xxx validate-active=true name=arp_ping ");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
"yzd",
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE);
|
||||
w = _team_link_watcher_from_string(
|
||||
"name=arp_ping target-host=xxx source-host=yzd validate-active=true",
|
||||
"source-host=yzd send-always=false name=arp_ping validate-active=true "
|
||||
"validate-inactive=false target-host=xxx",
|
||||
" source-host=yzd target-host=xxx validate-active=true name=arp_ping ");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
"yzd",
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=arp_ping target-host=xxx source-host=yzd validate-active=true validate-inactive=true send-always=true",
|
||||
"source-host=yzd send-always=true name=arp_ping validate-active=true validate-inactive=true target-host=xxx",
|
||||
"source-host=yzd send-always=true name=arp_ping validate-active=1 validate-inactive=yes target-host=xxx",
|
||||
" source-host=yzd target-host=xxx validate-inactive=true send-always=true validate-active=true name=arp_ping ");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
"yzd",
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE
|
||||
| NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE
|
||||
| NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS);
|
||||
w = _team_link_watcher_from_string(
|
||||
"name=arp_ping target-host=xxx source-host=yzd validate-active=true validate-inactive=true "
|
||||
"send-always=true",
|
||||
"source-host=yzd send-always=true name=arp_ping validate-active=true "
|
||||
"validate-inactive=true target-host=xxx",
|
||||
"source-host=yzd send-always=true name=arp_ping validate-active=1 validate-inactive=yes "
|
||||
"target-host=xxx",
|
||||
" source-host=yzd target-host=xxx validate-inactive=true send-always=true "
|
||||
"validate-active=true name=arp_ping ");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
"xxx",
|
||||
"yzd",
|
||||
-1,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE
|
||||
| NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE
|
||||
| NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS);
|
||||
|
||||
w = _team_link_watcher_from_string ("name=arp_ping missed-max=0 target-host=xxx vlanid=0 source-host=yzd");
|
||||
_team_link_watcher_cmp (&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"xxx",
|
||||
"yzd",
|
||||
0,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
w = _team_link_watcher_from_string(
|
||||
"name=arp_ping missed-max=0 target-host=xxx vlanid=0 source-host=yzd");
|
||||
_team_link_watcher_cmp(&w,
|
||||
"arp_ping",
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"xxx",
|
||||
"yzd",
|
||||
0,
|
||||
NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
NMTST_DEFINE();
|
||||
|
||||
int main (int argc, char **argv)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
nmtst_init (&argc, &argv, TRUE);
|
||||
nmtst_init(&argc, &argv, TRUE);
|
||||
|
||||
g_test_add_func ("/libnm-core-aux/test_team_link_watcher_tofro_string", test_team_link_watcher_tofro_string);
|
||||
g_test_add_func("/libnm-core-aux/test_team_link_watcher_tofro_string",
|
||||
test_team_link_watcher_tofro_string);
|
||||
|
||||
return g_test_run ();
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
[Interface]
|
||||
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
|
||||
ListenPort = 51820
|
||||
Address = 10.10.10.5/32
|
||||
DNS = 10.10.10.1
|
||||
|
||||
[Peer]
|
||||
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
clients_c_flags = ['-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT']
|
||||
|
||||
name = 'nm-online'
|
||||
|
||||
deps = [
|
||||
libnm_dep,
|
||||
libnm_nm_default_dep,
|
||||
]
|
||||
|
||||
executable(
|
||||
name,
|
||||
name + '.c',
|
||||
dependencies: deps,
|
||||
dependencies: [
|
||||
libnm_dep,
|
||||
libnm_nm_default_dep,
|
||||
libnm_libnm_aux_dep,
|
||||
],
|
||||
c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)],
|
||||
link_args: ldflags_linker_script_binary,
|
||||
link_depends: linker_script_binary,
|
||||
|
|
@ -18,11 +19,12 @@ executable(
|
|||
)
|
||||
|
||||
subdir('common')
|
||||
|
||||
if enable_nmcli
|
||||
subdir('cli')
|
||||
endif
|
||||
subdir('cli')
|
||||
|
||||
if enable_nmtui
|
||||
subdir('tui')
|
||||
endif
|
||||
|
||||
if enable_nm_cloud_setup
|
||||
subdir('cloud-setup')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2006 - 2008 Novell, Inc.
|
||||
* Copyright (C) 2008 - 2014 Red Hat, Inc.
|
||||
|
|
@ -23,282 +23,315 @@
|
|||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "nm-libnm-aux/nm-libnm-aux.h"
|
||||
|
||||
#define PROGRESS_STEPS 15
|
||||
|
||||
#define EXIT_NONE -1
|
||||
#define EXIT_NONE -1
|
||||
#define EXIT_FAILURE_OFFLINE 1
|
||||
#define EXIT_FAILURE_ERROR 2
|
||||
#define EXIT_FAILURE_LIBNM_BUG 42
|
||||
#define EXIT_FAILURE_UNSPECIFIED 43
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMainLoop *loop;
|
||||
NMClient *client;
|
||||
GCancellable *client_new_cancellable;
|
||||
guint client_new_timeout_id;
|
||||
guint handle_timeout_id;
|
||||
gulong client_notify_id;
|
||||
gboolean exit_no_nm;
|
||||
gboolean wait_startup;
|
||||
gboolean quiet;
|
||||
gint64 start_timestamp_ms;
|
||||
gint64 end_timestamp_ms;
|
||||
gint64 progress_step_duration;
|
||||
int retval;
|
||||
typedef struct {
|
||||
GMainLoop * loop;
|
||||
NMClient * client;
|
||||
GCancellable *client_new_cancellable;
|
||||
guint client_new_timeout_id;
|
||||
guint handle_timeout_id;
|
||||
gulong client_notify_id;
|
||||
gboolean exit_no_nm;
|
||||
gboolean wait_startup;
|
||||
gboolean quiet;
|
||||
gint64 start_timestamp_ms;
|
||||
gint64 end_timestamp_ms;
|
||||
gint64 progress_step_duration;
|
||||
int retval;
|
||||
} OnlineData;
|
||||
|
||||
static gint64
|
||||
_now_ms (void)
|
||||
_now_ms(void)
|
||||
{
|
||||
return g_get_monotonic_time () / (G_USEC_PER_SEC / 1000);
|
||||
return g_get_monotonic_time() / (G_USEC_PER_SEC / 1000);
|
||||
}
|
||||
|
||||
static void
|
||||
_return (OnlineData *data, int retval)
|
||||
_return(OnlineData *data, int retval)
|
||||
{
|
||||
nm_assert (data);
|
||||
nm_assert (data->retval == EXIT_FAILURE_UNSPECIFIED);
|
||||
nm_assert(data);
|
||||
nm_assert(data->retval == EXIT_FAILURE_UNSPECIFIED);
|
||||
|
||||
data->retval = retval;
|
||||
nm_clear_g_signal_handler (data->client, &data->client_notify_id);
|
||||
g_main_loop_quit (data->loop);
|
||||
data->retval = retval;
|
||||
nm_clear_g_signal_handler(data->client, &data->client_notify_id);
|
||||
g_main_loop_quit(data->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
_print_progress (gboolean wait_startup, int progress_next_step_i, gint64 remaining_ms, int retval)
|
||||
_print_progress(gboolean wait_startup, int progress_next_step_i, gint64 remaining_ms, int retval)
|
||||
{
|
||||
int i, j;
|
||||
int i, j;
|
||||
|
||||
j = progress_next_step_i < 0 ? PROGRESS_STEPS : progress_next_step_i;
|
||||
j = progress_next_step_i < 0 ? PROGRESS_STEPS : progress_next_step_i;
|
||||
|
||||
g_print ("\r%s", _("Connecting"));
|
||||
for (i = 0; i < PROGRESS_STEPS; i++)
|
||||
putchar (i < j ? '.' : ' ');
|
||||
g_print (" %4lds", (long) (MAX (0, remaining_ms + 999) / 1000));
|
||||
if (retval != EXIT_NONE) {
|
||||
const char *result;
|
||||
g_print("\r%s", _("Connecting"));
|
||||
for (i = 0; i < PROGRESS_STEPS; i++)
|
||||
putchar(i < j ? '.' : ' ');
|
||||
g_print(" %4lds", (long) (MAX(0, remaining_ms + 999) / 1000));
|
||||
if (retval != EXIT_NONE) {
|
||||
const char *result;
|
||||
|
||||
if (wait_startup) {
|
||||
if (retval == EXIT_SUCCESS)
|
||||
result = "started";
|
||||
else if (retval == EXIT_FAILURE_OFFLINE)
|
||||
result = "startup-pending";
|
||||
else
|
||||
result = "failure";
|
||||
}
|
||||
else {
|
||||
if (retval == EXIT_SUCCESS)
|
||||
result = "online";
|
||||
else
|
||||
result = "offline";
|
||||
}
|
||||
if (wait_startup) {
|
||||
if (retval == EXIT_SUCCESS)
|
||||
result = "started";
|
||||
else if (retval == EXIT_FAILURE_OFFLINE)
|
||||
result = "startup-pending";
|
||||
else
|
||||
result = "failure";
|
||||
} else {
|
||||
if (retval == EXIT_SUCCESS)
|
||||
result = "online";
|
||||
else
|
||||
result = "offline";
|
||||
}
|
||||
|
||||
g_print (" [%s]\n", result);
|
||||
}
|
||||
fflush (stdout);
|
||||
g_print(" [%s]\n", result);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
quit_if_connected (OnlineData *data)
|
||||
quit_if_connected(OnlineData *data)
|
||||
{
|
||||
NMState state;
|
||||
NMState state;
|
||||
|
||||
state = nm_client_get_state (data->client);
|
||||
if (!nm_client_get_nm_running (data->client)) {
|
||||
if (data->exit_no_nm) {
|
||||
_return (data, EXIT_FAILURE_OFFLINE);
|
||||
return TRUE;
|
||||
}
|
||||
} else if (data->wait_startup) {
|
||||
if (!nm_client_get_startup (data->client)) {
|
||||
_return (data, EXIT_SUCCESS);
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
if ( state == NM_STATE_CONNECTED_LOCAL
|
||||
|| state == NM_STATE_CONNECTED_SITE
|
||||
|| state == NM_STATE_CONNECTED_GLOBAL) {
|
||||
_return (data, EXIT_SUCCESS);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (data->exit_no_nm && (state != NM_STATE_CONNECTING)) {
|
||||
_return (data, EXIT_FAILURE_OFFLINE);
|
||||
return TRUE;
|
||||
}
|
||||
state = nm_client_get_state(data->client);
|
||||
if (!nm_client_get_nm_running(data->client)) {
|
||||
if (data->exit_no_nm) {
|
||||
_return(data, EXIT_FAILURE_OFFLINE);
|
||||
return TRUE;
|
||||
}
|
||||
} else if (data->wait_startup) {
|
||||
if (!nm_client_get_startup(data->client)) {
|
||||
_return(data, EXIT_SUCCESS);
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
if (state == NM_STATE_CONNECTED_LOCAL || state == NM_STATE_CONNECTED_SITE
|
||||
|| state == NM_STATE_CONNECTED_GLOBAL) {
|
||||
_return(data, EXIT_SUCCESS);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (data->exit_no_nm && (state != NM_STATE_CONNECTING)) {
|
||||
_return(data, EXIT_FAILURE_OFFLINE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
client_properties_changed (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
client_properties_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
quit_if_connected (user_data);
|
||||
quit_if_connected(user_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_timeout (gpointer user_data)
|
||||
handle_timeout(gpointer user_data)
|
||||
{
|
||||
OnlineData *data = user_data;
|
||||
const gint64 now = _now_ms ();
|
||||
gint64 remaining_ms = data->end_timestamp_ms - now;
|
||||
const gint64 elapsed_ms = now - data->start_timestamp_ms;
|
||||
int progress_next_step_i = 0;
|
||||
OnlineData * data = user_data;
|
||||
const gint64 now = _now_ms();
|
||||
gint64 remaining_ms = data->end_timestamp_ms - now;
|
||||
const gint64 elapsed_ms = now - data->start_timestamp_ms;
|
||||
int progress_next_step_i = 0;
|
||||
|
||||
data->handle_timeout_id = 0;
|
||||
data->handle_timeout_id = 0;
|
||||
|
||||
if (remaining_ms <= 3) {
|
||||
_return (data, EXIT_FAILURE_OFFLINE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
if (remaining_ms <= 3) {
|
||||
_return(data, EXIT_FAILURE_OFFLINE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
if (!data->quiet) {
|
||||
gint64 rem;
|
||||
if (!data->quiet) {
|
||||
gint64 rem;
|
||||
|
||||
/* calculate the next step (not the current): floor()+1 */
|
||||
progress_next_step_i = NM_MIN ((elapsed_ms / data->progress_step_duration) + 1, PROGRESS_STEPS);
|
||||
_print_progress (data->wait_startup, progress_next_step_i, remaining_ms, EXIT_NONE);
|
||||
/* calculate the next step (not the current): floor()+1 */
|
||||
progress_next_step_i =
|
||||
NM_MIN((elapsed_ms / data->progress_step_duration) + 1, PROGRESS_STEPS);
|
||||
_print_progress(data->wait_startup, progress_next_step_i, remaining_ms, EXIT_NONE);
|
||||
|
||||
/* synchronize the timeout with the ticking of the seconds. */
|
||||
rem = remaining_ms % 1000;
|
||||
if (rem <= 3)
|
||||
rem = rem + G_USEC_PER_SEC;
|
||||
/* add small offset to awake a bit after the second ticks */
|
||||
remaining_ms = NM_MIN (remaining_ms, rem + 10);
|
||||
/* synchronize the timeout with the ticking of the seconds. */
|
||||
rem = remaining_ms % 1000;
|
||||
if (rem <= 3)
|
||||
rem = rem + G_USEC_PER_SEC;
|
||||
/* add small offset to awake a bit after the second ticks */
|
||||
remaining_ms = NM_MIN(remaining_ms, rem + 10);
|
||||
|
||||
/* synchronize the timeout with the steps of the progress bar. */
|
||||
rem = (progress_next_step_i * data->progress_step_duration) - elapsed_ms;
|
||||
if (rem <= 3)
|
||||
rem = rem + data->progress_step_duration;
|
||||
/* add small offset to awake a bit after the second ticks */
|
||||
remaining_ms = NM_MIN (remaining_ms, rem + 10);
|
||||
}
|
||||
/* synchronize the timeout with the steps of the progress bar. */
|
||||
rem = (progress_next_step_i * data->progress_step_duration) - elapsed_ms;
|
||||
if (rem <= 3)
|
||||
rem = rem + data->progress_step_duration;
|
||||
/* add small offset to awake a bit after the second ticks */
|
||||
remaining_ms = NM_MIN(remaining_ms, rem + 10);
|
||||
}
|
||||
|
||||
data->handle_timeout_id = g_timeout_add (remaining_ms, handle_timeout, data);
|
||||
return G_SOURCE_REMOVE;
|
||||
data->handle_timeout_id = g_timeout_add(remaining_ms, handle_timeout, data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
got_client_timeout (gpointer user_data)
|
||||
got_client_timeout(gpointer user_data)
|
||||
{
|
||||
OnlineData *data = user_data;
|
||||
OnlineData *data = user_data;
|
||||
|
||||
data->client_new_timeout_id = 0;
|
||||
data->quiet = TRUE;
|
||||
g_printerr (_("Error: timeout creating NMClient object\n"));
|
||||
_return (data, EXIT_FAILURE_LIBNM_BUG);
|
||||
return G_SOURCE_REMOVE;
|
||||
data->client_new_timeout_id = 0;
|
||||
data->quiet = TRUE;
|
||||
g_printerr(_("Error: timeout creating NMClient object\n"));
|
||||
_return(data, EXIT_FAILURE_LIBNM_BUG);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
got_client (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
got_client(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
OnlineData *data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMClient *client;
|
||||
OnlineData * data = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_clear_g_source (&data->client_new_timeout_id);
|
||||
g_clear_object (&data->client_new_cancellable);
|
||||
nm_assert(NM_IS_CLIENT(source_object));
|
||||
nm_assert(NM_CLIENT(source_object) == data->client);
|
||||
|
||||
client = nm_client_new_finish (res, &error);
|
||||
if (!client) {
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
data->quiet = TRUE;
|
||||
g_printerr (_("Error: Could not create NMClient object: %s\n"),
|
||||
error->message);
|
||||
_return (data, EXIT_FAILURE_ERROR);
|
||||
return;
|
||||
}
|
||||
nm_clear_g_source(&data->client_new_timeout_id);
|
||||
g_clear_object(&data->client_new_cancellable);
|
||||
|
||||
data->client = client;
|
||||
if (!g_async_initable_init_finish(G_ASYNC_INITABLE(source_object), res, &error)) {
|
||||
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
data->quiet = TRUE;
|
||||
g_printerr(_("Error: Could not create NMClient object: %s\n"), error->message);
|
||||
_return(data, EXIT_FAILURE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quit_if_connected (data))
|
||||
return;
|
||||
if (quit_if_connected(data))
|
||||
return;
|
||||
|
||||
data->client_notify_id = g_signal_connect (data->client, "notify",
|
||||
G_CALLBACK (client_properties_changed), data);
|
||||
data->handle_timeout_id = g_timeout_add (data->quiet ? NM_MAX (0, data->end_timestamp_ms - _now_ms ()) : 0, handle_timeout, data);
|
||||
data->client_notify_id =
|
||||
g_signal_connect(data->client, "notify", G_CALLBACK(client_properties_changed), data);
|
||||
data->handle_timeout_id =
|
||||
g_timeout_add(data->quiet ? NM_MAX(0, data->end_timestamp_ms - _now_ms()) : 0,
|
||||
handle_timeout,
|
||||
data);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
OnlineData data = {
|
||||
.retval = EXIT_FAILURE_UNSPECIFIED,
|
||||
};
|
||||
int t_secs = 30;
|
||||
GOptionContext *opt_ctx = NULL;
|
||||
gboolean success;
|
||||
GOptionEntry options[] = {
|
||||
{"quiet", 'q', 0, G_OPTION_ARG_NONE, &data.quiet, N_("Don't print anything"), NULL},
|
||||
{"wait-for-startup", 's', 0, G_OPTION_ARG_NONE, &data.wait_startup, N_("Wait for NetworkManager startup instead of a connection"), NULL},
|
||||
{"timeout", 't', 0, G_OPTION_ARG_INT, &t_secs, N_("Time to wait for a connection, in seconds (without the option, default value is 30)"), "<timeout>"},
|
||||
{"exit", 'x', 0, G_OPTION_ARG_NONE, &data.exit_no_nm, N_("Exit immediately if NetworkManager is not running or connecting"), NULL},
|
||||
{ NULL },
|
||||
};
|
||||
OnlineData data = {
|
||||
.retval = EXIT_FAILURE_UNSPECIFIED,
|
||||
};
|
||||
int t_secs;
|
||||
GOptionContext *opt_ctx = NULL;
|
||||
gboolean success;
|
||||
GOptionEntry options[] = {
|
||||
{"quiet", 'q', 0, G_OPTION_ARG_NONE, &data.quiet, N_("Don't print anything"), NULL},
|
||||
{"wait-for-startup",
|
||||
's',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&data.wait_startup,
|
||||
N_("Wait for NetworkManager startup instead of a connection"),
|
||||
NULL},
|
||||
{"timeout",
|
||||
't',
|
||||
0,
|
||||
G_OPTION_ARG_INT,
|
||||
&t_secs,
|
||||
N_("Time to wait for a connection, in seconds (without the option, default value is 30)"),
|
||||
"<timeout>"},
|
||||
{"exit",
|
||||
'x',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&data.exit_no_nm,
|
||||
N_("Exit immediately if NetworkManager is not running or connecting"),
|
||||
NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Set locale to be able to use environment variables */
|
||||
setlocale (LC_ALL, "");
|
||||
/* Set locale to be able to use environment variables */
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
bindtextdomain(GETTEXT_PACKAGE, NMLOCALEDIR);
|
||||
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain(GETTEXT_PACKAGE);
|
||||
|
||||
data.start_timestamp_ms = _now_ms ();
|
||||
t_secs = _nm_utils_ascii_str_to_int64(g_getenv("NM_ONLINE_TIMEOUT"), 10, 0, G_MAXINT, 30);
|
||||
|
||||
opt_ctx = g_option_context_new (NULL);
|
||||
g_option_context_set_translation_domain (opt_ctx, GETTEXT_PACKAGE);
|
||||
g_option_context_set_ignore_unknown_options (opt_ctx, FALSE);
|
||||
g_option_context_set_help_enabled (opt_ctx, TRUE);
|
||||
g_option_context_add_main_entries (opt_ctx, options, NULL);
|
||||
data.start_timestamp_ms = _now_ms();
|
||||
|
||||
g_option_context_set_summary (opt_ctx,
|
||||
_("Waits for NetworkManager to finish activating startup network connections."));
|
||||
opt_ctx = g_option_context_new(NULL);
|
||||
g_option_context_set_translation_domain(opt_ctx, GETTEXT_PACKAGE);
|
||||
g_option_context_set_ignore_unknown_options(opt_ctx, FALSE);
|
||||
g_option_context_set_help_enabled(opt_ctx, TRUE);
|
||||
g_option_context_add_main_entries(opt_ctx, options, NULL);
|
||||
|
||||
success = g_option_context_parse (opt_ctx, &argc, &argv, NULL);
|
||||
g_option_context_free (opt_ctx);
|
||||
g_option_context_set_summary(
|
||||
opt_ctx,
|
||||
_("Waits for NetworkManager to finish activating startup network connections."));
|
||||
|
||||
if (!success) {
|
||||
g_printerr ("%s: %s\n", argv[0],
|
||||
_("Invalid option. Please use --help to see a list of valid options."));
|
||||
return EXIT_FAILURE_ERROR;
|
||||
}
|
||||
success = g_option_context_parse(opt_ctx, &argc, &argv, NULL);
|
||||
g_option_context_free(opt_ctx);
|
||||
|
||||
if (t_secs < 0 || t_secs > 3600) {
|
||||
g_printerr ("%s: %s\n", argv[0],
|
||||
_("Invalid option. Please use --help to see a list of valid options."));
|
||||
return EXIT_FAILURE_ERROR;
|
||||
}
|
||||
if (!success) {
|
||||
g_printerr("%s: %s\n",
|
||||
argv[0],
|
||||
_("Invalid option. Please use --help to see a list of valid options."));
|
||||
return EXIT_FAILURE_ERROR;
|
||||
}
|
||||
|
||||
if (t_secs == 0)
|
||||
data.quiet = TRUE;
|
||||
if (t_secs < 0 || t_secs > 3600) {
|
||||
g_printerr("%s: %s\n",
|
||||
argv[0],
|
||||
_("Invalid option. Please use --help to see a list of valid options."));
|
||||
return EXIT_FAILURE_ERROR;
|
||||
}
|
||||
|
||||
data.loop = g_main_loop_new (NULL, FALSE);
|
||||
if (t_secs == 0)
|
||||
data.quiet = TRUE;
|
||||
|
||||
data.end_timestamp_ms = data.start_timestamp_ms + (t_secs * 1000);
|
||||
data.progress_step_duration = NM_MAX (1, (data.end_timestamp_ms - data.start_timestamp_ms + PROGRESS_STEPS/2) / PROGRESS_STEPS);
|
||||
data.loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
data.client_new_cancellable = g_cancellable_new ();
|
||||
data.end_timestamp_ms = data.start_timestamp_ms + (t_secs * 1000);
|
||||
data.progress_step_duration = NM_MAX(
|
||||
1,
|
||||
(data.end_timestamp_ms - data.start_timestamp_ms + PROGRESS_STEPS / 2) / PROGRESS_STEPS);
|
||||
|
||||
data.client_new_timeout_id = g_timeout_add_seconds (30, got_client_timeout, &data);
|
||||
nm_client_new_async (data.client_new_cancellable, got_client, &data);
|
||||
data.client_new_cancellable = g_cancellable_new();
|
||||
|
||||
g_main_loop_run (data.loop);
|
||||
data.client_new_timeout_id = g_timeout_add_seconds(30, got_client_timeout, &data);
|
||||
|
||||
nm_clear_g_cancellable (&data.client_new_cancellable);
|
||||
nm_clear_g_source (&data.client_new_timeout_id);
|
||||
nm_clear_g_source (&data.handle_timeout_id);
|
||||
nm_clear_g_signal_handler (data.client, &data.client_notify_id);
|
||||
g_clear_object (&data.client);
|
||||
data.client = nmc_client_new_async(data.client_new_cancellable,
|
||||
got_client,
|
||||
&data,
|
||||
NM_CLIENT_INSTANCE_FLAGS,
|
||||
(guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
|
||||
NULL);
|
||||
|
||||
g_clear_pointer (&data.loop, g_main_loop_unref);
|
||||
g_main_loop_run(data.loop);
|
||||
|
||||
if (!data.quiet)
|
||||
_print_progress (data.wait_startup, -1, NM_MAX (0, data.end_timestamp_ms - _now_ms ()), data.retval);
|
||||
nm_clear_g_cancellable(&data.client_new_cancellable);
|
||||
nm_clear_g_source(&data.client_new_timeout_id);
|
||||
nm_clear_g_source(&data.handle_timeout_id);
|
||||
nm_clear_g_signal_handler(data.client, &data.client_notify_id);
|
||||
g_clear_object(&data.client);
|
||||
|
||||
return data.retval;
|
||||
nm_clear_pointer(&data.loop, g_main_loop_unref);
|
||||
|
||||
if (!data.quiet)
|
||||
_print_progress(data.wait_startup,
|
||||
-1,
|
||||
NM_MAX(0, data.end_timestamp_ms - _now_ms()),
|
||||
data.retval);
|
||||
|
||||
return data.retval;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,3 +1,5 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
name = 'nmtui'
|
||||
|
||||
common_c_flags = clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)]
|
||||
|
|
@ -51,6 +53,7 @@ deps = [
|
|||
libnmc_base_dep,
|
||||
libnmc_dep,
|
||||
libnmt_newt_dep,
|
||||
libnm_libnm_aux_dep,
|
||||
]
|
||||
|
||||
executable(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
sources = files(
|
||||
'nmt-newt-button-box.c',
|
||||
'nmt-newt-button.c',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -22,21 +22,22 @@
|
|||
|
||||
#include "nmt-newt-button.h"
|
||||
|
||||
G_DEFINE_TYPE (NmtNewtButtonBox, nmt_newt_button_box, NMT_TYPE_NEWT_CONTAINER)
|
||||
G_DEFINE_TYPE(NmtNewtButtonBox, nmt_newt_button_box, NMT_TYPE_NEWT_CONTAINER)
|
||||
|
||||
#define NMT_NEWT_BUTTON_BOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBoxPrivate))
|
||||
#define NMT_NEWT_BUTTON_BOX_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBoxPrivate))
|
||||
|
||||
typedef struct {
|
||||
NmtNewtButtonBoxOrientation orientation;
|
||||
GPtrArray *start_buttons, *end_buttons;
|
||||
NmtNewtButtonBoxOrientation orientation;
|
||||
GPtrArray * start_buttons, *end_buttons;
|
||||
} NmtNewtButtonBoxPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_0,
|
||||
|
||||
PROP_ORIENTATION,
|
||||
PROP_ORIENTATION,
|
||||
|
||||
LAST_PROP
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -56,20 +57,18 @@ enum {
|
|||
* Returns: a new #NmtNewtButtonBox
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_button_box_new (NmtNewtButtonBoxOrientation orientation)
|
||||
nmt_newt_button_box_new(NmtNewtButtonBoxOrientation orientation)
|
||||
{
|
||||
return g_object_new (NMT_TYPE_NEWT_BUTTON_BOX,
|
||||
"orientation", orientation,
|
||||
NULL);
|
||||
return g_object_new(NMT_TYPE_NEWT_BUTTON_BOX, "orientation", orientation, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_init (NmtNewtButtonBox *bbox)
|
||||
nmt_newt_button_box_init(NmtNewtButtonBox *bbox)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (bbox);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(bbox);
|
||||
|
||||
priv->start_buttons = g_ptr_array_new ();
|
||||
priv->end_buttons = g_ptr_array_new ();
|
||||
priv->start_buttons = g_ptr_array_new();
|
||||
priv->end_buttons = g_ptr_array_new();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,14 +83,13 @@ nmt_newt_button_box_init (NmtNewtButtonBox *bbox)
|
|||
* Returns: the newly-created button, already added to @bbox
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_button_box_add_start (NmtNewtButtonBox *bbox,
|
||||
const char *label)
|
||||
nmt_newt_button_box_add_start(NmtNewtButtonBox *bbox, const char *label)
|
||||
{
|
||||
NmtNewtWidget *button;
|
||||
NmtNewtWidget *button;
|
||||
|
||||
button = nmt_newt_button_new (label);
|
||||
nmt_newt_button_box_add_widget_start (bbox, button);
|
||||
return button;
|
||||
button = nmt_newt_button_new(label);
|
||||
nmt_newt_button_box_add_widget_start(bbox, button);
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -102,14 +100,13 @@ nmt_newt_button_box_add_start (NmtNewtButtonBox *bbox,
|
|||
* Adds the given widget to the "start" section of @bbox.
|
||||
*/
|
||||
void
|
||||
nmt_newt_button_box_add_widget_start (NmtNewtButtonBox *bbox,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_button_box_add_widget_start(NmtNewtButtonBox *bbox, NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (bbox);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(bbox);
|
||||
|
||||
NMT_NEWT_CONTAINER_CLASS (nmt_newt_button_box_parent_class)->
|
||||
add (NMT_NEWT_CONTAINER (bbox), widget);
|
||||
g_ptr_array_add (priv->start_buttons, widget);
|
||||
NMT_NEWT_CONTAINER_CLASS(nmt_newt_button_box_parent_class)
|
||||
->add(NMT_NEWT_CONTAINER(bbox), widget);
|
||||
g_ptr_array_add(priv->start_buttons, widget);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,14 +121,13 @@ nmt_newt_button_box_add_widget_start (NmtNewtButtonBox *bbox,
|
|||
* Returns: the newly-created button, already added to @bbox
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_button_box_add_end (NmtNewtButtonBox *bbox,
|
||||
const char *label)
|
||||
nmt_newt_button_box_add_end(NmtNewtButtonBox *bbox, const char *label)
|
||||
{
|
||||
NmtNewtWidget *button;
|
||||
NmtNewtWidget *button;
|
||||
|
||||
button = nmt_newt_button_new (label);
|
||||
nmt_newt_button_box_add_widget_end (bbox, button);
|
||||
return button;
|
||||
button = nmt_newt_button_new(label);
|
||||
nmt_newt_button_box_add_widget_end(bbox, button);
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -142,229 +138,221 @@ nmt_newt_button_box_add_end (NmtNewtButtonBox *bbox,
|
|||
* Adds the given widget to the "end" section of @bbox.
|
||||
*/
|
||||
void
|
||||
nmt_newt_button_box_add_widget_end (NmtNewtButtonBox *bbox,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_button_box_add_widget_end(NmtNewtButtonBox *bbox, NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (bbox);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(bbox);
|
||||
|
||||
NMT_NEWT_CONTAINER_CLASS (nmt_newt_button_box_parent_class)->
|
||||
add (NMT_NEWT_CONTAINER (bbox), widget);
|
||||
g_ptr_array_add (priv->end_buttons, widget);
|
||||
NMT_NEWT_CONTAINER_CLASS(nmt_newt_button_box_parent_class)
|
||||
->add(NMT_NEWT_CONTAINER(bbox), widget);
|
||||
g_ptr_array_add(priv->end_buttons, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_remove (NmtNewtContainer *container,
|
||||
NmtNewtWidget *child)
|
||||
nmt_newt_button_box_remove(NmtNewtContainer *container, NmtNewtWidget *child)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (container);
|
||||
int i;
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(container);
|
||||
int i;
|
||||
|
||||
NMT_NEWT_CONTAINER_CLASS (nmt_newt_button_box_parent_class)->
|
||||
remove (container, child);
|
||||
NMT_NEWT_CONTAINER_CLASS(nmt_newt_button_box_parent_class)->remove(container, child);
|
||||
|
||||
for (i = 0; i < priv->start_buttons->len; i++) {
|
||||
if (priv->start_buttons->pdata[i] == (gpointer) child) {
|
||||
g_ptr_array_remove_index (priv->start_buttons, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < priv->end_buttons->len; i++) {
|
||||
if (priv->end_buttons->pdata[i] == (gpointer) child) {
|
||||
g_ptr_array_remove_index (priv->end_buttons, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < priv->start_buttons->len; i++) {
|
||||
if (priv->start_buttons->pdata[i] == (gpointer) child) {
|
||||
g_ptr_array_remove_index(priv->start_buttons, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < priv->end_buttons->len; i++) {
|
||||
if (priv->end_buttons->pdata[i] == (gpointer) child) {
|
||||
g_ptr_array_remove_index(priv->end_buttons, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_buttons (GPtrArray *buttons, GPtrArray *cos)
|
||||
add_buttons(GPtrArray *buttons, GPtrArray *cos)
|
||||
{
|
||||
NmtNewtWidget *child;
|
||||
newtComponent *child_cos;
|
||||
int i, c;
|
||||
NmtNewtWidget *child;
|
||||
newtComponent *child_cos;
|
||||
int i, c;
|
||||
|
||||
for (i = 0; i < buttons->len; i++) {
|
||||
child = buttons->pdata[i];
|
||||
for (i = 0; i < buttons->len; i++) {
|
||||
child = buttons->pdata[i];
|
||||
|
||||
if (!nmt_newt_widget_get_visible (child))
|
||||
continue;
|
||||
if (!nmt_newt_widget_get_visible(child))
|
||||
continue;
|
||||
|
||||
child_cos = nmt_newt_widget_get_components (child);
|
||||
for (c = 0; child_cos[c]; c++)
|
||||
g_ptr_array_add (cos, child_cos[c]);
|
||||
g_free (child_cos);
|
||||
}
|
||||
child_cos = nmt_newt_widget_get_components(child);
|
||||
for (c = 0; child_cos[c]; c++)
|
||||
g_ptr_array_add(cos, child_cos[c]);
|
||||
g_free(child_cos);
|
||||
}
|
||||
}
|
||||
|
||||
static newtComponent *
|
||||
nmt_newt_button_box_get_components (NmtNewtWidget *widget)
|
||||
nmt_newt_button_box_get_components(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (widget);
|
||||
GPtrArray *cos;
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(widget);
|
||||
GPtrArray * cos;
|
||||
|
||||
cos = g_ptr_array_new ();
|
||||
add_buttons (priv->start_buttons, cos);
|
||||
add_buttons (priv->end_buttons, cos);
|
||||
g_ptr_array_add (cos, NULL);
|
||||
cos = g_ptr_array_new();
|
||||
add_buttons(priv->start_buttons, cos);
|
||||
add_buttons(priv->end_buttons, cos);
|
||||
g_ptr_array_add(cos, NULL);
|
||||
|
||||
return (newtComponent *) g_ptr_array_free (cos, FALSE);
|
||||
return (newtComponent *) g_ptr_array_free(cos, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
size_request_buttons (NmtNewtButtonBox *bbox,
|
||||
GPtrArray *buttons,
|
||||
int *width,
|
||||
int *height)
|
||||
size_request_buttons(NmtNewtButtonBox *bbox, GPtrArray *buttons, int *width, int *height)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (bbox);
|
||||
int child_width, child_height;
|
||||
int i;
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(bbox);
|
||||
int child_width, child_height;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buttons->len; i++) {
|
||||
NmtNewtWidget *child = buttons->pdata[i];
|
||||
for (i = 0; i < buttons->len; i++) {
|
||||
NmtNewtWidget *child = buttons->pdata[i];
|
||||
|
||||
nmt_newt_widget_size_request (child, &child_width, &child_height);
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
|
||||
*width += child_width;
|
||||
if (i > 0)
|
||||
*width += 1;
|
||||
*height = MAX (*height, child_height);
|
||||
} else {
|
||||
*height += child_height;
|
||||
if (i > 0)
|
||||
*height += 1;
|
||||
*width = MAX (*width, child_width);
|
||||
}
|
||||
}
|
||||
nmt_newt_widget_size_request(child, &child_width, &child_height);
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
|
||||
*width += child_width;
|
||||
if (i > 0)
|
||||
*width += 1;
|
||||
*height = MAX(*height, child_height);
|
||||
} else {
|
||||
*height += child_height;
|
||||
if (i > 0)
|
||||
*height += 1;
|
||||
*width = MAX(*width, child_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_size_request (NmtNewtWidget *widget,
|
||||
int *width,
|
||||
int *height)
|
||||
nmt_newt_button_box_size_request(NmtNewtWidget *widget, int *width, int *height)
|
||||
{
|
||||
NmtNewtButtonBox *bbox = NMT_NEWT_BUTTON_BOX (widget);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (widget);
|
||||
NmtNewtButtonBox * bbox = NMT_NEWT_BUTTON_BOX(widget);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(widget);
|
||||
|
||||
*width = *height = 0;
|
||||
size_request_buttons (bbox, priv->start_buttons, width, height);
|
||||
size_request_buttons (bbox, priv->end_buttons, width, height);
|
||||
*width = *height = 0;
|
||||
size_request_buttons(bbox, priv->start_buttons, width, height);
|
||||
size_request_buttons(bbox, priv->end_buttons, width, height);
|
||||
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL)
|
||||
*width += 1;
|
||||
else
|
||||
*height += 1;
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL)
|
||||
*width += 1;
|
||||
else
|
||||
*height += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_size_allocate (NmtNewtWidget *widget,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
nmt_newt_button_box_size_allocate(NmtNewtWidget *widget, int x, int y, int width, int height)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (widget);
|
||||
NmtNewtWidget *child;
|
||||
int child_x, child_y, child_width, child_height;
|
||||
int i;
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(widget);
|
||||
NmtNewtWidget * child;
|
||||
int child_x, child_y, child_width, child_height;
|
||||
int i;
|
||||
|
||||
child_x = x;
|
||||
child_y = y;
|
||||
for (i = 0; i < priv->start_buttons->len; i++) {
|
||||
child = priv->start_buttons->pdata[i];
|
||||
nmt_newt_widget_size_request (child, &child_width, &child_height);
|
||||
child_x = x;
|
||||
child_y = y;
|
||||
for (i = 0; i < priv->start_buttons->len; i++) {
|
||||
child = priv->start_buttons->pdata[i];
|
||||
nmt_newt_widget_size_request(child, &child_width, &child_height);
|
||||
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
|
||||
nmt_newt_widget_size_allocate (child, child_x, child_y, child_width, child_height);
|
||||
child_x += child_width + 1;
|
||||
} else {
|
||||
nmt_newt_widget_size_allocate (child, child_x, child_y, child_width, child_height);
|
||||
child_y += child_height + 1;
|
||||
}
|
||||
}
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
|
||||
nmt_newt_widget_size_allocate(child, child_x, child_y, child_width, child_height);
|
||||
child_x += child_width + 1;
|
||||
} else {
|
||||
nmt_newt_widget_size_allocate(child, child_x, child_y, child_width, child_height);
|
||||
child_y += child_height + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL)
|
||||
child_x = x + width;
|
||||
else
|
||||
child_y = y + height;
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL)
|
||||
child_x = x + width;
|
||||
else
|
||||
child_y = y + height;
|
||||
|
||||
for (i = priv->end_buttons->len - 1; i >= 0; i--) {
|
||||
child = priv->end_buttons->pdata[i];
|
||||
nmt_newt_widget_size_request (child, &child_width, &child_height);
|
||||
for (i = priv->end_buttons->len - 1; i >= 0; i--) {
|
||||
child = priv->end_buttons->pdata[i];
|
||||
nmt_newt_widget_size_request(child, &child_width, &child_height);
|
||||
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
|
||||
nmt_newt_widget_size_allocate (child,
|
||||
child_x - child_width, child_y,
|
||||
child_width, child_height);
|
||||
child_x -= child_width + 1;
|
||||
} else {
|
||||
nmt_newt_widget_size_allocate (child,
|
||||
child_x, child_y - child_height,
|
||||
child_width, child_height);
|
||||
child_y -= child_height + 1;
|
||||
}
|
||||
}
|
||||
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
|
||||
nmt_newt_widget_size_allocate(child,
|
||||
child_x - child_width,
|
||||
child_y,
|
||||
child_width,
|
||||
child_height);
|
||||
child_x -= child_width + 1;
|
||||
} else {
|
||||
nmt_newt_widget_size_allocate(child,
|
||||
child_x,
|
||||
child_y - child_height,
|
||||
child_width,
|
||||
child_height);
|
||||
child_y -= child_height + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_button_box_set_property(GObject * object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (object);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ORIENTATION:
|
||||
priv->orientation = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_ORIENTATION:
|
||||
priv->orientation = g_value_get_int(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_button_box_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE (object);
|
||||
NmtNewtButtonBoxPrivate *priv = NMT_NEWT_BUTTON_BOX_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_int (value, priv->orientation);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_int(value, priv->orientation);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_box_class_init (NmtNewtButtonBoxClass *bbox_class)
|
||||
nmt_newt_button_box_class_init(NmtNewtButtonBoxClass *bbox_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (bbox_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (bbox_class);
|
||||
NmtNewtContainerClass *container_class = NMT_NEWT_CONTAINER_CLASS (bbox_class);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(bbox_class);
|
||||
NmtNewtWidgetClass * widget_class = NMT_NEWT_WIDGET_CLASS(bbox_class);
|
||||
NmtNewtContainerClass *container_class = NMT_NEWT_CONTAINER_CLASS(bbox_class);
|
||||
|
||||
g_type_class_add_private (bbox_class, sizeof (NmtNewtButtonBoxPrivate));
|
||||
g_type_class_add_private(bbox_class, sizeof(NmtNewtButtonBoxPrivate));
|
||||
|
||||
object_class->get_property = nmt_newt_button_box_get_property;
|
||||
object_class->set_property = nmt_newt_button_box_set_property;
|
||||
object_class->get_property = nmt_newt_button_box_get_property;
|
||||
object_class->set_property = nmt_newt_button_box_set_property;
|
||||
|
||||
widget_class->get_components = nmt_newt_button_box_get_components;
|
||||
widget_class->size_request = nmt_newt_button_box_size_request;
|
||||
widget_class->size_allocate = nmt_newt_button_box_size_allocate;
|
||||
widget_class->get_components = nmt_newt_button_box_get_components;
|
||||
widget_class->size_request = nmt_newt_button_box_size_request;
|
||||
widget_class->size_allocate = nmt_newt_button_box_size_allocate;
|
||||
|
||||
container_class->remove = nmt_newt_button_box_remove;
|
||||
container_class->remove = nmt_newt_button_box_remove;
|
||||
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_ORIENTATION,
|
||||
g_param_spec_int ("orientation", "", "",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_ORIENTATION,
|
||||
g_param_spec_int("orientation",
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,40 +8,39 @@
|
|||
|
||||
#include "nmt-newt-grid.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_BUTTON_BOX (nmt_newt_button_box_get_type ())
|
||||
#define NMT_NEWT_BUTTON_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBox))
|
||||
#define NMT_NEWT_BUTTON_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBoxClass))
|
||||
#define NMT_IS_NEWT_BUTTON_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_BUTTON_BOX))
|
||||
#define NMT_IS_NEWT_BUTTON_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_BUTTON_BOX))
|
||||
#define NMT_NEWT_BUTTON_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBoxClass))
|
||||
#define NMT_TYPE_NEWT_BUTTON_BOX (nmt_newt_button_box_get_type())
|
||||
#define NMT_NEWT_BUTTON_BOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBox))
|
||||
#define NMT_NEWT_BUTTON_BOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBoxClass))
|
||||
#define NMT_IS_NEWT_BUTTON_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_BUTTON_BOX))
|
||||
#define NMT_IS_NEWT_BUTTON_BOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_BUTTON_BOX))
|
||||
#define NMT_NEWT_BUTTON_BOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_BUTTON_BOX, NmtNewtButtonBoxClass))
|
||||
|
||||
struct _NmtNewtButtonBox {
|
||||
NmtNewtContainer parent;
|
||||
|
||||
NmtNewtContainer parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtContainerClass parent;
|
||||
NmtNewtContainerClass parent;
|
||||
|
||||
} NmtNewtButtonBoxClass;
|
||||
|
||||
GType nmt_newt_button_box_get_type (void);
|
||||
GType nmt_newt_button_box_get_type(void);
|
||||
|
||||
typedef enum {
|
||||
NMT_NEWT_BUTTON_BOX_HORIZONTAL,
|
||||
NMT_NEWT_BUTTON_BOX_VERTICAL
|
||||
NMT_NEWT_BUTTON_BOX_HORIZONTAL,
|
||||
NMT_NEWT_BUTTON_BOX_VERTICAL
|
||||
} NmtNewtButtonBoxOrientation;
|
||||
|
||||
NmtNewtWidget *nmt_newt_button_box_new (NmtNewtButtonBoxOrientation orientation);
|
||||
NmtNewtWidget *nmt_newt_button_box_new(NmtNewtButtonBoxOrientation orientation);
|
||||
|
||||
NmtNewtWidget *nmt_newt_button_box_add_start (NmtNewtButtonBox *bbox,
|
||||
const char *label);
|
||||
NmtNewtWidget *nmt_newt_button_box_add_end (NmtNewtButtonBox *bbox,
|
||||
const char *label);
|
||||
NmtNewtWidget *nmt_newt_button_box_add_start(NmtNewtButtonBox *bbox, const char *label);
|
||||
NmtNewtWidget *nmt_newt_button_box_add_end(NmtNewtButtonBox *bbox, const char *label);
|
||||
|
||||
void nmt_newt_button_box_add_widget_start (NmtNewtButtonBox *bbox,
|
||||
NmtNewtWidget *widget);
|
||||
void nmt_newt_button_box_add_widget_end (NmtNewtButtonBox *bbox,
|
||||
NmtNewtWidget *widget);
|
||||
void nmt_newt_button_box_add_widget_start(NmtNewtButtonBox *bbox, NmtNewtWidget *widget);
|
||||
void nmt_newt_button_box_add_widget_end(NmtNewtButtonBox *bbox, NmtNewtWidget *widget);
|
||||
|
||||
#endif /* NMT_NEWT_BUTTON_BOX_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -15,28 +15,29 @@
|
|||
#include "nmt-newt-button.h"
|
||||
#include "nmt-newt-utils.h"
|
||||
|
||||
G_DEFINE_TYPE (NmtNewtButton, nmt_newt_button, NMT_TYPE_NEWT_COMPONENT)
|
||||
G_DEFINE_TYPE(NmtNewtButton, nmt_newt_button, NMT_TYPE_NEWT_COMPONENT)
|
||||
|
||||
#define NMT_NEWT_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_BUTTON, NmtNewtButtonPrivate))
|
||||
#define NMT_NEWT_BUTTON_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_BUTTON, NmtNewtButtonPrivate))
|
||||
|
||||
typedef struct {
|
||||
char *label;
|
||||
char *label;
|
||||
} NmtNewtButtonPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LABEL,
|
||||
PROP_0,
|
||||
PROP_LABEL,
|
||||
|
||||
LAST_PROP
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
enum {
|
||||
CLICKED,
|
||||
CLICKED,
|
||||
|
||||
LAST_SIGNAL
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
/**
|
||||
* nmt_newt_button_new:
|
||||
|
|
@ -47,11 +48,9 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||
* Returns: a new #NmtNewtButton
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_button_new (const char *label)
|
||||
nmt_newt_button_new(const char *label)
|
||||
{
|
||||
return g_object_new (NMT_TYPE_NEWT_BUTTON,
|
||||
"label", label,
|
||||
NULL);
|
||||
return g_object_new(NMT_TYPE_NEWT_BUTTON, "label", label, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -62,17 +61,16 @@ nmt_newt_button_new (const char *label)
|
|||
* Updates @button's label.
|
||||
*/
|
||||
void
|
||||
nmt_newt_button_set_label (NmtNewtButton *button,
|
||||
const char *label)
|
||||
nmt_newt_button_set_label(NmtNewtButton *button, const char *label)
|
||||
{
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE (button);
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE(button);
|
||||
|
||||
if (!g_strcmp0 (priv->label, label))
|
||||
return;
|
||||
if (!g_strcmp0(priv->label, label))
|
||||
return;
|
||||
|
||||
g_free (priv->label);
|
||||
priv->label = g_strdup (label);
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (button));
|
||||
g_free(priv->label);
|
||||
priv->label = g_strdup(label);
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(button));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,165 +82,151 @@ nmt_newt_button_set_label (NmtNewtButton *button,
|
|||
* Returns: @button's label.
|
||||
*/
|
||||
const char *
|
||||
nmt_newt_button_get_label (NmtNewtButton *button)
|
||||
nmt_newt_button_get_label(NmtNewtButton *button)
|
||||
{
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE (button);
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE(button);
|
||||
|
||||
return priv->label;
|
||||
return priv->label;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_init (NmtNewtButton *button)
|
||||
{
|
||||
}
|
||||
nmt_newt_button_init(NmtNewtButton *button)
|
||||
{}
|
||||
|
||||
static void
|
||||
nmt_newt_button_finalize (GObject *object)
|
||||
nmt_newt_button_finalize(GObject *object)
|
||||
{
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE (object);
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE(object);
|
||||
|
||||
g_free (priv->label);
|
||||
g_free(priv->label);
|
||||
|
||||
G_OBJECT_CLASS (nmt_newt_button_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS(nmt_newt_button_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static newtComponent
|
||||
nmt_newt_button_build_component (NmtNewtComponent *component,
|
||||
gboolean sensitive)
|
||||
nmt_newt_button_build_component(NmtNewtComponent *component, gboolean sensitive)
|
||||
{
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE (component);
|
||||
newtComponent co;
|
||||
char *label = NULL, *label_lc;
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE(component);
|
||||
newtComponent co;
|
||||
char * label = NULL, *label_lc;
|
||||
|
||||
if (sensitive) {
|
||||
label_lc = nmt_newt_locale_from_utf8 (priv->label);
|
||||
co = newtCompactButton (-1, -1, label_lc);
|
||||
g_free (label_lc);
|
||||
} else {
|
||||
label = g_strdup_printf (" <%s>", priv->label);
|
||||
label_lc = nmt_newt_locale_from_utf8 (label);
|
||||
co = newtLabel (-1, -1, label_lc);
|
||||
g_free (label_lc);
|
||||
newtLabelSetColors (co, NMT_NEWT_COLORSET_DISABLED_BUTTON);
|
||||
}
|
||||
if (sensitive) {
|
||||
label_lc = nmt_newt_locale_from_utf8(priv->label);
|
||||
co = newtCompactButton(-1, -1, label_lc);
|
||||
g_free(label_lc);
|
||||
} else {
|
||||
label = g_strdup_printf(" <%s>", priv->label);
|
||||
label_lc = nmt_newt_locale_from_utf8(label);
|
||||
co = newtLabel(-1, -1, label_lc);
|
||||
g_free(label_lc);
|
||||
newtLabelSetColors(co, NMT_NEWT_COLORSET_DISABLED_BUTTON);
|
||||
}
|
||||
|
||||
return co;
|
||||
return co;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_size_request (NmtNewtWidget *widget,
|
||||
int *width,
|
||||
int *height)
|
||||
nmt_newt_button_size_request(NmtNewtWidget *widget, int *width, int *height)
|
||||
{
|
||||
NMT_NEWT_WIDGET_CLASS (nmt_newt_button_parent_class)->size_request (widget, width, height);
|
||||
NMT_NEWT_WIDGET_CLASS(nmt_newt_button_parent_class)->size_request(widget, width, height);
|
||||
|
||||
/* remove the automatically-added left padding */
|
||||
(*width)--;
|
||||
/* remove the automatically-added left padding */
|
||||
(*width)--;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_size_allocate (NmtNewtWidget *widget,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
nmt_newt_button_size_allocate(NmtNewtWidget *widget, int x, int y, int width, int height)
|
||||
{
|
||||
/* account for the automatically-added left padding */
|
||||
x--;
|
||||
width++;
|
||||
/* account for the automatically-added left padding */
|
||||
x--;
|
||||
width++;
|
||||
|
||||
NMT_NEWT_WIDGET_CLASS (nmt_newt_button_parent_class)->size_allocate (widget, x, y, width, height);
|
||||
NMT_NEWT_WIDGET_CLASS(nmt_newt_button_parent_class)->size_allocate(widget, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_activated (NmtNewtWidget *widget)
|
||||
nmt_newt_button_activated(NmtNewtWidget *widget)
|
||||
{
|
||||
g_signal_emit (widget, signals[CLICKED], 0);
|
||||
g_signal_emit(widget, signals[CLICKED], 0);
|
||||
|
||||
NMT_NEWT_WIDGET_CLASS (nmt_newt_button_parent_class)->activated (widget);
|
||||
NMT_NEWT_WIDGET_CLASS(nmt_newt_button_parent_class)->activated(widget);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_button_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
nmt_newt_button_set_label (NMT_NEWT_BUTTON (object),
|
||||
g_value_get_string (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
nmt_newt_button_set_label(NMT_NEWT_BUTTON(object), g_value_get_string(value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_button_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE (object);
|
||||
NmtNewtButtonPrivate *priv = NMT_NEWT_BUTTON_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
g_value_set_string (value, priv->label);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
g_value_set_string(value, priv->label);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_button_class_init (NmtNewtButtonClass *button_class)
|
||||
nmt_newt_button_class_init(NmtNewtButtonClass *button_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (button_class);
|
||||
NmtNewtComponentClass *component_class = NMT_NEWT_COMPONENT_CLASS (button_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (button_class);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(button_class);
|
||||
NmtNewtComponentClass *component_class = NMT_NEWT_COMPONENT_CLASS(button_class);
|
||||
NmtNewtWidgetClass * widget_class = NMT_NEWT_WIDGET_CLASS(button_class);
|
||||
|
||||
g_type_class_add_private (button_class, sizeof (NmtNewtButtonPrivate));
|
||||
g_type_class_add_private(button_class, sizeof(NmtNewtButtonPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->set_property = nmt_newt_button_set_property;
|
||||
object_class->get_property = nmt_newt_button_get_property;
|
||||
object_class->finalize = nmt_newt_button_finalize;
|
||||
/* virtual methods */
|
||||
object_class->set_property = nmt_newt_button_set_property;
|
||||
object_class->get_property = nmt_newt_button_get_property;
|
||||
object_class->finalize = nmt_newt_button_finalize;
|
||||
|
||||
widget_class->size_request = nmt_newt_button_size_request;
|
||||
widget_class->size_allocate = nmt_newt_button_size_allocate;
|
||||
widget_class->activated = nmt_newt_button_activated;
|
||||
widget_class->size_request = nmt_newt_button_size_request;
|
||||
widget_class->size_allocate = nmt_newt_button_size_allocate;
|
||||
widget_class->activated = nmt_newt_button_activated;
|
||||
|
||||
component_class->build_component = nmt_newt_button_build_component;
|
||||
component_class->build_component = nmt_newt_button_build_component;
|
||||
|
||||
/* signals */
|
||||
/* signals */
|
||||
|
||||
/**
|
||||
* NmtNewtButton::clicked:
|
||||
* @button: the #NmtNewtButton
|
||||
*
|
||||
* Emitted when the button is clicked.
|
||||
*/
|
||||
signals[CLICKED] =
|
||||
g_signal_new ("clicked",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
/**
|
||||
* NmtNewtButton::clicked:
|
||||
* @button: the #NmtNewtButton
|
||||
*
|
||||
* Emitted when the button is clicked.
|
||||
*/
|
||||
signals[CLICKED] = g_signal_new("clicked",
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
/* properties */
|
||||
/* properties */
|
||||
|
||||
/**
|
||||
* NmtNewtButton:label:
|
||||
*
|
||||
* The button's label
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_LABEL,
|
||||
g_param_spec_string ("label", "", "",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtButton:label:
|
||||
*
|
||||
* The button's label
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_LABEL,
|
||||
g_param_spec_string("label", "", "", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,29 +8,30 @@
|
|||
|
||||
#include "nmt-newt-component.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_BUTTON (nmt_newt_button_get_type ())
|
||||
#define NMT_NEWT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_BUTTON, NmtNewtButton))
|
||||
#define NMT_NEWT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_BUTTON, NmtNewtButtonClass))
|
||||
#define NMT_IS_NEWT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_BUTTON))
|
||||
#define NMT_IS_NEWT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_BUTTON))
|
||||
#define NMT_NEWT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_BUTTON, NmtNewtButtonClass))
|
||||
#define NMT_TYPE_NEWT_BUTTON (nmt_newt_button_get_type())
|
||||
#define NMT_NEWT_BUTTON(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_BUTTON, NmtNewtButton))
|
||||
#define NMT_NEWT_BUTTON_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_BUTTON, NmtNewtButtonClass))
|
||||
#define NMT_IS_NEWT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_BUTTON))
|
||||
#define NMT_IS_NEWT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_BUTTON))
|
||||
#define NMT_NEWT_BUTTON_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_BUTTON, NmtNewtButtonClass))
|
||||
|
||||
struct _NmtNewtButton {
|
||||
NmtNewtComponent parent;
|
||||
|
||||
NmtNewtComponent parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtComponentClass parent;
|
||||
NmtNewtComponentClass parent;
|
||||
|
||||
} NmtNewtButtonClass;
|
||||
|
||||
GType nmt_newt_button_get_type (void);
|
||||
GType nmt_newt_button_get_type(void);
|
||||
|
||||
NmtNewtWidget *nmt_newt_button_new (const char *label);
|
||||
NmtNewtWidget *nmt_newt_button_new(const char *label);
|
||||
|
||||
void nmt_newt_button_set_label (NmtNewtButton *button,
|
||||
const char *label);
|
||||
const char *nmt_newt_button_get_label (NmtNewtButton *button);
|
||||
void nmt_newt_button_set_label(NmtNewtButton *button, const char *label);
|
||||
const char *nmt_newt_button_get_label(NmtNewtButton *button);
|
||||
|
||||
#endif /* NMT_NEWT_BUTTON_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -15,21 +15,22 @@
|
|||
#include "nmt-newt-checkbox.h"
|
||||
#include "nmt-newt-utils.h"
|
||||
|
||||
G_DEFINE_TYPE (NmtNewtCheckbox, nmt_newt_checkbox, NMT_TYPE_NEWT_COMPONENT)
|
||||
G_DEFINE_TYPE(NmtNewtCheckbox, nmt_newt_checkbox, NMT_TYPE_NEWT_COMPONENT)
|
||||
|
||||
#define NMT_NEWT_CHECKBOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckboxPrivate))
|
||||
#define NMT_NEWT_CHECKBOX_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckboxPrivate))
|
||||
|
||||
typedef struct {
|
||||
char *label_lc;
|
||||
gboolean active;
|
||||
char * label_lc;
|
||||
gboolean active;
|
||||
} NmtNewtCheckboxPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LABEL,
|
||||
PROP_ACTIVE,
|
||||
PROP_0,
|
||||
PROP_LABEL,
|
||||
PROP_ACTIVE,
|
||||
|
||||
LAST_PROP
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
#define CHECKBOX_INACTIVE ' '
|
||||
|
|
@ -45,11 +46,9 @@ enum {
|
|||
* Returns: a new #NmtNewtCheckbox
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_checkbox_new (const char *label)
|
||||
nmt_newt_checkbox_new(const char *label)
|
||||
{
|
||||
return g_object_new (NMT_TYPE_NEWT_CHECKBOX,
|
||||
"label", label,
|
||||
NULL);
|
||||
return g_object_new(NMT_TYPE_NEWT_CHECKBOX, "label", label, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,23 +59,22 @@ nmt_newt_checkbox_new (const char *label)
|
|||
* Updates @checkbox's checked state
|
||||
*/
|
||||
void
|
||||
nmt_newt_checkbox_set_active (NmtNewtCheckbox *checkbox,
|
||||
gboolean active)
|
||||
nmt_newt_checkbox_set_active(NmtNewtCheckbox *checkbox, gboolean active)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (checkbox);
|
||||
newtComponent co;
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(checkbox);
|
||||
newtComponent co;
|
||||
|
||||
active = !!active;
|
||||
if (active == priv->active)
|
||||
return;
|
||||
active = !!active;
|
||||
if (active == priv->active)
|
||||
return;
|
||||
|
||||
priv->active = active;
|
||||
priv->active = active;
|
||||
|
||||
co = nmt_newt_component_get_component (NMT_NEWT_COMPONENT (checkbox));
|
||||
if (co)
|
||||
newtCheckboxSetValue (co, priv->active ? CHECKBOX_ACTIVE : CHECKBOX_INACTIVE);
|
||||
co = nmt_newt_component_get_component(NMT_NEWT_COMPONENT(checkbox));
|
||||
if (co)
|
||||
newtCheckboxSetValue(co, priv->active ? CHECKBOX_ACTIVE : CHECKBOX_INACTIVE);
|
||||
|
||||
g_object_notify (G_OBJECT (checkbox), "active");
|
||||
g_object_notify(G_OBJECT(checkbox), "active");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -88,137 +86,130 @@ nmt_newt_checkbox_set_active (NmtNewtCheckbox *checkbox,
|
|||
* Returns: @checkbox's checked state
|
||||
*/
|
||||
gboolean
|
||||
nmt_newt_checkbox_get_active (NmtNewtCheckbox *checkbox)
|
||||
nmt_newt_checkbox_get_active(NmtNewtCheckbox *checkbox)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (checkbox);
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(checkbox);
|
||||
|
||||
return priv->active;
|
||||
return priv->active;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_checkbox_init (NmtNewtCheckbox *checkbox)
|
||||
nmt_newt_checkbox_init(NmtNewtCheckbox *checkbox)
|
||||
{}
|
||||
|
||||
static void
|
||||
nmt_newt_checkbox_finalize(GObject *object)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(object);
|
||||
|
||||
g_free(priv->label_lc);
|
||||
|
||||
G_OBJECT_CLASS(nmt_newt_checkbox_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_checkbox_finalize (GObject *object)
|
||||
checkbox_toggled_callback(newtComponent co, void *checkbox)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (object);
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(checkbox);
|
||||
gboolean active;
|
||||
|
||||
g_free (priv->label_lc);
|
||||
|
||||
G_OBJECT_CLASS (nmt_newt_checkbox_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
checkbox_toggled_callback (newtComponent co,
|
||||
void *checkbox)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (checkbox);
|
||||
gboolean active;
|
||||
|
||||
active = (newtCheckboxGetValue (co) == CHECKBOX_ACTIVE);
|
||||
if (active != priv->active) {
|
||||
priv->active = active;
|
||||
g_object_notify (checkbox, "active");
|
||||
}
|
||||
active = (newtCheckboxGetValue(co) == CHECKBOX_ACTIVE);
|
||||
if (active != priv->active) {
|
||||
priv->active = active;
|
||||
g_object_notify(checkbox, "active");
|
||||
}
|
||||
}
|
||||
|
||||
static newtComponent
|
||||
nmt_newt_checkbox_build_component (NmtNewtComponent *component,
|
||||
gboolean sensitive)
|
||||
nmt_newt_checkbox_build_component(NmtNewtComponent *component, gboolean sensitive)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (component);
|
||||
newtComponent co;
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(component);
|
||||
newtComponent co;
|
||||
|
||||
co = newtCheckbox (-1, -1, priv->label_lc,
|
||||
priv->active ? CHECKBOX_ACTIVE : CHECKBOX_INACTIVE,
|
||||
CHECKBOX_STATES, NULL);
|
||||
if (!sensitive)
|
||||
newtCheckboxSetFlags (co, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
|
||||
newtComponentAddCallback (co, checkbox_toggled_callback, component);
|
||||
return co;
|
||||
co = newtCheckbox(-1,
|
||||
-1,
|
||||
priv->label_lc,
|
||||
priv->active ? CHECKBOX_ACTIVE : CHECKBOX_INACTIVE,
|
||||
CHECKBOX_STATES,
|
||||
NULL);
|
||||
if (!sensitive)
|
||||
newtCheckboxSetFlags(co, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
|
||||
newtComponentAddCallback(co, checkbox_toggled_callback, component);
|
||||
return co;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_checkbox_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_checkbox_set_property(GObject * object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
NmtNewtCheckbox *checkbox = NMT_NEWT_CHECKBOX (object);
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (object);
|
||||
NmtNewtCheckbox * checkbox = NMT_NEWT_CHECKBOX(object);
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
g_free (priv->label_lc);
|
||||
priv->label_lc = nmt_newt_locale_from_utf8 (g_value_get_string (value));
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
nmt_newt_checkbox_set_active (checkbox, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
g_free(priv->label_lc);
|
||||
priv->label_lc = nmt_newt_locale_from_utf8(g_value_get_string(value));
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
nmt_newt_checkbox_set_active(checkbox, g_value_get_boolean(value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_checkbox_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_checkbox_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE (object);
|
||||
NmtNewtCheckboxPrivate *priv = NMT_NEWT_CHECKBOX_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
g_value_take_string (value, nmt_newt_locale_to_utf8 (priv->label_lc));
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
g_value_set_boolean (value, priv->active);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_LABEL:
|
||||
g_value_take_string(value, nmt_newt_locale_to_utf8(priv->label_lc));
|
||||
break;
|
||||
case PROP_ACTIVE:
|
||||
g_value_set_boolean(value, priv->active);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_checkbox_class_init (NmtNewtCheckboxClass *checkbox_class)
|
||||
nmt_newt_checkbox_class_init(NmtNewtCheckboxClass *checkbox_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (checkbox_class);
|
||||
NmtNewtComponentClass *component_class = NMT_NEWT_COMPONENT_CLASS (checkbox_class);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(checkbox_class);
|
||||
NmtNewtComponentClass *component_class = NMT_NEWT_COMPONENT_CLASS(checkbox_class);
|
||||
|
||||
g_type_class_add_private (checkbox_class, sizeof (NmtNewtCheckboxPrivate));
|
||||
g_type_class_add_private(checkbox_class, sizeof(NmtNewtCheckboxPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->set_property = nmt_newt_checkbox_set_property;
|
||||
object_class->get_property = nmt_newt_checkbox_get_property;
|
||||
object_class->finalize = nmt_newt_checkbox_finalize;
|
||||
/* virtual methods */
|
||||
object_class->set_property = nmt_newt_checkbox_set_property;
|
||||
object_class->get_property = nmt_newt_checkbox_get_property;
|
||||
object_class->finalize = nmt_newt_checkbox_finalize;
|
||||
|
||||
component_class->build_component = nmt_newt_checkbox_build_component;
|
||||
component_class->build_component = nmt_newt_checkbox_build_component;
|
||||
|
||||
/**
|
||||
* NmtNewtCheckbox:label:
|
||||
*
|
||||
* The checkbox's label
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_LABEL,
|
||||
g_param_spec_string ("label", "", "",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtCheckbox:active:
|
||||
*
|
||||
* The checkbox's checked state
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_ACTIVE,
|
||||
g_param_spec_boolean ("active", "", "",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtCheckbox:label:
|
||||
*
|
||||
* The checkbox's label
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_LABEL,
|
||||
g_param_spec_string("label", "", "", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtCheckbox:active:
|
||||
*
|
||||
* The checkbox's checked state
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_ACTIVE,
|
||||
g_param_spec_boolean("active", "", "", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,29 +8,30 @@
|
|||
|
||||
#include "nmt-newt-component.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_CHECKBOX (nmt_newt_checkbox_get_type ())
|
||||
#define NMT_NEWT_CHECKBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckbox))
|
||||
#define NMT_NEWT_CHECKBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckboxClass))
|
||||
#define NMT_IS_NEWT_CHECKBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_CHECKBOX))
|
||||
#define NMT_IS_NEWT_CHECKBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_CHECKBOX))
|
||||
#define NMT_NEWT_CHECKBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckboxClass))
|
||||
#define NMT_TYPE_NEWT_CHECKBOX (nmt_newt_checkbox_get_type())
|
||||
#define NMT_NEWT_CHECKBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckbox))
|
||||
#define NMT_NEWT_CHECKBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckboxClass))
|
||||
#define NMT_IS_NEWT_CHECKBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_CHECKBOX))
|
||||
#define NMT_IS_NEWT_CHECKBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_CHECKBOX))
|
||||
#define NMT_NEWT_CHECKBOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_CHECKBOX, NmtNewtCheckboxClass))
|
||||
|
||||
struct _NmtNewtCheckbox {
|
||||
NmtNewtComponent parent;
|
||||
|
||||
NmtNewtComponent parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtComponentClass parent;
|
||||
NmtNewtComponentClass parent;
|
||||
|
||||
} NmtNewtCheckboxClass;
|
||||
|
||||
GType nmt_newt_checkbox_get_type (void);
|
||||
GType nmt_newt_checkbox_get_type(void);
|
||||
|
||||
NmtNewtWidget *nmt_newt_checkbox_new (const char *label);
|
||||
NmtNewtWidget *nmt_newt_checkbox_new(const char *label);
|
||||
|
||||
void nmt_newt_checkbox_set_active (NmtNewtCheckbox *checkbox,
|
||||
gboolean active);
|
||||
gboolean nmt_newt_checkbox_get_active (NmtNewtCheckbox *checkbox);
|
||||
void nmt_newt_checkbox_set_active(NmtNewtCheckbox *checkbox, gboolean active);
|
||||
gboolean nmt_newt_checkbox_get_active(NmtNewtCheckbox *checkbox);
|
||||
|
||||
#endif /* NMT_NEWT_CHECKBOX_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -17,136 +17,136 @@
|
|||
#include "nmt-newt-form.h"
|
||||
#include "nmt-newt-hacks.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (NmtNewtComponent, nmt_newt_component, NMT_TYPE_NEWT_WIDGET)
|
||||
G_DEFINE_ABSTRACT_TYPE(NmtNewtComponent, nmt_newt_component, NMT_TYPE_NEWT_WIDGET)
|
||||
|
||||
#define NMT_NEWT_COMPONENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponentPrivate))
|
||||
#define NMT_NEWT_COMPONENT_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponentPrivate))
|
||||
|
||||
typedef struct {
|
||||
newtComponent co;
|
||||
gboolean own_component;
|
||||
gboolean sensitive;
|
||||
newtComponent co;
|
||||
gboolean own_component;
|
||||
gboolean sensitive;
|
||||
} NmtNewtComponentPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_0,
|
||||
|
||||
PROP_COMPONENT,
|
||||
PROP_SENSITIVE,
|
||||
PROP_COMPONENT,
|
||||
PROP_SENSITIVE,
|
||||
|
||||
LAST_PROP
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static void
|
||||
nmt_newt_component_init (NmtNewtComponent *component)
|
||||
nmt_newt_component_init(NmtNewtComponent *component)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (component);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(component);
|
||||
|
||||
priv->sensitive = TRUE;
|
||||
priv->sensitive = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_unrealize (NmtNewtWidget *widget)
|
||||
nmt_newt_component_unrealize(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
|
||||
if (!priv->co)
|
||||
return;
|
||||
if (!priv->co)
|
||||
return;
|
||||
|
||||
newtComponentAddCallback (priv->co, NULL, NULL);
|
||||
newtComponentAddDestroyCallback (priv->co, NULL, NULL);
|
||||
newtComponentAddCallback(priv->co, NULL, NULL);
|
||||
newtComponentAddDestroyCallback(priv->co, NULL, NULL);
|
||||
|
||||
if (priv->own_component)
|
||||
newtComponentDestroy (priv->co);
|
||||
priv->co = NULL;
|
||||
if (priv->own_component)
|
||||
newtComponentDestroy(priv->co);
|
||||
priv->co = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
component_destroy_callback (newtComponent co,
|
||||
void *component)
|
||||
component_destroy_callback(newtComponent co, void *component)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (component);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(component);
|
||||
|
||||
priv->own_component = FALSE;
|
||||
nmt_newt_widget_unrealize (component);
|
||||
nmt_newt_widget_needs_rebuild (component);
|
||||
priv->own_component = FALSE;
|
||||
nmt_newt_widget_unrealize(component);
|
||||
nmt_newt_widget_needs_rebuild(component);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_realize (NmtNewtWidget *widget)
|
||||
nmt_newt_component_realize(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
|
||||
nmt_newt_component_unrealize (widget);
|
||||
priv->co = NMT_NEWT_COMPONENT_GET_CLASS (widget)->
|
||||
build_component (NMT_NEWT_COMPONENT (widget), priv->sensitive);
|
||||
priv->own_component = TRUE;
|
||||
if (!priv->sensitive)
|
||||
newtComponentTakesFocus (priv->co, FALSE);
|
||||
newtComponentAddDestroyCallback (priv->co, component_destroy_callback, widget);
|
||||
nmt_newt_component_unrealize(widget);
|
||||
priv->co = NMT_NEWT_COMPONENT_GET_CLASS(widget)->build_component(NMT_NEWT_COMPONENT(widget),
|
||||
priv->sensitive);
|
||||
priv->own_component = TRUE;
|
||||
if (!priv->sensitive)
|
||||
newtComponentTakesFocus(priv->co, FALSE);
|
||||
newtComponentAddDestroyCallback(priv->co, component_destroy_callback, widget);
|
||||
}
|
||||
|
||||
static newtComponent *
|
||||
nmt_newt_component_get_components (NmtNewtWidget *widget)
|
||||
nmt_newt_component_get_components(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
newtComponent *cos;
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
newtComponent * cos;
|
||||
|
||||
priv->own_component = FALSE;
|
||||
cos = g_new0 (newtComponent, 2);
|
||||
cos[0] = priv->co;
|
||||
return cos;
|
||||
priv->own_component = FALSE;
|
||||
cos = g_new0(newtComponent, 2);
|
||||
cos[0] = priv->co;
|
||||
return cos;
|
||||
}
|
||||
|
||||
static NmtNewtWidget *
|
||||
nmt_newt_component_find_component (NmtNewtWidget *widget,
|
||||
newtComponent co)
|
||||
nmt_newt_component_find_component(NmtNewtWidget *widget, newtComponent co)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
|
||||
if (co == priv->co)
|
||||
return widget;
|
||||
else
|
||||
return NULL;
|
||||
if (co == priv->co)
|
||||
return widget;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_size_request (NmtNewtWidget *widget,
|
||||
int *width,
|
||||
int *height)
|
||||
nmt_newt_component_size_request(NmtNewtWidget *widget, int *width, int *height)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
|
||||
newtComponentGetSize (priv->co, width, height);
|
||||
newtComponentGetSize(priv->co, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_size_allocate (NmtNewtWidget *widget,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
nmt_newt_component_size_allocate(NmtNewtWidget *widget, int x, int y, int width, int height)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
newtGrid grid;
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
newtGrid grid;
|
||||
|
||||
/* You can't directly place a newtComponent, so we create a newtGrid,
|
||||
* position the component within that, and then place the grid.
|
||||
*/
|
||||
grid = newtCreateGrid (1, 1);
|
||||
newtGridSetField (grid, 0, 0,
|
||||
NEWT_GRID_COMPONENT, priv->co,
|
||||
x, y, 0, 0,
|
||||
NEWT_ANCHOR_LEFT | NEWT_ANCHOR_TOP, 0);
|
||||
newtGridPlace (grid, 0, 0);
|
||||
newtGridFree (grid, FALSE);
|
||||
/* You can't directly place a newtComponent, so we create a newtGrid,
|
||||
* position the component within that, and then place the grid.
|
||||
*/
|
||||
grid = newtCreateGrid(1, 1);
|
||||
newtGridSetField(grid,
|
||||
0,
|
||||
0,
|
||||
NEWT_GRID_COMPONENT,
|
||||
priv->co,
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
0,
|
||||
NEWT_ANCHOR_LEFT | NEWT_ANCHOR_TOP,
|
||||
0);
|
||||
newtGridPlace(grid, 0, 0);
|
||||
newtGridFree(grid, FALSE);
|
||||
}
|
||||
|
||||
static newtComponent
|
||||
nmt_newt_component_get_focus_component (NmtNewtWidget *widget)
|
||||
nmt_newt_component_get_focus_component(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (widget);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(widget);
|
||||
|
||||
return priv->co;
|
||||
return priv->co;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,11 +161,11 @@ nmt_newt_component_get_focus_component (NmtNewtWidget *widget)
|
|||
* Returns: @component's #newtComponent
|
||||
*/
|
||||
newtComponent
|
||||
nmt_newt_component_get_component (NmtNewtComponent *component)
|
||||
nmt_newt_component_get_component(NmtNewtComponent *component)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (component);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(component);
|
||||
|
||||
return priv->co;
|
||||
return priv->co;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -180,11 +180,11 @@ nmt_newt_component_get_component (NmtNewtComponent *component)
|
|||
* Returns: @component's #NmtNewtComponent:sensitive property
|
||||
*/
|
||||
gboolean
|
||||
nmt_newt_component_get_sensitive (NmtNewtComponent *component)
|
||||
nmt_newt_component_get_sensitive(NmtNewtComponent *component)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (component);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(component);
|
||||
|
||||
return priv->sensitive;
|
||||
return priv->sensitive;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -195,102 +195,99 @@ nmt_newt_component_get_sensitive (NmtNewtComponent *component)
|
|||
* Sets @component's #NmtNewtComponent:sensitive property.
|
||||
*/
|
||||
void
|
||||
nmt_newt_component_set_sensitive (NmtNewtComponent *component,
|
||||
gboolean sensitive)
|
||||
nmt_newt_component_set_sensitive(NmtNewtComponent *component, gboolean sensitive)
|
||||
{
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE (component);
|
||||
NmtNewtComponentPrivate *priv = NMT_NEWT_COMPONENT_GET_PRIVATE(component);
|
||||
|
||||
sensitive = !!sensitive;
|
||||
if (priv->sensitive == sensitive)
|
||||
return;
|
||||
sensitive = !!sensitive;
|
||||
if (priv->sensitive == sensitive)
|
||||
return;
|
||||
|
||||
priv->sensitive = sensitive;
|
||||
g_object_notify (G_OBJECT (component), "sensitive");
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (component));
|
||||
priv->sensitive = sensitive;
|
||||
g_object_notify(G_OBJECT(component), "sensitive");
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(component));
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_component_set_property(GObject * object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
NmtNewtComponent *component = NMT_NEWT_COMPONENT (object);
|
||||
NmtNewtComponent *component = NMT_NEWT_COMPONENT(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_SENSITIVE:
|
||||
nmt_newt_component_set_sensitive (component, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_SENSITIVE:
|
||||
nmt_newt_component_set_sensitive(component, g_value_get_boolean(value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_component_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtComponent *component = NMT_NEWT_COMPONENT (object);
|
||||
NmtNewtComponent *component = NMT_NEWT_COMPONENT(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_COMPONENT:
|
||||
g_value_set_pointer (value, nmt_newt_component_get_component (component));
|
||||
break;
|
||||
case PROP_SENSITIVE:
|
||||
g_value_set_boolean (value, nmt_newt_component_get_sensitive (component));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_COMPONENT:
|
||||
g_value_set_pointer(value, nmt_newt_component_get_component(component));
|
||||
break;
|
||||
case PROP_SENSITIVE:
|
||||
g_value_set_boolean(value, nmt_newt_component_get_sensitive(component));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_component_class_init (NmtNewtComponentClass *component_class)
|
||||
nmt_newt_component_class_init(NmtNewtComponentClass *component_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (component_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (component_class);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(component_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS(component_class);
|
||||
|
||||
g_type_class_add_private (component_class, sizeof (NmtNewtComponentPrivate));
|
||||
g_type_class_add_private(component_class, sizeof(NmtNewtComponentPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->set_property = nmt_newt_component_set_property;
|
||||
object_class->get_property = nmt_newt_component_get_property;
|
||||
/* virtual methods */
|
||||
object_class->set_property = nmt_newt_component_set_property;
|
||||
object_class->get_property = nmt_newt_component_get_property;
|
||||
|
||||
widget_class->realize = nmt_newt_component_realize;
|
||||
widget_class->unrealize = nmt_newt_component_unrealize;
|
||||
widget_class->get_components = nmt_newt_component_get_components;
|
||||
widget_class->find_component = nmt_newt_component_find_component;
|
||||
widget_class->size_request = nmt_newt_component_size_request;
|
||||
widget_class->size_allocate = nmt_newt_component_size_allocate;
|
||||
widget_class->get_focus_component = nmt_newt_component_get_focus_component;
|
||||
widget_class->realize = nmt_newt_component_realize;
|
||||
widget_class->unrealize = nmt_newt_component_unrealize;
|
||||
widget_class->get_components = nmt_newt_component_get_components;
|
||||
widget_class->find_component = nmt_newt_component_find_component;
|
||||
widget_class->size_request = nmt_newt_component_size_request;
|
||||
widget_class->size_allocate = nmt_newt_component_size_allocate;
|
||||
widget_class->get_focus_component = nmt_newt_component_get_focus_component;
|
||||
|
||||
/* properties */
|
||||
/* properties */
|
||||
|
||||
/**
|
||||
* NmtNewtComponent:component:
|
||||
*
|
||||
* The component's #newtComponent
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_COMPONENT,
|
||||
g_param_spec_pointer ("component", "", "",
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtComponent:sensitive:
|
||||
*
|
||||
* Whether the component is sensitive. Insensitive components will
|
||||
* be skipped over in the keyboard tab chain, and may be displayed
|
||||
* differently.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_SENSITIVE,
|
||||
g_param_spec_boolean ("sensitive", "", "",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtComponent:component:
|
||||
*
|
||||
* The component's #newtComponent
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_COMPONENT,
|
||||
g_param_spec_pointer("component", "", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtComponent:sensitive:
|
||||
*
|
||||
* Whether the component is sensitive. Insensitive components will
|
||||
* be skipped over in the keyboard tab chain, and may be displayed
|
||||
* differently.
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_SENSITIVE,
|
||||
g_param_spec_boolean("sensitive",
|
||||
"",
|
||||
"",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,33 +8,34 @@
|
|||
|
||||
#include "nmt-newt-widget.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_COMPONENT (nmt_newt_component_get_type ())
|
||||
#define NMT_NEWT_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponent))
|
||||
#define NMT_NEWT_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponentClass))
|
||||
#define NMT_IS_NEWT_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_COMPONENT))
|
||||
#define NMT_IS_NEWT_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_COMPONENT))
|
||||
#define NMT_NEWT_COMPONENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponentClass))
|
||||
#define NMT_TYPE_NEWT_COMPONENT (nmt_newt_component_get_type())
|
||||
#define NMT_NEWT_COMPONENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponent))
|
||||
#define NMT_NEWT_COMPONENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponentClass))
|
||||
#define NMT_IS_NEWT_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_COMPONENT))
|
||||
#define NMT_IS_NEWT_COMPONENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_COMPONENT))
|
||||
#define NMT_NEWT_COMPONENT_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_COMPONENT, NmtNewtComponentClass))
|
||||
|
||||
struct _NmtNewtComponent {
|
||||
NmtNewtWidget parent;
|
||||
|
||||
NmtNewtWidget parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtWidgetClass parent;
|
||||
NmtNewtWidgetClass parent;
|
||||
|
||||
/* methods */
|
||||
newtComponent (*build_component) (NmtNewtComponent *component,
|
||||
gboolean sensitive);
|
||||
/* methods */
|
||||
newtComponent (*build_component)(NmtNewtComponent *component, gboolean sensitive);
|
||||
|
||||
} NmtNewtComponentClass;
|
||||
|
||||
GType nmt_newt_component_get_type (void);
|
||||
GType nmt_newt_component_get_type(void);
|
||||
|
||||
newtComponent nmt_newt_component_get_component (NmtNewtComponent *component);
|
||||
newtComponent nmt_newt_component_get_component(NmtNewtComponent *component);
|
||||
|
||||
gboolean nmt_newt_component_get_sensitive (NmtNewtComponent *component);
|
||||
void nmt_newt_component_set_sensitive (NmtNewtComponent *component,
|
||||
gboolean sensitive);
|
||||
gboolean nmt_newt_component_get_sensitive(NmtNewtComponent *component);
|
||||
void nmt_newt_component_set_sensitive(NmtNewtComponent *component, gboolean sensitive);
|
||||
|
||||
#endif /* NMT_NEWT_COMPONENT_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -19,145 +19,142 @@
|
|||
|
||||
#include "nmt-newt-component.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (NmtNewtContainer, nmt_newt_container, NMT_TYPE_NEWT_WIDGET)
|
||||
G_DEFINE_ABSTRACT_TYPE(NmtNewtContainer, nmt_newt_container, NMT_TYPE_NEWT_WIDGET)
|
||||
|
||||
#define NMT_NEWT_CONTAINER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainerPrivate))
|
||||
#define NMT_NEWT_CONTAINER_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainerPrivate))
|
||||
|
||||
typedef struct {
|
||||
GPtrArray *children;
|
||||
GPtrArray *children;
|
||||
|
||||
} NmtNewtContainerPrivate;
|
||||
|
||||
static void child_needs_rebuild (NmtNewtWidget *widget, gpointer user_data);
|
||||
static void child_needs_rebuild(NmtNewtWidget *widget, gpointer user_data);
|
||||
|
||||
static void
|
||||
nmt_newt_container_init (NmtNewtContainer *container)
|
||||
nmt_newt_container_init(NmtNewtContainer *container)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (container);
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(container);
|
||||
|
||||
priv->children = g_ptr_array_new ();
|
||||
priv->children = g_ptr_array_new();
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_finalize (GObject *object)
|
||||
nmt_newt_container_finalize(GObject *object)
|
||||
{
|
||||
NmtNewtContainer *container = NMT_NEWT_CONTAINER (object);
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (object);
|
||||
NmtNewtContainer * container = NMT_NEWT_CONTAINER(object);
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(object);
|
||||
|
||||
while (priv->children->len)
|
||||
nmt_newt_container_remove (container, priv->children->pdata[0]);
|
||||
while (priv->children->len)
|
||||
nmt_newt_container_remove(container, priv->children->pdata[0]);
|
||||
|
||||
G_OBJECT_CLASS (nmt_newt_container_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS(nmt_newt_container_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_realize (NmtNewtWidget *widget)
|
||||
nmt_newt_container_realize(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (widget);
|
||||
int i;
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(widget);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->children->len; i++)
|
||||
nmt_newt_widget_realize (priv->children->pdata[i]);
|
||||
for (i = 0; i < priv->children->len; i++)
|
||||
nmt_newt_widget_realize(priv->children->pdata[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_unrealize (NmtNewtWidget *widget)
|
||||
nmt_newt_container_unrealize(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (widget);
|
||||
int i;
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(widget);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->children->len; i++)
|
||||
nmt_newt_widget_unrealize (priv->children->pdata[i]);
|
||||
for (i = 0; i < priv->children->len; i++)
|
||||
nmt_newt_widget_unrealize(priv->children->pdata[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
child_needs_rebuild (NmtNewtWidget *widget,
|
||||
gpointer user_data)
|
||||
child_needs_rebuild(NmtNewtWidget *widget, gpointer user_data)
|
||||
{
|
||||
NmtNewtWidget *container = user_data;
|
||||
NmtNewtWidget *container = user_data;
|
||||
|
||||
nmt_newt_widget_needs_rebuild (container);
|
||||
nmt_newt_widget_needs_rebuild(container);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_real_child_validity_changed (NmtNewtContainer *container,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_container_real_child_validity_changed(NmtNewtContainer *container, NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv;
|
||||
int i;
|
||||
NmtNewtContainerPrivate *priv;
|
||||
int i;
|
||||
|
||||
if (widget) {
|
||||
if (!nmt_newt_widget_get_visible (widget))
|
||||
return;
|
||||
if (!nmt_newt_widget_get_valid (widget)) {
|
||||
nmt_newt_widget_set_valid (NMT_NEWT_WIDGET (container), FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (widget) {
|
||||
if (!nmt_newt_widget_get_visible(widget))
|
||||
return;
|
||||
if (!nmt_newt_widget_get_valid(widget)) {
|
||||
nmt_newt_widget_set_valid(NMT_NEWT_WIDGET(container), FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
priv = NMT_NEWT_CONTAINER_GET_PRIVATE (container);
|
||||
for (i = 0; i < priv->children->len; i++) {
|
||||
widget = priv->children->pdata[i];
|
||||
if ( nmt_newt_widget_get_visible (widget)
|
||||
&& !nmt_newt_widget_get_valid (widget)) {
|
||||
nmt_newt_widget_set_valid (NMT_NEWT_WIDGET (container), FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
priv = NMT_NEWT_CONTAINER_GET_PRIVATE(container);
|
||||
for (i = 0; i < priv->children->len; i++) {
|
||||
widget = priv->children->pdata[i];
|
||||
if (nmt_newt_widget_get_visible(widget) && !nmt_newt_widget_get_valid(widget)) {
|
||||
nmt_newt_widget_set_valid(NMT_NEWT_WIDGET(container), FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nmt_newt_widget_set_valid (NMT_NEWT_WIDGET (container), TRUE);
|
||||
nmt_newt_widget_set_valid(NMT_NEWT_WIDGET(container), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_child_validity_changed (NmtNewtContainer *container,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_container_child_validity_changed(NmtNewtContainer *container, NmtNewtWidget *widget)
|
||||
{
|
||||
NMT_NEWT_CONTAINER_GET_CLASS (container)->child_validity_changed (container, widget);
|
||||
NMT_NEWT_CONTAINER_GET_CLASS(container)->child_validity_changed(container, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
child_validity_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer container)
|
||||
child_validity_notify(GObject *object, GParamSpec *pspec, gpointer container)
|
||||
{
|
||||
nmt_newt_container_child_validity_changed (container, NMT_NEWT_WIDGET (object));
|
||||
nmt_newt_container_child_validity_changed(container, NMT_NEWT_WIDGET(object));
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_real_add (NmtNewtContainer *container,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_container_real_add(NmtNewtContainer *container, NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (container);
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(container);
|
||||
|
||||
g_signal_connect (widget, "needs-rebuild", G_CALLBACK (child_needs_rebuild), container);
|
||||
g_signal_connect (widget, "notify::valid", G_CALLBACK (child_validity_notify), container);
|
||||
g_ptr_array_add (priv->children, g_object_ref_sink (widget));
|
||||
nmt_newt_widget_set_parent (widget, NMT_NEWT_WIDGET (container));
|
||||
g_signal_connect(widget, "needs-rebuild", G_CALLBACK(child_needs_rebuild), container);
|
||||
g_signal_connect(widget, "notify::valid", G_CALLBACK(child_validity_notify), container);
|
||||
g_ptr_array_add(priv->children, g_object_ref_sink(widget));
|
||||
nmt_newt_widget_set_parent(widget, NMT_NEWT_WIDGET(container));
|
||||
|
||||
nmt_newt_container_child_validity_changed (container, widget);
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (container));
|
||||
nmt_newt_container_child_validity_changed(container, widget);
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(container));
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_real_remove (NmtNewtContainer *container,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_container_real_remove(NmtNewtContainer *container, NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (container);
|
||||
int i;
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(container);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->children->len; i++) {
|
||||
if (widget == priv->children->pdata[i]) {
|
||||
g_ptr_array_remove_index (priv->children, i);
|
||||
g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (child_needs_rebuild), container);
|
||||
g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (child_validity_notify), container);
|
||||
nmt_newt_widget_set_parent (widget, NULL);
|
||||
g_object_unref (widget);
|
||||
for (i = 0; i < priv->children->len; i++) {
|
||||
if (widget == priv->children->pdata[i]) {
|
||||
g_ptr_array_remove_index(priv->children, i);
|
||||
g_signal_handlers_disconnect_by_func(widget,
|
||||
G_CALLBACK(child_needs_rebuild),
|
||||
container);
|
||||
g_signal_handlers_disconnect_by_func(widget,
|
||||
G_CALLBACK(child_validity_notify),
|
||||
container);
|
||||
nmt_newt_widget_set_parent(widget, NULL);
|
||||
g_object_unref(widget);
|
||||
|
||||
nmt_newt_container_child_validity_changed (container, NULL);
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (container));
|
||||
return;
|
||||
}
|
||||
}
|
||||
nmt_newt_container_child_validity_changed(container, NULL);
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(container));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -172,29 +169,27 @@ nmt_newt_container_real_remove (NmtNewtContainer *container,
|
|||
* container-type-specific methods to add widgets to containers.
|
||||
*/
|
||||
void
|
||||
nmt_newt_container_remove (NmtNewtContainer *container,
|
||||
NmtNewtWidget *widget)
|
||||
nmt_newt_container_remove(NmtNewtContainer *container, NmtNewtWidget *widget)
|
||||
{
|
||||
NMT_NEWT_CONTAINER_GET_CLASS (container)->remove (container, widget);
|
||||
NMT_NEWT_CONTAINER_GET_CLASS(container)->remove(container, widget);
|
||||
}
|
||||
|
||||
static NmtNewtWidget *
|
||||
nmt_newt_container_find_component (NmtNewtWidget *widget,
|
||||
newtComponent co)
|
||||
nmt_newt_container_find_component(NmtNewtWidget *widget, newtComponent co)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (widget);
|
||||
NmtNewtWidget *found, *child;
|
||||
int i;
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(widget);
|
||||
NmtNewtWidget * found, *child;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->children->len; i++) {
|
||||
child = priv->children->pdata[i];
|
||||
for (i = 0; i < priv->children->len; i++) {
|
||||
child = priv->children->pdata[i];
|
||||
|
||||
found = nmt_newt_widget_find_component (child, co);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
found = nmt_newt_widget_find_component(child, co);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -206,33 +201,33 @@ nmt_newt_container_find_component (NmtNewtWidget *widget,
|
|||
* Returns: (transfer full): a list of @container's children.
|
||||
*/
|
||||
GSList *
|
||||
nmt_newt_container_get_children (NmtNewtContainer *container)
|
||||
nmt_newt_container_get_children(NmtNewtContainer *container)
|
||||
{
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE (container);
|
||||
GSList *ret;
|
||||
int i;
|
||||
NmtNewtContainerPrivate *priv = NMT_NEWT_CONTAINER_GET_PRIVATE(container);
|
||||
GSList * ret;
|
||||
int i;
|
||||
|
||||
for (i = 0, ret = NULL; i < priv->children->len; i++)
|
||||
ret = g_slist_prepend (ret, g_object_ref (priv->children->pdata[i]));
|
||||
return g_slist_reverse (ret);
|
||||
for (i = 0, ret = NULL; i < priv->children->len; i++)
|
||||
ret = g_slist_prepend(ret, g_object_ref(priv->children->pdata[i]));
|
||||
return g_slist_reverse(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_container_class_init (NmtNewtContainerClass *container_class)
|
||||
nmt_newt_container_class_init(NmtNewtContainerClass *container_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (container_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (container_class);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(container_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS(container_class);
|
||||
|
||||
g_type_class_add_private (container_class, sizeof (NmtNewtContainerPrivate));
|
||||
g_type_class_add_private(container_class, sizeof(NmtNewtContainerPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->finalize = nmt_newt_container_finalize;
|
||||
/* virtual methods */
|
||||
object_class->finalize = nmt_newt_container_finalize;
|
||||
|
||||
widget_class->realize = nmt_newt_container_realize;
|
||||
widget_class->unrealize = nmt_newt_container_unrealize;
|
||||
widget_class->find_component = nmt_newt_container_find_component;
|
||||
widget_class->realize = nmt_newt_container_realize;
|
||||
widget_class->unrealize = nmt_newt_container_unrealize;
|
||||
widget_class->find_component = nmt_newt_container_find_component;
|
||||
|
||||
container_class->add = nmt_newt_container_real_add;
|
||||
container_class->remove = nmt_newt_container_real_remove;
|
||||
container_class->child_validity_changed = nmt_newt_container_real_child_validity_changed;
|
||||
container_class->add = nmt_newt_container_real_add;
|
||||
container_class->remove = nmt_newt_container_real_remove;
|
||||
container_class->child_validity_changed = nmt_newt_container_real_child_validity_changed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,37 +8,36 @@
|
|||
|
||||
#include "nmt-newt-widget.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_CONTAINER (nmt_newt_container_get_type ())
|
||||
#define NMT_NEWT_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainer))
|
||||
#define NMT_NEWT_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainerClass))
|
||||
#define NMT_IS_NEWT_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_CONTAINER))
|
||||
#define NMT_IS_NEWT_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_CONTAINER))
|
||||
#define NMT_NEWT_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainerClass))
|
||||
#define NMT_TYPE_NEWT_CONTAINER (nmt_newt_container_get_type())
|
||||
#define NMT_NEWT_CONTAINER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainer))
|
||||
#define NMT_NEWT_CONTAINER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainerClass))
|
||||
#define NMT_IS_NEWT_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_CONTAINER))
|
||||
#define NMT_IS_NEWT_CONTAINER_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_CONTAINER))
|
||||
#define NMT_NEWT_CONTAINER_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_CONTAINER, NmtNewtContainerClass))
|
||||
|
||||
struct _NmtNewtContainer {
|
||||
NmtNewtWidget parent;
|
||||
|
||||
NmtNewtWidget parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtWidgetClass parent;
|
||||
NmtNewtWidgetClass parent;
|
||||
|
||||
/* methods */
|
||||
void (*add) (NmtNewtContainer *container,
|
||||
NmtNewtWidget *child);
|
||||
void (*remove) (NmtNewtContainer *container,
|
||||
NmtNewtWidget *child);
|
||||
/* methods */
|
||||
void (*add)(NmtNewtContainer *container, NmtNewtWidget *child);
|
||||
void (*remove)(NmtNewtContainer *container, NmtNewtWidget *child);
|
||||
|
||||
void (*child_validity_changed) (NmtNewtContainer *container,
|
||||
NmtNewtWidget *child);
|
||||
void (*child_validity_changed)(NmtNewtContainer *container, NmtNewtWidget *child);
|
||||
|
||||
} NmtNewtContainerClass;
|
||||
|
||||
GType nmt_newt_container_get_type (void);
|
||||
GType nmt_newt_container_get_type(void);
|
||||
|
||||
void nmt_newt_container_remove (NmtNewtContainer *container,
|
||||
NmtNewtWidget *widget);
|
||||
void nmt_newt_container_remove(NmtNewtContainer *container, NmtNewtWidget *widget);
|
||||
|
||||
GSList *nmt_newt_container_get_children (NmtNewtContainer *container);
|
||||
GSList *nmt_newt_container_get_children(NmtNewtContainer *container);
|
||||
|
||||
#endif /* NMT_NEWT_CONTAINER_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -19,22 +19,23 @@
|
|||
|
||||
#include "nmt-newt-entry-numeric.h"
|
||||
|
||||
G_DEFINE_TYPE (NmtNewtEntryNumeric, nmt_newt_entry_numeric, NMT_TYPE_NEWT_ENTRY)
|
||||
G_DEFINE_TYPE(NmtNewtEntryNumeric, nmt_newt_entry_numeric, NMT_TYPE_NEWT_ENTRY)
|
||||
|
||||
#define NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericPrivate))
|
||||
#define NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericPrivate))
|
||||
|
||||
typedef struct {
|
||||
gint64 min, max;
|
||||
bool optional;
|
||||
gint64 min, max;
|
||||
bool optional;
|
||||
} NmtNewtEntryNumericPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_MINIMUM,
|
||||
PROP_MAXIMUM,
|
||||
PROP_OPTIONAL,
|
||||
PROP_0,
|
||||
PROP_MINIMUM,
|
||||
PROP_MAXIMUM,
|
||||
PROP_OPTIONAL,
|
||||
|
||||
LAST_PROP
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -49,14 +50,9 @@ enum {
|
|||
* Returns: a new #NmtNewtEntryNumeric
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_entry_numeric_new (int width,
|
||||
gint64 min,
|
||||
gint64 max)
|
||||
nmt_newt_entry_numeric_new(int width, gint64 min, gint64 max)
|
||||
{
|
||||
return nmt_newt_entry_numeric_new_full (width,
|
||||
min,
|
||||
max,
|
||||
FALSE);
|
||||
return nmt_newt_entry_numeric_new_full(width, min, max, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,171 +68,177 @@ nmt_newt_entry_numeric_new (int width,
|
|||
* Returns: a new #NmtNewtEntryNumeric
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_entry_numeric_new_full (int width,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gboolean optional)
|
||||
nmt_newt_entry_numeric_new_full(int width, gint64 min, gint64 max, gboolean optional)
|
||||
{
|
||||
return g_object_new (NMT_TYPE_NEWT_ENTRY_NUMERIC,
|
||||
"width", width,
|
||||
"minimum", min,
|
||||
"maximum", max,
|
||||
"optional", optional,
|
||||
NULL);
|
||||
return g_object_new(NMT_TYPE_NEWT_ENTRY_NUMERIC,
|
||||
"width",
|
||||
width,
|
||||
"minimum",
|
||||
min,
|
||||
"maximum",
|
||||
max,
|
||||
"optional",
|
||||
optional,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
newt_entry_numeric_filter (NmtNewtEntry *entry,
|
||||
const char *text,
|
||||
int ch,
|
||||
int position,
|
||||
gpointer user_data)
|
||||
newt_entry_numeric_filter(NmtNewtEntry *entry,
|
||||
const char * text,
|
||||
int ch,
|
||||
int position,
|
||||
gpointer user_data)
|
||||
{
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE (entry);
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(entry);
|
||||
|
||||
if (g_ascii_isdigit (ch))
|
||||
return TRUE;
|
||||
if (g_ascii_isdigit(ch))
|
||||
return TRUE;
|
||||
|
||||
if (ch == '-' && position == 0 && priv->min < 0)
|
||||
return TRUE;
|
||||
if (ch == '-' && position == 0 && priv->min < 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
newt_entry_numeric_validate (NmtNewtEntry *entry,
|
||||
const char *text,
|
||||
gpointer user_data)
|
||||
newt_entry_numeric_validate(NmtNewtEntry *entry, const char *text, gpointer user_data)
|
||||
{
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE (entry);
|
||||
gint64 val;
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(entry);
|
||||
gint64 val;
|
||||
|
||||
if (!*text)
|
||||
return priv->optional ? TRUE : FALSE;
|
||||
if (!*text)
|
||||
return priv->optional ? TRUE : FALSE;
|
||||
|
||||
val = _nm_utils_ascii_str_to_int64 (text, 10, priv->min, priv->max, G_MAXINT64);
|
||||
return val != G_MAXINT64 || errno == 0;
|
||||
val = _nm_utils_ascii_str_to_int64(text, 10, priv->min, priv->max, G_MAXINT64);
|
||||
return val != G_MAXINT64 || errno == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_numeric_init (NmtNewtEntryNumeric *entry)
|
||||
nmt_newt_entry_numeric_init(NmtNewtEntryNumeric *entry)
|
||||
{
|
||||
nmt_newt_entry_set_filter (NMT_NEWT_ENTRY (entry), newt_entry_numeric_filter, NULL);
|
||||
nmt_newt_entry_set_validator (NMT_NEWT_ENTRY (entry), newt_entry_numeric_validate, NULL);
|
||||
nmt_newt_entry_set_filter(NMT_NEWT_ENTRY(entry), newt_entry_numeric_filter, NULL);
|
||||
nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(entry), newt_entry_numeric_validate, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_numeric_constructed (GObject *object)
|
||||
nmt_newt_entry_numeric_constructed(GObject *object)
|
||||
{
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE (object);
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(object);
|
||||
|
||||
if (!*nmt_newt_entry_get_text (NMT_NEWT_ENTRY (object))) {
|
||||
char buf[32];
|
||||
if (!*nmt_newt_entry_get_text(NMT_NEWT_ENTRY(object))) {
|
||||
char buf[32];
|
||||
|
||||
g_snprintf (buf, sizeof (buf), "%lld", (long long) priv->min);
|
||||
nmt_newt_entry_set_text (NMT_NEWT_ENTRY (object), buf);
|
||||
}
|
||||
g_snprintf(buf, sizeof(buf), "%lld", (long long) priv->min);
|
||||
nmt_newt_entry_set_text(NMT_NEWT_ENTRY(object), buf);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nmt_newt_entry_numeric_parent_class)->constructed (object);
|
||||
G_OBJECT_CLASS(nmt_newt_entry_numeric_parent_class)->constructed(object);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_numeric_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_entry_numeric_set_property(GObject * object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE (object);
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MINIMUM:
|
||||
priv->min = g_value_get_int64 (value);
|
||||
break;
|
||||
case PROP_MAXIMUM:
|
||||
priv->max = g_value_get_int64 (value);
|
||||
break;
|
||||
case PROP_OPTIONAL:
|
||||
priv->optional = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_MINIMUM:
|
||||
priv->min = g_value_get_int64(value);
|
||||
break;
|
||||
case PROP_MAXIMUM:
|
||||
priv->max = g_value_get_int64(value);
|
||||
break;
|
||||
case PROP_OPTIONAL:
|
||||
priv->optional = g_value_get_boolean(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_numeric_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_entry_numeric_get_property(GObject * object,
|
||||
guint prop_id,
|
||||
GValue * value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE (object);
|
||||
NmtNewtEntryNumericPrivate *priv = NMT_NEWT_ENTRY_NUMERIC_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MINIMUM:
|
||||
g_value_set_int64 (value, priv->min);
|
||||
break;
|
||||
case PROP_MAXIMUM:
|
||||
g_value_set_int64 (value, priv->max);
|
||||
break;
|
||||
case PROP_OPTIONAL:
|
||||
g_value_set_boolean (value, priv->optional);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_MINIMUM:
|
||||
g_value_set_int64(value, priv->min);
|
||||
break;
|
||||
case PROP_MAXIMUM:
|
||||
g_value_set_int64(value, priv->max);
|
||||
break;
|
||||
case PROP_OPTIONAL:
|
||||
g_value_set_boolean(value, priv->optional);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_numeric_class_init (NmtNewtEntryNumericClass *entry_class)
|
||||
nmt_newt_entry_numeric_class_init(NmtNewtEntryNumericClass *entry_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (entry_class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(entry_class);
|
||||
|
||||
g_type_class_add_private (entry_class, sizeof (NmtNewtEntryNumericPrivate));
|
||||
g_type_class_add_private(entry_class, sizeof(NmtNewtEntryNumericPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->constructed = nmt_newt_entry_numeric_constructed;
|
||||
object_class->set_property = nmt_newt_entry_numeric_set_property;
|
||||
object_class->get_property = nmt_newt_entry_numeric_get_property;
|
||||
/* virtual methods */
|
||||
object_class->constructed = nmt_newt_entry_numeric_constructed;
|
||||
object_class->set_property = nmt_newt_entry_numeric_set_property;
|
||||
object_class->get_property = nmt_newt_entry_numeric_get_property;
|
||||
|
||||
/**
|
||||
* NmtNewtEntryNumeric:minimum:
|
||||
*
|
||||
* The minimum #NmtNewtWidget:valid value for the entry. If this
|
||||
* is non-negative, then the entry will not allow negative numbers
|
||||
* to be entered.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_MINIMUM,
|
||||
g_param_spec_int64 ("minimum", "", "",
|
||||
G_MININT64, G_MAXINT64, 0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntryNumeric:maximum:
|
||||
*
|
||||
* The maximum #NmtNewtWidget:valid value for the entry.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_MAXIMUM,
|
||||
g_param_spec_int64 ("maximum", "", "",
|
||||
G_MININT64, G_MAXINT64, G_MAXINT64,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntryNumeric:optional:
|
||||
*
|
||||
* If %TRUE, allow empty string to indicate some default value.
|
||||
* It means the property is optional and can be left at the default
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_OPTIONAL,
|
||||
g_param_spec_boolean ("optional", "", "",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntryNumeric:minimum:
|
||||
*
|
||||
* The minimum #NmtNewtWidget:valid value for the entry. If this
|
||||
* is non-negative, then the entry will not allow negative numbers
|
||||
* to be entered.
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_MINIMUM,
|
||||
g_param_spec_int64("minimum",
|
||||
"",
|
||||
"",
|
||||
G_MININT64,
|
||||
G_MAXINT64,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntryNumeric:maximum:
|
||||
*
|
||||
* The maximum #NmtNewtWidget:valid value for the entry.
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_MAXIMUM,
|
||||
g_param_spec_int64("maximum",
|
||||
"",
|
||||
"",
|
||||
G_MININT64,
|
||||
G_MAXINT64,
|
||||
G_MAXINT64,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntryNumeric:optional:
|
||||
*
|
||||
* If %TRUE, allow empty string to indicate some default value.
|
||||
* It means the property is optional and can be left at the default
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_OPTIONAL,
|
||||
g_param_spec_boolean("optional",
|
||||
"",
|
||||
"",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,32 +8,32 @@
|
|||
|
||||
#include "nmt-newt-entry.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_ENTRY_NUMERIC (nmt_newt_entry_numeric_get_type ())
|
||||
#define NMT_NEWT_ENTRY_NUMERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumeric))
|
||||
#define NMT_NEWT_ENTRY_NUMERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericClass))
|
||||
#define NMT_IS_NEWT_ENTRY_NUMERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_ENTRY_NUMERIC))
|
||||
#define NMT_IS_NEWT_ENTRY_NUMERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_ENTRY_NUMERIC))
|
||||
#define NMT_NEWT_ENTRY_NUMERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericClass))
|
||||
#define NMT_TYPE_NEWT_ENTRY_NUMERIC (nmt_newt_entry_numeric_get_type())
|
||||
#define NMT_NEWT_ENTRY_NUMERIC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumeric))
|
||||
#define NMT_NEWT_ENTRY_NUMERIC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericClass))
|
||||
#define NMT_IS_NEWT_ENTRY_NUMERIC(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_ENTRY_NUMERIC))
|
||||
#define NMT_IS_NEWT_ENTRY_NUMERIC_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_ENTRY_NUMERIC))
|
||||
#define NMT_NEWT_ENTRY_NUMERIC_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_ENTRY_NUMERIC, NmtNewtEntryNumericClass))
|
||||
|
||||
struct _NmtNewtEntryNumeric {
|
||||
NmtNewtEntry parent;
|
||||
|
||||
NmtNewtEntry parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtEntryClass parent;
|
||||
NmtNewtEntryClass parent;
|
||||
|
||||
} NmtNewtEntryNumericClass;
|
||||
|
||||
GType nmt_newt_entry_numeric_get_type (void);
|
||||
GType nmt_newt_entry_numeric_get_type(void);
|
||||
|
||||
NmtNewtWidget *nmt_newt_entry_numeric_new (int width,
|
||||
gint64 min,
|
||||
gint64 max);
|
||||
NmtNewtWidget *nmt_newt_entry_numeric_new(int width, gint64 min, gint64 max);
|
||||
|
||||
NmtNewtWidget *nmt_newt_entry_numeric_new_full (int width,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gboolean optional);
|
||||
NmtNewtWidget *
|
||||
nmt_newt_entry_numeric_new_full(int width, gint64 min, gint64 max, gboolean optional);
|
||||
|
||||
#endif /* NMT_NEWT_ENTRY_NUMERIC_H */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -20,32 +20,33 @@
|
|||
#include "nmt-newt-hacks.h"
|
||||
#include "nmt-newt-utils.h"
|
||||
|
||||
G_DEFINE_TYPE (NmtNewtEntry, nmt_newt_entry, NMT_TYPE_NEWT_COMPONENT)
|
||||
G_DEFINE_TYPE(NmtNewtEntry, nmt_newt_entry, NMT_TYPE_NEWT_COMPONENT)
|
||||
|
||||
#define NMT_NEWT_ENTRY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_NEWT_ENTRY, NmtNewtEntryPrivate))
|
||||
#define NMT_NEWT_ENTRY_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_NEWT_ENTRY, NmtNewtEntryPrivate))
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
NmtNewtEntryFlags flags;
|
||||
char *text;
|
||||
int last_cursor_pos;
|
||||
guint idle_update;
|
||||
int width;
|
||||
NmtNewtEntryFlags flags;
|
||||
char * text;
|
||||
int last_cursor_pos;
|
||||
guint idle_update;
|
||||
|
||||
NmtNewtEntryFilter filter;
|
||||
gpointer filter_data;
|
||||
NmtNewtEntryFilter filter;
|
||||
gpointer filter_data;
|
||||
|
||||
NmtNewtEntryValidator validator;
|
||||
gpointer validator_data;
|
||||
NmtNewtEntryValidator validator;
|
||||
gpointer validator_data;
|
||||
} NmtNewtEntryPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TEXT,
|
||||
PROP_WIDTH,
|
||||
PROP_FLAGS,
|
||||
PROP_PASSWORD,
|
||||
PROP_0,
|
||||
PROP_TEXT,
|
||||
PROP_WIDTH,
|
||||
PROP_FLAGS,
|
||||
PROP_PASSWORD,
|
||||
|
||||
LAST_PROP
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -70,13 +71,9 @@ enum {
|
|||
* Returns: a new #NmtNewtEntry
|
||||
*/
|
||||
NmtNewtWidget *
|
||||
nmt_newt_entry_new (int width,
|
||||
NmtNewtEntryFlags flags)
|
||||
nmt_newt_entry_new(int width, NmtNewtEntryFlags flags)
|
||||
{
|
||||
return g_object_new (NMT_TYPE_NEWT_ENTRY,
|
||||
"width", width,
|
||||
"flags", flags,
|
||||
NULL);
|
||||
return g_object_new(NMT_TYPE_NEWT_ENTRY, "width", width, "flags", flags, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,31 +104,28 @@ nmt_newt_entry_new (int width,
|
|||
* nmt_newt_entry_set_text().
|
||||
*/
|
||||
void
|
||||
nmt_newt_entry_set_filter (NmtNewtEntry *entry,
|
||||
NmtNewtEntryFilter filter,
|
||||
gpointer user_data)
|
||||
nmt_newt_entry_set_filter(NmtNewtEntry *entry, NmtNewtEntryFilter filter, gpointer user_data)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
priv->filter = filter;
|
||||
priv->filter_data = user_data;
|
||||
priv->filter = filter;
|
||||
priv->filter_data = user_data;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_check_valid (NmtNewtEntry *entry)
|
||||
nmt_newt_entry_check_valid(NmtNewtEntry *entry)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
gboolean valid;
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
gboolean valid;
|
||||
|
||||
if ( (priv->flags & NMT_NEWT_ENTRY_NONEMPTY)
|
||||
&& *priv->text == '\0')
|
||||
valid = FALSE;
|
||||
else if (priv->validator)
|
||||
valid = !!priv->validator (entry, priv->text, priv->validator_data);
|
||||
else
|
||||
valid = TRUE;
|
||||
if ((priv->flags & NMT_NEWT_ENTRY_NONEMPTY) && *priv->text == '\0')
|
||||
valid = FALSE;
|
||||
else if (priv->validator)
|
||||
valid = !!priv->validator(entry, priv->text, priv->validator_data);
|
||||
else
|
||||
valid = TRUE;
|
||||
|
||||
nmt_newt_widget_set_valid (NMT_NEWT_WIDGET (entry), valid);
|
||||
nmt_newt_widget_set_valid(NMT_NEWT_WIDGET(entry), valid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -156,47 +150,45 @@ nmt_newt_entry_check_valid (NmtNewtEntry *entry)
|
|||
* will not be considered #NmtNewtWidget:valid.
|
||||
*/
|
||||
void
|
||||
nmt_newt_entry_set_validator (NmtNewtEntry *entry,
|
||||
NmtNewtEntryValidator validator,
|
||||
gpointer user_data)
|
||||
nmt_newt_entry_set_validator(NmtNewtEntry * entry,
|
||||
NmtNewtEntryValidator validator,
|
||||
gpointer user_data)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
priv->validator = validator;
|
||||
priv->validator_data = user_data;
|
||||
priv->validator = validator;
|
||||
priv->validator_data = user_data;
|
||||
|
||||
nmt_newt_entry_check_valid (entry);
|
||||
nmt_newt_entry_check_valid(entry);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_set_text_internal (NmtNewtEntry *entry,
|
||||
const char *text,
|
||||
newtComponent co)
|
||||
nmt_newt_entry_set_text_internal(NmtNewtEntry *entry, const char *text, newtComponent co)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
if (!text)
|
||||
text = "";
|
||||
if (!text)
|
||||
text = "";
|
||||
|
||||
if (!strcmp (priv->text, text))
|
||||
return;
|
||||
if (!strcmp(priv->text, text))
|
||||
return;
|
||||
|
||||
g_free (priv->text);
|
||||
priv->text = g_strdup (text);
|
||||
g_free(priv->text);
|
||||
priv->text = g_strdup(text);
|
||||
|
||||
if (co) {
|
||||
char *text_lc;
|
||||
if (co) {
|
||||
char *text_lc;
|
||||
|
||||
text_lc = priv->text ? nmt_newt_locale_from_utf8 (priv->text) : NULL;
|
||||
newtEntrySet (co, text_lc, TRUE);
|
||||
g_free (text_lc);
|
||||
priv->last_cursor_pos = -1;
|
||||
}
|
||||
text_lc = priv->text ? nmt_newt_locale_from_utf8(priv->text) : NULL;
|
||||
newtEntrySet(co, text_lc, TRUE);
|
||||
g_free(text_lc);
|
||||
priv->last_cursor_pos = -1;
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (entry));
|
||||
nmt_newt_entry_check_valid (entry);
|
||||
g_object_notify (G_OBJECT (entry), "text");
|
||||
g_object_thaw_notify (G_OBJECT (entry));
|
||||
g_object_freeze_notify(G_OBJECT(entry));
|
||||
nmt_newt_entry_check_valid(entry);
|
||||
g_object_notify(G_OBJECT(entry), "text");
|
||||
g_object_thaw_notify(G_OBJECT(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -209,13 +201,12 @@ nmt_newt_entry_set_text_internal (NmtNewtEntry *entry,
|
|||
* be re-run.
|
||||
*/
|
||||
void
|
||||
nmt_newt_entry_set_text (NmtNewtEntry *entry,
|
||||
const char *text)
|
||||
nmt_newt_entry_set_text(NmtNewtEntry *entry, const char *text)
|
||||
{
|
||||
newtComponent co;
|
||||
newtComponent co;
|
||||
|
||||
co = nmt_newt_component_get_component (NMT_NEWT_COMPONENT (entry));
|
||||
nmt_newt_entry_set_text_internal (entry, text, co);
|
||||
co = nmt_newt_component_get_component(NMT_NEWT_COMPONENT(entry));
|
||||
nmt_newt_entry_set_text_internal(entry, text, co);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -227,11 +218,11 @@ nmt_newt_entry_set_text (NmtNewtEntry *entry,
|
|||
* Returns: @entry's text
|
||||
*/
|
||||
const char *
|
||||
nmt_newt_entry_get_text (NmtNewtEntry *entry)
|
||||
nmt_newt_entry_get_text(NmtNewtEntry *entry)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
return priv->text;
|
||||
return priv->text;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -242,18 +233,17 @@ nmt_newt_entry_get_text (NmtNewtEntry *entry)
|
|||
* Updates @entry's width
|
||||
*/
|
||||
void
|
||||
nmt_newt_entry_set_width (NmtNewtEntry *entry,
|
||||
int width)
|
||||
nmt_newt_entry_set_width(NmtNewtEntry *entry, int width)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
if (priv->width == width)
|
||||
return;
|
||||
if (priv->width == width)
|
||||
return;
|
||||
|
||||
priv->width = width;
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (entry));
|
||||
priv->width = width;
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(entry));
|
||||
|
||||
g_object_notify (G_OBJECT (entry), "width");
|
||||
g_object_notify(G_OBJECT(entry), "width");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -265,261 +255,252 @@ nmt_newt_entry_set_width (NmtNewtEntry *entry,
|
|||
* Returns: @entry's width
|
||||
*/
|
||||
int
|
||||
nmt_newt_entry_get_width (NmtNewtEntry *entry)
|
||||
nmt_newt_entry_get_width(NmtNewtEntry *entry)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
return priv->width;
|
||||
return priv->width;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_init (NmtNewtEntry *entry)
|
||||
nmt_newt_entry_init(NmtNewtEntry *entry)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
priv->text = g_strdup ("");
|
||||
priv->last_cursor_pos = -1;
|
||||
priv->text = g_strdup("");
|
||||
priv->last_cursor_pos = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_constructed (GObject *object)
|
||||
nmt_newt_entry_constructed(GObject *object)
|
||||
{
|
||||
nmt_newt_entry_check_valid (NMT_NEWT_ENTRY (object));
|
||||
nmt_newt_entry_check_valid(NMT_NEWT_ENTRY(object));
|
||||
|
||||
G_OBJECT_CLASS (nmt_newt_entry_parent_class)->constructed (object);
|
||||
G_OBJECT_CLASS(nmt_newt_entry_parent_class)->constructed(object);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_finalize (GObject *object)
|
||||
nmt_newt_entry_finalize(GObject *object)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (object);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(object);
|
||||
|
||||
g_free (priv->text);
|
||||
if (priv->idle_update)
|
||||
g_source_remove (priv->idle_update);
|
||||
g_free(priv->text);
|
||||
if (priv->idle_update)
|
||||
g_source_remove(priv->idle_update);
|
||||
|
||||
G_OBJECT_CLASS (nmt_newt_entry_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS(nmt_newt_entry_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_update_entry (gpointer entry)
|
||||
idle_update_entry(gpointer entry)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
newtComponent co = nmt_newt_component_get_component (entry);
|
||||
char *text;
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
newtComponent co = nmt_newt_component_get_component(entry);
|
||||
char * text;
|
||||
|
||||
priv->idle_update = 0;
|
||||
if (!co)
|
||||
return FALSE;
|
||||
priv->idle_update = 0;
|
||||
if (!co)
|
||||
return FALSE;
|
||||
|
||||
priv->last_cursor_pos = newtEntryGetCursorPosition (co);
|
||||
priv->last_cursor_pos = newtEntryGetCursorPosition(co);
|
||||
|
||||
text = nmt_newt_locale_to_utf8 (newtEntryGetValue (co));
|
||||
nmt_newt_entry_set_text_internal (entry, text, NULL);
|
||||
g_free (text);
|
||||
text = nmt_newt_locale_to_utf8(newtEntryGetValue(co));
|
||||
nmt_newt_entry_set_text_internal(entry, text, NULL);
|
||||
g_free(text);
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
entry_filter (newtComponent entry,
|
||||
void *self,
|
||||
int ch,
|
||||
int cursor)
|
||||
entry_filter(newtComponent entry, void *self, int ch, int cursor)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (self);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(self);
|
||||
|
||||
if (g_ascii_isprint (ch)) {
|
||||
if (priv->filter) {
|
||||
char *text = nmt_newt_locale_to_utf8 (newtEntryGetValue (entry));
|
||||
if (g_ascii_isprint(ch)) {
|
||||
if (priv->filter) {
|
||||
char *text = nmt_newt_locale_to_utf8(newtEntryGetValue(entry));
|
||||
|
||||
if (!priv->filter (self, text, ch, cursor, priv->filter_data)) {
|
||||
g_free (text);
|
||||
return 0;
|
||||
}
|
||||
g_free (text);
|
||||
}
|
||||
}
|
||||
if (!priv->filter(self, text, ch, cursor, priv->filter_data)) {
|
||||
g_free(text);
|
||||
return 0;
|
||||
}
|
||||
g_free(text);
|
||||
}
|
||||
}
|
||||
|
||||
if (!priv->idle_update)
|
||||
priv->idle_update = g_idle_add (idle_update_entry, self);
|
||||
return ch;
|
||||
if (!priv->idle_update)
|
||||
priv->idle_update = g_idle_add(idle_update_entry, self);
|
||||
return ch;
|
||||
}
|
||||
|
||||
static guint
|
||||
convert_flags (NmtNewtEntryFlags flags)
|
||||
convert_flags(NmtNewtEntryFlags flags)
|
||||
{
|
||||
guint newt_flags = NEWT_FLAG_RETURNEXIT;
|
||||
guint newt_flags = NEWT_FLAG_RETURNEXIT;
|
||||
|
||||
if (!(flags & NMT_NEWT_ENTRY_NOSCROLL))
|
||||
newt_flags |= NEWT_FLAG_SCROLL;
|
||||
if (flags & NMT_NEWT_ENTRY_PASSWORD)
|
||||
newt_flags |= NEWT_FLAG_PASSWORD;
|
||||
if (!(flags & NMT_NEWT_ENTRY_NOSCROLL))
|
||||
newt_flags |= NEWT_FLAG_SCROLL;
|
||||
if (flags & NMT_NEWT_ENTRY_PASSWORD)
|
||||
newt_flags |= NEWT_FLAG_PASSWORD;
|
||||
|
||||
return newt_flags;
|
||||
return newt_flags;
|
||||
}
|
||||
|
||||
static newtComponent
|
||||
nmt_newt_entry_build_component (NmtNewtComponent *component,
|
||||
gboolean sensitive)
|
||||
nmt_newt_entry_build_component(NmtNewtComponent *component, gboolean sensitive)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (component);
|
||||
newtComponent co;
|
||||
char *text_lc;
|
||||
int flags;
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(component);
|
||||
newtComponent co;
|
||||
char * text_lc;
|
||||
int flags;
|
||||
|
||||
flags = convert_flags (priv->flags);
|
||||
if (!sensitive)
|
||||
flags |= NEWT_FLAG_DISABLED;
|
||||
flags = convert_flags(priv->flags);
|
||||
if (!sensitive)
|
||||
flags |= NEWT_FLAG_DISABLED;
|
||||
|
||||
text_lc = priv->text ? nmt_newt_locale_from_utf8 (priv->text) : NULL;
|
||||
co = newtEntry (-1, -1, text_lc, priv->width, NULL, flags);
|
||||
g_free (text_lc);
|
||||
text_lc = priv->text ? nmt_newt_locale_from_utf8(priv->text) : NULL;
|
||||
co = newtEntry(-1, -1, text_lc, priv->width, NULL, flags);
|
||||
g_free(text_lc);
|
||||
|
||||
if (priv->last_cursor_pos != -1)
|
||||
newtEntrySetCursorPosition (co, priv->last_cursor_pos);
|
||||
if (priv->last_cursor_pos != -1)
|
||||
newtEntrySetCursorPosition(co, priv->last_cursor_pos);
|
||||
|
||||
newtEntrySetFilter (co, entry_filter, component);
|
||||
return co;
|
||||
newtEntrySetFilter(co, entry_filter, component);
|
||||
return co;
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_activated (NmtNewtWidget *widget)
|
||||
nmt_newt_entry_activated(NmtNewtWidget *widget)
|
||||
{
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (widget);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(widget);
|
||||
|
||||
if (priv->idle_update) {
|
||||
g_source_remove (priv->idle_update);
|
||||
idle_update_entry (widget);
|
||||
}
|
||||
if (priv->idle_update) {
|
||||
g_source_remove(priv->idle_update);
|
||||
idle_update_entry(widget);
|
||||
}
|
||||
|
||||
NMT_NEWT_WIDGET_CLASS (nmt_newt_entry_parent_class)->activated (widget);
|
||||
NMT_NEWT_WIDGET_CLASS(nmt_newt_entry_parent_class)->activated(widget);
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_entry_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtEntry *entry = NMT_NEWT_ENTRY (object);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntry * entry = NMT_NEWT_ENTRY(object);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TEXT:
|
||||
nmt_newt_entry_set_text (entry, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
nmt_newt_entry_set_width (entry, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
priv->flags = g_value_get_uint (value);
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (entry));
|
||||
break;
|
||||
case PROP_PASSWORD:
|
||||
if (g_value_get_boolean (value))
|
||||
priv->flags |= NMT_NEWT_ENTRY_PASSWORD;
|
||||
else
|
||||
priv->flags &= ~NMT_NEWT_ENTRY_PASSWORD;
|
||||
nmt_newt_widget_needs_rebuild (NMT_NEWT_WIDGET (entry));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_TEXT:
|
||||
nmt_newt_entry_set_text(entry, g_value_get_string(value));
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
nmt_newt_entry_set_width(entry, g_value_get_int(value));
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
priv->flags = g_value_get_uint(value);
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(entry));
|
||||
break;
|
||||
case PROP_PASSWORD:
|
||||
if (g_value_get_boolean(value))
|
||||
priv->flags |= NMT_NEWT_ENTRY_PASSWORD;
|
||||
else
|
||||
priv->flags &= ~NMT_NEWT_ENTRY_PASSWORD;
|
||||
nmt_newt_widget_needs_rebuild(NMT_NEWT_WIDGET(entry));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
nmt_newt_entry_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NmtNewtEntry *entry = NMT_NEWT_ENTRY (object);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE (entry);
|
||||
NmtNewtEntry * entry = NMT_NEWT_ENTRY(object);
|
||||
NmtNewtEntryPrivate *priv = NMT_NEWT_ENTRY_GET_PRIVATE(entry);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TEXT:
|
||||
g_value_set_string (value, nmt_newt_entry_get_text (entry));
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
g_value_set_int (value, priv->width);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
g_value_set_uint (value, priv->flags);
|
||||
break;
|
||||
case PROP_PASSWORD:
|
||||
g_value_set_boolean (value, (priv->flags & NMT_NEWT_ENTRY_PASSWORD) != 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
switch (prop_id) {
|
||||
case PROP_TEXT:
|
||||
g_value_set_string(value, nmt_newt_entry_get_text(entry));
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
g_value_set_int(value, priv->width);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
g_value_set_uint(value, priv->flags);
|
||||
break;
|
||||
case PROP_PASSWORD:
|
||||
g_value_set_boolean(value, (priv->flags & NMT_NEWT_ENTRY_PASSWORD) != 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmt_newt_entry_class_init (NmtNewtEntryClass *entry_class)
|
||||
nmt_newt_entry_class_init(NmtNewtEntryClass *entry_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (entry_class);
|
||||
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (entry_class);
|
||||
NmtNewtComponentClass *component_class = NMT_NEWT_COMPONENT_CLASS (entry_class);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(entry_class);
|
||||
NmtNewtWidgetClass * widget_class = NMT_NEWT_WIDGET_CLASS(entry_class);
|
||||
NmtNewtComponentClass *component_class = NMT_NEWT_COMPONENT_CLASS(entry_class);
|
||||
|
||||
g_type_class_add_private (entry_class, sizeof (NmtNewtEntryPrivate));
|
||||
g_type_class_add_private(entry_class, sizeof(NmtNewtEntryPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->constructed = nmt_newt_entry_constructed;
|
||||
object_class->set_property = nmt_newt_entry_set_property;
|
||||
object_class->get_property = nmt_newt_entry_get_property;
|
||||
object_class->finalize = nmt_newt_entry_finalize;
|
||||
/* virtual methods */
|
||||
object_class->constructed = nmt_newt_entry_constructed;
|
||||
object_class->set_property = nmt_newt_entry_set_property;
|
||||
object_class->get_property = nmt_newt_entry_get_property;
|
||||
object_class->finalize = nmt_newt_entry_finalize;
|
||||
|
||||
widget_class->activated = nmt_newt_entry_activated;
|
||||
widget_class->activated = nmt_newt_entry_activated;
|
||||
|
||||
component_class->build_component = nmt_newt_entry_build_component;
|
||||
component_class->build_component = nmt_newt_entry_build_component;
|
||||
|
||||
/**
|
||||
* NmtNewtEntry:text
|
||||
*
|
||||
* The entry's text
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_TEXT,
|
||||
g_param_spec_string ("text", "", "",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:width
|
||||
*
|
||||
* The entry's width in characters
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_WIDTH,
|
||||
g_param_spec_int ("width", "", "",
|
||||
-1, 80, -1,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:flags
|
||||
*
|
||||
* The entry's #NmtNewtEntryFlags
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_FLAGS,
|
||||
g_param_spec_uint ("flags", "", "",
|
||||
0, 0xFFFF, 0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:password
|
||||
*
|
||||
* %TRUE if #NmtNewtEntry:flags contains %NMT_NEWT_ENTRY_PASSWORD,
|
||||
* %FALSE if not.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_PASSWORD,
|
||||
g_param_spec_boolean ("password", "", "",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:text
|
||||
*
|
||||
* The entry's text
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_TEXT,
|
||||
g_param_spec_string("text", "", "", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:width
|
||||
*
|
||||
* The entry's width in characters
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_WIDTH,
|
||||
g_param_spec_int("width", "", "", -1, 80, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:flags
|
||||
*
|
||||
* The entry's #NmtNewtEntryFlags
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_FLAGS,
|
||||
g_param_spec_uint("flags",
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
0xFFFF,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NmtNewtEntry:password
|
||||
*
|
||||
* %TRUE if #NmtNewtEntry:flags contains %NMT_NEWT_ENTRY_PASSWORD,
|
||||
* %FALSE if not.
|
||||
*/
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_PASSWORD,
|
||||
g_param_spec_boolean("password",
|
||||
"",
|
||||
"",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
|
@ -8,50 +8,47 @@
|
|||
|
||||
#include "nmt-newt-component.h"
|
||||
|
||||
#define NMT_TYPE_NEWT_ENTRY (nmt_newt_entry_get_type ())
|
||||
#define NMT_NEWT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_NEWT_ENTRY, NmtNewtEntry))
|
||||
#define NMT_NEWT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_NEWT_ENTRY, NmtNewtEntryClass))
|
||||
#define NMT_IS_NEWT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMT_TYPE_NEWT_ENTRY))
|
||||
#define NMT_IS_NEWT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMT_TYPE_NEWT_ENTRY))
|
||||
#define NMT_NEWT_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMT_TYPE_NEWT_ENTRY, NmtNewtEntryClass))
|
||||
#define NMT_TYPE_NEWT_ENTRY (nmt_newt_entry_get_type())
|
||||
#define NMT_NEWT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_NEWT_ENTRY, NmtNewtEntry))
|
||||
#define NMT_NEWT_ENTRY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_NEWT_ENTRY, NmtNewtEntryClass))
|
||||
#define NMT_IS_NEWT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_NEWT_ENTRY))
|
||||
#define NMT_IS_NEWT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_NEWT_ENTRY))
|
||||
#define NMT_NEWT_ENTRY_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_NEWT_ENTRY, NmtNewtEntryClass))
|
||||
|
||||
struct _NmtNewtEntry {
|
||||
NmtNewtComponent parent;
|
||||
|
||||
NmtNewtComponent parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NmtNewtComponentClass parent;
|
||||
NmtNewtComponentClass parent;
|
||||
|
||||
} NmtNewtEntryClass;
|
||||
|
||||
GType nmt_newt_entry_get_type (void);
|
||||
GType nmt_newt_entry_get_type(void);
|
||||
|
||||
typedef gboolean (*NmtNewtEntryFilter) (NmtNewtEntry *, const char *text, int ch, int position, gpointer);
|
||||
typedef gboolean (*NmtNewtEntryValidator) (NmtNewtEntry *, const char *text, gpointer);
|
||||
typedef gboolean (
|
||||
*NmtNewtEntryFilter)(NmtNewtEntry *, const char *text, int ch, int position, gpointer);
|
||||
typedef gboolean (*NmtNewtEntryValidator)(NmtNewtEntry *, const char *text, gpointer);
|
||||
|
||||
typedef enum {
|
||||
NMT_NEWT_ENTRY_NOSCROLL = (1 << 0),
|
||||
NMT_NEWT_ENTRY_PASSWORD = (1 << 1),
|
||||
NMT_NEWT_ENTRY_NONEMPTY = (1 << 2)
|
||||
NMT_NEWT_ENTRY_NOSCROLL = (1 << 0),
|
||||
NMT_NEWT_ENTRY_PASSWORD = (1 << 1),
|
||||
NMT_NEWT_ENTRY_NONEMPTY = (1 << 2)
|
||||
} NmtNewtEntryFlags;
|
||||
|
||||
NmtNewtWidget *nmt_newt_entry_new (int width,
|
||||
NmtNewtEntryFlags flags);
|
||||
NmtNewtWidget *nmt_newt_entry_new(int width, NmtNewtEntryFlags flags);
|
||||
|
||||
void nmt_newt_entry_set_filter (NmtNewtEntry *entry,
|
||||
NmtNewtEntryFilter filter,
|
||||
gpointer user_data);
|
||||
void nmt_newt_entry_set_validator (NmtNewtEntry *entry,
|
||||
NmtNewtEntryValidator validator,
|
||||
gpointer user_data);
|
||||
void nmt_newt_entry_set_filter(NmtNewtEntry *entry, NmtNewtEntryFilter filter, gpointer user_data);
|
||||
void nmt_newt_entry_set_validator(NmtNewtEntry * entry,
|
||||
NmtNewtEntryValidator validator,
|
||||
gpointer user_data);
|
||||
|
||||
void nmt_newt_entry_set_text (NmtNewtEntry *entry,
|
||||
const char *text);
|
||||
const char *nmt_newt_entry_get_text (NmtNewtEntry *entry);
|
||||
void nmt_newt_entry_set_text(NmtNewtEntry *entry, const char *text);
|
||||
const char *nmt_newt_entry_get_text(NmtNewtEntry *entry);
|
||||
|
||||
void nmt_newt_entry_set_width (NmtNewtEntry *entry,
|
||||
int width);
|
||||
int nmt_newt_entry_get_width (NmtNewtEntry *entry);
|
||||
void nmt_newt_entry_set_width(NmtNewtEntry *entry, int width);
|
||||
int nmt_newt_entry_get_width(NmtNewtEntry *entry);
|
||||
|
||||
#endif /* NMT_NEWT_ENTRY_H */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue