mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-31 20:40:18 +01:00
release: bump version to 1.39.4 (development)
This commit is contained in:
commit
e2476b1063
213 changed files with 5520 additions and 9063 deletions
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
set -ex
|
||||
|
||||
export PAGER=cat
|
||||
|
||||
IS_FEDORA=0
|
||||
IS_CENTOS=0
|
||||
IS_ALPINE=0
|
||||
|
|
|
|||
23
Makefile.am
23
Makefile.am
|
|
@ -1691,7 +1691,6 @@ libnm_lib_h_pub_real = \
|
|||
src/libnm-client-public/nm-object.h \
|
||||
src/libnm-client-public/nm-remote-connection.h \
|
||||
src/libnm-client-public/nm-secret-agent-old.h \
|
||||
src/libnm-client-public/nm-types.h \
|
||||
src/libnm-client-public/nm-vpn-connection.h \
|
||||
src/libnm-client-public/nm-vpn-editor.h \
|
||||
src/libnm-client-public/nm-vpn-plugin-old.h \
|
||||
|
|
@ -2329,12 +2328,8 @@ src_libnm_systemd_core_libnm_systemd_core_la_libadd = \
|
|||
|
||||
src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
|
||||
src/libnm-systemd-core/nm-default-systemd-core.h \
|
||||
src/libnm-systemd-core/nm-sd-utils-core.c \
|
||||
src/libnm-systemd-core/nm-sd-utils-core.h \
|
||||
src/libnm-systemd-core/nm-sd.c \
|
||||
src/libnm-systemd-core/nm-sd.h \
|
||||
src/libnm-systemd-core/nm-sd-utils-dhcp.h \
|
||||
src/libnm-systemd-core/nm-sd-utils-dhcp.c \
|
||||
src/libnm-systemd-core/sd-adapt-core/condition.h \
|
||||
src/libnm-systemd-core/sd-adapt-core/conf-parser.h \
|
||||
src/libnm-systemd-core/sd-adapt-core/device-util.h \
|
||||
|
|
@ -2345,16 +2340,8 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
|
|||
src/libnm-systemd-core/sd-adapt-core/sd-daemon.h \
|
||||
src/libnm-systemd-core/sd-adapt-core/sd-device.h \
|
||||
src/libnm-systemd-core/sd-adapt-core/udev-util.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/arp-util.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/arp-util.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-option.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp-protocol.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c \
|
||||
|
|
@ -2369,10 +2356,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
|
|||
src/libnm-systemd-core/src/libsystemd-network/lldp-rx-internal.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/network-common.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/network-common.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/network-internal.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/network-internal.h \
|
||||
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c \
|
||||
src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c \
|
||||
|
|
@ -2384,9 +2367,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
|
|||
src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h \
|
||||
src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c \
|
||||
src/libnm-systemd-core/src/systemd/_sd-common.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-dhcp-client.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-dhcp-option.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h \
|
||||
|
|
@ -2547,8 +2527,6 @@ src_core_libNetworkManager_la_SOURCES = \
|
|||
src/core/dns/nm-dns-dnsmasq.h \
|
||||
src/core/dns/nm-dns-systemd-resolved.c \
|
||||
src/core/dns/nm-dns-systemd-resolved.h \
|
||||
src/core/dns/nm-dns-unbound.c \
|
||||
src/core/dns/nm-dns-unbound.h \
|
||||
\
|
||||
src/core/dnsmasq/nm-dnsmasq-manager.c \
|
||||
src/core/dnsmasq/nm-dnsmasq-manager.h \
|
||||
|
|
@ -5337,6 +5315,7 @@ EXTRA_DIST += \
|
|||
src/tests/client/test-client.check-on-disk/test_002.expected \
|
||||
src/tests/client/test-client.check-on-disk/test_003.expected \
|
||||
src/tests/client/test-client.check-on-disk/test_004.expected \
|
||||
src/tests/client/test-client.check-on-disk/test_offline.expected \
|
||||
\
|
||||
src/tests/client/meson.build \
|
||||
$(NULL)
|
||||
|
|
|
|||
19
NEWS
19
NEWS
|
|
@ -1,3 +1,22 @@
|
|||
=============================================
|
||||
NetworkManager-1.40
|
||||
Overview of changes since NetworkManager-1.38
|
||||
=============================================
|
||||
|
||||
This is a snapshot of NetworkManager development. The API is
|
||||
subject to change and not guaranteed to be compatible with
|
||||
the later release.
|
||||
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||
|
||||
* Drop unused, internal systemd DHCPv4 client. This is long
|
||||
replaced by nettools' n-dhcp4 implementation.
|
||||
* The nmcli command now supports --offline argument with "add" and
|
||||
"modify" commands, allowing operation on keyfile-formatted connection
|
||||
profiles without the service running (e.g. during system provisioning).
|
||||
* The device state file /run/NetworkManager/devices/$ifindex now has
|
||||
new sections [dhcp4] and [dhcp6] containing the DHCP options for the
|
||||
current lease.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.38
|
||||
Overview of changes since NetworkManager-1.36
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@
|
|||
/* Define to path of dnsmasq binary */
|
||||
#mesondefine DNSMASQ_PATH
|
||||
|
||||
/* Define to path of unbound dnssec-trigger-script */
|
||||
#mesondefine DNSSEC_TRIGGER_PATH
|
||||
|
||||
/* Gettext package */
|
||||
#mesondefine GETTEXT_PACKAGE
|
||||
|
||||
|
|
|
|||
31
configure.ac
31
configure.ac
|
|
@ -7,8 +7,8 @@ dnl - add corresponding NM_VERSION_x_y_z macros in
|
|||
dnl "shared/nm-version-macros.h.in"
|
||||
dnl - update number in meson.build
|
||||
m4_define([nm_major_version], [1])
|
||||
m4_define([nm_minor_version], [38])
|
||||
m4_define([nm_micro_version], [0])
|
||||
m4_define([nm_minor_version], [39])
|
||||
m4_define([nm_micro_version], [4])
|
||||
m4_define([nm_version],
|
||||
[nm_major_version.nm_minor_version.nm_micro_version])
|
||||
|
||||
|
|
@ -306,11 +306,12 @@ AC_ARG_WITH(udev-dir,
|
|||
[Absolute path of the udev base directory. Set to 'no' not to install the udev rules]),
|
||||
[], [with_udev_dir="yes"])
|
||||
if test "$with_udev_dir" != 'no'; then
|
||||
if test "$with_udev_dir" != 'yes' && printf '%s' "$with_udev_dir" | grep -v -q '^/'; then
|
||||
AC_MSG_ERROR([--with-udev-dir must be an absolute path or 'yes' or 'no'. Instead it is '$with_udev_dir'])
|
||||
fi
|
||||
if test "$with_udev_dir" = 'yes'; then
|
||||
with_udev_dir="\$(prefix)/lib/udev"
|
||||
if test "$with_udev_dir" = 'yes' -o "$with_udev_dir" = "" ; then
|
||||
with_udev_dir="\${prefix}/lib/udev"
|
||||
else
|
||||
if printf '%s' "$with_udev_dir" | grep -v -q '^/'; then
|
||||
AC_MSG_ERROR([--with-udev-dir must be an absolute path or 'yes' or 'no'. Instead it is '$with_udev_dir'])
|
||||
fi
|
||||
fi
|
||||
UDEV_DIR="$with_udev_dir"
|
||||
AC_SUBST(UDEV_DIR)
|
||||
|
|
@ -745,7 +746,6 @@ AC_SUBST(GLIB_MKENUMS)
|
|||
|
||||
AC_ARG_WITH(dbus-sys-dir,
|
||||
AS_HELP_STRING([--with-dbus-sys-dir=DIR], [where D-BUS system.d directory is]))
|
||||
|
||||
if test -n "$with_dbus_sys_dir" ; then
|
||||
DBUS_SYS_DIR="$with_dbus_sys_dir"
|
||||
else
|
||||
|
|
@ -1006,18 +1006,6 @@ fi
|
|||
AC_DEFINE_UNQUOTED(DNSMASQ_PATH, "$DNSMASQ_PATH", [Define to path of dnsmasq binary])
|
||||
AC_SUBST(DNSMASQ_PATH)
|
||||
|
||||
# dnssec-trigger-script path
|
||||
AC_ARG_WITH(dnssec_trigger,
|
||||
AS_HELP_STRING([--with-dnssec-trigger=/path/to/dnssec-trigger-script], [path to unbound dnssec-trigger-script]))
|
||||
if test "x${with_dnssec_trigger}" = x; then
|
||||
AC_PATH_PROG(DNSSEC_TRIGGER_PATH, dnssec-trigger-script, /usr/libexec/dnssec-trigger-script,
|
||||
/usr/local/libexec:/usr/local/lib:/usr/local/lib/dnssec-trigger:/usr/libexec:/usr/lib:/usr/lib/dnssec-trigger)
|
||||
else
|
||||
DNSSEC_TRIGGER_PATH="$with_dnssec_trigger"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(DNSSEC_TRIGGER_PATH, "$DNSSEC_TRIGGER_PATH", [Define to path of unbound dnssec-trigger-script])
|
||||
AC_SUBST(DNSSEC_TRIGGER_PATH)
|
||||
|
||||
# system CA certificates path
|
||||
AC_ARG_WITH(system-ca-path,
|
||||
AS_HELP_STRING([--with-system-ca-path=/path/to/ssl/certs], [path to system CA certificates]))
|
||||
|
|
@ -1374,8 +1362,10 @@ echo " exec_prefix: $exec_prefix"
|
|||
echo " sysconfdir: $sysconfdir"
|
||||
echo " localstatedir: $localstatedir"
|
||||
echo " runstatedir: $runstatedir"
|
||||
echo " datarootdir: $datarootdir"
|
||||
echo " datadir: $datadir"
|
||||
echo " systemdunitdir: $with_systemdsystemunitdir"
|
||||
echo " udev-dir: $with_udev_dir"
|
||||
echo " nmbinary: $nmbinary"
|
||||
echo " nmconfdir: $nmconfdir"
|
||||
echo " nmlibdir: $nmlibdir"
|
||||
|
|
@ -1383,6 +1373,7 @@ echo " nmdatadir: $nmdatadir"
|
|||
echo " nmstatedir: $nmstatedir"
|
||||
echo " nmrundir: $nmrundir"
|
||||
echo " system-ca-path: $with_system_ca_path"
|
||||
echo " dbus-sys-dir: $DBUS_SYS_DIR"
|
||||
echo
|
||||
|
||||
echo "Platform:"
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
%global glib2_version %(pkg-config --modversion glib-2.0 2>/dev/null || echo bad)
|
||||
|
||||
%global epoch_version 1
|
||||
%global rpm_version __VERSION__
|
||||
%global real_version __VERSION__
|
||||
%global rpm_version %{real_version}
|
||||
%global release_version __RELEASE_VERSION__
|
||||
%global snapshot __SNAPSHOT__
|
||||
%global git_sha __COMMIT__
|
||||
|
|
|
|||
|
|
@ -548,9 +548,13 @@ done
|
|||
|
||||
do_command git push "$ORIGIN" "${BRANCHES[@]}" || die "failed to to push branches ${BRANCHES[@]} to $ORIGIN"
|
||||
|
||||
FAIL=0
|
||||
for r in "${RELEASE_FILES[@]}"; do
|
||||
do_command ssh master.gnome.org ftpadmin install --unattended "$r" || die "ftpadmin install failed"
|
||||
do_command ssh master.gnome.org ftpadmin install --unattended "$r" || FAIL=1
|
||||
done
|
||||
if [ "$FAIL" = 1 ]; then
|
||||
die "ftpadmin install failed. This was the last step. Invoke the command manually"
|
||||
fi
|
||||
|
||||
CLEANUP_CHECKOUT_BRANCH=
|
||||
if [ "$DRY_RUN" = 0 ]; then
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ git_remote_add_gnome() {
|
|||
}
|
||||
|
||||
git_remote_add_github() {
|
||||
git remote add "${2-origin}" "git://github.com/$1.git"
|
||||
git remote add "${2-origin}" "https://github.com/$1.git"
|
||||
git remote 'set-url' --push "${2-origin}" "git@github.com:$1.git"
|
||||
}
|
||||
|
||||
|
|
@ -319,16 +319,25 @@ MAKEREPO_GIT_IGNORE_LAST="makerepo.gitignore.last-$CURRENT_BRANCH"
|
|||
|
||||
get_local_mirror() {
|
||||
local URL="$1"
|
||||
local DIRNAME
|
||||
local FULLNAME
|
||||
|
||||
if [[ -z "$URL" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local DIRNAME="$(echo $URL.git | sed -e 's#^.*/\([^/]\+\)$#\1#' -e 's/\(.*\)\.git$/\1/')"
|
||||
local FULLNAME="$srcdir/.git/.makerepo-${DIRNAME}.git"
|
||||
|
||||
[[ -n "$NO_REMOTE" ]] && return
|
||||
|
||||
DIRNAME="${URL##*/}"
|
||||
DIRNAME="${DIRNAME%.git}"
|
||||
FULLNAME="$srcdir/.git/.makerepo-${DIRNAME}.git"
|
||||
|
||||
if [ ! -d "$FULLNAME" ] && [ -d "$FULLNAME.git" ]; then
|
||||
# due to a bug, old versions of the script might have created "*.git.git/" directories.
|
||||
# rename.
|
||||
mv "$FULLNAME.git" "$FULLNAME"
|
||||
fi
|
||||
|
||||
if [[ ! -d "$FULLNAME" ]]; then
|
||||
if [[ -f "$FULLNAME" ]]; then
|
||||
# create a file with name $FULLNAME, to suppress local mirroring
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ do_cleanup() {
|
|||
local IDX="$1"
|
||||
local NAME_PREFIX="${2:-net}"
|
||||
local PEER_PREFIX="${3:-d_}"
|
||||
local NETNS_PREFIX="${4:-tt}"
|
||||
|
||||
logger --id "nm-env-prepare-$IDX" "cleanup start # $@"
|
||||
|
||||
pkill -F "/tmp/nm-dnsmasq-$PEER_PREFIX$IDX.pid" dnsmasq &>/dev/null || :
|
||||
rm -rf "/tmp/nm-dnsmasq-$PEER_PREFIX$IDX.pid"
|
||||
|
|
@ -24,40 +27,60 @@ do_cleanup() {
|
|||
|
||||
rm -rf "/tmp/nm-radvd-$PEER_PREFIX$IDX.conf"
|
||||
|
||||
ip link del "$PEER_PREFIX$IDX" &>/dev/null || :
|
||||
ip -netns "$NETNS_PREFIX$IDX" link del "$PEER_PREFIX$IDX" &>/dev/null || :
|
||||
|
||||
ip netns del "$NETNS_PREFIX$IDX" &>/dev/null || :
|
||||
|
||||
logger --id "nm-env-prepare-$IDX" "cleanup complete # $@"
|
||||
}
|
||||
|
||||
do_setup() {
|
||||
local IDX="$1"
|
||||
local NAME_PREFIX="${2:-net}"
|
||||
local PEER_PREFIX="${3:-d_}"
|
||||
local NETNS_PREFIX="${4:-tt}"
|
||||
|
||||
do_cleanup "$IDX"
|
||||
logger --id "nm-env-prepare-$IDX" "setup start # $@"
|
||||
|
||||
ip link add "$NAME_PREFIX$IDX" type veth peer "$PEER_PREFIX$IDX"
|
||||
ip link set "$PEER_PREFIX$IDX" up
|
||||
ip netns add "$NETNS_PREFIX$IDX"
|
||||
ip -netns "$NETNS_PREFIX$IDX" link set lo up
|
||||
|
||||
ip addr add "192.168.$((120 + IDX)).1/23" dev "$PEER_PREFIX$IDX"
|
||||
ip addr add "192:168:$((120 + IDX))::1/64" dev "$PEER_PREFIX$IDX"
|
||||
ip -netns "$NETNS_PREFIX$IDX" link add "$NAME_PREFIX$IDX" type veth peer "$PEER_PREFIX$IDX"
|
||||
ip -netns "$NETNS_PREFIX$IDX" link set "$PEER_PREFIX$IDX" up
|
||||
|
||||
ip -netns "$NETNS_PREFIX$IDX" addr add "192.168.$((120 + IDX)).1/23" dev "$PEER_PREFIX$IDX"
|
||||
ip -netns "$NETNS_PREFIX$IDX" addr add "192:168:$((120 + IDX))::1/64" dev "$PEER_PREFIX$IDX"
|
||||
|
||||
# PPPoE inside the rootless container is not actually working, because
|
||||
# /dev/ppp is not accessible. Still start it, so that we at least can
|
||||
# test how far it goes...
|
||||
echo "192.168.$((120 + $IDX)).180-200" > "/tmp/nm-pppoe-allip-$PEER_PREFIX$IDX"
|
||||
pppoe-server -X "/tmp/nm-pppoe-$PEER_PREFIX$IDX.pid" -S isp -C isp -L "192.168.$((120 + IDX)).1" -p "/tmp/nm-pppoe-allip-$PEER_PREFIX$IDX" -I "$PEER_PREFIX$IDX" &
|
||||
ip netns exec "$NETNS_PREFIX$IDX" \
|
||||
pppoe-server \
|
||||
-X "/tmp/nm-pppoe-$PEER_PREFIX$IDX.pid" \
|
||||
-S isp \
|
||||
-C isp \
|
||||
-L "192.168.$((120 + IDX)).1" \
|
||||
-p "/tmp/nm-pppoe-allip-$PEER_PREFIX$IDX" \
|
||||
-I "$PEER_PREFIX$IDX" \
|
||||
&
|
||||
|
||||
dnsmasq \
|
||||
--conf-file=/dev/null \
|
||||
--pid-file="/tmp/nm-dnsmasq-$PEER_PREFIX$IDX.pid" \
|
||||
--no-hosts \
|
||||
--keep-in-foreground \
|
||||
--bind-interfaces \
|
||||
--except-interface=lo \
|
||||
--clear-on-reload \
|
||||
--listen-address="192.168.$((120 + $IDX)).1" \
|
||||
--dhcp-range="192.168.$((120 + $IDX)).100,192.168.$((120 + $IDX)).150" \
|
||||
--no-ping \
|
||||
&
|
||||
ip netns exec "$NETNS_PREFIX$IDX" \
|
||||
dnsmasq \
|
||||
--conf-file=/dev/null \
|
||||
--pid-file="/tmp/nm-dnsmasq-$PEER_PREFIX$IDX.pid" \
|
||||
--no-hosts \
|
||||
--keep-in-foreground \
|
||||
--bind-interfaces \
|
||||
--log-debug \
|
||||
--log-queries \
|
||||
--log-dhcp \
|
||||
--except-interface=lo \
|
||||
--clear-on-reload \
|
||||
--listen-address="192.168.$((120 + $IDX)).1" \
|
||||
--dhcp-range="192.168.$((120 + $IDX)).100,192.168.$((120 + $IDX)).150" \
|
||||
--no-ping \
|
||||
&
|
||||
|
||||
cat <<EOF > "/tmp/nm-radvd-$PEER_PREFIX$IDX.conf"
|
||||
interface $PEER_PREFIX$IDX
|
||||
|
|
@ -70,10 +93,17 @@ interface $PEER_PREFIX$IDX
|
|||
|
||||
};
|
||||
EOF
|
||||
radvd \
|
||||
--config "/tmp/nm-radvd-$PEER_PREFIX$IDX.conf" \
|
||||
--pidfile "/tmp/nm-radvd-$PEER_PREFIX$IDX.pid" \
|
||||
&
|
||||
ip netns exec "$NETNS_PREFIX$IDX" \
|
||||
radvd \
|
||||
--config "/tmp/nm-radvd-$PEER_PREFIX$IDX.conf" \
|
||||
--pidfile "/tmp/nm-radvd-$PEER_PREFIX$IDX.pid" \
|
||||
--logmethod syslog \
|
||||
-d 5 \
|
||||
&
|
||||
|
||||
ip -netns ""$NETNS_PREFIX$IDX"" link set "$NAME_PREFIX$IDX" netns $$
|
||||
|
||||
logger --id "nm-env-prepare-$IDX" "setup complete: netns=$NETNS_PREFIX$IDX, iface=$NAME_PREFIX$IDX, peer=$PEER_PREFIX$IDX # $@"
|
||||
}
|
||||
|
||||
do_redo() {
|
||||
|
|
@ -81,8 +111,27 @@ do_redo() {
|
|||
do_setup "$@"
|
||||
}
|
||||
|
||||
do_one_time_setup() {
|
||||
if [ ! -d /tmp/sys2 ]; then
|
||||
# `ip -netns t exec ...` will try to mount sysfs. But kernel rejects that in
|
||||
# the container, unless a writable sysfs is already mounted. Due to --priviledged,
|
||||
# we have /sys mounted rw, however, ip will first unmount /sys before trying to
|
||||
# remount it. We thus need it mounted as rw one additional time.
|
||||
#
|
||||
# Let's do this setup step once, and never clean it up.
|
||||
# https://github.com/containers/podman/issues/11887#issuecomment-938706628
|
||||
mkdir /tmp/sys2
|
||||
mount -t sysfs --make-private /tmp/sys2
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
# We do this one-time-setup always when the script runs, and never clean it
|
||||
# up.
|
||||
do_one_time_setup
|
||||
|
||||
|
||||
IDX=1
|
||||
NAME_PREFIX=net
|
||||
PEER_PREFIX=
|
||||
|
|
|
|||
|
|
@ -109,7 +109,54 @@ find NetworkManager bind mounted at $BASEDIR_NM
|
|||
run \`nm-env-prepare.sh setup --idx 1\` to setup test interfaces
|
||||
|
||||
Configure NetworkManager with
|
||||
\$ ./configure --enable-maintainer-mode --enable-more-warnings=error --with-more-asserts="\${NM_BUILD_MORE_ASSERTS:-1000}" --with-nm-cloud-setup=yes --prefix=/opt/test --localstatedir=/var --sysconfdir=/etc --enable-gtk-doc --enable-introspection --with-ofono=yes --with-dhclient=yes --with-dhcpcanon=yes --with-dhcpcd=yes --enable-more-logging --enable-compile-warnings=yes --enable-address-sanitizer=no --enable-undefined-sanitizer=no --with-valgrind=yes --enable-concheck --enable-wimax --enable-ifcfg-rh=yes --enable-config-plugin-ibft=yes --enable-ifcfg-suse --enable-ifupdown=yes --enable-ifnet --enable-vala=yes --enable-polkit=yes --with-libnm-glib=yes --with-nmcli=yes --with-nmtui=yes --with-modem-manager-1 --with-suspend-resume=systemd --enable-teamdctl=yes --enable-ovs=yes --enable-tests="\${NM_BUILD_TESTS:-yes}" --with-netconfig=/bin/nowhere/netconfig --with-resolvconf=/bin/nowhere/resolvconf --with-crypto=nss --with-session-tracking=systemd --with-consolekit=yes --with-systemd-logind=yes --with-iwd=yes --enable-json-validation=yes --with-consolekit=yes --with-config-dns-rc-manager-default=auto --with-config-dhcp-default=internal "\${NM_CONFIGURE_OTPS[@]}"
|
||||
\$ ./configure \
|
||||
--enable-address-sanitizer=no \
|
||||
--enable-compile-warnings=yes \
|
||||
--enable-concheck \
|
||||
--enable-config-plugin-ibft=yes \
|
||||
--enable-gtk-doc \
|
||||
--enable-ifcfg-rh=yes \
|
||||
--enable-ifcfg-suse \
|
||||
--enable-ifnet \
|
||||
--enable-ifupdown=yes \
|
||||
--enable-introspection \
|
||||
--enable-json-validation=yes \
|
||||
--enable-maintainer-mode \
|
||||
--enable-more-logging \
|
||||
--enable-more-warnings=error \
|
||||
--enable-ovs=yes \
|
||||
--enable-polkit=yes \
|
||||
--enable-teamdctl=yes \
|
||||
--enable-undefined-sanitizer=no \
|
||||
--enable-vala=yes \
|
||||
--enable-wimax \
|
||||
--localstatedir=/var \
|
||||
--prefix=/opt/test \
|
||||
--sysconfdir=/etc \
|
||||
--with-config-dhcp-default=internal \
|
||||
--with-config-dns-rc-manager-default=auto \
|
||||
--with-consolekit=yes \
|
||||
--with-consolekit=yes \
|
||||
--with-crypto=nss \
|
||||
--with-dhclient=yes \
|
||||
--with-dhcpcanon=yes \
|
||||
--with-dhcpcd=yes \
|
||||
--with-iwd=yes \
|
||||
--with-libnm-glib=yes \
|
||||
--with-modem-manager-1 \
|
||||
--with-netconfig=/bin/nowhere/netconfig \
|
||||
--with-nm-cloud-setup=yes \
|
||||
--with-nmcli=yes \
|
||||
--with-nmtui=yes \
|
||||
--with-ofono=yes \
|
||||
--with-resolvconf=/bin/nowhere/resolvconf \
|
||||
--with-session-tracking=systemd \
|
||||
--with-suspend-resume=systemd \
|
||||
--with-systemd-logind=yes \
|
||||
--with-valgrind=yes \
|
||||
--enable-tests="\${NM_BUILD_TESTS:-yes}" \
|
||||
--with-more-asserts="\${NM_BUILD_MORE_ASSERTS:-1000}" \
|
||||
"\${NM_CONFIGURE_OTPS[@]}"
|
||||
Test with:
|
||||
\$ systemctl stop NetworkManager; /opt/test/sbin/NetworkManager --debug 2>&1 | tee -a /tmp/nm-log.txt
|
||||
EOF
|
||||
|
|
@ -249,6 +296,8 @@ RUN dnf install -y \\
|
|||
mlocate \\
|
||||
mobile-broadband-provider-info-devel \\
|
||||
newt-devel \\
|
||||
nispor \\
|
||||
nmstate \\
|
||||
nss-devel \\
|
||||
polkit-devel \\
|
||||
ppp \\
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ def find_checkpoint(nmc, path):
|
|||
|
||||
|
||||
def find_checkpoint_last(nmc):
|
||||
l = [c.get_path() for c in nmc.get_checkpoints()]
|
||||
if not l:
|
||||
return None
|
||||
l.sort(key=checkpoint_path_to_num)
|
||||
return l[-1]
|
||||
return max(
|
||||
nmc.get_checkpoints(),
|
||||
key=lambda c: checkpoint_path_to_num(c.get_path()),
|
||||
default=None,
|
||||
)
|
||||
|
||||
|
||||
def validate_path(path, nmc):
|
||||
|
|
|
|||
|
|
@ -345,19 +345,12 @@ no-auto-default=*
|
|||
<para><literal>systemd-resolved</literal>: NetworkManager will
|
||||
push the DNS configuration to systemd-resolved</para>
|
||||
|
||||
<para><literal>unbound</literal>: NetworkManager will talk
|
||||
to unbound and dnssec-triggerd, using "Conditional Forwarding"
|
||||
with DNSSEC support. <filename>/etc/resolv.conf</filename>
|
||||
will be managed by dnssec-trigger daemon. This option is
|
||||
deprecated. Note that dnssec-trigger ships a NetworkManager dispatcher
|
||||
script so this DNS plugin is not necessary.</para>
|
||||
|
||||
<para><literal>none</literal>: NetworkManager will not
|
||||
modify resolv.conf. This implies
|
||||
<literal>rc-manager</literal> <literal>unmanaged</literal></para>
|
||||
|
||||
<para>Note that the plugins <literal>dnsmasq</literal>, <literal>systemd-resolved</literal>
|
||||
and <literal>unbound</literal> are caching local nameservers.
|
||||
<para>Note that the plugins <literal>dnsmasq</literal> and <literal>systemd-resolved</literal>
|
||||
are caching local nameservers.
|
||||
Hence, when NetworkManager writes <filename>&nmrundir;/resolv.conf</filename>
|
||||
and <filename>/etc/resolv.conf</filename> (according to <literal>rc-manager</literal>
|
||||
setting below), the name server there will be localhost only.
|
||||
|
|
|
|||
|
|
@ -614,6 +614,32 @@ Connection 'ethernet-4' (de89cdeb-a3e1-4d53-8fa0-c22546c775f4) successfully
|
|||
<screen><prompt>$ </prompt><userinput>nmcli connection add type bluetooth con-name "My Bluetooth Hotspot" autoconnect no ifname btnap0 bluetooth.type nap ipv4.method shared ipv6.method shared</userinput></screen>
|
||||
</example>
|
||||
|
||||
<example><title>Offline use</title>
|
||||
<screen><prompt>$ </prompt><userinput>nmcli --offline con add type ethernet '
|
||||
conn.id eth0 \
|
||||
conn.interface-name eth0 \
|
||||
>/sysroot/etc/NetworkManager/system-connections/eth0.nmconnection</userinput></screen>
|
||||
<para>
|
||||
Creates a connection file in keyfile format without using the NetworkManager service.
|
||||
This allows for use of familiar <command>nmcli</command> syntax in situations
|
||||
where the service is not running, such as during system installation of image
|
||||
provisioning and ensures the resulting file is correctly formatted.
|
||||
</para>
|
||||
<screen><prompt>$ </prompt><userinput>nmcli --offline con modify type ethernet '
|
||||
conn.id eth0-ipv6 \
|
||||
ipv4.method disabled \
|
||||
</sysroot/etc/NetworkManager/system-connections/eth0.nmconnection \
|
||||
>/sysroot/etc/NetworkManager/system-connections/eth0-ipv6.nmconnection</userinput></screen>
|
||||
<para>
|
||||
Read and write a connection file without using the NetworkManager service, modifying
|
||||
some properties along the way.
|
||||
</para>
|
||||
<para>
|
||||
This allows templating of the connection profiles using familiar
|
||||
<command>nmcli</command> syntax in situations where the service is not running.
|
||||
</para>
|
||||
</example>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
|
|
|||
|
|
@ -314,6 +314,23 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><group choice='plain'>
|
||||
<arg choice='plain'><option>--offline</option></arg>
|
||||
</group></term>
|
||||
|
||||
<listitem>
|
||||
<para>Work without a daemon. Makes <command>connection add</command> and
|
||||
<command>connection modify</command> commands accept and produce connection
|
||||
data via standard input/output. Ordinarily, nmcli would communicate with
|
||||
the NetworkManager service.</para>
|
||||
|
||||
<para>The connection data format (keyfile) is described in
|
||||
<citerefentry><refentrytitle>nm-settings-keyfile</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
manual.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><group choice='plain'>
|
||||
<arg choice='plain'><option>-v</option></arg>
|
||||
|
|
@ -928,7 +945,7 @@
|
|||
<arg choice='plain'><option>uuid</option></arg>
|
||||
<arg choice='plain'><option>path</option></arg>
|
||||
</group>
|
||||
<arg choice='plain'><replaceable>ID</replaceable></arg>
|
||||
<arg><replaceable>ID</replaceable></arg>
|
||||
<arg rep='repeat' choice='plain'>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><replaceable>option</replaceable> <replaceable>value</replaceable></arg>
|
||||
|
|
@ -962,7 +979,14 @@
|
|||
|
||||
<para>The connection is identified by its name, UUID or D-Bus path. If
|
||||
<replaceable>ID</replaceable> is ambiguous, a keyword <option>id</option>,
|
||||
<option>uuid</option> or <option>path</option> can be used.</para>
|
||||
<option>uuid</option> or <option>path</option> can be used.
|
||||
The <replaceable>ID</replaceable> is not used with the global
|
||||
<option>--offline</option> option.</para>
|
||||
|
||||
<para>When the global <option>--offline</option> is used, the
|
||||
command reads the connection from the standard input and prints the
|
||||
modified connection to standard output instead of making the
|
||||
the NetworkManager daemon act upon specified connection.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
@ -1096,6 +1120,10 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>When the global <option>--offline</option> is used, the
|
||||
command prints the resulting connection to standard output instead of
|
||||
actually adding the connection via the NetworkManager daemon.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
|
|||
35
meson.build
35
meson.build
|
|
@ -6,7 +6,7 @@ project(
|
|||
# - add corresponding NM_VERSION_x_y_z macros in
|
||||
# "src/libnm-core-public/nm-version-macros.h.in"
|
||||
# - update number in configure.ac
|
||||
version: '1.38.0',
|
||||
version: '1.39.4',
|
||||
license: 'GPL2+',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
|
|
@ -353,10 +353,14 @@ if enable_introspection
|
|||
endif
|
||||
|
||||
udev_udevdir = get_option('udev_dir')
|
||||
install_udevdir = (udev_udevdir != 'no')
|
||||
|
||||
if install_udevdir and udev_udevdir == ''
|
||||
udev_udevdir = dependency('udev').get_pkgconfig_variable('udevdir')
|
||||
if udev_udevdir == 'no'
|
||||
install_udevdir = false
|
||||
else
|
||||
install_udevdir = true
|
||||
if (udev_udevdir == '' or udev_udevdir == 'yes')
|
||||
udev_udevdir = join_paths(nm_prefix, 'lib/udev')
|
||||
endif
|
||||
assert(udev_udevdir.startswith('/'), 'udev_dir must be an absolute path, but is ' + udev_udevdir)
|
||||
endif
|
||||
|
||||
systemd_systemdsystemunitdir = get_option('systemdsystemunitdir')
|
||||
|
|
@ -364,7 +368,7 @@ install_systemdunitdir = (systemd_systemdsystemunitdir != 'no')
|
|||
|
||||
if install_systemdunitdir and systemd_systemdsystemunitdir == ''
|
||||
assert(systemd_dep.found(), 'systemd required but not found, please provide a valid systemd user unit dir or disable it')
|
||||
systemd_systemdsystemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir')
|
||||
systemd_systemdsystemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir', define_variable: ['rootprefix', nm_prefix])
|
||||
endif
|
||||
|
||||
enable_systemd_journal = get_option('systemd_journal')
|
||||
|
|
@ -551,7 +555,7 @@ endif
|
|||
dbus_conf_dir = get_option('dbus_conf_dir')
|
||||
if dbus_conf_dir == ''
|
||||
assert(dbus_dep.found(), 'D-Bus required but not found, please provide a valid system bus config dir')
|
||||
dbus_conf_dir = join_paths(dbus_dep.get_pkgconfig_variable('datadir'), 'dbus-1', 'system.d')
|
||||
dbus_conf_dir = join_paths(dbus_dep.get_pkgconfig_variable('datarootdir', define_variable: ['prefix', nm_prefix]), 'dbus-1', 'system.d')
|
||||
endif
|
||||
|
||||
dbus_interfaces_dir = dbus_dep.get_pkgconfig_variable('interfaces_dir', define_variable: ['datadir', nm_datadir])
|
||||
|
|
@ -683,18 +687,11 @@ endforeach
|
|||
|
||||
# external misc tools paths
|
||||
default_paths = ['/sbin', '/usr/sbin']
|
||||
dnssec_ts_paths = ['/usr/local/libexec',
|
||||
'/usr/local/lib',
|
||||
'/usr/local/lib/dnssec-trigger',
|
||||
'/usr/libexec',
|
||||
'/usr/lib',
|
||||
'/usr/lib/dnssec-trigger']
|
||||
|
||||
# 0: cmdline option, 1: paths, 2: fallback
|
||||
progs = [['iptables', default_paths, '/usr/sbin/iptables'],
|
||||
['nft', default_paths, '/usr/sbin/nft'],
|
||||
['dnsmasq', default_paths, ''],
|
||||
['dnssec_trigger', dnssec_ts_paths, join_paths(nm_libexecdir, 'dnssec-trigger-script') ],
|
||||
progs = [['iptables', default_paths, '/usr/sbin/iptables'],
|
||||
['nft', default_paths, '/usr/sbin/nft'],
|
||||
['dnsmasq', default_paths, ''],
|
||||
]
|
||||
|
||||
foreach prog : progs
|
||||
|
|
@ -1020,6 +1017,7 @@ output = '\nSystem paths:\n'
|
|||
output += ' prefix: ' + nm_prefix + '\n'
|
||||
output += ' exec_prefix: ' + nm_prefix + '\n'
|
||||
output += ' systemdunitdir: ' + systemd_systemdsystemunitdir + '\n'
|
||||
output += ' udev_dir: ' + udev_udevdir + '\n'
|
||||
output += ' nmbinary: ' + nm_pkgsbindir + '\n'
|
||||
output += ' nmconfdir: ' + nm_pkgconfdir + '\n'
|
||||
output += ' nmlibdir: ' + nm_pkglibdir + '\n'
|
||||
|
|
@ -1028,7 +1026,8 @@ output += ' nmstatedir: ' + nm_pkgstatedir + '\n'
|
|||
output += ' nmrundir: ' + nm_pkgrundir + '\n'
|
||||
output += ' nmvpndir: ' + nm_vpndir + '\n'
|
||||
output += ' nmplugindir: ' + nm_plugindir + '\n'
|
||||
output += ' system-ca-path: ' + system_ca_path + '\n'
|
||||
output += ' system_ca_path: ' + system_ca_path + '\n'
|
||||
output += ' dbus_conf_dir: ' + dbus_conf_dir + '\n'
|
||||
output += '\nPlatform:\n'
|
||||
output += ' session tracking: ' + ','.join(session_trackers) + '\n'
|
||||
output += ' suspend/resume: ' + suspend_resume + '\n'
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ option('kernel_firmware_dir', type: 'string', value: '/lib/firmware', descriptio
|
|||
option('iptables', type: 'string', value: '', description: 'path to iptables')
|
||||
option('nft', type: 'string', value: '', description: 'path to nft')
|
||||
option('dnsmasq', type: 'string', value: '', description: 'path to dnsmasq')
|
||||
option('dnssec_trigger', type: 'string', value: '', description: 'path to unbound dnssec-trigger-script')
|
||||
|
||||
# platform
|
||||
option('dist_version', type: 'string', value: '', description: 'Define the NM\'s distribution version string')
|
||||
|
|
|
|||
18
src/c-list/.github/workflows/ci.yml
vendored
18
src/c-list/.github/workflows/ci.yml
vendored
|
|
@ -9,23 +9,19 @@ on:
|
|||
jobs:
|
||||
ci:
|
||||
name: CI with Default Configuration
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Run through C-Util CI
|
||||
uses: c-util/automation/src/ci-c-util@v1
|
||||
with:
|
||||
m32: 1
|
||||
valgrind: 1
|
||||
uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1
|
||||
with:
|
||||
cabuild_ref: "v1"
|
||||
m32: true
|
||||
matrixmode: true
|
||||
valgrind: true
|
||||
|
||||
ci-msvc:
|
||||
name: CI with MSVC
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-2016, windows-latest]
|
||||
os: [windows-2019, windows-latest]
|
||||
|
||||
steps:
|
||||
- name: Fetch Sources
|
||||
|
|
|
|||
|
|
@ -30,11 +30,12 @@ AUTHORS-LGPL:
|
|||
along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
COPYRIGHT: (ordered alphabetically)
|
||||
Copyright (C) 2015-2019 Red Hat, Inc.
|
||||
Copyright (C) 2015-2022 Red Hat, Inc.
|
||||
|
||||
AUTHORS: (ordered alphabetically)
|
||||
Danilo Horta <danilo.horta@pm.me>
|
||||
David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
Lucas De Marchi <lucas.de.marchi@gmail.com>
|
||||
Michele Dionisio
|
||||
Thomas Haller <thaller@redhat.com>
|
||||
Tom Gundersen <teg@jklm.no>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
# c-list - Circular Intrusive Double Linked List Collection
|
||||
|
||||
## CHANGES WITH 4:
|
||||
|
||||
* The minimum required meson version is now 0.60.0.
|
||||
|
||||
* New function c_list_split() is added. It reverses c_list_splice()
|
||||
and thus allows to split a list in half.
|
||||
|
||||
* TBD
|
||||
|
||||
Contributions from: David Rheinsberg
|
||||
|
||||
- TBD, YYYY-MM-DD
|
||||
|
||||
## CHANGES WITH 3:
|
||||
|
||||
* API break: The c_list_loop_*() symbols were removed, since we saw
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ The requirements for this project are:
|
|||
|
||||
At build-time, the following software is required:
|
||||
|
||||
* `meson >= 0.41`
|
||||
* `meson >= 0.60`
|
||||
* `pkg-config >= 0.29`
|
||||
|
||||
### Build
|
||||
|
|
|
|||
|
|
@ -1,15 +1,46 @@
|
|||
project(
|
||||
'c-list',
|
||||
'c',
|
||||
version: '3',
|
||||
license: 'Apache',
|
||||
default_options: [
|
||||
'c_std=c99',
|
||||
],
|
||||
license: 'Apache',
|
||||
meson_version: '>=0.60.0',
|
||||
version: '3.0.0',
|
||||
)
|
||||
major = meson.project_version().split('.')[0]
|
||||
project_description = 'Circular Intrusive Double Linked List Collection'
|
||||
|
||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
||||
mod_pkgconfig = import('pkgconfig')
|
||||
|
||||
# See c-stdaux for details on these. We do not have c-stdaux as dependency, so
|
||||
# we keep a duplicated set here, reduced to the minimum.
|
||||
cflags = meson.get_compiler('c').get_supported_arguments(
|
||||
'-D_GNU_SOURCE',
|
||||
|
||||
'-Wno-gnu-alignof-expression',
|
||||
'-Wno-maybe-uninitialized',
|
||||
'-Wno-unknown-warning-option',
|
||||
'-Wno-unused-parameter',
|
||||
|
||||
'-Wno-error=type-limits',
|
||||
'-Wno-error=missing-field-initializers',
|
||||
|
||||
'-Wdate-time',
|
||||
'-Wdeclaration-after-statement',
|
||||
'-Wlogical-op',
|
||||
'-Wmissing-include-dirs',
|
||||
'-Wmissing-noreturn',
|
||||
'-Wnested-externs',
|
||||
'-Wredundant-decls',
|
||||
'-Wshadow',
|
||||
'-Wstrict-aliasing=3',
|
||||
'-Wsuggest-attribute=noreturn',
|
||||
'-Wundef',
|
||||
'-Wwrite-strings',
|
||||
)
|
||||
add_project_arguments(cflags, language: 'c')
|
||||
|
||||
subdir('src')
|
||||
|
||||
meson.override_dependency('libclist-'+major, libclist_dep, static: true)
|
||||
|
|
|
|||
|
|
@ -259,6 +259,31 @@ static inline void c_list_splice(CList *target, CList *source) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* c_list_split() - split one list in two
|
||||
* @source: the list to split
|
||||
* @where: new starting element of newlist
|
||||
* @target: new list
|
||||
*
|
||||
* This splits @source in two. All elements following @where (including @where)
|
||||
* are moved to @target, replacing any old list. If @where points to @source
|
||||
* (i.e., the end of the list), @target will be empty.
|
||||
*/
|
||||
static inline void c_list_split(CList *source, CList *where, CList *target) {
|
||||
if (where == source) {
|
||||
*target = (CList)C_LIST_INIT(*target);
|
||||
} else {
|
||||
target->next = where;
|
||||
target->prev = source->prev;
|
||||
|
||||
where->prev->next = source;
|
||||
source->prev = where->prev;
|
||||
|
||||
where->prev = target;
|
||||
target->prev->next = target;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* c_list_first() - return pointer to first element, or NULL if empty
|
||||
* @list: list to operate on, or NULL
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ if not meson.is_subproject()
|
|||
install_headers('c-list.h')
|
||||
|
||||
mod_pkgconfig.generate(
|
||||
version: meson.project_version(),
|
||||
name: 'libclist',
|
||||
filebase: 'libclist',
|
||||
description: project_description,
|
||||
filebase: 'libclist-'+major,
|
||||
name: 'libclist',
|
||||
version: meson.project_version(),
|
||||
)
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ typedef struct {
|
|||
} Node;
|
||||
|
||||
static void test_api(void) {
|
||||
CList *list_iter, *list_safe, list = C_LIST_INIT(list);
|
||||
CList *list_iter, *list_safe;
|
||||
CList list = C_LIST_INIT(list), list2 = C_LIST_INIT(list2);
|
||||
Node node = { .id = 0, .link = C_LIST_INIT(node.link) };
|
||||
|
||||
assert(c_list_init(&list) == &list);
|
||||
|
|
@ -68,7 +69,7 @@ static void test_api(void) {
|
|||
c_list_unlink(&node.link);
|
||||
assert(!c_list_is_linked(&node.link));
|
||||
|
||||
/* swap / splice list operators */
|
||||
/* swap / splice / split list operators */
|
||||
|
||||
c_list_swap(&list, &list);
|
||||
assert(c_list_is_empty(&list));
|
||||
|
|
@ -76,6 +77,10 @@ static void test_api(void) {
|
|||
c_list_splice(&list, &list);
|
||||
assert(c_list_is_empty(&list));
|
||||
|
||||
c_list_split(&list, &list, &list2);
|
||||
assert(c_list_is_empty(&list));
|
||||
assert(c_list_is_empty(&list2));
|
||||
|
||||
/* direct/raw iterators */
|
||||
|
||||
c_list_for_each(list_iter, &list)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,18 @@
|
|||
#include <string.h>
|
||||
#include "c-list.h"
|
||||
|
||||
static void assert_list_integrity(CList *list) {
|
||||
CList *iter;
|
||||
|
||||
iter = list;
|
||||
do {
|
||||
assert(iter->next->prev == iter);
|
||||
assert(iter->prev->next == iter);
|
||||
|
||||
iter = iter->next;
|
||||
} while (iter != list);
|
||||
}
|
||||
|
||||
static void test_iterators(void) {
|
||||
CList *iter, *safe, a, b, list = C_LIST_INIT(list);
|
||||
unsigned int i;
|
||||
|
|
@ -158,6 +170,85 @@ static void test_splice(void) {
|
|||
assert(c_list_last(&target) == &e2);
|
||||
}
|
||||
|
||||
static void test_split(void) {
|
||||
CList e1, e2;
|
||||
|
||||
/* split empty list */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_split(&source, &source, &target);
|
||||
assert(c_list_is_empty(&source));
|
||||
assert(c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 1-element list excluding the element */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_split(&source, &source, &target);
|
||||
assert(!c_list_is_empty(&source));
|
||||
assert(c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 1-element list including the element */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_split(&source, &e1, &target);
|
||||
assert(c_list_is_empty(&source));
|
||||
assert(!c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 2-element list excluding the elements */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_link_tail(&source, &e2);
|
||||
c_list_split(&source, &source, &target);
|
||||
assert(!c_list_is_empty(&source));
|
||||
assert(c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 2-element list including one element */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_link_tail(&source, &e2);
|
||||
c_list_split(&source, &e2, &target);
|
||||
assert(!c_list_is_empty(&source));
|
||||
assert(!c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
|
||||
/* split 2-element list including both elements */
|
||||
{
|
||||
CList source = C_LIST_INIT(source), target;
|
||||
|
||||
c_list_link_tail(&source, &e1);
|
||||
c_list_link_tail(&source, &e2);
|
||||
c_list_split(&source, &e1, &target);
|
||||
assert(c_list_is_empty(&source));
|
||||
assert(!c_list_is_empty(&target));
|
||||
assert_list_integrity(&source);
|
||||
assert_list_integrity(&target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void test_flush(void) {
|
||||
CList e1 = C_LIST_INIT(e1), e2 = C_LIST_INIT(e2);
|
||||
CList list1 = C_LIST_INIT(list1), list2 = C_LIST_INIT(list2);
|
||||
|
|
@ -220,6 +311,7 @@ int main(void) {
|
|||
test_iterators();
|
||||
test_swap();
|
||||
test_splice();
|
||||
test_split();
|
||||
test_flush();
|
||||
test_macros();
|
||||
test_gnu();
|
||||
|
|
|
|||
30
src/c-rbtree/.github/workflows/ci.yml
vendored
30
src/c-rbtree/.github/workflows/ci.yml
vendored
|
|
@ -9,25 +9,15 @@ on:
|
|||
jobs:
|
||||
ci:
|
||||
name: CI with Default Configuration
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Run through C-Util CI
|
||||
uses: c-util/automation/src/ci-c-util@v1
|
||||
with:
|
||||
m32: 1
|
||||
valgrind: 1
|
||||
|
||||
uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1
|
||||
with:
|
||||
cabuild_ref: "v1"
|
||||
m32: true
|
||||
matrixmode: true
|
||||
valgrind: true
|
||||
ci-ptrace:
|
||||
name: Reduced CI with PTrace
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CRBTREE_TEST_PTRACE: '1'
|
||||
|
||||
steps:
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Run through C-Util CI
|
||||
uses: c-util/automation/src/ci-c-util@v1
|
||||
uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1
|
||||
with:
|
||||
cabuild_ref: "v1"
|
||||
mesonargs: '-Dptrace=true'
|
||||
|
|
|
|||
3
src/c-rbtree/.gitmodules
vendored
3
src/c-rbtree/.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "subprojects/c-stdaux"]
|
||||
path = subprojects/c-stdaux
|
||||
url = https://github.com/c-util/c-stdaux.git
|
||||
|
|
@ -30,7 +30,7 @@ AUTHORS-LGPL:
|
|||
along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
COPYRIGHT: (ordered alphabetically)
|
||||
Copyright (C) 2015-2019 Red Hat, Inc.
|
||||
Copyright (C) 2015-2022 Red Hat, Inc.
|
||||
|
||||
AUTHORS: (ordered alphabetically)
|
||||
David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
# c-rbtree - Intrusive Red-Black Tree Collection
|
||||
|
||||
## CHANGES WITH 4:
|
||||
|
||||
* Add 'ptrace' build option to enable running tests using 'ptrace'
|
||||
to verify extended execution properties. This option should not
|
||||
be used in setups where 'ptrace' cannot be employed (like running
|
||||
under gdb or valgrind). This option only affects the test-suite.
|
||||
|
||||
* meson-0.60.0 is now the minimum required meson version.
|
||||
|
||||
* TBD
|
||||
|
||||
Contributions from: David Rheinsberg
|
||||
|
||||
- TBD, YYYY-MM-DD
|
||||
|
||||
## CHANGES WITH 3:
|
||||
|
||||
* Add more helpers. Add both a collection of iteratiors and helpers
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ The requirements for this project are:
|
|||
|
||||
At build-time, the following software is required:
|
||||
|
||||
* `meson >= 0.41`
|
||||
* `meson >= 0.60`
|
||||
* `pkg-config >= 0.29`
|
||||
|
||||
### Build
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
project(
|
||||
'c-rbtree',
|
||||
'c',
|
||||
version: '3',
|
||||
license: 'Apache',
|
||||
default_options: [
|
||||
'c_std=c11'
|
||||
],
|
||||
license: 'Apache',
|
||||
meson_version: '>=0.60.0',
|
||||
version: '3.0.0',
|
||||
)
|
||||
major = meson.project_version().split('.')[0]
|
||||
project_description = 'Intrusive Red-Black Tree Collection'
|
||||
|
||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
||||
mod_pkgconfig = import('pkgconfig')
|
||||
use_ptrace = get_option('ptrace')
|
||||
|
||||
sub_cstdaux = subproject('c-stdaux')
|
||||
|
||||
dep_cstdaux = sub_cstdaux.get_variable('libcstdaux_dep')
|
||||
dep_cstdaux = dependency('libcstdaux-1')
|
||||
add_project_arguments(dep_cstdaux.get_variable('cflags').split(' '), language: 'c')
|
||||
|
||||
subdir('src')
|
||||
|
||||
meson.override_dependency('libcrbtree-'+major, libcrbtree_dep, static: true)
|
||||
|
|
|
|||
1
src/c-rbtree/meson_options.txt
Normal file
1
src/c-rbtree/meson_options.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
option('ptrace', type: 'boolean', value: false, description: 'Allow ptrace in test suite')
|
||||
|
|
@ -144,6 +144,11 @@ static inline void c_rbnode_init(CRBNode *n) {
|
|||
*
|
||||
* Return: Pointer to parent container, or NULL.
|
||||
*/
|
||||
/*
|
||||
* Note: This was carefully designed to avoid multiple evaluation of `_what`,
|
||||
* but avoid context-expression-extensions. That is why it uses the
|
||||
* possibly odd style of `(x ?: offsetof(...)) - offsetof(...))`.
|
||||
*/
|
||||
#define c_rbnode_entry(_what, _t, _m) \
|
||||
((_t *)(void *)(((unsigned long)(void *)(_what) ?: \
|
||||
offsetof(_t, _m)) - offsetof(_t, _m)))
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ libcrbtree_deps = [
|
|||
dep_cstdaux,
|
||||
]
|
||||
|
||||
libcrbtree_private = static_library(
|
||||
'crbtree-private',
|
||||
libcrbtree_both = both_libraries(
|
||||
'crbtree-'+major,
|
||||
[
|
||||
'c-rbtree.c',
|
||||
],
|
||||
|
|
@ -18,26 +18,19 @@ libcrbtree_private = static_library(
|
|||
'-fno-common',
|
||||
],
|
||||
dependencies: libcrbtree_deps,
|
||||
pic: true,
|
||||
)
|
||||
|
||||
libcrbtree_shared = shared_library(
|
||||
'crbtree',
|
||||
objects: libcrbtree_private.extract_all_objects(),
|
||||
dependencies: libcrbtree_deps,
|
||||
install: not meson.is_subproject(),
|
||||
soversion: 0,
|
||||
link_depends: libcrbtree_symfile,
|
||||
link_args: [
|
||||
'-Wl,--no-undefined',
|
||||
'-Wl,--version-script=@0@'.format(libcrbtree_symfile),
|
||||
],
|
||||
link_depends: libcrbtree_symfile,
|
||||
soversion: 0,
|
||||
)
|
||||
|
||||
libcrbtree_dep = declare_dependency(
|
||||
include_directories: include_directories('.'),
|
||||
link_with: libcrbtree_private,
|
||||
dependencies: libcrbtree_deps,
|
||||
include_directories: include_directories('.'),
|
||||
link_with: libcrbtree_both.get_static_lib(),
|
||||
version: meson.project_version(),
|
||||
)
|
||||
|
||||
|
|
@ -45,11 +38,11 @@ if not meson.is_subproject()
|
|||
install_headers('c-rbtree.h')
|
||||
|
||||
mod_pkgconfig.generate(
|
||||
libraries: libcrbtree_shared,
|
||||
version: meson.project_version(),
|
||||
name: 'libcrbtree',
|
||||
filebase: 'libcrbtree',
|
||||
description: project_description,
|
||||
filebase: 'libcrbtree-'+major,
|
||||
libraries: libcrbtree_both.get_shared_lib(),
|
||||
name: 'libcrbtree',
|
||||
version: meson.project_version(),
|
||||
)
|
||||
endif
|
||||
|
||||
|
|
@ -57,7 +50,7 @@ endif
|
|||
# target: test-*
|
||||
#
|
||||
|
||||
test_api = executable('test-api', ['test-api.c'], link_with: libcrbtree_shared)
|
||||
test_api = executable('test-api', ['test-api.c'], link_with: libcrbtree_both.get_shared_lib())
|
||||
test('API Symbol Visibility', test_api)
|
||||
|
||||
test_basic = executable('test-basic', ['test-basic.c'], dependencies: libcrbtree_dep)
|
||||
|
|
@ -70,7 +63,9 @@ test_misc = executable('test-misc', ['test-misc.c'], dependencies: libcrbtree_de
|
|||
test('Miscellaneous', test_misc)
|
||||
|
||||
test_parallel = executable('test-parallel', ['test-parallel.c'], dependencies: libcrbtree_dep)
|
||||
test('Lockless Parallel Readers', test_parallel)
|
||||
if use_ptrace
|
||||
test('Lockless Parallel Readers', test_parallel)
|
||||
endif
|
||||
|
||||
test_posix = executable('test-posix', ['test-posix.c'], dependencies: libcrbtree_dep)
|
||||
test('Posix tsearch(3p) Comparison', test_posix)
|
||||
|
|
|
|||
|
|
@ -364,9 +364,6 @@ int main(int argc, char **argv) {
|
|||
unsigned int i;
|
||||
int r;
|
||||
|
||||
if (!getenv("CRBTREE_TEST_PTRACE"))
|
||||
return 77;
|
||||
|
||||
/* we want stable tests, so use fixed seed */
|
||||
srand(0xdeadbeef);
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit c5f166d02ff68af5cdcbad1bdcea2cb134e34ce4
|
||||
3
src/c-rbtree/subprojects/libcstdaux-1.wrap
Normal file
3
src/c-rbtree/subprojects/libcstdaux-1.wrap
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/c-util/c-stdaux.git
|
||||
revision = v1
|
||||
16
src/c-siphash/.github/workflows/ci.yml
vendored
16
src/c-siphash/.github/workflows/ci.yml
vendored
|
|
@ -9,13 +9,9 @@ on:
|
|||
jobs:
|
||||
ci:
|
||||
name: CI with Default Configuration
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Run through C-Util CI
|
||||
uses: c-util/automation/src/ci-c-util@v1
|
||||
with:
|
||||
m32: 1
|
||||
valgrind: 1
|
||||
uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1
|
||||
with:
|
||||
cabuild_ref: "v1"
|
||||
m32: true
|
||||
matrixmode: true
|
||||
valgrind: true
|
||||
|
|
|
|||
3
src/c-siphash/.gitmodules
vendored
3
src/c-siphash/.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "subprojects/c-stdaux"]
|
||||
path = subprojects/c-stdaux
|
||||
url = https://github.com/c-util/c-stdaux.git
|
||||
|
|
@ -30,7 +30,7 @@ AUTHORS-LGPL:
|
|||
along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
COPYRIGHT: (ordered alphabetically)
|
||||
Copyright (C) 2015-2019 Red Hat, Inc.
|
||||
Copyright (C) 2015-2022 Red Hat, Inc.
|
||||
|
||||
AUTHORS: (ordered alphabetically)
|
||||
David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ The requirements for this project are:
|
|||
|
||||
At build-time, the following software is required:
|
||||
|
||||
* `meson >= 0.41`
|
||||
* `meson >= 0.60`
|
||||
* `pkg-config >= 0.29`
|
||||
|
||||
### Build
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
project(
|
||||
'c-siphash',
|
||||
'c',
|
||||
version: '1',
|
||||
license: 'Apache',
|
||||
default_options: [
|
||||
'c_std=c11'
|
||||
],
|
||||
license: 'Apache',
|
||||
meson_version: '>=0.60.0',
|
||||
version: '1.0.0',
|
||||
)
|
||||
major = meson.project_version().split('.')[0]
|
||||
project_description = 'Streaming-capable SipHash Implementation'
|
||||
|
||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
||||
mod_pkgconfig = import('pkgconfig')
|
||||
|
||||
sub_cstdaux = subproject('c-stdaux')
|
||||
|
||||
dep_cstdaux = sub_cstdaux.get_variable('libcstdaux_dep')
|
||||
dep_cstdaux = dependency('libcstdaux-1')
|
||||
add_project_arguments(dep_cstdaux.get_variable('cflags').split(' '), language: 'c')
|
||||
|
||||
subdir('src')
|
||||
|
||||
meson.override_dependency('libcsiphash-'+major, libcsiphash_dep, static: true)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ libcsiphash_deps = [
|
|||
dep_cstdaux,
|
||||
]
|
||||
|
||||
libcsiphash_private = static_library(
|
||||
'csiphash-private',
|
||||
libcsiphash_both = both_libraries(
|
||||
'csiphash-'+major,
|
||||
[
|
||||
'c-siphash.c',
|
||||
],
|
||||
|
|
@ -18,26 +18,19 @@ libcsiphash_private = static_library(
|
|||
'-fno-common',
|
||||
],
|
||||
dependencies: libcsiphash_deps,
|
||||
pic: true,
|
||||
)
|
||||
|
||||
libcsiphash_shared = shared_library(
|
||||
'csiphash',
|
||||
objects: libcsiphash_private.extract_all_objects(),
|
||||
dependencies: libcsiphash_deps,
|
||||
install: not meson.is_subproject(),
|
||||
soversion: 0,
|
||||
link_depends: libcsiphash_symfile,
|
||||
link_args: [
|
||||
'-Wl,--no-undefined',
|
||||
'-Wl,--version-script=@0@'.format(libcsiphash_symfile),
|
||||
],
|
||||
link_depends: libcsiphash_symfile,
|
||||
soversion: 0,
|
||||
)
|
||||
|
||||
libcsiphash_dep = declare_dependency(
|
||||
include_directories: include_directories('.'),
|
||||
link_with: libcsiphash_private,
|
||||
dependencies: libcsiphash_deps,
|
||||
include_directories: include_directories('.'),
|
||||
link_with: libcsiphash_both.get_static_lib(),
|
||||
version: meson.project_version(),
|
||||
)
|
||||
|
||||
|
|
@ -45,11 +38,11 @@ if not meson.is_subproject()
|
|||
install_headers('c-siphash.h')
|
||||
|
||||
mod_pkgconfig.generate(
|
||||
libraries: libcsiphash_shared,
|
||||
version: meson.project_version(),
|
||||
name: 'libcsiphash',
|
||||
filebase: 'libcsiphash',
|
||||
description: project_description,
|
||||
filebase: 'libcsiphash-'+major,
|
||||
libraries: libcsiphash_both.get_shared_lib(),
|
||||
name: 'libcsiphash',
|
||||
version: meson.project_version(),
|
||||
)
|
||||
endif
|
||||
|
||||
|
|
@ -57,7 +50,7 @@ endif
|
|||
# target: test-*
|
||||
#
|
||||
|
||||
test_api = executable('test-api', ['test-api.c'], link_with: libcsiphash_shared)
|
||||
test_api = executable('test-api', ['test-api.c'], link_with: libcsiphash_both.get_shared_lib())
|
||||
test('API Symbol Visibility', test_api)
|
||||
|
||||
test_basic = executable('test-basic', ['test-basic.c'], dependencies: libcsiphash_dep)
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit c5f166d02ff68af5cdcbad1bdcea2cb134e34ce4
|
||||
3
src/c-siphash/subprojects/libcstdaux-1.wrap
Normal file
3
src/c-siphash/subprojects/libcstdaux-1.wrap
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/c-util/c-stdaux.git
|
||||
revision = v1
|
||||
16
src/c-stdaux/.github/workflows/ci.yml
vendored
16
src/c-stdaux/.github/workflows/ci.yml
vendored
|
|
@ -9,13 +9,9 @@ on:
|
|||
jobs:
|
||||
ci:
|
||||
name: CI with Default Configuration
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Run through C-Util CI
|
||||
uses: c-util/automation/src/ci-c-util@v1
|
||||
with:
|
||||
m32: 1
|
||||
valgrind: 1
|
||||
uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1
|
||||
with:
|
||||
cabuild_ref: "v1"
|
||||
m32: true
|
||||
matrixmode: true
|
||||
valgrind: true
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ AUTHORS-LGPL:
|
|||
along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
COPYRIGHT: (ordered alphabetically)
|
||||
Copyright (C) 2018-2019 Red Hat, Inc.
|
||||
Copyright (C) 2018-2022 Red Hat, Inc.
|
||||
|
||||
AUTHORS: (ordered alphabetically)
|
||||
David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ The requirements for this project are:
|
|||
|
||||
At build-time, the following software is required:
|
||||
|
||||
* `meson >= 0.41`
|
||||
* `meson >= 0.60`
|
||||
* `pkg-config >= 0.29`
|
||||
|
||||
### Build
|
||||
|
|
|
|||
|
|
@ -1,15 +1,86 @@
|
|||
project(
|
||||
'c-stdaux',
|
||||
'c',
|
||||
version: '1',
|
||||
license: 'Apache',
|
||||
default_options: [
|
||||
'c_std=c11'
|
||||
],
|
||||
license: 'Apache',
|
||||
meson_version: '>=0.60.0',
|
||||
version: '1.0.0',
|
||||
)
|
||||
major = meson.project_version().split('.')[0]
|
||||
project_description = 'Auxiliary macros and functions for the C standard library'
|
||||
|
||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
||||
mod_pkgconfig = import('pkgconfig')
|
||||
|
||||
#
|
||||
# CFLAGS
|
||||
#
|
||||
# We have a set of compiler flags for GCC and CLANG which adjust their warnings
|
||||
# and behavior to our coding-style.
|
||||
#
|
||||
# This variable is exported to dependent projects via meson for them to use as
|
||||
# well. Since these exports are limited to strings, we need to be careful that
|
||||
# the individual entries do not contain spaces (see the assertion below).
|
||||
#
|
||||
cflags = meson.get_compiler('c').get_supported_arguments(
|
||||
# Enable GNU features of our dependencies. See feature_test_macros(7).
|
||||
'-D_GNU_SOURCE',
|
||||
|
||||
# Prevent CLANG from complaining that alignof-expressions are GNU-only.
|
||||
'-Wno-gnu-alignof-expression',
|
||||
# Never complain about *MAYBE* uninit variables. This is very flaky and
|
||||
# produces bogus results with LTO.
|
||||
'-Wno-maybe-uninitialized',
|
||||
# Do not complain about unknown GCC/CLANG warnings.
|
||||
'-Wno-unknown-warning-option',
|
||||
# There is no standardized way to mark unused arguments, so never
|
||||
# complain about them.
|
||||
'-Wno-unused-parameter',
|
||||
|
||||
# Preprocessor evaluations often lead to warnings about comparisons
|
||||
# that are always true/false. Make sure they do not break a build but
|
||||
# keep them on for diagnostics.
|
||||
'-Wno-error=type-limits',
|
||||
# As we use designated field-initializers, this warning should never
|
||||
# trigger, but still does on GCC in combination with some other
|
||||
# preprocessor checks. Lets just make sure it does not break builds.
|
||||
'-Wno-error=missing-field-initializers',
|
||||
|
||||
# Warn if we ever use `__DATE__` and similar in our build. We want
|
||||
# reproducible builds.
|
||||
'-Wdate-time',
|
||||
# We strictly follow decl-before-statements, so check it.
|
||||
'-Wdeclaration-after-statement',
|
||||
# More strict logical-op sanity checks.
|
||||
'-Wlogical-op',
|
||||
# Loudly complain about missing include-directories.
|
||||
'-Wmissing-include-dirs',
|
||||
# We want hints about noreturn functions, so warn about them.
|
||||
'-Wmissing-noreturn',
|
||||
# Warn if an extern-decl is inside a function. We want imports as
|
||||
# global attributes, never as local ones.
|
||||
'-Wnested-externs',
|
||||
# Warn about redundant declarations. We want declarations in headers
|
||||
# and want them to be unique.
|
||||
'-Wredundant-decls',
|
||||
# Warn about shadowed variables so we do not accidentally override
|
||||
# variables of parent scopes and thus confuse macros.
|
||||
'-Wshadow',
|
||||
# Warn about aliasing violations. Level-3 produces the least false
|
||||
# positives, but is the slowest. Force it to avoid breaking -Werror
|
||||
# builds.
|
||||
'-Wstrict-aliasing=3',
|
||||
# Suggest 'noreturn' attributes. They are useful, we want them!
|
||||
'-Wsuggest-attribute=noreturn',
|
||||
# Warn about undefined identifiers in preprocessor conditionals.
|
||||
'-Wundef',
|
||||
# Make sure literal strings are considered 'const'.
|
||||
'-Wwrite-strings',
|
||||
)
|
||||
assert(not ''.join(cflags).contains(' '), 'Malformed compiler flags.')
|
||||
add_project_arguments(cflags, language: 'c')
|
||||
|
||||
subdir('src')
|
||||
|
||||
meson.override_dependency('libcstdaux-'+major, libcstdaux_dep, static: true)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
libcstdaux_dep = declare_dependency(
|
||||
include_directories: include_directories('.'),
|
||||
variables: { 'cflags': ' '.join(cflags) },
|
||||
version: meson.project_version(),
|
||||
)
|
||||
|
||||
|
|
@ -13,10 +14,10 @@ if not meson.is_subproject()
|
|||
install_headers('c-stdaux.h')
|
||||
|
||||
mod_pkgconfig.generate(
|
||||
version: meson.project_version(),
|
||||
name: 'libcstdaux',
|
||||
filebase: 'libcstdaux',
|
||||
description: project_description,
|
||||
filebase: 'libcstdaux-'+major,
|
||||
name: 'libcstdaux',
|
||||
version: meson.project_version(),
|
||||
)
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ static void test_destructors(void) {
|
|||
|
||||
/* make sure c_closep() deals fine with negative FDs */
|
||||
{
|
||||
_c_cleanup_(c_closep) int t = 0;
|
||||
_c_cleanup_(c_closep) _c_unused_ int t = 0;
|
||||
t = -1;
|
||||
}
|
||||
|
||||
|
|
@ -370,7 +370,7 @@ static void test_destructors(void) {
|
|||
* path works as well.
|
||||
*/
|
||||
for (i = 0; i < 2; ++i) {
|
||||
_c_cleanup_(c_closep) int t = -1;
|
||||
_c_cleanup_(c_closep) _c_unused_ int t = -1;
|
||||
|
||||
t = eventfd(0, EFD_CLOEXEC);
|
||||
c_assert(t >= 0);
|
||||
|
|
@ -401,7 +401,7 @@ static void test_destructors(void) {
|
|||
|
||||
/* make sure c_flosep() deals fine with NULL */
|
||||
{
|
||||
_c_cleanup_(c_fclosep) FILE *t = (void *)0xdeadbeef;
|
||||
_c_cleanup_(c_fclosep) _c_unused_ FILE *t = (void *)0xdeadbeef;
|
||||
t = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ static void test_destructors(void) {
|
|||
* path works as well.
|
||||
*/
|
||||
for (i = 0; i < 2; ++i) {
|
||||
_c_cleanup_(c_fclosep) FILE *t = NULL;
|
||||
_c_cleanup_(c_fclosep) _c_unused_ FILE *t = NULL;
|
||||
int tfd;
|
||||
|
||||
tfd = eventfd(0, EFD_CLOEXEC);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include "libnm-platform/nm-linux-platform.h"
|
||||
#include "libnm-platform/nm-platform-utils.h"
|
||||
#include "nm-auth-utils.h"
|
||||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -1155,7 +1154,7 @@ nm_utils_file_is_in_path(const char *abs_filename, const char *abs_path)
|
|||
g_return_val_if_fail(abs_filename && abs_filename[0] == '/', NULL);
|
||||
g_return_val_if_fail(abs_path && abs_path[0] == '/', NULL);
|
||||
|
||||
path = nm_sd_utils_path_startswith(abs_filename, abs_path);
|
||||
path = nm_path_startswith(abs_filename, abs_path);
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ set_bond_attr_or_default(NMDevice *device, NMSettingBond *s_bond, const char *op
|
|||
NMDeviceBond *self = NM_DEVICE_BOND(device);
|
||||
const char *value;
|
||||
|
||||
value = nm_setting_bond_get_option_or_default(s_bond, opt);
|
||||
value = nm_setting_bond_get_option_normalized(s_bond, opt);
|
||||
if (!value) {
|
||||
if (_LOGT_ENABLED(LOGD_BOND) && nm_setting_bond_get_option_by_name(s_bond, opt))
|
||||
_LOGT(LOGD_BOND, "bond option '%s' not set as it conflicts with other options", opt);
|
||||
|
|
@ -346,7 +346,7 @@ set_bond_arp_ip_targets(NMDevice *device, NMSettingBond *s_bond)
|
|||
set_arp_targets(
|
||||
device,
|
||||
cur_arp_ip_target,
|
||||
nm_setting_bond_get_option_or_default(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
|
||||
nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -361,7 +361,7 @@ apply_bonding_config(NMDeviceBond *self)
|
|||
s_bond = nm_device_get_applied_setting(device, NM_TYPE_SETTING_BOND);
|
||||
g_return_val_if_fail(s_bond, FALSE);
|
||||
|
||||
mode_str = nm_setting_bond_get_option_or_default(s_bond, NM_SETTING_BOND_OPTION_MODE);
|
||||
mode_str = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE);
|
||||
mode = _nm_setting_bond_mode_from_string(mode_str);
|
||||
g_return_val_if_fail(mode != NM_BOND_MODE_UNKNOWN, FALSE);
|
||||
|
||||
|
|
@ -424,8 +424,14 @@ commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_
|
|||
queue_id_str);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure)
|
||||
static NMTernary
|
||||
attach_port(NMDevice *device,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceBond *self = NM_DEVICE_BOND(device);
|
||||
NMSettingBondPort *s_port;
|
||||
|
|
@ -442,7 +448,7 @@ enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboole
|
|||
nm_device_bring_up(port, TRUE, NULL);
|
||||
|
||||
if (!success) {
|
||||
_LOGI(LOGD_BOND, "assigning bond port %s: failed", nm_device_get_ip_iface(port));
|
||||
_LOGI(LOGD_BOND, "attaching bond port %s: failed", nm_device_get_ip_iface(port));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -450,15 +456,15 @@ enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboole
|
|||
|
||||
commit_port_options(device, port, s_port);
|
||||
|
||||
_LOGI(LOGD_BOND, "assigned bond port %s", nm_device_get_ip_iface(port));
|
||||
_LOGI(LOGD_BOND, "attached bond port %s", nm_device_get_ip_iface(port));
|
||||
} else
|
||||
_LOGI(LOGD_BOND, "bond port %s was assigned", nm_device_get_ip_iface(port));
|
||||
_LOGI(LOGD_BOND, "bond port %s was attached", nm_device_get_ip_iface(port));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
detach_port(NMDevice *device, NMDevice *port, gboolean configure)
|
||||
{
|
||||
NMDeviceBond *self = NM_DEVICE_BOND(device);
|
||||
gboolean success;
|
||||
|
|
@ -472,10 +478,10 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
configure = FALSE;
|
||||
}
|
||||
|
||||
ifindex_slave = nm_device_get_ip_ifindex(slave);
|
||||
ifindex_slave = nm_device_get_ip_ifindex(port);
|
||||
|
||||
if (ifindex_slave <= 0)
|
||||
_LOGD(LOGD_BOND, "bond slave %s is already released", nm_device_get_ip_iface(slave));
|
||||
_LOGD(LOGD_BOND, "bond port %s is already detached", nm_device_get_ip_iface(port));
|
||||
|
||||
if (configure) {
|
||||
NMConnection *applied;
|
||||
|
|
@ -490,9 +496,9 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
ifindex_slave);
|
||||
|
||||
if (success) {
|
||||
_LOGI(LOGD_BOND, "released bond slave %s", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_BOND, "detached bond port %s", nm_device_get_ip_iface(port));
|
||||
} else {
|
||||
_LOGW(LOGD_BOND, "failed to release bond slave %s", nm_device_get_ip_iface(slave));
|
||||
_LOGW(LOGD_BOND, "failed to detach bond port %s", nm_device_get_ip_iface(port));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -512,12 +518,12 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
* other state is noticed by the now-released slave.
|
||||
*/
|
||||
if (ifindex_slave > 0) {
|
||||
if (!nm_device_bring_up(slave, TRUE, NULL))
|
||||
_LOGW(LOGD_BOND, "released bond slave could not be brought up.");
|
||||
if (!nm_device_bring_up(port, TRUE, NULL))
|
||||
_LOGW(LOGD_BOND, "detached bond port could not be brought up.");
|
||||
}
|
||||
} else {
|
||||
if (ifindex_slave > 0) {
|
||||
_LOGI(LOGD_BOND, "bond slave %s was released", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_BOND, "bond port %s was detached", nm_device_get_ip_iface(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -612,7 +618,7 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
|
|||
s_bond = nm_connection_get_setting_bond(con_new);
|
||||
g_return_if_fail(s_bond);
|
||||
|
||||
value = nm_setting_bond_get_option_or_default(s_bond, NM_SETTING_BOND_OPTION_MODE);
|
||||
value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE);
|
||||
mode = _nm_setting_bond_mode_from_string(value);
|
||||
g_return_if_fail(mode != NM_BOND_MODE_UNKNOWN);
|
||||
|
||||
|
|
@ -663,8 +669,8 @@ nm_device_bond_class_init(NMDeviceBondClass *klass)
|
|||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->attach_port = attach_port;
|
||||
device_class->detach_port = detach_port;
|
||||
device_class->can_reapply_change = can_reapply_change;
|
||||
device_class->reapply_connection = reapply_connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -974,8 +974,14 @@ deactivate(NMDevice *device)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
|
||||
static NMTernary
|
||||
attach_port(NMDevice *device,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE(device);
|
||||
NMConnection *master_connection;
|
||||
|
|
@ -985,7 +991,7 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool
|
|||
if (configure) {
|
||||
if (!nm_platform_link_enslave(nm_device_get_platform(device),
|
||||
nm_device_get_ip_ifindex(device),
|
||||
nm_device_get_ip_ifindex(slave)))
|
||||
nm_device_get_ip_ifindex(port)))
|
||||
return FALSE;
|
||||
|
||||
master_connection = nm_device_get_applied_connection(device);
|
||||
|
|
@ -1009,25 +1015,25 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool
|
|||
* (except for the default one) and so there's no need to flush. */
|
||||
|
||||
if (plat_vlans
|
||||
&& !nm_platform_link_set_bridge_vlans(nm_device_get_platform(slave),
|
||||
nm_device_get_ifindex(slave),
|
||||
&& !nm_platform_link_set_bridge_vlans(nm_device_get_platform(port),
|
||||
nm_device_get_ifindex(port),
|
||||
TRUE,
|
||||
plat_vlans))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
commit_slave_options(slave, s_port);
|
||||
commit_slave_options(port, s_port);
|
||||
|
||||
_LOGI(LOGD_BRIDGE, "attached bridge port %s", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_BRIDGE, "attached bridge port %s", nm_device_get_ip_iface(port));
|
||||
} else {
|
||||
_LOGI(LOGD_BRIDGE, "bridge port %s was attached", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_BRIDGE, "bridge port %s was attached", nm_device_get_ip_iface(port));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
detach_port(NMDevice *device, NMDevice *port, gboolean configure)
|
||||
{
|
||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE(device);
|
||||
gboolean success;
|
||||
|
|
@ -1040,10 +1046,10 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
configure = FALSE;
|
||||
}
|
||||
|
||||
ifindex_slave = nm_device_get_ip_ifindex(slave);
|
||||
ifindex_slave = nm_device_get_ip_ifindex(port);
|
||||
|
||||
if (ifindex_slave <= 0) {
|
||||
_LOGD(LOGD_TEAM, "bond slave %s is already released", nm_device_get_ip_iface(slave));
|
||||
_LOGD(LOGD_TEAM, "bridge port %s is already detached", nm_device_get_ip_iface(port));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1053,12 +1059,12 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
ifindex_slave);
|
||||
|
||||
if (success) {
|
||||
_LOGI(LOGD_BRIDGE, "detached bridge port %s", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_BRIDGE, "detached bridge port %s", nm_device_get_ip_iface(port));
|
||||
} else {
|
||||
_LOGW(LOGD_BRIDGE, "failed to detach bridge port %s", nm_device_get_ip_iface(slave));
|
||||
_LOGW(LOGD_BRIDGE, "failed to detach bridge port %s", nm_device_get_ip_iface(port));
|
||||
}
|
||||
} else {
|
||||
_LOGI(LOGD_BRIDGE, "bridge port %s was detached", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_BRIDGE, "bridge port %s was detached", nm_device_get_ip_iface(port));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1084,10 +1090,6 @@ create_and_realize(NMDevice *device,
|
|||
s_bridge = nm_connection_get_setting_bridge(connection);
|
||||
nm_assert(s_bridge);
|
||||
|
||||
s_wired = nm_connection_get_setting_wired(connection);
|
||||
if (s_wired)
|
||||
mtu = nm_setting_wired_get_mtu(s_wired);
|
||||
|
||||
hwaddr = nm_setting_bridge_get_mac_address(s_bridge);
|
||||
if (!hwaddr
|
||||
&& nm_device_hw_addr_get_cloned(device, connection, FALSE, &hwaddr_cloned, NULL, NULL)) {
|
||||
|
|
@ -1112,6 +1114,11 @@ create_and_realize(NMDevice *device,
|
|||
|
||||
_platform_lnk_bridge_init_from_setting(s_bridge, &props);
|
||||
|
||||
s_wired = nm_connection_get_setting_wired(connection);
|
||||
nm_assert(s_wired);
|
||||
|
||||
mtu = nm_setting_wired_get_mtu(s_wired);
|
||||
|
||||
/* If mtu != 0, we set the MTU of the new bridge at creation time. However, kernel will still
|
||||
* automatically adjust the MTU of the bridge based on the minimum of the slave's MTU.
|
||||
* We don't want this automatism as the user asked for a fixed MTU.
|
||||
|
|
@ -1182,8 +1189,8 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass)
|
|||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->attach_port = attach_port;
|
||||
device_class->detach_port = detach_port;
|
||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -206,38 +206,44 @@ update_connection(NMDevice *device, NMConnection *connection)
|
|||
g_object_set(G_OBJECT(s_vrf), NM_SETTING_VRF_TABLE, priv->props.table, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
|
||||
static NMTernary
|
||||
attach_port(NMDevice *device,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceVrf *self = NM_DEVICE_VRF(device);
|
||||
gboolean success = TRUE;
|
||||
const char *slave_iface = nm_device_get_ip_iface(slave);
|
||||
NMDeviceVrf *self = NM_DEVICE_VRF(device);
|
||||
gboolean success = TRUE;
|
||||
const char *port_iface = nm_device_get_ip_iface(port);
|
||||
|
||||
nm_device_master_check_slave_physical_port(device, slave, LOGD_DEVICE);
|
||||
nm_device_master_check_slave_physical_port(device, port, LOGD_DEVICE);
|
||||
|
||||
if (configure) {
|
||||
nm_device_take_down(slave, TRUE);
|
||||
nm_device_take_down(port, TRUE);
|
||||
success = nm_platform_link_enslave(nm_device_get_platform(device),
|
||||
nm_device_get_ip_ifindex(device),
|
||||
nm_device_get_ip_ifindex(slave));
|
||||
nm_device_bring_up(slave, TRUE, NULL);
|
||||
nm_device_get_ip_ifindex(port));
|
||||
nm_device_bring_up(port, TRUE, NULL);
|
||||
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
||||
_LOGI(LOGD_DEVICE, "enslaved VRF slave %s", slave_iface);
|
||||
_LOGI(LOGD_DEVICE, "attached VRF port %s", port_iface);
|
||||
} else
|
||||
_LOGI(LOGD_BOND, "VRF slave %s was enslaved", slave_iface);
|
||||
_LOGI(LOGD_BOND, "VRF port %s was attached", port_iface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
detach_port(NMDevice *device, NMDevice *port, gboolean configure)
|
||||
{
|
||||
NMDeviceVrf *self = NM_DEVICE_VRF(device);
|
||||
gboolean success;
|
||||
int ifindex_slave;
|
||||
int ifindex_port;
|
||||
int ifindex;
|
||||
|
||||
if (configure) {
|
||||
|
|
@ -246,26 +252,26 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
configure = FALSE;
|
||||
}
|
||||
|
||||
ifindex_slave = nm_device_get_ip_ifindex(slave);
|
||||
ifindex_port = nm_device_get_ip_ifindex(port);
|
||||
|
||||
if (ifindex_slave <= 0)
|
||||
_LOGD(LOGD_DEVICE, "VRF slave %s is already released", nm_device_get_ip_iface(slave));
|
||||
if (ifindex_port <= 0)
|
||||
_LOGD(LOGD_DEVICE, "VRF port %s is already detached", nm_device_get_ip_iface(port));
|
||||
|
||||
if (configure) {
|
||||
if (ifindex_slave > 0) {
|
||||
if (ifindex_port > 0) {
|
||||
success = nm_platform_link_release(nm_device_get_platform(device),
|
||||
nm_device_get_ip_ifindex(device),
|
||||
ifindex_slave);
|
||||
ifindex_port);
|
||||
|
||||
if (success) {
|
||||
_LOGI(LOGD_DEVICE, "released VRF slave %s", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_DEVICE, "detached VRF port %s", nm_device_get_ip_iface(port));
|
||||
} else {
|
||||
_LOGW(LOGD_DEVICE, "failed to release VRF slave %s", nm_device_get_ip_iface(slave));
|
||||
_LOGW(LOGD_DEVICE, "failed to detach VRF port %s", nm_device_get_ip_iface(port));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ifindex_slave > 0) {
|
||||
_LOGI(LOGD_DEVICE, "VRF slave %s was released", nm_device_get_ip_iface(slave));
|
||||
if (ifindex_port > 0) {
|
||||
_LOGI(LOGD_DEVICE, "VRF port %s was detached", nm_device_get_ip_iface(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -316,8 +322,8 @@ nm_device_vrf_class_init(NMDeviceVrfClass *klass)
|
|||
device_class->is_master = TRUE;
|
||||
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_VRF);
|
||||
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->attach_port = attach_port;
|
||||
device_class->detach_port = detach_port;
|
||||
device_class->link_changed = link_changed;
|
||||
device_class->unrealize_notify = unrealize_notify;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
|
|
|
|||
|
|
@ -120,11 +120,12 @@ typedef enum _nm_packed {
|
|||
} AddrMethodState;
|
||||
|
||||
typedef struct {
|
||||
CList lst_slave;
|
||||
NMDevice *slave;
|
||||
gulong watch_id;
|
||||
bool slave_is_enslaved;
|
||||
bool configure;
|
||||
CList lst_slave;
|
||||
NMDevice *slave;
|
||||
GCancellable *cancellable;
|
||||
gulong watch_id;
|
||||
bool slave_is_enslaved;
|
||||
bool configure;
|
||||
} SlaveInfo;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -604,6 +605,7 @@ typedef struct _NMDevicePrivate {
|
|||
const NMDeviceIPState state;
|
||||
NMDeviceIPState state_;
|
||||
};
|
||||
gulong dnsmgr_update_pending_signal_id;
|
||||
} ip_data;
|
||||
|
||||
union {
|
||||
|
|
@ -2929,6 +2931,13 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_dev_ip_state_dnsmgr_update_pending_changed(NMDnsManager *dnsmgr, GParamSpec *pspec, NMDevice *self)
|
||||
{
|
||||
_dev_ip_state_check(self, AF_INET);
|
||||
_dev_ip_state_check(self, AF_INET6);
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ip_state_req_timeout_cancel(NMDevice *self, int addr_family)
|
||||
{
|
||||
|
|
@ -3321,6 +3330,27 @@ got_ip_state:
|
|||
combinedip_state = priv->ip_data.state;
|
||||
}
|
||||
|
||||
if (combinedip_state == NM_DEVICE_IP_STATE_READY
|
||||
&& priv->ip_data.state <= NM_DEVICE_IP_STATE_PENDING
|
||||
&& nm_dns_manager_get_update_pending(nm_manager_get_dns_manager(priv->manager))) {
|
||||
/* We would be ready, but a DNS update is pending. That prevents us from getting fully ready. */
|
||||
if (priv->ip_data.dnsmgr_update_pending_signal_id == 0) {
|
||||
priv->ip_data.dnsmgr_update_pending_signal_id =
|
||||
g_signal_connect(nm_manager_get_dns_manager(priv->manager),
|
||||
"notify::" NM_DNS_MANAGER_UPDATE_PENDING,
|
||||
G_CALLBACK(_dev_ip_state_dnsmgr_update_pending_changed),
|
||||
self);
|
||||
_LOGT_ip(AF_UNSPEC,
|
||||
"check-state: (combined) state: wait for DNS before becoming ready");
|
||||
}
|
||||
combinedip_state = NM_DEVICE_IP_STATE_PENDING;
|
||||
}
|
||||
if (combinedip_state != NM_DEVICE_IP_STATE_PENDING
|
||||
&& priv->ip_data.dnsmgr_update_pending_signal_id != 0) {
|
||||
nm_clear_g_signal_handler(nm_manager_get_dns_manager(priv->manager),
|
||||
&priv->ip_data.dnsmgr_update_pending_signal_id);
|
||||
}
|
||||
|
||||
_LOGT_ip(AF_UNSPEC,
|
||||
"check-state: (combined) state %s => %s",
|
||||
nm_device_ip_state_to_string(priv->ip_data.state),
|
||||
|
|
@ -5898,43 +5928,16 @@ find_slave_info(NMDevice *self, NMDevice *slave)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_master_enslave_slave:
|
||||
* @self: the master device
|
||||
* @slave: the slave device to enslave
|
||||
* @connection: (allow-none): the slave device's connection
|
||||
*
|
||||
* If @self is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function enslaves @slave.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
|
||||
* other devices.
|
||||
*/
|
||||
static gboolean
|
||||
nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection)
|
||||
static void
|
||||
attach_port_done(NMDevice *self, NMDevice *slave, gboolean success)
|
||||
{
|
||||
SlaveInfo *info;
|
||||
gboolean success = FALSE;
|
||||
gboolean configure;
|
||||
|
||||
g_return_val_if_fail(self != NULL, FALSE);
|
||||
g_return_val_if_fail(slave != NULL, FALSE);
|
||||
g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->enslave_slave != NULL, FALSE);
|
||||
|
||||
info = find_slave_info(self, slave);
|
||||
if (!info)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
if (info->slave_is_enslaved)
|
||||
success = TRUE;
|
||||
else {
|
||||
configure = (info->configure && connection != NULL);
|
||||
if (configure)
|
||||
g_return_val_if_fail(nm_device_get_state(slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
|
||||
|
||||
success = NM_DEVICE_GET_CLASS(self)->enslave_slave(self, slave, connection, configure);
|
||||
info->slave_is_enslaved = success;
|
||||
}
|
||||
info->slave_is_enslaved = success;
|
||||
|
||||
nm_device_slave_notify_enslave(info->slave, success);
|
||||
|
||||
|
|
@ -5954,8 +5957,71 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co
|
|||
*/
|
||||
if (success)
|
||||
nm_device_activate_schedule_stage3_ip_config(self, FALSE);
|
||||
}
|
||||
|
||||
return success;
|
||||
static void
|
||||
attach_port_cb(NMDevice *self, GError *error, gpointer user_data)
|
||||
{
|
||||
NMDevice *slave = user_data;
|
||||
SlaveInfo *info;
|
||||
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
return;
|
||||
|
||||
info = find_slave_info(self, slave);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
nm_clear_g_cancellable(&info->cancellable);
|
||||
attach_port_done(self, slave, !error);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_master_enslave_slave:
|
||||
* @self: the master device
|
||||
* @slave: the slave device to enslave
|
||||
* @connection: (allow-none): the slave device's connection
|
||||
*
|
||||
* If @self is capable of enslaving other devices (ie it's a bridge, bond, team,
|
||||
* etc) then this function enslaves @slave.
|
||||
*/
|
||||
static void
|
||||
nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection)
|
||||
{
|
||||
SlaveInfo *info;
|
||||
NMTernary success;
|
||||
gboolean configure;
|
||||
|
||||
g_return_if_fail(self);
|
||||
g_return_if_fail(slave);
|
||||
g_return_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port);
|
||||
|
||||
info = find_slave_info(self, slave);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (info->slave_is_enslaved)
|
||||
success = TRUE;
|
||||
else {
|
||||
configure = (info->configure && connection != NULL);
|
||||
if (configure)
|
||||
g_return_if_fail(nm_device_get_state(slave) >= NM_DEVICE_STATE_DISCONNECTED);
|
||||
|
||||
nm_clear_g_cancellable(&info->cancellable);
|
||||
info->cancellable = g_cancellable_new();
|
||||
success = NM_DEVICE_GET_CLASS(self)->attach_port(self,
|
||||
slave,
|
||||
connection,
|
||||
configure,
|
||||
info->cancellable,
|
||||
attach_port_cb,
|
||||
slave);
|
||||
|
||||
if (success == NM_TERNARY_DEFAULT)
|
||||
return;
|
||||
}
|
||||
|
||||
attach_port_done(self, slave, success);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5988,7 +6054,7 @@ nm_device_master_release_slave(NMDevice *self,
|
|||
RELEASE_SLAVE_TYPE_NO_CONFIG,
|
||||
RELEASE_SLAVE_TYPE_CONFIG,
|
||||
RELEASE_SLAVE_TYPE_CONFIG_FORCE));
|
||||
g_return_if_fail(NM_DEVICE_GET_CLASS(self)->release_slave != NULL);
|
||||
g_return_if_fail(NM_DEVICE_GET_CLASS(self)->detach_port != NULL);
|
||||
|
||||
info = find_slave_info(self, slave);
|
||||
|
||||
|
|
@ -6009,13 +6075,14 @@ nm_device_master_release_slave(NMDevice *self,
|
|||
|
||||
g_return_if_fail(self == slave_priv->master);
|
||||
nm_assert(slave == info->slave);
|
||||
nm_clear_g_cancellable(&info->cancellable);
|
||||
|
||||
/* first, let subclasses handle the release ... */
|
||||
if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave)
|
||||
|| release_type >= RELEASE_SLAVE_TYPE_CONFIG_FORCE)
|
||||
NM_DEVICE_GET_CLASS(self)->release_slave(self,
|
||||
slave,
|
||||
release_type >= RELEASE_SLAVE_TYPE_CONFIG);
|
||||
NM_DEVICE_GET_CLASS(self)->detach_port(self,
|
||||
slave,
|
||||
release_type >= RELEASE_SLAVE_TYPE_CONFIG);
|
||||
|
||||
/* raise notifications about the release, including clearing is_enslaved. */
|
||||
nm_device_slave_notify_release(slave, reason);
|
||||
|
|
@ -6356,7 +6423,7 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink)
|
|||
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
}
|
||||
|
||||
if (master && NM_DEVICE_GET_CLASS(master)->enslave_slave) {
|
||||
if (master && NM_DEVICE_GET_CLASS(master)->attach_port) {
|
||||
nm_device_master_add_slave(master, self, FALSE);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -7581,7 +7648,7 @@ nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure)
|
|||
|
||||
g_return_val_if_fail(NM_IS_DEVICE(self), FALSE);
|
||||
g_return_val_if_fail(NM_IS_DEVICE(slave), FALSE);
|
||||
g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->enslave_slave != NULL, FALSE);
|
||||
g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port, FALSE);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
slave_priv = NM_DEVICE_GET_PRIVATE(slave);
|
||||
|
|
@ -10036,6 +10103,7 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d
|
|||
FALSE);
|
||||
|
||||
if (notify_data->lease_update.accepted) {
|
||||
nm_manager_write_device_state(priv->manager, self, NULL);
|
||||
if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY) {
|
||||
_dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY);
|
||||
nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4),
|
||||
|
|
@ -12342,7 +12410,8 @@ delete_on_deactivate_check_and_schedule(NMDevice *self)
|
|||
static void
|
||||
_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean from_reapply)
|
||||
{
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
|
||||
_dev_ipsharedx_cleanup(self, addr_family);
|
||||
|
||||
|
|
@ -12358,6 +12427,9 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gbool
|
|||
|
||||
_dev_ipmanual_cleanup(self);
|
||||
|
||||
nm_clear_g_signal_handler(nm_manager_get_dns_manager(priv->manager),
|
||||
&priv->ip_data.dnsmgr_update_pending_signal_id);
|
||||
|
||||
_dev_ip_state_cleanup(self, AF_UNSPEC, from_reapply);
|
||||
_dev_ip_state_cleanup(self, addr_family, from_reapply);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ typedef enum {
|
|||
} NMDeviceCheckDevAvailableFlags;
|
||||
|
||||
typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data);
|
||||
typedef void (*NMDeviceAttachPortCallback)(NMDevice *self, GError *error, gpointer user_data);
|
||||
|
||||
typedef struct _NMDeviceClass {
|
||||
NMDBusObjectClass parent;
|
||||
|
|
@ -373,12 +374,18 @@ typedef struct _NMDeviceClass {
|
|||
NMConnection *connection,
|
||||
GError **error);
|
||||
|
||||
gboolean (*enslave_slave)(NMDevice *self,
|
||||
NMDevice *slave,
|
||||
NMConnection *connection,
|
||||
gboolean configure);
|
||||
|
||||
void (*release_slave)(NMDevice *self, NMDevice *slave, gboolean configure);
|
||||
/* Attachs a port asynchronously. Returns TRUE/FALSE on immediate
|
||||
* success/error; in such cases, the callback is not invoked. If the
|
||||
* action couldn't be completed immediately, DEFAULT is returned and
|
||||
* the callback will always be invoked asynchronously. */
|
||||
NMTernary (*attach_port)(NMDevice *self,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data);
|
||||
void (*detach_port)(NMDevice *self, NMDevice *port, gboolean configure);
|
||||
|
||||
void (*parent_changed_notify)(NMDevice *self,
|
||||
int old_ifindex,
|
||||
|
|
|
|||
|
|
@ -78,20 +78,26 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
|||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
|
||||
static NMTernary
|
||||
attach_port(NMDevice *device,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (!configure)
|
||||
return TRUE;
|
||||
|
||||
if (!NM_IS_DEVICE_OVS_PORT(slave))
|
||||
if (!NM_IS_DEVICE_OVS_PORT(port))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
detach_port(NMDevice *device, NMDevice *port, gboolean configure)
|
||||
{}
|
||||
|
||||
void
|
||||
|
|
@ -159,8 +165,8 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass)
|
|||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
||||
device_class->ready_for_ip_config = ready_for_ip_config;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->attach_port = attach_port;
|
||||
device_class->detach_port = detach_port;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,20 +72,42 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
|
|||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
NMDevice *device;
|
||||
NMDevice *port;
|
||||
GCancellable *cancellable;
|
||||
NMDeviceAttachPortCallback callback;
|
||||
gpointer callback_user_data;
|
||||
} AttachPortData;
|
||||
|
||||
static void
|
||||
add_iface_cb(GError *error, gpointer user_data)
|
||||
{
|
||||
NMDevice *slave = user_data;
|
||||
AttachPortData *data = user_data;
|
||||
NMDeviceOvsPort *self;
|
||||
gs_free_error GError *local = NULL;
|
||||
|
||||
if (error && !g_error_matches(error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) {
|
||||
nm_log_warn(LOGD_DEVICE,
|
||||
"device %s could not be added to a ovs port: %s",
|
||||
nm_device_get_iface(slave),
|
||||
error->message);
|
||||
nm_device_state_changed(slave, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_OVSDB_FAILED);
|
||||
if (g_cancellable_is_cancelled(data->cancellable)) {
|
||||
local = nm_utils_error_new_cancelled(FALSE, NULL);
|
||||
error = local;
|
||||
} else if (error && !nm_utils_error_is_cancelled_or_disposing(error)) {
|
||||
self = NM_DEVICE_OVS_PORT(data->device);
|
||||
_LOGW(LOGD_DEVICE,
|
||||
"device %s could not be added to a ovs port: %s",
|
||||
nm_device_get_iface(data->port),
|
||||
error->message);
|
||||
nm_device_state_changed(data->port,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_OVSDB_FAILED);
|
||||
}
|
||||
|
||||
g_object_unref(slave);
|
||||
data->callback(data->device, error, data->callback_user_data);
|
||||
|
||||
g_object_unref(data->device);
|
||||
g_object_unref(data->port);
|
||||
nm_clear_g_cancellable(&data->cancellable);
|
||||
|
||||
nm_g_slice_free(data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -115,14 +137,21 @@ set_mtu_cb(GError *error, gpointer user_data)
|
|||
g_object_unref(self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
|
||||
static NMTernary
|
||||
attach_port(NMDevice *device,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device);
|
||||
NMActiveConnection *ac_port = NULL;
|
||||
NMActiveConnection *ac_bridge = NULL;
|
||||
NMDevice *bridge_device;
|
||||
NMSettingWired *s_wired;
|
||||
AttachPortData *data;
|
||||
|
||||
if (!configure)
|
||||
return TRUE;
|
||||
|
|
@ -131,42 +160,49 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool
|
|||
ac_bridge = nm_active_connection_get_master(ac_port);
|
||||
if (!ac_bridge) {
|
||||
_LOGW(LOGD_DEVICE,
|
||||
"can't enslave %s: bridge active-connection not found",
|
||||
nm_device_get_iface(slave));
|
||||
"can't attach %s: bridge active-connection not found",
|
||||
nm_device_get_iface(port));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bridge_device = nm_active_connection_get_device(ac_bridge);
|
||||
if (!bridge_device) {
|
||||
_LOGW(LOGD_DEVICE, "can't enslave %s: bridge device not found", nm_device_get_iface(slave));
|
||||
_LOGW(LOGD_DEVICE, "can't attach %s: bridge device not found", nm_device_get_iface(port));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data = g_slice_new(AttachPortData);
|
||||
*data = (AttachPortData){
|
||||
.device = g_object_ref(device),
|
||||
.port = g_object_ref(port),
|
||||
.cancellable = g_object_ref(cancellable),
|
||||
.callback = callback,
|
||||
.callback_user_data = user_data,
|
||||
};
|
||||
|
||||
nm_ovsdb_add_interface(nm_ovsdb_get(),
|
||||
nm_active_connection_get_applied_connection(ac_bridge),
|
||||
nm_device_get_applied_connection(device),
|
||||
nm_device_get_applied_connection(slave),
|
||||
nm_device_get_applied_connection(port),
|
||||
bridge_device,
|
||||
slave,
|
||||
port,
|
||||
add_iface_cb,
|
||||
g_object_ref(slave));
|
||||
data);
|
||||
|
||||
/* DPDK ports does not have a link after the devbind, so the MTU must be
|
||||
* set on ovsdb after adding the interface. */
|
||||
if (NM_IS_DEVICE_OVS_INTERFACE(slave) && _ovs_interface_is_dpdk(slave)) {
|
||||
s_wired = nm_device_get_applied_setting(slave, NM_TYPE_SETTING_WIRED);
|
||||
|
||||
if (!s_wired || !nm_setting_wired_get_mtu(s_wired))
|
||||
return TRUE;
|
||||
|
||||
nm_ovsdb_set_interface_mtu(nm_ovsdb_get(),
|
||||
nm_device_get_ip_iface(slave),
|
||||
nm_setting_wired_get_mtu(s_wired),
|
||||
set_mtu_cb,
|
||||
g_object_ref(slave));
|
||||
if (NM_IS_DEVICE_OVS_INTERFACE(port) && _ovs_interface_is_dpdk(port)) {
|
||||
s_wired = nm_device_get_applied_setting(port, NM_TYPE_SETTING_WIRED);
|
||||
if (s_wired && nm_setting_wired_get_mtu(s_wired)) {
|
||||
nm_ovsdb_set_interface_mtu(nm_ovsdb_get(),
|
||||
nm_device_get_ip_iface(port),
|
||||
nm_setting_wired_get_mtu(s_wired),
|
||||
set_mtu_cb,
|
||||
g_object_ref(port));
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return NM_TERNARY_DEFAULT;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -186,31 +222,31 @@ del_iface_cb(GError *error, gpointer user_data)
|
|||
}
|
||||
|
||||
static void
|
||||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
detach_port(NMDevice *device, NMDevice *port, gboolean configure)
|
||||
{
|
||||
NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device);
|
||||
bool slave_not_managed = !NM_IN_SET(nm_device_sys_iface_state_get(slave),
|
||||
NM_DEVICE_SYS_IFACE_STATE_MANAGED,
|
||||
NM_DEVICE_SYS_IFACE_STATE_ASSUME);
|
||||
NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device);
|
||||
bool port_not_managed = !NM_IN_SET(nm_device_sys_iface_state_get(port),
|
||||
NM_DEVICE_SYS_IFACE_STATE_MANAGED,
|
||||
NM_DEVICE_SYS_IFACE_STATE_ASSUME);
|
||||
|
||||
_LOGI(LOGD_DEVICE, "releasing ovs interface %s", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_DEVICE, "detaching ovs interface %s", nm_device_get_ip_iface(port));
|
||||
|
||||
/* Even if the an interface's device has gone away (e.g. externally
|
||||
* removed and thus we're called with configure=FALSE), we still need
|
||||
* to make sure its OVSDB entry is gone.
|
||||
*/
|
||||
if (configure || slave_not_managed) {
|
||||
if (configure || port_not_managed) {
|
||||
nm_ovsdb_del_interface(nm_ovsdb_get(),
|
||||
nm_device_get_iface(slave),
|
||||
nm_device_get_iface(port),
|
||||
del_iface_cb,
|
||||
g_object_ref(slave));
|
||||
g_object_ref(port));
|
||||
}
|
||||
|
||||
if (configure) {
|
||||
/* Open VSwitch is going to delete this one. We must ignore what happens
|
||||
* next with the interface. */
|
||||
if (NM_IS_DEVICE_OVS_INTERFACE(slave))
|
||||
nm_device_update_from_platform_link(slave, NULL);
|
||||
if (NM_IS_DEVICE_OVS_INTERFACE(port))
|
||||
nm_device_update_from_platform_link(port, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -245,8 +281,8 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass)
|
|||
device_class->get_generic_capabilities = get_generic_capabilities;
|
||||
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
||||
device_class->ready_for_ip_config = ready_for_ip_config;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->attach_port = attach_port;
|
||||
device_class->detach_port = detach_port;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
device_class->reapply_connection = nm_device_ovs_reapply_connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,6 +376,9 @@ ovsdb_call_method(NMOvsdb *self,
|
|||
NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self);
|
||||
OvsdbMethodCall *call;
|
||||
|
||||
/* FIXME(shutdown): this function should accept a cancellable to
|
||||
* interrupt the operation. */
|
||||
|
||||
/* Ensure we're not unsynchronized before we queue the method call. */
|
||||
ovsdb_try_connect(self);
|
||||
|
||||
|
|
@ -1550,7 +1553,7 @@ _external_ids_to_string(const GArray *arr)
|
|||
if (!arr)
|
||||
return g_strdup("empty");
|
||||
|
||||
nm_str_buf_init(&strbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
|
||||
strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
|
||||
nm_str_buf_append(&strbuf, "[");
|
||||
for (i = 0; i < arr->len; i++) {
|
||||
const NMUtilsNamedValue *n = &g_array_index(arr, NMUtilsNamedValue, i);
|
||||
|
|
|
|||
|
|
@ -790,19 +790,25 @@ deactivate(NMDevice *device)
|
|||
teamd_cleanup(self, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
|
||||
static NMTernary
|
||||
attach_port(NMDevice *device,
|
||||
NMDevice *port,
|
||||
NMConnection *connection,
|
||||
gboolean configure,
|
||||
GCancellable *cancellable,
|
||||
NMDeviceAttachPortCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceTeam *self = NM_DEVICE_TEAM(device);
|
||||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
||||
gboolean success = TRUE;
|
||||
const char *slave_iface = nm_device_get_ip_iface(slave);
|
||||
NMDeviceTeam *self = NM_DEVICE_TEAM(device);
|
||||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
||||
gboolean success = TRUE;
|
||||
const char *port_iface = nm_device_get_ip_iface(port);
|
||||
NMSettingTeamPort *s_team_port;
|
||||
|
||||
nm_device_master_check_slave_physical_port(device, slave, LOGD_TEAM);
|
||||
nm_device_master_check_slave_physical_port(device, port, LOGD_TEAM);
|
||||
|
||||
if (configure) {
|
||||
nm_device_take_down(slave, TRUE);
|
||||
nm_device_take_down(port, TRUE);
|
||||
|
||||
s_team_port = nm_connection_get_setting_team_port(connection);
|
||||
if (s_team_port) {
|
||||
|
|
@ -811,19 +817,19 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool
|
|||
if (config) {
|
||||
if (!priv->tdc) {
|
||||
_LOGW(LOGD_TEAM,
|
||||
"enslaved team port %s config not changed, not connected to teamd",
|
||||
slave_iface);
|
||||
"attached team port %s config not changed, not connected to teamd",
|
||||
port_iface);
|
||||
} else {
|
||||
gs_free char *sanitized_config = NULL;
|
||||
int err;
|
||||
|
||||
sanitized_config = g_strdup(config);
|
||||
g_strdelimit(sanitized_config, "\r\n", ' ');
|
||||
err = teamdctl_port_config_update_raw(priv->tdc, slave_iface, sanitized_config);
|
||||
err = teamdctl_port_config_update_raw(priv->tdc, port_iface, sanitized_config);
|
||||
if (err != 0) {
|
||||
_LOGE(LOGD_TEAM,
|
||||
"failed to update config for port %s (err=%d)",
|
||||
slave_iface,
|
||||
port_iface,
|
||||
err);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -832,8 +838,8 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool
|
|||
}
|
||||
success = nm_platform_link_enslave(nm_device_get_platform(device),
|
||||
nm_device_get_ip_ifindex(device),
|
||||
nm_device_get_ip_ifindex(slave));
|
||||
nm_device_bring_up(slave, TRUE, NULL);
|
||||
nm_device_get_ip_ifindex(port));
|
||||
nm_device_bring_up(port, TRUE, NULL);
|
||||
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
|
@ -841,21 +847,21 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool
|
|||
nm_clear_g_source(&priv->teamd_read_timeout);
|
||||
priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self);
|
||||
|
||||
_LOGI(LOGD_TEAM, "enslaved team port %s", slave_iface);
|
||||
_LOGI(LOGD_TEAM, "attached team port %s", port_iface);
|
||||
} else
|
||||
_LOGI(LOGD_TEAM, "team port %s was enslaved", slave_iface);
|
||||
_LOGI(LOGD_TEAM, "team port %s was attached", port_iface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
||||
detach_port(NMDevice *device, NMDevice *port, gboolean configure)
|
||||
{
|
||||
NMDeviceTeam *self = NM_DEVICE_TEAM(device);
|
||||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self);
|
||||
gboolean do_release, success;
|
||||
NMSettingTeamPort *s_port;
|
||||
int ifindex_slave;
|
||||
int ifindex_port;
|
||||
int ifindex;
|
||||
|
||||
do_release = configure;
|
||||
|
|
@ -865,39 +871,39 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure)
|
|||
do_release = FALSE;
|
||||
}
|
||||
|
||||
ifindex_slave = nm_device_get_ip_ifindex(slave);
|
||||
ifindex_port = nm_device_get_ip_ifindex(port);
|
||||
|
||||
if (ifindex_slave <= 0) {
|
||||
_LOGD(LOGD_TEAM, "team port %s is already released", nm_device_get_ip_iface(slave));
|
||||
if (ifindex_port <= 0) {
|
||||
_LOGD(LOGD_TEAM, "team port %s is already detached", nm_device_get_ip_iface(port));
|
||||
} else if (do_release) {
|
||||
success = nm_platform_link_release(nm_device_get_platform(device),
|
||||
nm_device_get_ip_ifindex(device),
|
||||
ifindex_slave);
|
||||
ifindex_port);
|
||||
if (success)
|
||||
_LOGI(LOGD_TEAM, "released team port %s", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_TEAM, "detached team port %s", nm_device_get_ip_iface(port));
|
||||
else
|
||||
_LOGW(LOGD_TEAM, "failed to release team port %s", nm_device_get_ip_iface(slave));
|
||||
_LOGW(LOGD_TEAM, "failed to detach team port %s", nm_device_get_ip_iface(port));
|
||||
|
||||
/* Kernel team code "closes" the port when releasing it, (which clears
|
||||
* IFF_UP), so we must bring it back up here to ensure carrier changes and
|
||||
* other state is noticed by the now-released port.
|
||||
*/
|
||||
if (!nm_device_bring_up(slave, TRUE, NULL)) {
|
||||
if (!nm_device_bring_up(port, TRUE, NULL)) {
|
||||
_LOGW(LOGD_TEAM,
|
||||
"released team port %s could not be brought up",
|
||||
nm_device_get_ip_iface(slave));
|
||||
"detached team port %s could not be brought up",
|
||||
nm_device_get_ip_iface(port));
|
||||
}
|
||||
|
||||
nm_clear_g_source(&priv->teamd_read_timeout);
|
||||
priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self);
|
||||
} else
|
||||
_LOGI(LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface(slave));
|
||||
_LOGI(LOGD_TEAM, "team port %s was detached", nm_device_get_ip_iface(port));
|
||||
|
||||
/* Delete any port configuration we previously set */
|
||||
if (configure && priv->tdc
|
||||
&& (s_port = nm_device_get_applied_setting(slave, NM_TYPE_SETTING_TEAM_PORT))
|
||||
&& (s_port = nm_device_get_applied_setting(port, NM_TYPE_SETTING_TEAM_PORT))
|
||||
&& (nm_setting_team_port_get_config(s_port)))
|
||||
teamdctl_port_config_update_raw(priv->tdc, nm_device_get_ip_iface(slave), "{}");
|
||||
teamdctl_port_config_update_raw(priv->tdc, nm_device_get_ip_iface(port), "{}");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1064,8 +1070,8 @@ nm_device_team_class_init(NMDeviceTeamClass *klass)
|
|||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->attach_port = attach_port;
|
||||
device_class->detach_port = detach_port;
|
||||
|
||||
obj_properties[PROP_CONFIG] = g_param_spec_string(NM_DEVICE_TEAM_CONFIG,
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3Co
|
|||
|
||||
if (!IS_IPv4 && l3cd) {
|
||||
if (nm_dhcp_utils_merge_new_dhcp6_lease(priv->l3cd, l3cd, &l3cd_merged)) {
|
||||
_LOGD("lease merged with existing one");
|
||||
l3cd = nm_l3_config_data_seal(l3cd_merged);
|
||||
}
|
||||
}
|
||||
|
|
@ -327,14 +328,6 @@ nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3Co
|
|||
keys[i],
|
||||
(char *) g_hash_table_lookup(options, keys[i]));
|
||||
}
|
||||
|
||||
if (priv->config.addr_family == AF_INET6) {
|
||||
gs_free char *event_id = NULL;
|
||||
|
||||
event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
|
||||
if (event_id)
|
||||
_LOGT("event-id: \"%s\"", event_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1080,7 +1073,7 @@ config_init(NMDhcpClientConfig *config, const NMDhcpClientConfig *src)
|
|||
if (!config->send_hostname) {
|
||||
nm_clear_g_free((gpointer *) &config->hostname);
|
||||
} else if ((config->use_fqdn && !nm_sd_dns_name_is_valid(config->hostname))
|
||||
|| (!config->use_fqdn && !nm_sd_hostname_is_valid(config->hostname, FALSE))) {
|
||||
|| (!config->use_fqdn && !nm_hostname_is_valid(config->hostname, FALSE))) {
|
||||
nm_log_warn(LOGD_DHCP,
|
||||
"dhcp%c: %s '%s' is invalid, will be ignored",
|
||||
nm_utils_addr_family_to_char(config->addr_family),
|
||||
|
|
|
|||
|
|
@ -13,22 +13,24 @@
|
|||
#include <ctype.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include "libnm-glib-aux/nm-dedup-multi.h"
|
||||
#include "libnm-std-aux/unaligned.h"
|
||||
#include "libnm-glib-aux/nm-str-buf.h"
|
||||
#include "n-dhcp4/src/n-dhcp4.h"
|
||||
|
||||
#include "libnm-glib-aux/nm-dedup-multi.h"
|
||||
#include "libnm-glib-aux/nm-io-utils.h"
|
||||
#include "libnm-glib-aux/nm-str-buf.h"
|
||||
#include "libnm-std-aux/unaligned.h"
|
||||
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-config.h"
|
||||
#include "nm-dhcp-utils.h"
|
||||
#include "nm-dhcp-options.h"
|
||||
#include "nm-core-utils.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "libnm-platform/nm-platform.h"
|
||||
#include "nm-config.h"
|
||||
#include "nm-core-utils.h"
|
||||
#include "nm-dhcp-client-logging.h"
|
||||
#include "n-dhcp4/src/n-dhcp4.h"
|
||||
#include "nm-dhcp-options.h"
|
||||
#include "nm-dhcp-utils.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
#include "libnm-systemd-core/nm-sd-utils-dhcp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -887,12 +889,15 @@ dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data)
|
|||
|
||||
r = n_dhcp4_client_dispatch(priv->client);
|
||||
if (r < 0) {
|
||||
/* FIXME: if any operation (e.g. send()) fails during the
|
||||
/* If any operation (e.g. send()) fails during the
|
||||
* dispatch, n-dhcp4 returns an error without arming timers
|
||||
* or progressing state, so the only reasonable thing to do
|
||||
* is to move to failed state so that the client will be
|
||||
* restarted. Ideally n-dhcp4 should retry failed operations
|
||||
* a predefined number of times (possibly infinite).
|
||||
* restarted.
|
||||
*
|
||||
* That means, n_dhcp4_client_dispatch() must not fail if it can
|
||||
* somehow workaround the problem. A failure is really fatal
|
||||
* and the client needs to be restarted.
|
||||
*/
|
||||
_LOGE("error %d dispatching events", r);
|
||||
nm_clear_g_source_inst(&priv->event_source);
|
||||
|
|
@ -1107,18 +1112,20 @@ ip4_start(NMDhcpClient *client, GError **error)
|
|||
if (client_config->v4.last_address)
|
||||
inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
|
||||
else {
|
||||
/*
|
||||
* TODO: we stick to the systemd-networkd lease file format. Quite easy for now to
|
||||
* just use the functions in systemd code. Anyway, as in the end we just use the
|
||||
* ip address from all the options found in the lease, write a function that parses
|
||||
* the lease file just for the assigned address and returns it in &last_address.
|
||||
* Then drop reference to systemd-networkd structures and functions.
|
||||
*/
|
||||
nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
|
||||
gs_free char *contents = NULL;
|
||||
gs_free char *s_addr = NULL;
|
||||
|
||||
dhcp_lease_load(&lease, lease_file);
|
||||
if (lease)
|
||||
sd_dhcp_lease_get_address(lease, &last_addr);
|
||||
nm_utils_file_get_contents(-1,
|
||||
lease_file,
|
||||
64 * 1024,
|
||||
NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
|
||||
&contents,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nm_parse_env_file(contents, "ADDRESS", &s_addr);
|
||||
if (s_addr)
|
||||
nm_utils_parse_inaddr_bin(AF_INET, s_addr, NULL, &last_addr);
|
||||
}
|
||||
|
||||
if (last_addr.s_addr) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include "libnm-platform/nm-platform.h"
|
||||
#include "nm-dhcp-client-logging.h"
|
||||
#include "libnm-systemd-core/nm-sd.h"
|
||||
#include "libnm-systemd-core/nm-sd-utils-dhcp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -47,7 +46,6 @@ static GType nm_dhcp_systemd_get_type(void);
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
sd_dhcp_client *client4;
|
||||
sd_dhcp6_client *client6;
|
||||
char *lease_file;
|
||||
|
||||
|
|
@ -69,675 +67,6 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NML3ConfigData *
|
||||
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
||||
const char *iface,
|
||||
int ifindex,
|
||||
sd_dhcp_lease *lease,
|
||||
GError **error)
|
||||
{
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
const struct in_addr *addr_list;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const char *s;
|
||||
nm_auto_free_gstring GString *str = NULL;
|
||||
nm_auto_free sd_dhcp_route **routes_static = NULL;
|
||||
nm_auto_free sd_dhcp_route **routes_classless = NULL;
|
||||
const char *const *search_domains = NULL;
|
||||
guint32 default_route_metric_offset;
|
||||
guint16 mtu;
|
||||
int i;
|
||||
int num;
|
||||
int is_classless;
|
||||
int n_routes_static;
|
||||
int n_routes_classless;
|
||||
const void *data;
|
||||
gsize data_len;
|
||||
gboolean has_router_from_classless = FALSE;
|
||||
const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
|
||||
gint64 ts_time = time(NULL);
|
||||
struct in_addr a_address;
|
||||
struct in_addr a_netmask;
|
||||
struct in_addr a_next_server;
|
||||
struct in_addr server_id;
|
||||
struct in_addr broadcast;
|
||||
const struct in_addr *a_router;
|
||||
guint32 a_plen;
|
||||
guint32 a_lifetime;
|
||||
guint32 renewal;
|
||||
guint32 rebinding;
|
||||
gs_free nm_sd_dhcp_option *private_options = NULL;
|
||||
|
||||
nm_assert(lease != NULL);
|
||||
|
||||
if (sd_dhcp_lease_get_address(lease, &a_address) < 0) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get address from lease");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_netmask(lease, &a_netmask) < 0) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get netmask from lease");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_lifetime(lease, &a_lifetime) < 0) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get lifetime from lease");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
|
||||
_nm_utils_inet4_ntop(a_address.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
|
||||
|
||||
a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr);
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_SUBNET_MASK,
|
||||
_nm_utils_inet4_ntop(a_netmask.s_addr, addr_str));
|
||||
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME,
|
||||
a_lifetime);
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_NM_EXPIRY,
|
||||
(guint64) (ts_time + a_lifetime));
|
||||
|
||||
if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) {
|
||||
_nm_utils_inet4_ntop(a_next_server.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
|
||||
}
|
||||
|
||||
nm_l3_config_data_add_address_4(l3cd,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
.plen = a_plen,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.timestamp = ts,
|
||||
.lifetime = a_lifetime,
|
||||
.preferred = a_lifetime,
|
||||
}));
|
||||
|
||||
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
|
||||
_nm_utils_inet4_ntop(server_id.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_SERVER_ID, addr_str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_broadcast(lease, &broadcast) >= 0) {
|
||||
_nm_utils_inet4_ntop(broadcast.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_BROADCAST, addr_str);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_dns(lease, &addr_list);
|
||||
if (num > 0) {
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
_nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str);
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
|
||||
|
||||
if (addr_list[i].s_addr == 0 || nm_ip4_addr_is_localhost(addr_list[i].s_addr)) {
|
||||
/* Skip localhost addresses, like also networkd does.
|
||||
* See https://github.com/systemd/systemd/issues/4524. */
|
||||
continue;
|
||||
}
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr);
|
||||
}
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
|
||||
str->str);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_search_domains(lease, (char ***) &search_domains);
|
||||
if (num > 0) {
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]);
|
||||
nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]);
|
||||
}
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST,
|
||||
str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_domainname(lease, &s) >= 0) {
|
||||
gs_strfreev char **domains = NULL;
|
||||
char **d;
|
||||
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s);
|
||||
|
||||
/* Multiple domains sometimes stuffed into option 15 "Domain Name".
|
||||
* As systemd escapes such characters, split them at \\032. */
|
||||
domains = g_strsplit(s, "\\032", 0);
|
||||
for (d = domains; *d; d++)
|
||||
nm_l3_config_data_add_domain(l3cd, AF_INET, *d);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
|
||||
}
|
||||
|
||||
default_route_metric_offset = 0;
|
||||
n_routes_static = sd_dhcp_lease_get_static_routes(lease, &routes_static);
|
||||
n_routes_classless = sd_dhcp_lease_get_classless_routes(lease, &routes_classless);
|
||||
for (is_classless = 1; is_classless >= 0; is_classless--) {
|
||||
int n_routes = (is_classless ? n_routes_classless : n_routes_static);
|
||||
sd_dhcp_route *const *routes = (is_classless ? routes_classless : routes_static);
|
||||
|
||||
if (n_routes <= 0)
|
||||
continue;
|
||||
|
||||
nm_gstring_prepare(&str);
|
||||
|
||||
for (i = 0; i < n_routes; i++) {
|
||||
char network_net_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
char gateway_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
guint8 r_plen;
|
||||
struct in_addr r_network;
|
||||
struct in_addr r_gateway;
|
||||
in_addr_t network_net;
|
||||
guint32 m;
|
||||
|
||||
if (sd_dhcp_route_get_destination(routes[i], &r_network) < 0)
|
||||
continue;
|
||||
if (sd_dhcp_route_get_destination_prefix_length(routes[i], &r_plen) < 0 || r_plen > 32)
|
||||
continue;
|
||||
if (sd_dhcp_route_get_gateway(routes[i], &r_gateway) < 0)
|
||||
continue;
|
||||
|
||||
network_net = nm_utils_ip4_address_clear_host_address(r_network.s_addr, r_plen);
|
||||
_nm_utils_inet4_ntop(network_net, network_net_str);
|
||||
_nm_utils_inet4_ntop(r_gateway.s_addr, gateway_str);
|
||||
|
||||
g_string_append_printf(nm_gstring_add_space_delimiter(str),
|
||||
"%s/%d %s",
|
||||
network_net_str,
|
||||
(int) r_plen,
|
||||
gateway_str);
|
||||
|
||||
if (!is_classless && n_routes_classless > 0) {
|
||||
/* RFC 3443: if the DHCP server returns both a Classless Static Routes
|
||||
* option and a Static Routes option, the DHCP client MUST ignore the
|
||||
* Static Routes option. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r_plen == 0) {
|
||||
if (!is_classless) {
|
||||
/* for option 33 (static route), RFC 2132 says:
|
||||
*
|
||||
* The default route (0.0.0.0) is an illegal destination for a static
|
||||
* route. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric_offset++;
|
||||
has_router_from_classless = TRUE;
|
||||
} else
|
||||
m = 0;
|
||||
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.network = network_net,
|
||||
.plen = r_plen,
|
||||
.gateway = r_gateway.s_addr,
|
||||
.pref_src = a_address.s_addr,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
if (str->len > 0) {
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
is_classless ? NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE
|
||||
: NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
|
||||
str->str);
|
||||
}
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_router(lease, &a_router);
|
||||
if (num > 0) {
|
||||
default_route_metric_offset = 0;
|
||||
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
guint32 m;
|
||||
|
||||
s = _nm_utils_inet4_ntop(a_router[i].s_addr, addr_str);
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), s);
|
||||
|
||||
if (a_router[i].s_addr == 0) {
|
||||
/* silently skip 0.0.0.0 */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (has_router_from_classless) {
|
||||
/* If the DHCP server returns both a Classless Static Routes option and a
|
||||
* Router option, the DHCP client MUST ignore the Router option [RFC 3442].
|
||||
*
|
||||
* Be more lenient and ignore the Router option only if Classless Static
|
||||
* Routes contain a default gateway (as other DHCP backends do).
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric_offset++;
|
||||
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = a_router[i].s_addr,
|
||||
.pref_src = a_address.s_addr,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}));
|
||||
}
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
|
||||
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
|
||||
nm_l3_config_data_set_mtu(l3cd, mtu);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_ntp(lease, &addr_list);
|
||||
if (num > 0) {
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
_nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str);
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
|
||||
}
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_root_path(lease, &s) >= 0) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_t1(lease, &renewal) >= 0) {
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME,
|
||||
renewal);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_t2(lease, &rebinding) >= 0) {
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME,
|
||||
rebinding);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_timezone(lease, &s) >= 0) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) {
|
||||
if (!!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
|
||||
nm_l3_config_data_set_metered(l3cd, TRUE);
|
||||
}
|
||||
|
||||
num = nm_sd_dhcp_lease_get_private_options(lease, &private_options);
|
||||
if (num > 0) {
|
||||
for (i = 0; i < num; i++) {
|
||||
guint8 code = private_options[i].code;
|
||||
const guint8 *l_data = private_options[i].data;
|
||||
gsize l_data_len = private_options[i].data_len;
|
||||
char *option_string;
|
||||
|
||||
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) {
|
||||
if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
gs_free char *to_free = NULL;
|
||||
const char *escaped;
|
||||
|
||||
escaped =
|
||||
nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
escaped ?: "");
|
||||
|
||||
nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
|
||||
nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE) {
|
||||
/* nettools and dhclient parse option 249 (Microsoft Classless Static Route)
|
||||
* as fallback for routes and ignores them from private options.
|
||||
*
|
||||
* The systemd plugin does not, and for consistency with nettools we
|
||||
* also don't expose it as private option either. */
|
||||
continue;
|
||||
}
|
||||
|
||||
option_string = nm_utils_bin2hexstr_full(l_data, l_data_len, ':', FALSE, NULL);
|
||||
nm_dhcp_option_take_option(options, AF_INET, code, option_string);
|
||||
}
|
||||
}
|
||||
|
||||
nm_dhcp_option_add_requests_to_options(options, AF_INET);
|
||||
|
||||
nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
bound4_handle(NMDhcpSystemd *self, gboolean extended)
|
||||
{
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const char *iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
sd_dhcp_lease *lease = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (sd_dhcp_client_get_lease(priv->client4, &lease) < 0 || !lease) {
|
||||
_LOGW("no lease!");
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD("lease available");
|
||||
|
||||
l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
&error);
|
||||
if (!l3cd) {
|
||||
_LOGW("%s", error->message);
|
||||
g_clear_error(&error);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_lease_save(lease, priv->lease_file);
|
||||
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
|
||||
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
|
||||
l3cd);
|
||||
}
|
||||
|
||||
static int
|
||||
dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
|
||||
{
|
||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD(user_data);
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
sd_dhcp_lease *lease = NULL;
|
||||
struct in_addr addr;
|
||||
int r;
|
||||
|
||||
nm_assert(priv->client4 == client);
|
||||
|
||||
_LOGD("client event %d", event);
|
||||
|
||||
switch (event) {
|
||||
case SD_DHCP_CLIENT_EVENT_EXPIRED:
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_STOP:
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_RENEW:
|
||||
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
|
||||
bound4_handle(self, TRUE);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
|
||||
bound4_handle(self, FALSE);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_SELECTING:
|
||||
r = sd_dhcp_client_get_lease(priv->client4, &lease);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (nm_dhcp_client_server_id_is_rejected(NM_DHCP_CLIENT(user_data), &addr)) {
|
||||
_LOGD("server-id %s is in the reject-list, ignoring",
|
||||
nm_utils_inet_ntop(AF_INET, &addr, addr_str));
|
||||
return -ENOMSG;
|
||||
}
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE:
|
||||
break;
|
||||
default:
|
||||
_LOGW("unhandled DHCP event %d", event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_start(NMDhcpClient *client, GError **error)
|
||||
{
|
||||
nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL;
|
||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD(client);
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
gs_free char *lease_file = NULL;
|
||||
GBytes *hwaddr;
|
||||
const uint8_t *hwaddr_arr;
|
||||
gsize hwaddr_len;
|
||||
int arp_type;
|
||||
GBytes *client_id;
|
||||
gs_unref_bytes GBytes *client_id_new = NULL;
|
||||
GBytes *vendor_class_identifier;
|
||||
const uint8_t *client_id_arr;
|
||||
size_t client_id_len;
|
||||
struct in_addr last_addr = {0};
|
||||
const char *hostname;
|
||||
const char *mud_url;
|
||||
int r, i;
|
||||
GBytes *bcast_hwaddr;
|
||||
const uint8_t *bcast_hwaddr_arr;
|
||||
gsize bcast_hwaddr_len;
|
||||
|
||||
g_return_val_if_fail(!priv->client4, FALSE);
|
||||
g_return_val_if_fail(!priv->client6, FALSE);
|
||||
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
||||
/* TODO: honor nm_dhcp_client_get_anycast_address() */
|
||||
|
||||
r = sd_dhcp_client_new(&sd_client, FALSE);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to create dhcp-client: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_LOGT("dhcp-client4: set " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(sd_client));
|
||||
|
||||
r = sd_dhcp_client_attach_event(sd_client, NULL, 0);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to attach event: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hwaddr = client_config->hwaddr;
|
||||
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|
||||
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
|
||||
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bcast_hwaddr_arr = NULL;
|
||||
bcast_hwaddr = client_config->bcast_hwaddr;
|
||||
if (bcast_hwaddr) {
|
||||
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
|
||||
if (bcast_hwaddr_len != hwaddr_len)
|
||||
bcast_hwaddr_arr = NULL;
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_mac(sd_client,
|
||||
hwaddr_arr,
|
||||
bcast_hwaddr_arr,
|
||||
hwaddr_len,
|
||||
(guint16) arp_type);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set MAC address: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_ifindex(sd_client, nm_dhcp_client_get_ifindex(client));
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set ifindex: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nm_dhcp_utils_get_leasefile_path(AF_INET,
|
||||
"internal",
|
||||
client_config->iface,
|
||||
client_config->uuid,
|
||||
&lease_file);
|
||||
|
||||
if (client_config->v4.last_address)
|
||||
inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
|
||||
else {
|
||||
nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
|
||||
|
||||
dhcp_lease_load(&lease, lease_file);
|
||||
if (lease)
|
||||
sd_dhcp_lease_get_address(lease, &last_addr);
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_request_broadcast(sd_client, client_config->v4.request_broadcast);
|
||||
nm_assert(r >= 0);
|
||||
|
||||
if (last_addr.s_addr) {
|
||||
r = sd_dhcp_client_set_request_address(sd_client, &last_addr);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set last IPv4 address: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
client_id = client_config->client_id;
|
||||
if (!client_id) {
|
||||
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
|
||||
client_id = client_id_new;
|
||||
}
|
||||
|
||||
if (!(client_id_arr = g_bytes_get_data(client_id, &client_id_len)) || client_id_len < 2) {
|
||||
/* invalid client-ids are not expected. */
|
||||
nm_assert_not_reached();
|
||||
|
||||
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "no valid IPv4 client-id");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Note that we always set a client-id. In particular for infiniband that is necessary,
|
||||
* see https://tools.ietf.org/html/rfc4390#section-2.1 . */
|
||||
r = sd_dhcp_client_set_client_id(sd_client,
|
||||
client_id_arr[0],
|
||||
client_id_arr + 1,
|
||||
NM_MIN(client_id_len - 1, _NM_MAX_CLIENT_ID_LEN));
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set IPv4 client-id: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Add requested options */
|
||||
for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options); i++) {
|
||||
if (_nm_dhcp_option_dhcp4_options[i].include) {
|
||||
nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255);
|
||||
r = sd_dhcp_client_set_request_option(sd_client,
|
||||
_nm_dhcp_option_dhcp4_options[i].option_num);
|
||||
nm_assert(r >= 0 || r == -EEXIST);
|
||||
}
|
||||
}
|
||||
|
||||
hostname = client_config->hostname;
|
||||
if (hostname) {
|
||||
/* FIXME: sd-dhcp decides which hostname/FQDN option to send (12 or 81)
|
||||
* only based on whether the hostname has a domain part or not. At the
|
||||
* moment there is no way to force one or another.
|
||||
*/
|
||||
r = sd_dhcp_client_set_hostname(sd_client, hostname);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set DHCP hostname: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
mud_url = client_config->mud_url;
|
||||
if (mud_url) {
|
||||
r = sd_dhcp_client_set_mud_url(sd_client, mud_url);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set DHCP MUDURL: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
vendor_class_identifier = client_config->vendor_class_identifier;
|
||||
if (vendor_class_identifier) {
|
||||
const char *option_data;
|
||||
gsize len;
|
||||
|
||||
option_data = g_bytes_get_data(vendor_class_identifier, &len);
|
||||
nm_assert(option_data);
|
||||
nm_assert(len <= 255);
|
||||
|
||||
option_data = nm_strndup_a(300, option_data, len, NULL);
|
||||
|
||||
r = sd_dhcp_client_set_vendor_class_identifier(sd_client, option_data);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set DHCP vendor class identifier: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_callback(sd_client, dhcp_event_cb, client);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set callback: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->client4 = g_steal_pointer(&sd_client);
|
||||
|
||||
g_free(priv->lease_file);
|
||||
priv->lease_file = g_steal_pointer(&lease_file);
|
||||
|
||||
nm_dhcp_client_set_effective_client_id(client, client_id);
|
||||
|
||||
r = sd_dhcp_client_start(priv->client4);
|
||||
if (r < 0) {
|
||||
sd_dhcp_client_set_callback(priv->client4, NULL, NULL);
|
||||
nm_clear_pointer(&priv->client4, sd_dhcp_client_unref);
|
||||
nm_utils_error_set_errno(error, r, "failed to start DHCP client: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NML3ConfigData *
|
||||
lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
|
||||
const char *iface,
|
||||
|
|
@ -952,7 +281,6 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error)
|
|||
GBytes *duid;
|
||||
gboolean prefix_delegation;
|
||||
|
||||
g_return_val_if_fail(!priv->client4, FALSE);
|
||||
g_return_val_if_fail(!priv->client6, FALSE);
|
||||
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
|
@ -1079,18 +407,13 @@ stop(NMDhcpClient *client, gboolean release)
|
|||
|
||||
NM_DHCP_CLIENT_CLASS(nm_dhcp_systemd_parent_class)->stop(client, release);
|
||||
|
||||
_LOGT("dhcp-client%d: stop %p",
|
||||
priv->client4 ? '4' : '6',
|
||||
priv->client4 ? (gpointer) priv->client4 : (gpointer) priv->client6);
|
||||
_LOGT("dhcp-client6: stop");
|
||||
|
||||
if (priv->client4) {
|
||||
sd_dhcp_client_set_callback(priv->client4, NULL, NULL);
|
||||
r = sd_dhcp_client_stop(priv->client4);
|
||||
} else if (priv->client6) {
|
||||
sd_dhcp6_client_set_callback(priv->client6, NULL, NULL);
|
||||
r = sd_dhcp6_client_stop(priv->client6);
|
||||
}
|
||||
if (!priv->client6)
|
||||
return;
|
||||
|
||||
sd_dhcp6_client_set_callback(priv->client6, NULL, NULL);
|
||||
r = sd_dhcp6_client_stop(priv->client6);
|
||||
if (r)
|
||||
_LOGW("failed to stop client (%d)", r);
|
||||
}
|
||||
|
|
@ -1108,12 +431,6 @@ dispose(GObject *object)
|
|||
|
||||
nm_clear_g_free(&priv->lease_file);
|
||||
|
||||
if (priv->client4) {
|
||||
sd_dhcp_client_stop(priv->client4);
|
||||
sd_dhcp_client_unref(priv->client4);
|
||||
priv->client4 = NULL;
|
||||
}
|
||||
|
||||
if (priv->client6) {
|
||||
sd_dhcp6_client_stop(priv->client6);
|
||||
sd_dhcp6_client_unref(priv->client6);
|
||||
|
|
@ -1131,14 +448,13 @@ nm_dhcp_systemd_class_init(NMDhcpSystemdClass *sdhcp_class)
|
|||
|
||||
object_class->dispose = dispose;
|
||||
|
||||
client_class->ip4_start = ip4_start;
|
||||
client_class->ip6_start = ip6_start;
|
||||
client_class->stop = stop;
|
||||
}
|
||||
|
||||
const NMDhcpClientFactory _nm_dhcp_client_factory_systemd = {
|
||||
.name = "systemd",
|
||||
.get_type_4 = nm_dhcp_systemd_get_type,
|
||||
.get_type_4 = nm_dhcp_nettools_get_type,
|
||||
.get_type_6 = nm_dhcp_systemd_get_type,
|
||||
.undocumented = TRUE,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ process_classful_routes(const char *iface,
|
|||
return;
|
||||
|
||||
if ((NM_PTRARRAY_LEN(searches) % 2) != 0) {
|
||||
_LOG2I(LOGD_DHCP, iface, " static routes provided, but invalid");
|
||||
_LOG2I(LOGD_DHCP4, iface, " static routes provided, but invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -305,11 +305,11 @@ process_classful_routes(const char *iface,
|
|||
guint32 rt_addr, rt_route;
|
||||
|
||||
if (inet_pton(AF_INET, *s, &rt_addr) <= 0) {
|
||||
_LOG2W(LOGD_DHCP, iface, "DHCP provided invalid static route address: '%s'", *s);
|
||||
_LOG2W(LOGD_DHCP4, iface, "DHCP provided invalid static route address: '%s'", *s);
|
||||
continue;
|
||||
}
|
||||
if (inet_pton(AF_INET, *(s + 1), &rt_route) <= 0) {
|
||||
_LOG2W(LOGD_DHCP, iface, "DHCP provided invalid static route gateway: '%s'", *(s + 1));
|
||||
_LOG2W(LOGD_DHCP4, iface, "DHCP provided invalid static route gateway: '%s'", *(s + 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ process_classful_routes(const char *iface,
|
|||
|
||||
nm_l3_config_data_add_route_4(l3cd, &route);
|
||||
|
||||
_LOG2I(LOGD_DHCP,
|
||||
_LOG2I(LOGD_DHCP4,
|
||||
iface,
|
||||
" static route %s",
|
||||
nm_platform_ip4_route_to_string(&route, sbuf, sizeof(sbuf)));
|
||||
|
|
@ -352,6 +352,7 @@ process_domain_search(int addr_family, const char *iface, const char *str, NML3C
|
|||
{
|
||||
gs_free const char **searches = NULL;
|
||||
gs_free char *unescaped = NULL;
|
||||
NMLogDomain logd = NM_IS_IPv4(addr_family) ? LOGD_DHCP4 : LOGD_DHCP6;
|
||||
const char **s;
|
||||
char *p;
|
||||
int i;
|
||||
|
|
@ -373,13 +374,13 @@ process_domain_search(int addr_family, const char *iface, const char *str, NML3C
|
|||
} while (*p++);
|
||||
|
||||
if (strchr(unescaped, '\\')) {
|
||||
_LOG2W(LOGD_DHCP, iface, " invalid domain search: '%s'", unescaped);
|
||||
_LOG2W(logd, iface, " invalid domain search: '%s'", unescaped);
|
||||
return;
|
||||
}
|
||||
|
||||
searches = nm_strsplit_set(unescaped, " ");
|
||||
for (s = searches; searches && *s; s++) {
|
||||
_LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s);
|
||||
_LOG2I(logd, iface, " domain search '%s'", *s);
|
||||
nm_l3_config_data_add_search(l3cd, addr_family, *s);
|
||||
}
|
||||
}
|
||||
|
|
@ -822,26 +823,6 @@ nm_dhcp_utils_get_leasefile_path(int addr_family,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
char *
|
||||
nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease)
|
||||
{
|
||||
const char *start;
|
||||
const char *iaid;
|
||||
|
||||
if (!lease)
|
||||
return NULL;
|
||||
|
||||
iaid = g_hash_table_lookup(lease, "iaid");
|
||||
if (!iaid)
|
||||
return NULL;
|
||||
|
||||
start = g_hash_table_lookup(lease, "life_starts");
|
||||
if (!start)
|
||||
return NULL;
|
||||
|
||||
return g_strdup_printf("%s|%s", iaid, start);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData *l3cd_old,
|
||||
const NML3ConfigData *l3cd_new,
|
||||
|
|
|
|||
|
|
@ -678,19 +678,23 @@ typedef struct {
|
|||
|
||||
char *name_owner;
|
||||
|
||||
GSource *main_timeout_source;
|
||||
GSource *burst_retry_timeout_source;
|
||||
|
||||
gint64 burst_start_at;
|
||||
|
||||
GPid process_pid;
|
||||
|
||||
guint name_owner_changed_id;
|
||||
guint main_timeout_id;
|
||||
|
||||
guint burst_retry_timeout_id;
|
||||
|
||||
guint8 burst_count;
|
||||
|
||||
bool is_stopped : 1;
|
||||
|
||||
bool set_server_ex_args_dirty : 1;
|
||||
|
||||
bool update_pending : 1;
|
||||
|
||||
} NMDnsDnsmasqPrivate;
|
||||
|
||||
struct _NMDnsDnsmasq {
|
||||
|
|
@ -704,7 +708,8 @@ struct _NMDnsDnsmasqClass {
|
|||
|
||||
G_DEFINE_TYPE(NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN)
|
||||
|
||||
#define NM_DNS_DNSMASQ_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDnsDnsmasq, NM_IS_DNS_DNSMASQ)
|
||||
#define NM_DNS_DNSMASQ_GET_PRIVATE(self) \
|
||||
_NM_GET_PRIVATE(self, NMDnsDnsmasq, NM_IS_DNS_DNSMASQ, NMDnsPlugin)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -717,6 +722,55 @@ static gboolean start_dnsmasq(NMDnsDnsmasq *self, gboolean force_start, GError *
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_update_pending_detect(NMDnsDnsmasq *self)
|
||||
{
|
||||
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE(self);
|
||||
|
||||
if (priv->is_stopped)
|
||||
return FALSE;
|
||||
if (priv->main_timeout_source) {
|
||||
/* we are waiting for dnsmasq to start. */
|
||||
return TRUE;
|
||||
}
|
||||
if (priv->update_cancellable) {
|
||||
/* An update is in progress. Busy. */
|
||||
return TRUE;
|
||||
}
|
||||
if (priv->set_server_ex_args_dirty) {
|
||||
/* the args just changed and were not yet sent. Busy. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_pending_maybe_changed(NMDnsDnsmasq *self)
|
||||
{
|
||||
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE(self);
|
||||
gboolean update_pending;
|
||||
|
||||
update_pending = _update_pending_detect(self);
|
||||
if (priv->update_pending == update_pending)
|
||||
return;
|
||||
|
||||
priv->update_pending = update_pending;
|
||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_update_pending(NMDnsPlugin *plugin)
|
||||
{
|
||||
NMDnsDnsmasq *self = NM_DNS_DNSMASQ(plugin);
|
||||
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE(self);
|
||||
|
||||
nm_assert(priv->update_pending == _update_pending_detect(self));
|
||||
return priv->update_pending;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
add_dnsmasq_nameserver(NMDnsDnsmasq *self,
|
||||
GVariantBuilder *servers,
|
||||
|
|
@ -871,6 +925,7 @@ static void
|
|||
dnsmasq_update_done(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
NMDnsDnsmasq *self;
|
||||
NMDnsDnsmasqPrivate *priv;
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *response = NULL;
|
||||
|
||||
|
|
@ -880,10 +935,16 @@ dnsmasq_update_done(GObject *source_object, GAsyncResult *res, gpointer user_dat
|
|||
return;
|
||||
|
||||
self = user_data;
|
||||
priv = NM_DNS_DNSMASQ_GET_PRIVATE(self);
|
||||
|
||||
nm_clear_g_cancellable(&priv->update_cancellable);
|
||||
|
||||
if (!response)
|
||||
_LOGW("dnsmasq update failed: %s", error->message);
|
||||
else
|
||||
_LOGD("dnsmasq update successful");
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -899,6 +960,8 @@ send_dnsmasq_update(NMDnsDnsmasq *self)
|
|||
nm_clear_g_cancellable(&priv->update_cancellable);
|
||||
priv->update_cancellable = g_cancellable_new();
|
||||
|
||||
priv->set_server_ex_args_dirty = FALSE;
|
||||
|
||||
g_dbus_connection_call(priv->dbus_connection,
|
||||
priv->name_owner,
|
||||
DNSMASQ_DBUS_PATH,
|
||||
|
|
@ -911,6 +974,8 @@ send_dnsmasq_update(NMDnsDnsmasq *self)
|
|||
priv->update_cancellable,
|
||||
dnsmasq_update_done,
|
||||
self);
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -928,17 +993,19 @@ _main_cleanup(NMDnsDnsmasq *self, gboolean emit_failed)
|
|||
|
||||
nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id);
|
||||
|
||||
nm_clear_g_source(&priv->main_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->main_timeout_source);
|
||||
nm_clear_g_cancellable(&priv->update_cancellable);
|
||||
|
||||
/* cancelling the main_cancellable will also cause _gl_pid_spawn*() to terminate the
|
||||
* process in the background. */
|
||||
nm_clear_g_cancellable(&priv->main_cancellable);
|
||||
|
||||
if (!priv->is_stopped && priv->burst_retry_timeout_id == 0) {
|
||||
if (!priv->is_stopped && !priv->burst_retry_timeout_source) {
|
||||
start_dnsmasq(self, FALSE, NULL);
|
||||
send_dnsmasq_update(self);
|
||||
}
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -961,8 +1028,10 @@ name_owner_changed(NMDnsDnsmasq *self, const char *name_owner)
|
|||
}
|
||||
|
||||
_LOGT("D-Bus name for dnsmasq got owner %s", name_owner);
|
||||
nm_clear_g_source(&priv->main_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->main_timeout_source);
|
||||
send_dnsmasq_update(self);
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1047,11 +1116,11 @@ _burst_retry_timeout_cb(gpointer user_data)
|
|||
NMDnsDnsmasq *self = user_data;
|
||||
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE(self);
|
||||
|
||||
priv->burst_retry_timeout_id = 0;
|
||||
nm_clear_g_source_inst(&priv->burst_retry_timeout_source);
|
||||
|
||||
start_dnsmasq(self, TRUE, NULL);
|
||||
send_dnsmasq_update(self);
|
||||
return G_SOURCE_REMOVE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1090,33 +1159,35 @@ start_dnsmasq(NMDnsDnsmasq *self, gboolean force_start, GError **error)
|
|||
|| priv->burst_start_at + RATELIMIT_INTERVAL_MSEC <= now) {
|
||||
priv->burst_start_at = now;
|
||||
priv->burst_count = 1;
|
||||
nm_clear_g_source(&priv->burst_retry_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->burst_retry_timeout_source);
|
||||
_LOGT("rate-limit: start burst interval of %d seconds %s",
|
||||
RATELIMIT_INTERVAL_MSEC / 1000,
|
||||
force_start ? " (force)" : "");
|
||||
} else if (priv->burst_count < RATELIMIT_BURST) {
|
||||
nm_assert(priv->burst_retry_timeout_id == 0);
|
||||
nm_assert(!priv->burst_retry_timeout_source);
|
||||
priv->burst_count++;
|
||||
_LOGT("rate-limit: %u try within burst interval of %d seconds",
|
||||
(guint) priv->burst_count,
|
||||
RATELIMIT_INTERVAL_MSEC / 1000);
|
||||
} else {
|
||||
if (priv->burst_retry_timeout_id == 0) {
|
||||
if (!priv->burst_retry_timeout_source) {
|
||||
_LOGW("dnsmasq dies and gets respawned too quickly. Back off. Something is very wrong");
|
||||
priv->burst_retry_timeout_id =
|
||||
g_timeout_add_seconds((2 * RATELIMIT_INTERVAL_MSEC) / 1000,
|
||||
_burst_retry_timeout_cb,
|
||||
self);
|
||||
priv->burst_retry_timeout_source =
|
||||
nm_g_timeout_add_seconds_source((2 * RATELIMIT_INTERVAL_MSEC) / 1000,
|
||||
_burst_retry_timeout_cb,
|
||||
self);
|
||||
} else
|
||||
_LOGT("rate-limit: currently rate-limited from restart");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
priv->main_timeout_id = g_timeout_add(10000, spawn_timeout_cb, self);
|
||||
priv->main_timeout_source = nm_g_timeout_add_source(10000, spawn_timeout_cb, self);
|
||||
|
||||
priv->main_cancellable = g_cancellable_new();
|
||||
|
||||
_gl_pid_spawn(dm_binary, priv->main_cancellable, spawn_notify, self);
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1136,8 +1207,11 @@ update(NMDnsPlugin *plugin,
|
|||
nm_clear_pointer(&priv->set_server_ex_args, g_variant_unref);
|
||||
priv->set_server_ex_args =
|
||||
g_variant_ref_sink(create_update_args(self, global_config, ip_data_lst_head, hostdomain));
|
||||
priv->set_server_ex_args_dirty = TRUE;
|
||||
|
||||
send_dnsmasq_update(self);
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1151,11 +1225,13 @@ stop(NMDnsPlugin *plugin)
|
|||
|
||||
priv->is_stopped = TRUE;
|
||||
priv->burst_start_at = 0;
|
||||
nm_clear_g_source(&priv->burst_retry_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->burst_retry_timeout_source);
|
||||
|
||||
/* Cancelling the cancellable will also terminate the
|
||||
* process (in the background). */
|
||||
_main_cleanup(self, FALSE);
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1178,7 +1254,7 @@ dispose(GObject *object)
|
|||
|
||||
priv->is_stopped = TRUE;
|
||||
|
||||
nm_clear_g_source(&priv->burst_retry_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->burst_retry_timeout_source);
|
||||
|
||||
_main_cleanup(self, FALSE);
|
||||
|
||||
|
|
@ -1197,8 +1273,9 @@ nm_dns_dnsmasq_class_init(NMDnsDnsmasqClass *dns_class)
|
|||
|
||||
object_class->dispose = dispose;
|
||||
|
||||
plugin_class->plugin_name = "dnsmasq";
|
||||
plugin_class->is_caching = TRUE;
|
||||
plugin_class->stop = stop;
|
||||
plugin_class->update = update;
|
||||
plugin_class->plugin_name = "dnsmasq";
|
||||
plugin_class->is_caching = TRUE;
|
||||
plugin_class->stop = stop;
|
||||
plugin_class->update = update;
|
||||
plugin_class->get_update_pending = get_update_pending;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "libnm-glib-aux/nm-str-buf.h"
|
||||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "devices/nm-device.h"
|
||||
|
|
@ -35,7 +34,6 @@
|
|||
#include "nm-dns-dnsmasq.h"
|
||||
#include "nm-dns-plugin.h"
|
||||
#include "nm-dns-systemd-resolved.h"
|
||||
#include "nm-dns-unbound.h"
|
||||
#include "nm-ip-config.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-manager.h"
|
||||
|
|
@ -57,6 +55,8 @@
|
|||
#define HAS_NETCONFIG 1
|
||||
#endif
|
||||
|
||||
#define UPDATE_PENDING_UNBLOCK_TIMEOUT_MSEC 5000
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum { SR_SUCCESS, SR_NOTFOUND, SR_ERROR } SpawnResult;
|
||||
|
|
@ -78,7 +78,11 @@ enum {
|
|||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMDnsManager, PROP_MODE, PROP_RC_MANAGER, PROP_CONFIGURATION, );
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMDnsManager,
|
||||
PROP_MODE,
|
||||
PROP_RC_MANAGER,
|
||||
PROP_CONFIGURATION,
|
||||
PROP_UPDATE_PENDING, );
|
||||
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
|
|
@ -89,6 +93,11 @@ typedef struct {
|
|||
CList ip_data_lst_head;
|
||||
GVariant *config_variant;
|
||||
|
||||
/* A DNS plugin should not be marked as pending indefinitely.
|
||||
* We are only blocked if "update_pending" is TRUE and we have
|
||||
* "update_pending_unblock" timer ticking. */
|
||||
GSource *update_pending_unblock;
|
||||
|
||||
bool ip_data_lst_need_sort : 1;
|
||||
|
||||
bool configs_lst_need_sort : 1;
|
||||
|
|
@ -98,6 +107,8 @@ typedef struct {
|
|||
|
||||
bool config_changed : 1;
|
||||
|
||||
bool update_pending : 1;
|
||||
|
||||
char *hostdomain;
|
||||
guint updates_queue;
|
||||
|
||||
|
|
@ -109,6 +120,9 @@ typedef struct {
|
|||
NMDnsPlugin *sd_resolve_plugin;
|
||||
NMDnsPlugin *plugin;
|
||||
|
||||
gulong update_changed_signal_id_sd;
|
||||
gulong update_changed_signal_id;
|
||||
|
||||
NMConfig *config;
|
||||
|
||||
struct {
|
||||
|
|
@ -137,28 +151,23 @@ NM_DEFINE_SINGLETON_GETTER(NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER
|
|||
|
||||
#define _NMLOG_PREFIX_NAME "dns-mgr"
|
||||
#define _NMLOG_DOMAIN LOGD_DNS
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMLogLevel __level = (level); \
|
||||
\
|
||||
if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \
|
||||
char __prefix[20]; \
|
||||
const NMDnsManager *const __self = (self); \
|
||||
\
|
||||
_nm_log(__level, \
|
||||
_NMLOG_DOMAIN, \
|
||||
0, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
"%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
_NMLOG_PREFIX_NAME, \
|
||||
((!__self || __self == singleton_instance) \
|
||||
? "" \
|
||||
: nm_sprintf_buf(__prefix, "[%p]", __self)) \
|
||||
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
} \
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMLogLevel __level = (level); \
|
||||
\
|
||||
if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \
|
||||
_nm_unused const NMDnsManager *const __self = (self); \
|
||||
\
|
||||
_nm_log(__level, \
|
||||
_NMLOG_DOMAIN, \
|
||||
0, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
"%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
_NMLOG_PREFIX_NAME _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -207,6 +216,85 @@ static NM_UTILS_LOOKUP_STR_DEFINE(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_update_pending_detect(NMDnsManager *self)
|
||||
{
|
||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
if (priv->plugin && nm_dns_plugin_get_update_pending(priv->plugin))
|
||||
return TRUE;
|
||||
if (priv->sd_resolve_plugin && nm_dns_plugin_get_update_pending(priv->sd_resolve_plugin))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_update_pending_unblock_cb(gpointer user_data)
|
||||
{
|
||||
NMDnsManager *self = user_data;
|
||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
nm_assert(priv->update_pending);
|
||||
nm_assert(priv->update_pending_unblock);
|
||||
nm_assert(_update_pending_detect(self));
|
||||
|
||||
nm_clear_g_source_inst(&priv->update_pending_unblock);
|
||||
|
||||
_LOGW(
|
||||
"update-pending changed: DNS plugin did not become ready again. Assume something is wrong");
|
||||
|
||||
_notify(self, PROP_UPDATE_PENDING);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_pending_maybe_changed(NMDnsManager *self)
|
||||
{
|
||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
gboolean update_pending;
|
||||
|
||||
update_pending = _update_pending_detect(self);
|
||||
if (priv->update_pending == update_pending)
|
||||
return;
|
||||
|
||||
if (update_pending) {
|
||||
nm_assert(!priv->update_pending_unblock);
|
||||
priv->update_pending_unblock = nm_g_timeout_add_source(UPDATE_PENDING_UNBLOCK_TIMEOUT_MSEC,
|
||||
_update_pending_unblock_cb,
|
||||
self);
|
||||
} else
|
||||
nm_clear_g_source_inst(&priv->update_pending_unblock);
|
||||
|
||||
priv->update_pending = update_pending;
|
||||
_LOGD("update-pending changed: %spending", update_pending ? "" : "not ");
|
||||
_notify(self, PROP_UPDATE_PENDING);
|
||||
}
|
||||
|
||||
static void
|
||||
_update_pending_changed_cb(NMDnsPlugin *plugin, gboolean update_pending, NMDnsManager *self)
|
||||
{
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dns_manager_get_update_pending(NMDnsManager *self)
|
||||
{
|
||||
NMDnsManagerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE);
|
||||
|
||||
priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
nm_assert(priv->update_pending == _update_pending_detect(self));
|
||||
nm_assert(priv->update_pending || !priv->update_pending_unblock);
|
||||
|
||||
/* update-pending can only be TRUE for a certain time (before we assume
|
||||
* something is really wrong with the plugin). That is, as long as
|
||||
* update_pending_unblock is ticking. */
|
||||
return !!priv->update_pending_unblock;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_dns_config_ip_data_get_dns_priority1(const NML3ConfigData *l3cd, int addr_family)
|
||||
{
|
||||
|
|
@ -2015,7 +2103,7 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s
|
|||
domain = hostname;
|
||||
}
|
||||
|
||||
if (!nm_sd_hostname_is_valid(domain, FALSE))
|
||||
if (!nm_hostname_is_valid(domain, FALSE))
|
||||
domain = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -2120,6 +2208,7 @@ _clear_plugin(NMDnsManager *self)
|
|||
nm_clear_g_source(&priv->plugin_ratelimit.timer);
|
||||
|
||||
if (priv->plugin) {
|
||||
nm_clear_g_signal_handler(priv->plugin, &priv->update_changed_signal_id);
|
||||
nm_dns_plugin_stop(priv->plugin);
|
||||
g_clear_object(&priv->plugin);
|
||||
return TRUE;
|
||||
|
|
@ -2127,6 +2216,20 @@ _clear_plugin(NMDnsManager *self)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_clear_sd_resolved_plugin(NMDnsManager *self)
|
||||
{
|
||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
if (priv->sd_resolve_plugin) {
|
||||
nm_clear_g_signal_handler(priv->sd_resolve_plugin, &priv->update_changed_signal_id_sd);
|
||||
nm_dns_plugin_stop(priv->sd_resolve_plugin);
|
||||
g_clear_object(&priv->sd_resolve_plugin);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static NMDnsManagerResolvConfManager
|
||||
_check_resconf_immutable(NMDnsManagerResolvConfManager rc_manager)
|
||||
{
|
||||
|
|
@ -2313,16 +2416,14 @@ again:
|
|||
priv->plugin = nm_dns_dnsmasq_new();
|
||||
plugin_changed = TRUE;
|
||||
}
|
||||
} else if (nm_streq0(mode, "unbound")) {
|
||||
if (force_reload_plugin || !NM_IS_DNS_UNBOUND(priv->plugin)) {
|
||||
_clear_plugin(self);
|
||||
priv->plugin = nm_dns_unbound_new();
|
||||
plugin_changed = TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!NM_IN_STRSET(mode, "none", "default")) {
|
||||
if (mode)
|
||||
_LOGW("init: unknown dns mode '%s'", mode);
|
||||
if (mode) {
|
||||
if (nm_streq(mode, "unbound"))
|
||||
_LOGW("init: ns mode 'unbound' was removed. Update your configuration");
|
||||
else
|
||||
_LOGW("init: unknown dns mode '%s'", mode);
|
||||
}
|
||||
mode = "default";
|
||||
}
|
||||
if (_clear_plugin(self))
|
||||
|
|
@ -2359,7 +2460,7 @@ again:
|
|||
priv->sd_resolve_plugin = nm_dns_systemd_resolved_new();
|
||||
systemd_resolved_changed = TRUE;
|
||||
}
|
||||
} else if (nm_clear_g_object(&priv->sd_resolve_plugin))
|
||||
} else if (_clear_sd_resolved_plugin(self))
|
||||
systemd_resolved_changed = TRUE;
|
||||
|
||||
g_object_freeze_notify(G_OBJECT(self));
|
||||
|
|
@ -2390,6 +2491,23 @@ again:
|
|||
""));
|
||||
}
|
||||
|
||||
if (plugin_changed && priv->plugin && priv->update_changed_signal_id == 0) {
|
||||
priv->update_changed_signal_id = g_signal_connect(priv->plugin,
|
||||
NM_DNS_PLUGIN_UPDATE_PENDING_CHANGED,
|
||||
G_CALLBACK(_update_pending_changed_cb),
|
||||
self);
|
||||
}
|
||||
|
||||
if (systemd_resolved_changed && priv->sd_resolve_plugin
|
||||
&& priv->update_changed_signal_id_sd == 0) {
|
||||
priv->update_changed_signal_id_sd = g_signal_connect(priv->sd_resolve_plugin,
|
||||
NM_DNS_PLUGIN_UPDATE_PENDING_CHANGED,
|
||||
G_CALLBACK(_update_pending_changed_cb),
|
||||
self);
|
||||
}
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
|
||||
g_object_thaw_notify(G_OBJECT(self));
|
||||
}
|
||||
|
||||
|
|
@ -2594,6 +2712,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
|||
case PROP_CONFIGURATION:
|
||||
g_value_set_variant(value, _get_config_variant(self));
|
||||
break;
|
||||
case PROP_UPDATE_PENDING:
|
||||
g_value_set_boolean(value, nm_dns_manager_get_update_pending(self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -2641,9 +2762,11 @@ dispose(GObject *object)
|
|||
if (priv->config)
|
||||
g_signal_handlers_disconnect_by_func(priv->config, config_changed_cb, self);
|
||||
|
||||
g_clear_object(&priv->sd_resolve_plugin);
|
||||
_clear_sd_resolved_plugin(self);
|
||||
_clear_plugin(self);
|
||||
|
||||
nm_clear_g_source_inst(&priv->update_pending_unblock);
|
||||
|
||||
c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_data_lst_head, ip_data_lst)
|
||||
_dns_config_ip_data_free(ip_data);
|
||||
|
||||
|
|
@ -2719,6 +2842,13 @@ nm_dns_manager_class_init(NMDnsManagerClass *klass)
|
|||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_properties[PROP_UPDATE_PENDING] =
|
||||
g_param_spec_boolean(NM_DNS_MANAGER_UPDATE_PENDING,
|
||||
"",
|
||||
"",
|
||||
FALSE,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
|
||||
signals[CONFIG_CHANGED] = g_signal_new(NM_DNS_MANAGER_CONFIG_CHANGED,
|
||||
|
|
|
|||
|
|
@ -80,9 +80,10 @@ typedef struct _NMDnsConfigData {
|
|||
(G_TYPE_INSTANCE_GET_CLASS((o), NM_TYPE_DNS_MANAGER, NMDnsManagerClass))
|
||||
|
||||
/* properties */
|
||||
#define NM_DNS_MANAGER_MODE "mode"
|
||||
#define NM_DNS_MANAGER_RC_MANAGER "rc-manager"
|
||||
#define NM_DNS_MANAGER_CONFIGURATION "configuration"
|
||||
#define NM_DNS_MANAGER_MODE "mode"
|
||||
#define NM_DNS_MANAGER_RC_MANAGER "rc-manager"
|
||||
#define NM_DNS_MANAGER_CONFIGURATION "configuration"
|
||||
#define NM_DNS_MANAGER_UPDATE_PENDING "update-pending"
|
||||
|
||||
/* internal signals */
|
||||
#define NM_DNS_MANAGER_CONFIG_CHANGED "config-changed"
|
||||
|
|
@ -149,6 +150,8 @@ void nm_dns_manager_stop(NMDnsManager *self);
|
|||
|
||||
NMDnsPlugin *nm_dns_manager_get_systemd_resolved(NMDnsManager *self);
|
||||
|
||||
gboolean nm_dns_manager_get_update_pending(NMDnsManager *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
char *nmtst_dns_create_resolv_conf(const char *const *searches,
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum {
|
||||
UPDATE_PENDING_CHANGED,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
typedef struct _NMDnsPluginPrivate {
|
||||
GPid pid;
|
||||
guint watch_id;
|
||||
char *progname;
|
||||
char *pidfile;
|
||||
bool update_pending_inited : 1;
|
||||
bool update_pending : 1;
|
||||
} NMDnsPluginPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT)
|
||||
|
|
@ -32,26 +37,29 @@ G_DEFINE_ABSTRACT_TYPE(NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT)
|
|||
|
||||
#define _NMLOG_PREFIX_NAME "dns-plugin"
|
||||
#define _NMLOG_DOMAIN LOGD_DNS
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMLogLevel __level = (level); \
|
||||
\
|
||||
if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \
|
||||
char __prefix[20]; \
|
||||
const NMDnsPlugin *const __self = (self); \
|
||||
\
|
||||
_nm_log(__level, \
|
||||
_NMLOG_DOMAIN, \
|
||||
0, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
"%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
_NMLOG_PREFIX_NAME, \
|
||||
(!__self ? "" : nm_sprintf_buf(__prefix, "[%p]", __self)) \
|
||||
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
} \
|
||||
#define _NMLOG(level, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NMLogLevel __level = (level); \
|
||||
\
|
||||
if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \
|
||||
char __prefix[20]; \
|
||||
const NMDnsPlugin *const __self = (self); \
|
||||
\
|
||||
_nm_log(__level, \
|
||||
_NMLOG_DOMAIN, \
|
||||
0, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
"%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
_NMLOG_PREFIX_NAME, \
|
||||
(!__self ? "" \
|
||||
: nm_sprintf_buf(__prefix, \
|
||||
"[" NM_HASH_OBFUSCATE_PTR_FMT "]", \
|
||||
NM_HASH_OBFUSCATE_PTR( \
|
||||
__self))) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -104,10 +112,109 @@ nm_dns_plugin_stop(NMDnsPlugin *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_dns_plugin_init(NMDnsPlugin *self)
|
||||
{}
|
||||
static gboolean
|
||||
_get_update_pending(NMDnsPlugin *self)
|
||||
{
|
||||
NMDnsPluginClass *klass;
|
||||
|
||||
nm_assert(NM_IS_DNS_PLUGIN(self));
|
||||
|
||||
klass = NM_DNS_PLUGIN_GET_CLASS(self);
|
||||
if (klass->get_update_pending) {
|
||||
if (klass->get_update_pending(self))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dns_plugin_get_update_pending(NMDnsPlugin *self)
|
||||
{
|
||||
NMDnsPluginPrivate *priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_DNS_PLUGIN(self), FALSE);
|
||||
|
||||
priv = NM_DNS_PLUGIN_GET_PRIVATE(self);
|
||||
|
||||
/* We cache the boolean and rely on the subclass to call
|
||||
* _nm_dns_plugin_update_pending_maybe_changed(). The subclass
|
||||
* anyway must get it right to notify us when the value (maybe)
|
||||
* changes. By caching the value, the subclass is free to notify
|
||||
* even if the value did not actually change.
|
||||
*
|
||||
* Also, this allows the base implementation to combine multiple
|
||||
* sources/reasons (if we need that in the future). */
|
||||
|
||||
if (!priv->update_pending_inited) {
|
||||
priv->update_pending_inited = TRUE;
|
||||
priv->update_pending = _get_update_pending(self);
|
||||
_LOGD("[%s] update-pending changed (%spending)",
|
||||
nm_dns_plugin_get_name(self),
|
||||
priv->update_pending ? "" : "not ");
|
||||
} else
|
||||
nm_assert(priv->update_pending == _get_update_pending(self));
|
||||
|
||||
return priv->update_pending;
|
||||
}
|
||||
|
||||
void
|
||||
_nm_dns_plugin_update_pending_maybe_changed(NMDnsPlugin *self)
|
||||
{
|
||||
NMDnsPluginPrivate *priv;
|
||||
gboolean v;
|
||||
|
||||
g_return_if_fail(NM_IS_DNS_PLUGIN(self));
|
||||
|
||||
priv = NM_DNS_PLUGIN_GET_PRIVATE(self);
|
||||
|
||||
v = _get_update_pending(self);
|
||||
|
||||
if (!priv->update_pending_inited)
|
||||
priv->update_pending_inited = TRUE;
|
||||
else if (priv->update_pending == v)
|
||||
return;
|
||||
|
||||
priv->update_pending = v;
|
||||
|
||||
_LOGD("[%s] update-pending changed (%spending)",
|
||||
nm_dns_plugin_get_name(self),
|
||||
priv->update_pending ? "" : "not ");
|
||||
|
||||
g_signal_emit(self, signals[UPDATE_PENDING_CHANGED], 0, (gboolean) priv->update_pending);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_dns_plugin_class_init(NMDnsPluginClass *plugin_class)
|
||||
{}
|
||||
nm_dns_plugin_init(NMDnsPlugin *self)
|
||||
{
|
||||
NMDnsPluginPrivate *priv;
|
||||
|
||||
priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_DNS_PLUGIN, NMDnsPluginPrivate);
|
||||
|
||||
self->_priv = priv;
|
||||
|
||||
nm_assert(priv->update_pending_inited == FALSE);
|
||||
nm_assert(priv->update_pending == FALSE);
|
||||
|
||||
nm_shutdown_wait_obj_register_object(self, "dns-plugin");
|
||||
}
|
||||
|
||||
static void
|
||||
nm_dns_plugin_class_init(NMDnsPluginClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(NMDnsPluginPrivate));
|
||||
|
||||
signals[UPDATE_PENDING_CHANGED] = g_signal_new(NM_DNS_PLUGIN_UPDATE_PENDING_CHANGED,
|
||||
G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_BOOLEAN);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,13 @@
|
|||
#define NM_DNS_PLUGIN_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass))
|
||||
|
||||
#define NM_DNS_PLUGIN_UPDATE_PENDING_CHANGED "update-pending-changed"
|
||||
|
||||
struct _NMDnsPluginPrivate;
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
GObject parent;
|
||||
struct _NMDnsPluginPrivate *_priv;
|
||||
} NMDnsPlugin;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -39,6 +44,8 @@ typedef struct {
|
|||
|
||||
void (*stop)(NMDnsPlugin *self);
|
||||
|
||||
gboolean (*get_update_pending)(NMDnsPlugin *self);
|
||||
|
||||
const char *plugin_name;
|
||||
|
||||
/* Types should set to TRUE if they start a local caching nameserver
|
||||
|
|
@ -63,4 +70,8 @@ gboolean nm_dns_plugin_update(NMDnsPlugin *self,
|
|||
|
||||
void nm_dns_plugin_stop(NMDnsPlugin *self);
|
||||
|
||||
gboolean nm_dns_plugin_get_update_pending(NMDnsPlugin *self);
|
||||
|
||||
void _nm_dns_plugin_update_pending_maybe_changed(NMDnsPlugin *self);
|
||||
|
||||
#endif /* __NM_DNS_PLUGIN_H__ */
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ static const char *const DBUS_OP_SET_LINK_DNS_OVER_TLS = "SetLinkDNSOverTLS";
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int ifindex;
|
||||
CList configs_lst_head;
|
||||
int ifindex;
|
||||
GPtrArray *ip_data_list;
|
||||
} InterfaceConfig;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -50,6 +50,7 @@ typedef struct {
|
|||
GVariant *argument;
|
||||
NMDnsSystemdResolved *self;
|
||||
int ifindex;
|
||||
int ref_count;
|
||||
} RequestItem;
|
||||
|
||||
struct _NMDnsSystemdResolvedResolveHandle {
|
||||
|
|
@ -82,10 +83,13 @@ typedef struct {
|
|||
char *dbus_owner;
|
||||
CList handle_lst_head;
|
||||
guint name_owner_changed_id;
|
||||
guint n_pending;
|
||||
bool send_updates_warn_ratelimited : 1;
|
||||
bool try_start_blocked : 1;
|
||||
bool stopped : 1;
|
||||
bool dbus_initied : 1;
|
||||
bool send_updates_waiting : 1;
|
||||
bool update_pending : 1;
|
||||
/* These two variables ensure that the log is not spammed with
|
||||
* API (not) supported messages.
|
||||
* They can be removed when no distro uses systemd-resolved < v240 anymore
|
||||
|
|
@ -106,7 +110,7 @@ struct _NMDnsSystemdResolvedClass {
|
|||
G_DEFINE_TYPE(NMDnsSystemdResolved, nm_dns_systemd_resolved, NM_TYPE_DNS_PLUGIN)
|
||||
|
||||
#define NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self) \
|
||||
_NM_GET_PRIVATE(self, NMDnsSystemdResolved, NM_IS_DNS_SYSTEMD_RESOLVED)
|
||||
_NM_GET_PRIVATE(self, NMDnsSystemdResolved, NM_IS_DNS_SYSTEMD_RESOLVED, NMDnsPlugin)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -146,10 +150,88 @@ static void _resolve_start(NMDnsSystemdResolved *self, NMDnsSystemdResolvedResol
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_request_item_free(RequestItem *request_item)
|
||||
static gboolean
|
||||
_update_pending_detect(NMDnsSystemdResolved *self)
|
||||
{
|
||||
c_list_unlink_stale(&request_item->request_queue_lst);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
|
||||
if (priv->n_pending > 0) {
|
||||
/* we have pending calls. We definitely want to wait for them to complete. */
|
||||
return TRUE;
|
||||
}
|
||||
if (!priv->dbus_initied) {
|
||||
if (!priv->dbus_connection)
|
||||
return FALSE;
|
||||
/* D-Bus not yet initialized (and we don't know the name owner yet). Pending. */
|
||||
return TRUE;
|
||||
}
|
||||
if (priv->try_start_timeout_source) {
|
||||
/* We are waiting to D-Bus activate resolved. Pending. */
|
||||
return TRUE;
|
||||
}
|
||||
if (priv->try_start_blocked) {
|
||||
/* We earlier tried to start resolved, but are rate limited. We are not pending an update
|
||||
* (that we expect to complete any time soon). */
|
||||
return FALSE;
|
||||
}
|
||||
if (priv->send_updates_waiting) {
|
||||
/* we wait to send updates. We are pending. */
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_pending_maybe_changed(NMDnsSystemdResolved *self)
|
||||
{
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
gboolean update_pending;
|
||||
|
||||
/* Important: we need to make sure that we call _update_pending_maybe_changed(), when
|
||||
* the state changes. */
|
||||
|
||||
update_pending = _update_pending_detect(self);
|
||||
if (priv->update_pending != update_pending) {
|
||||
priv->update_pending = update_pending;
|
||||
_nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_update_pending(NMDnsPlugin *plugin)
|
||||
{
|
||||
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
|
||||
nm_assert(priv->update_pending == _update_pending_detect(self));
|
||||
return priv->update_pending;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static RequestItem *
|
||||
_request_item_ref(RequestItem *request_item)
|
||||
{
|
||||
nm_assert(request_item);
|
||||
nm_assert(request_item->ref_count > 0);
|
||||
nm_assert(request_item->ref_count < G_MAXINT);
|
||||
nm_assert(!c_list_is_empty(&request_item->request_queue_lst));
|
||||
|
||||
request_item->ref_count++;
|
||||
return request_item;
|
||||
}
|
||||
|
||||
static void
|
||||
_request_item_unref(RequestItem *request_item)
|
||||
{
|
||||
nm_assert(request_item);
|
||||
nm_assert(request_item->ref_count > 0);
|
||||
|
||||
if (--request_item->ref_count > 0)
|
||||
return;
|
||||
|
||||
nm_assert(c_list_is_empty(&request_item->request_queue_lst));
|
||||
|
||||
g_variant_unref(request_item->argument);
|
||||
nm_g_slice_free(request_item);
|
||||
}
|
||||
|
|
@ -165,6 +247,7 @@ _request_item_append(NMDnsSystemdResolved *self,
|
|||
|
||||
request_item = g_slice_new(RequestItem);
|
||||
*request_item = (RequestItem){
|
||||
.ref_count = 1,
|
||||
.operation = operation,
|
||||
.argument = g_variant_ref_sink(argument),
|
||||
.self = self,
|
||||
|
|
@ -178,8 +261,8 @@ _request_item_append(NMDnsSystemdResolved *self,
|
|||
static void
|
||||
_interface_config_free(InterfaceConfig *config)
|
||||
{
|
||||
nm_c_list_elem_free_all(&config->configs_lst_head, NULL);
|
||||
g_slice_free(InterfaceConfig, config);
|
||||
nm_g_ptr_array_unref(config->ip_data_list);
|
||||
nm_g_slice_free(config);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -191,42 +274,48 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data)
|
|||
NMDnsSystemdResolvedPrivate *priv;
|
||||
RequestItem *request_item;
|
||||
NMLogLevel log_level;
|
||||
|
||||
v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), r, &error);
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
return;
|
||||
const char *operation;
|
||||
int ifindex;
|
||||
|
||||
request_item = user_data;
|
||||
self = request_item->self;
|
||||
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
operation = request_item->operation;
|
||||
ifindex = request_item->ifindex;
|
||||
_request_item_unref(request_item);
|
||||
|
||||
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
|
||||
v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), r, &error);
|
||||
if (nm_utils_error_is_cancelled(error))
|
||||
goto out_dec_pending;
|
||||
|
||||
if (v) {
|
||||
if (request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE
|
||||
if (operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE
|
||||
&& priv->has_link_default_route == NM_TERNARY_DEFAULT) {
|
||||
priv->has_link_default_route = NM_TERNARY_TRUE;
|
||||
_LOGD("systemd-resolved support for SetLinkDefaultRoute(): API supported");
|
||||
}
|
||||
if (request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS
|
||||
if (operation == DBUS_OP_SET_LINK_DNS_OVER_TLS
|
||||
&& priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT) {
|
||||
priv->has_link_dns_over_tls = NM_TERNARY_TRUE;
|
||||
_LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API supported");
|
||||
}
|
||||
priv->send_updates_warn_ratelimited = FALSE;
|
||||
return;
|
||||
goto out_dec_pending;
|
||||
}
|
||||
|
||||
if (nm_g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
|
||||
if (priv->has_link_default_route == NM_TERNARY_DEFAULT
|
||||
&& request_item->operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) {
|
||||
&& operation == DBUS_OP_SET_LINK_DEFAULT_ROUTE) {
|
||||
priv->has_link_default_route = NM_TERNARY_FALSE;
|
||||
_LOGD("systemd-resolved support for SetLinkDefaultRoute(): API not supported");
|
||||
}
|
||||
if (priv->has_link_dns_over_tls == NM_TERNARY_DEFAULT
|
||||
&& request_item->operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) {
|
||||
&& operation == DBUS_OP_SET_LINK_DNS_OVER_TLS) {
|
||||
priv->has_link_dns_over_tls = NM_TERNARY_FALSE;
|
||||
_LOGD("systemd-resolved support for SetLinkDNSOverTLS(): API not supported");
|
||||
}
|
||||
return;
|
||||
goto out_dec_pending;
|
||||
}
|
||||
|
||||
log_level = LOGL_DEBUG;
|
||||
|
|
@ -234,18 +323,25 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data)
|
|||
priv->send_updates_warn_ratelimited = TRUE;
|
||||
log_level = LOGL_WARN;
|
||||
}
|
||||
_NMLOG(log_level,
|
||||
"send-updates %s@%d failed: %s",
|
||||
request_item->operation,
|
||||
request_item->ifindex,
|
||||
error->message);
|
||||
_NMLOG(log_level, "send-updates %s@%d failed: %s", operation, ifindex, error->message);
|
||||
|
||||
out_dec_pending:
|
||||
nm_assert(priv->n_pending > 0);
|
||||
if (--priv->n_pending <= 0) {
|
||||
_update_pending_maybe_changed(self);
|
||||
/* We keep @self alive while pending operations are in progress. It's simpler
|
||||
* to implement. But this requires that we implement "stop()" signal to cancel
|
||||
* all pending requests. Cancelling is necessary, because during shutdown,
|
||||
* we must wrap up fast, and not hang an undefined amount time. */
|
||||
g_object_unref(self);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_add_ip_config(NMDnsSystemdResolved *self,
|
||||
GVariantBuilder *dns,
|
||||
GVariantBuilder *domains,
|
||||
NMDnsConfigIPData *ip_data)
|
||||
update_add_ip_config(NMDnsSystemdResolved *self,
|
||||
GVariantBuilder *dns,
|
||||
GVariantBuilder *domains,
|
||||
const NMDnsConfigIPData *ip_data)
|
||||
{
|
||||
gsize addr_size;
|
||||
guint n;
|
||||
|
|
@ -258,8 +354,12 @@ update_add_ip_config(NMDnsSystemdResolved *self,
|
|||
addr_size = nm_utils_addr_family_to_size(ip_data->addr_family);
|
||||
|
||||
if ((!ip_data->domains.search || !ip_data->domains.search[0])
|
||||
&& !ip_data->domains.has_default_route_exclusive && !ip_data->domains.has_default_route)
|
||||
&& !ip_data->domains.has_default_route_exclusive && !ip_data->domains.has_default_route) {
|
||||
/* we have no search domain (which systemd-resolved uses to routing the request), but
|
||||
* also the "DefaultRoute" is not set on the interface. This setting has no effect and
|
||||
* gets ignored. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n);
|
||||
for (i = 0; i < n; i++) {
|
||||
|
|
@ -295,23 +395,28 @@ free_pending_updates(NMDnsSystemdResolved *self)
|
|||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
RequestItem *request_item;
|
||||
|
||||
while ((request_item =
|
||||
c_list_first_entry(&priv->request_queue_lst_head, RequestItem, request_queue_lst)))
|
||||
_request_item_free(request_item);
|
||||
while (
|
||||
(request_item =
|
||||
c_list_first_entry(&priv->request_queue_lst_head, RequestItem, request_queue_lst))) {
|
||||
c_list_unlink(&request_item->request_queue_lst);
|
||||
_request_item_unref(request_item);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
|
||||
prepare_one_interface(NMDnsSystemdResolved *self, const InterfaceConfig *ic)
|
||||
{
|
||||
GVariantBuilder dns;
|
||||
GVariantBuilder domains;
|
||||
NMCListElem *elem;
|
||||
NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
|
||||
NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
|
||||
NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT;
|
||||
const char *mdns_arg = NULL, *llmnr_arg = NULL, *dns_over_tls_arg = NULL;
|
||||
NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
|
||||
NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
|
||||
NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT;
|
||||
const char *mdns_arg = NULL;
|
||||
const char *llmnr_arg = NULL;
|
||||
const char *dns_over_tls_arg = NULL;
|
||||
gboolean has_config = FALSE;
|
||||
gboolean has_default_route = FALSE;
|
||||
guint i;
|
||||
|
||||
g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))"));
|
||||
g_variant_builder_add(&dns, "i", ic->ifindex);
|
||||
|
|
@ -321,18 +426,22 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
|
|||
g_variant_builder_add(&domains, "i", ic->ifindex);
|
||||
g_variant_builder_open(&domains, G_VARIANT_TYPE("a(sb)"));
|
||||
|
||||
c_list_for_each_entry (elem, &ic->configs_lst_head, lst) {
|
||||
NMDnsConfigIPData *ip_data = elem->data;
|
||||
if (ic->ip_data_list) {
|
||||
for (i = 0; i < ic->ip_data_list->len; i++) {
|
||||
const NMDnsConfigIPData *ip_data = ic->ip_data_list->pdata[i];
|
||||
|
||||
has_config |= update_add_ip_config(self, &dns, &domains, ip_data);
|
||||
if (update_add_ip_config(self, &dns, &domains, ip_data))
|
||||
has_config = TRUE;
|
||||
|
||||
if (ip_data->domains.has_default_route)
|
||||
has_default_route = TRUE;
|
||||
if (ip_data->domains.has_default_route)
|
||||
has_default_route = TRUE;
|
||||
|
||||
if (NM_IS_IPv4(ip_data->addr_family)) {
|
||||
mdns = NM_MAX(mdns, nm_l3_config_data_get_mdns(ip_data->l3cd));
|
||||
llmnr = NM_MAX(llmnr, nm_l3_config_data_get_llmnr(ip_data->l3cd));
|
||||
dns_over_tls = NM_MAX(dns_over_tls, nm_l3_config_data_get_dns_over_tls(ip_data->l3cd));
|
||||
if (NM_IS_IPv4(ip_data->addr_family)) {
|
||||
mdns = NM_MAX(mdns, nm_l3_config_data_get_mdns(ip_data->l3cd));
|
||||
llmnr = NM_MAX(llmnr, nm_l3_config_data_get_llmnr(ip_data->l3cd));
|
||||
dns_over_tls =
|
||||
NM_MAX(dns_over_tls, nm_l3_config_data_get_dns_over_tls(ip_data->l3cd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,6 +548,7 @@ again:
|
|||
goto again;
|
||||
}
|
||||
|
||||
_update_pending_maybe_changed(self);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
@ -447,6 +557,9 @@ ensure_resolved_running(NMDnsSystemdResolved *self)
|
|||
{
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
|
||||
if (priv->stopped)
|
||||
return NM_TERNARY_FALSE;
|
||||
|
||||
if (!priv->dbus_initied)
|
||||
return NM_TERNARY_DEFAULT;
|
||||
|
||||
|
|
@ -469,6 +582,7 @@ ensure_resolved_running(NMDnsSystemdResolved *self)
|
|||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
_update_pending_maybe_changed(self);
|
||||
return NM_TERNARY_DEFAULT;
|
||||
}
|
||||
|
||||
|
|
@ -523,6 +637,12 @@ send_updates(NMDnsSystemdResolved *self)
|
|||
request_item->operation,
|
||||
(ss = g_variant_print(request_item->argument, FALSE)));
|
||||
|
||||
if (priv->n_pending++ == 0) {
|
||||
/* We are inside send_updates(). All callers are already calling
|
||||
* _update_pending_maybe_changed() afterwards. */
|
||||
g_object_ref(self);
|
||||
}
|
||||
|
||||
g_dbus_connection_call(priv->dbus_connection,
|
||||
priv->dbus_owner,
|
||||
SYSTEMD_RESOLVED_DBUS_PATH,
|
||||
|
|
@ -534,7 +654,7 @@ send_updates(NMDnsSystemdResolved *self)
|
|||
-1,
|
||||
priv->cancellable,
|
||||
call_done,
|
||||
request_item);
|
||||
_request_item_ref(request_item));
|
||||
}
|
||||
|
||||
start_resolve:
|
||||
|
|
@ -554,43 +674,54 @@ update(NMDnsPlugin *plugin,
|
|||
const char *hostdomain,
|
||||
GError **error)
|
||||
{
|
||||
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
gs_unref_hashtable GHashTable *interfaces = NULL;
|
||||
gs_free gpointer *interfaces_keys = NULL;
|
||||
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
gs_unref_hashtable GHashTable *interfaces = NULL;
|
||||
const NMUtilsNamedValue *interfaces_arr;
|
||||
NMUtilsNamedValue interfaces_arr_stack[50];
|
||||
gs_free NMUtilsNamedValue *interfaces_arr_heap = NULL;
|
||||
guint interfaces_len;
|
||||
int ifindex;
|
||||
gpointer pointer;
|
||||
NMDnsConfigIPData *ip_data;
|
||||
GHashTableIter iter;
|
||||
gs_unref_array GArray *dirty_array = NULL;
|
||||
guint i;
|
||||
|
||||
nm_assert(!priv->stopped);
|
||||
|
||||
/* Group configs by ifindex/interfaces. */
|
||||
interfaces =
|
||||
g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _interface_config_free);
|
||||
|
||||
c_list_for_each_entry (ip_data, ip_data_lst_head, ip_data_lst) {
|
||||
InterfaceConfig *ic = NULL;
|
||||
InterfaceConfig *ic = NULL;
|
||||
int ifindex = ip_data->data->ifindex;
|
||||
|
||||
ifindex = ip_data->data->ifindex;
|
||||
nm_assert(ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd));
|
||||
|
||||
ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(ifindex));
|
||||
if (!ic) {
|
||||
ic = g_slice_new(InterfaceConfig);
|
||||
ic->ifindex = ifindex;
|
||||
c_list_init(&ic->configs_lst_head);
|
||||
ic = g_slice_new(InterfaceConfig);
|
||||
*ic = (InterfaceConfig){
|
||||
.ifindex = ifindex,
|
||||
.ip_data_list = g_ptr_array_sized_new(4),
|
||||
};
|
||||
g_hash_table_insert(interfaces, GINT_TO_POINTER(ifindex), ic);
|
||||
}
|
||||
|
||||
c_list_link_tail(&ic->configs_lst_head, &nm_c_list_elem_new_stale(ip_data)->lst);
|
||||
g_ptr_array_add(ic->ip_data_list, ip_data);
|
||||
}
|
||||
|
||||
free_pending_updates(self);
|
||||
|
||||
interfaces_keys =
|
||||
nm_utils_hash_keys_to_array(interfaces, nm_cmp_int2ptr_p_with_data, NULL, &interfaces_len);
|
||||
interfaces_arr = nm_utils_hash_to_array_with_buffer(interfaces,
|
||||
&interfaces_len,
|
||||
nm_cmp_int2ptr_p_with_data,
|
||||
NULL,
|
||||
interfaces_arr_stack,
|
||||
&interfaces_arr_heap);
|
||||
for (i = 0; i < interfaces_len; i++) {
|
||||
InterfaceConfig *ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(interfaces_keys[i]));
|
||||
const InterfaceConfig *ic = interfaces_arr[i].value_ptr;
|
||||
|
||||
if (prepare_one_interface(self, ic))
|
||||
g_hash_table_add(priv->dirty_interfaces, GINT_TO_POINTER(ic->ifindex));
|
||||
|
|
@ -602,23 +733,38 @@ update(NMDnsPlugin *plugin,
|
|||
* resolved, and the current update doesn't contain that interface,
|
||||
* reset the resolved configuration for that ifindex. */
|
||||
g_hash_table_iter_init(&iter, priv->dirty_interfaces);
|
||||
while (g_hash_table_iter_next(&iter, (gpointer *) &pointer, NULL)) {
|
||||
ifindex = GPOINTER_TO_INT(pointer);
|
||||
if (!g_hash_table_contains(interfaces, GINT_TO_POINTER(ifindex))) {
|
||||
while (g_hash_table_iter_next(&iter, &pointer, NULL)) {
|
||||
int ifindex = GPOINTER_TO_INT(pointer);
|
||||
|
||||
if (g_hash_table_contains(interfaces, GINT_TO_POINTER(ifindex))) {
|
||||
/* the interface is still tracked and still dirty. Keep. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dirty_array)
|
||||
dirty_array = g_array_new(FALSE, FALSE, sizeof(int));
|
||||
g_array_append_val(dirty_array, ifindex);
|
||||
|
||||
g_hash_table_iter_remove(&iter);
|
||||
}
|
||||
if (dirty_array) {
|
||||
g_array_sort_with_data(dirty_array, nm_cmp_int2ptr_p_with_data, NULL);
|
||||
for (i = 0; i < dirty_array->len; i++) {
|
||||
int ifindex = g_array_index(dirty_array, int, i);
|
||||
InterfaceConfig ic;
|
||||
|
||||
_LOGT("clear previously configured ifindex %d", ifindex);
|
||||
ic = (InterfaceConfig){
|
||||
.ifindex = ifindex,
|
||||
.configs_lst_head = C_LIST_INIT(ic.configs_lst_head),
|
||||
.ifindex = ifindex,
|
||||
.ip_data_list = NULL,
|
||||
};
|
||||
prepare_one_interface(self, &ic);
|
||||
g_hash_table_iter_remove(&iter);
|
||||
}
|
||||
}
|
||||
|
||||
priv->send_updates_waiting = TRUE;
|
||||
send_updates(self);
|
||||
_update_pending_maybe_changed(self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -649,6 +795,7 @@ name_owner_changed(NMDnsSystemdResolved *self, const char *owner)
|
|||
}
|
||||
|
||||
send_updates(self);
|
||||
_update_pending_maybe_changed(self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -956,6 +1103,48 @@ nm_dns_systemd_resolved_resolve_cancel(NMDnsSystemdResolvedResolveHandle *handle
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
stop(NMDnsPlugin *plugin)
|
||||
{
|
||||
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
NMDnsSystemdResolvedResolveHandle *handle;
|
||||
|
||||
/* This function must be re-entrant!!
|
||||
*
|
||||
* Currently there is no concept of unregistering/shutting down. It's not
|
||||
* clear whether we should de-configure anything in systemd-resolved, we
|
||||
* don't.
|
||||
*
|
||||
* Implementing stop() is important because pending operations take a
|
||||
* reference on @self. We can only cancel (fast shutdown) the instance
|
||||
* by cancelling those requests. */
|
||||
|
||||
priv->stopped = TRUE;
|
||||
priv->try_start_blocked = TRUE;
|
||||
|
||||
nm_clear_g_cancellable(&priv->cancellable);
|
||||
|
||||
nm_clear_g_free(&priv->dbus_owner);
|
||||
|
||||
while ((handle = c_list_first_entry(&priv->handle_lst_head,
|
||||
NMDnsSystemdResolvedResolveHandle,
|
||||
handle_lst))) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_utils_error_set_cancelled(&error, TRUE, "NMDnsSystemdResolved");
|
||||
_resolve_complete_error(handle, error);
|
||||
}
|
||||
|
||||
free_pending_updates(self);
|
||||
|
||||
nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id);
|
||||
|
||||
nm_clear_g_source_inst(&priv->try_start_timeout_source);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self)
|
||||
{
|
||||
|
|
@ -974,6 +1163,8 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self)
|
|||
return;
|
||||
}
|
||||
|
||||
priv->update_pending = TRUE;
|
||||
|
||||
priv->name_owner_changed_id =
|
||||
nm_dbus_connection_signal_subscribe_name_owner_changed(priv->dbus_connection,
|
||||
SYSTEMD_RESOLVED_DBUS_SERVICE,
|
||||
|
|
@ -998,33 +1189,15 @@ nm_dns_systemd_resolved_new(void)
|
|||
static void
|
||||
dispose(GObject *object)
|
||||
{
|
||||
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(object);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
NMDnsSystemdResolvedResolveHandle *handle;
|
||||
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(object);
|
||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
||||
|
||||
while ((handle = c_list_first_entry(&priv->handle_lst_head,
|
||||
NMDnsSystemdResolvedResolveHandle,
|
||||
handle_lst))) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_utils_error_set_cancelled(&error, TRUE, "NMDnsSystemdResolved");
|
||||
_resolve_complete_error(handle, error);
|
||||
}
|
||||
|
||||
free_pending_updates(self);
|
||||
|
||||
nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id);
|
||||
|
||||
nm_clear_g_cancellable(&priv->cancellable);
|
||||
|
||||
nm_clear_g_source_inst(&priv->try_start_timeout_source);
|
||||
stop(NM_DNS_PLUGIN(self));
|
||||
|
||||
g_clear_object(&priv->dbus_connection);
|
||||
nm_clear_pointer(&priv->dirty_interfaces, g_hash_table_unref);
|
||||
nm_clear_pointer(&priv->dirty_interfaces, g_hash_table_destroy);
|
||||
|
||||
G_OBJECT_CLASS(nm_dns_systemd_resolved_parent_class)->dispose(object);
|
||||
|
||||
nm_clear_g_free(&priv->dbus_owner);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1035,7 +1208,9 @@ nm_dns_systemd_resolved_class_init(NMDnsSystemdResolvedClass *dns_class)
|
|||
|
||||
object_class->dispose = dispose;
|
||||
|
||||
plugin_class->plugin_name = "systemd-resolved";
|
||||
plugin_class->is_caching = TRUE;
|
||||
plugin_class->update = update;
|
||||
plugin_class->plugin_name = "systemd-resolved";
|
||||
plugin_class->is_caching = TRUE;
|
||||
plugin_class->stop = stop;
|
||||
plugin_class->update = update;
|
||||
plugin_class->get_update_pending = get_update_pending;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
* Author: Pavel Šimerda <psimerda@redhat.com>
|
||||
*/
|
||||
|
||||
#include "src/core/nm-default-daemon.h"
|
||||
|
||||
#include "nm-dns-unbound.h"
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMDnsUnbound {
|
||||
NMDnsPlugin parent;
|
||||
};
|
||||
|
||||
struct _NMDnsUnboundClass {
|
||||
NMDnsPluginClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
update(NMDnsPlugin *plugin,
|
||||
const NMGlobalDnsConfig *global_config,
|
||||
const CList *ip_config_lst_head,
|
||||
const char *hostdomain,
|
||||
GError **error)
|
||||
{
|
||||
char *argv[] = {DNSSEC_TRIGGER_PATH, "--async", "--update", NULL};
|
||||
gs_free_error GError *local = NULL;
|
||||
int status;
|
||||
|
||||
/* TODO: We currently call a script installed with the dnssec-trigger
|
||||
* package that queries all information itself. Later, the dependency
|
||||
* on that package will be optional and the only hard dependency will
|
||||
* be unbound.
|
||||
*
|
||||
* Unbound configuration should be later handled by this plugin directly,
|
||||
* without calling custom scripts. The dnssec-trigger functionality
|
||||
* may be eventually merged into NetworkManager.
|
||||
*/
|
||||
if (!g_spawn_sync("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &local)) {
|
||||
nm_utils_error_set(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"error spawning dns-trigger: %s",
|
||||
local->message);
|
||||
return FALSE;
|
||||
}
|
||||
if (status != 0) {
|
||||
nm_utils_error_set(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"dns-trigger exited with error code %d",
|
||||
status);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_dns_unbound_init(NMDnsUnbound *unbound)
|
||||
{}
|
||||
|
||||
NMDnsPlugin *
|
||||
nm_dns_unbound_new(void)
|
||||
{
|
||||
return g_object_new(NM_TYPE_DNS_UNBOUND, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_dns_unbound_class_init(NMDnsUnboundClass *klass)
|
||||
{
|
||||
NMDnsPluginClass *plugin_class = NM_DNS_PLUGIN_CLASS(klass);
|
||||
|
||||
plugin_class->plugin_name = "unbound";
|
||||
plugin_class->is_caching = TRUE;
|
||||
plugin_class->update = update;
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_DNS_UNBOUND_H__
|
||||
#define __NETWORKMANAGER_DNS_UNBOUND_H__
|
||||
|
||||
#include "nm-dns-plugin.h"
|
||||
|
||||
#define NM_TYPE_DNS_UNBOUND (nm_dns_unbound_get_type())
|
||||
#define NM_DNS_UNBOUND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNS_UNBOUND, NMDnsUnbound))
|
||||
#define NM_DNS_UNBOUND_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DNS_UNBOUND, NMDnsUnboundClass))
|
||||
#define NM_IS_DNS_UNBOUND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DNS_UNBOUND))
|
||||
#define NM_IS_DNS_UNBOUND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DNS_UNBOUND))
|
||||
#define NM_DNS_UNBOUND_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DNS_UNBOUND, NMDnsUnboundClass))
|
||||
|
||||
typedef struct _NMDnsUnbound NMDnsUnbound;
|
||||
typedef struct _NMDnsUnboundClass NMDnsUnboundClass;
|
||||
|
||||
GType nm_dns_unbound_get_type(void);
|
||||
|
||||
NMDnsPlugin *nm_dns_unbound_new(void);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DNS_UNBOUND_H__ */
|
||||
|
|
@ -123,7 +123,6 @@ libNetworkManager = static_library(
|
|||
'dns/nm-dns-manager.c',
|
||||
'dns/nm-dns-plugin.c',
|
||||
'dns/nm-dns-systemd-resolved.c',
|
||||
'dns/nm-dns-unbound.c',
|
||||
'dnsmasq/nm-dnsmasq-manager.c',
|
||||
'dnsmasq/nm-dnsmasq-utils.c',
|
||||
'ppp/nm-ppp-manager-call.c',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "nm-utils.h"
|
||||
#include "nm-dhcp-config.h"
|
||||
#include "devices/nm-device.h"
|
||||
#include "dhcp/nm-dhcp-options.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "libnm-core-intern/nm-keyfile-internal.h"
|
||||
|
|
@ -2573,13 +2575,16 @@ nm_config_device_state_write(int ifindex,
|
|||
NMTernary nm_owned,
|
||||
guint32 route_metric_default_aspired,
|
||||
guint32 route_metric_default_effective,
|
||||
const char *next_server,
|
||||
const char *root_path,
|
||||
const char *dhcp_bootfile)
|
||||
NMDhcpConfig *dhcp4_config,
|
||||
NMDhcpConfig *dhcp6_config)
|
||||
{
|
||||
char path[NM_STRLEN(NM_CONFIG_DEVICE_STATE_DIR "/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
|
||||
GError *local = NULL;
|
||||
nm_auto_unref_keyfile GKeyFile *kf = NULL;
|
||||
GError *local = NULL;
|
||||
nm_auto_unref_keyfile GKeyFile *kf = NULL;
|
||||
const char *root_path = NULL;
|
||||
const char *next_server = NULL;
|
||||
const char *dhcp_bootfile = NULL;
|
||||
int IS_IPv4;
|
||||
|
||||
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||
g_return_val_if_fail(!connection_uuid || *connection_uuid, FALSE);
|
||||
|
|
@ -2630,6 +2635,15 @@ nm_config_device_state_write(int ifindex,
|
|||
route_metric_default_aspired);
|
||||
}
|
||||
}
|
||||
|
||||
if (dhcp4_config) {
|
||||
next_server = nm_dhcp_config_get_option(dhcp4_config, "next_server");
|
||||
root_path = nm_dhcp_config_get_option(dhcp4_config, "root_path");
|
||||
dhcp_bootfile = nm_dhcp_config_get_option(dhcp4_config, "filename");
|
||||
if (!dhcp_bootfile)
|
||||
dhcp_bootfile = nm_dhcp_config_get_option(dhcp4_config, "bootfile_name");
|
||||
}
|
||||
|
||||
if (next_server) {
|
||||
g_key_file_set_string(kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
|
|
@ -2649,6 +2663,28 @@ nm_config_device_state_write(int ifindex,
|
|||
dhcp_bootfile);
|
||||
}
|
||||
|
||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||
NMDhcpConfig *dhcp_config = IS_IPv4 ? dhcp4_config : dhcp6_config;
|
||||
gs_free NMUtilsNamedValue *values = NULL;
|
||||
guint i;
|
||||
guint num;
|
||||
|
||||
if (!dhcp_config)
|
||||
continue;
|
||||
|
||||
values = nm_dhcp_config_get_option_values(dhcp_config, &num);
|
||||
for (i = 0; i < num; i++) {
|
||||
gs_free char *name_full = NULL;
|
||||
const char *prefix = IS_IPv4 ? "dhcp4" : "dhcp6";
|
||||
|
||||
if (NM_STR_HAS_PREFIX(values[i].name, NM_DHCP_OPTION_REQPREFIX))
|
||||
continue;
|
||||
|
||||
name_full = g_strdup_printf("%s.%s", prefix, values[i].name);
|
||||
g_key_file_set_string(kf, prefix, name_full, values[i].value_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_key_file_save_to_file(kf, path, &local)) {
|
||||
_LOGW("device-state: write #%d (%s) failed: %s", ifindex, path, local->message);
|
||||
g_error_free(local);
|
||||
|
|
|
|||
|
|
@ -183,9 +183,8 @@ gboolean nm_config_device_state_write(int
|
|||
NMTernary nm_owned,
|
||||
guint32 route_metric_default_aspired,
|
||||
guint32 route_metric_default_effective,
|
||||
const char *next_server,
|
||||
const char *root_path,
|
||||
const char *dhcp_bootfile);
|
||||
NMDhcpConfig *dhcp4_config,
|
||||
NMDhcpConfig *dhcp6_config);
|
||||
|
||||
void nm_config_device_state_prune_stale(GHashTable *preserve_ifindexes,
|
||||
NMPlatform *preserve_in_platform);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include "libnm-glib-aux/nm-secret-utils.h"
|
||||
#include "libnm-glib-aux/nm-time-utils.h"
|
||||
#include "libnm-glib-aux/nm-str-buf.h"
|
||||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
#include "nm-utils.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-setting-connection.h"
|
||||
|
|
@ -5114,7 +5113,7 @@ nm_utils_spawn_helper(const char *const *args,
|
|||
fcntl(info->child_stdout, F_SETFL, fd_flags | O_NONBLOCK);
|
||||
|
||||
/* Watch process stdin */
|
||||
nm_str_buf_init(&info->out_buffer, 32, TRUE);
|
||||
info->out_buffer = NM_STR_BUF_INIT(32, TRUE);
|
||||
for (arg = args; *arg; arg++) {
|
||||
nm_str_buf_append(&info->out_buffer, *arg);
|
||||
nm_str_buf_append_c(&info->out_buffer, '\0');
|
||||
|
|
@ -5128,7 +5127,7 @@ nm_utils_spawn_helper(const char *const *args,
|
|||
g_source_attach(info->output_source, g_main_context_get_thread_default());
|
||||
|
||||
/* Watch process stdout */
|
||||
nm_str_buf_init(&info->in_buffer, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
|
||||
info->in_buffer = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
|
||||
info->input_source = nm_g_unix_fd_source_new(info->child_stdout,
|
||||
G_IO_IN | G_IO_ERR | G_IO_HUP,
|
||||
G_PRIORITY_DEFAULT,
|
||||
|
|
@ -5223,7 +5222,7 @@ again:
|
|||
* @shortened: (out) (transfer full): on return, the shortened hostname
|
||||
*
|
||||
* Checks whether the input hostname is valid. If not, tries to shorten it
|
||||
* to HOST_NAME_MAX or to the first dot, whatever comes earlier.
|
||||
* to HOST_NAME_MAX (64) or to the first dot, whatever comes earlier.
|
||||
* The new hostname is returned in @shortened.
|
||||
*
|
||||
* Returns: %TRUE if the input hostname was already valid or if was shortened
|
||||
|
|
@ -5239,7 +5238,7 @@ nm_utils_shorten_hostname(const char *hostname, char **shortened)
|
|||
nm_assert(hostname);
|
||||
nm_assert(shortened);
|
||||
|
||||
if (nm_sd_hostname_is_valid(hostname, FALSE)) {
|
||||
if (nm_hostname_is_valid(hostname, FALSE)) {
|
||||
*shortened = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -5249,11 +5248,11 @@ nm_utils_shorten_hostname(const char *hostname, char **shortened)
|
|||
l = (dot - hostname);
|
||||
else
|
||||
l = strlen(hostname);
|
||||
l = MIN(l, (gsize) HOST_NAME_MAX);
|
||||
l = MIN(l, (gsize) NM_HOST_NAME_MAX);
|
||||
|
||||
s = g_strndup(hostname, l);
|
||||
|
||||
if (!nm_sd_hostname_is_valid(s, FALSE)) {
|
||||
if (!nm_hostname_is_valid(s, FALSE)) {
|
||||
*shortened = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,29 @@ nm_dhcp_config_set_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd)
|
|||
_notify(self, PROP_OPTIONS);
|
||||
}
|
||||
|
||||
NMUtilsNamedValue *
|
||||
nm_dhcp_config_get_option_values(NMDhcpConfig *self, guint *num)
|
||||
{
|
||||
NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE(self);
|
||||
NMDhcpLease *lease;
|
||||
NMUtilsNamedValue *buffer = NULL;
|
||||
|
||||
if (!priv->l3cd) {
|
||||
NM_SET_OUT(num, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lease = nm_l3_config_data_get_dhcp_lease(priv->l3cd, nm_dhcp_config_get_addr_family(self));
|
||||
nm_utils_named_values_from_strdict_full(nm_dhcp_lease_get_options(lease),
|
||||
num,
|
||||
nm_strcmp_p_with_data,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
&buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_dhcp_config_get_option(NMDhcpConfig *self, const char *key)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ int nm_dhcp_config_get_addr_family(NMDhcpConfig *self);
|
|||
|
||||
void nm_dhcp_config_set_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd);
|
||||
|
||||
const char *nm_dhcp_config_get_option(NMDhcpConfig *self, const char *option);
|
||||
NMUtilsNamedValue *nm_dhcp_config_get_option_values(NMDhcpConfig *self, guint *num);
|
||||
const char *nm_dhcp_config_get_option(NMDhcpConfig *self, const char *option);
|
||||
|
||||
GVariant *nm_dhcp_config_get_options(NMDhcpConfig *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -679,8 +679,7 @@ _fw_nft_set(gboolean add, const char *ip_iface, in_addr_t addr, guint8 plen)
|
|||
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL,
|
||||
&ss1));
|
||||
|
||||
stdin_buf = g_bytes_new_static(nm_str_buf_get_str(&strbuf), strbuf.len);
|
||||
|
||||
stdin_buf = nm_str_buf_finalize_to_gbytes(&strbuf);
|
||||
_fw_nft_call_sync(stdin_buf, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "devices/nm-device-factory.h"
|
||||
#include "devices/nm-device-generic.h"
|
||||
#include "devices/nm-device.h"
|
||||
#include "dns/nm-dns-manager.h"
|
||||
#include "dhcp/nm-dhcp-manager.h"
|
||||
#include "libnm-core-aux-intern/nm-common-macros.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
|
|
@ -144,6 +145,9 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMManager,
|
|||
typedef struct {
|
||||
NMPlatform *platform;
|
||||
|
||||
NMDnsManager *dns_mgr;
|
||||
gulong dns_mgr_update_pending_signal_id;
|
||||
|
||||
GArray *capabilities;
|
||||
|
||||
CList active_connections_lst_head; /* Oldest ACs at the beginning */
|
||||
|
|
@ -346,6 +350,9 @@ static NMActiveConnection *_new_active_connection(NMManager *self,
|
|||
|
||||
static void policy_activating_ac_changed(GObject *object, GParamSpec *pspec, gpointer user_data);
|
||||
|
||||
static void device_has_pending_action_changed(NMDevice *device, GParamSpec *pspec, NMManager *self);
|
||||
static void check_if_startup_complete(NMManager *self);
|
||||
|
||||
static gboolean find_master(NMManager *self,
|
||||
NMConnection *connection,
|
||||
NMDevice *device,
|
||||
|
|
@ -1601,7 +1608,11 @@ manager_device_state_changed(NMDevice *device,
|
|||
nm_settings_device_added(priv->settings, device);
|
||||
}
|
||||
|
||||
static void device_has_pending_action_changed(NMDevice *device, GParamSpec *pspec, NMManager *self);
|
||||
static void
|
||||
_dns_mgr_update_pending_cb(NMDevice *device, GParamSpec *pspec, NMManager *self)
|
||||
{
|
||||
check_if_startup_complete(self);
|
||||
}
|
||||
|
||||
static void
|
||||
check_if_startup_complete(NMManager *self)
|
||||
|
|
@ -1616,6 +1627,20 @@ check_if_startup_complete(NMManager *self)
|
|||
if (!priv->devices_inited)
|
||||
return;
|
||||
|
||||
if (nm_dns_manager_get_update_pending(nm_manager_get_dns_manager(self))) {
|
||||
if (priv->dns_mgr_update_pending_signal_id == 0) {
|
||||
priv->dns_mgr_update_pending_signal_id =
|
||||
g_signal_connect(nm_manager_get_dns_manager(self),
|
||||
"notify::" NM_DNS_MANAGER_UPDATE_PENDING,
|
||||
G_CALLBACK(_dns_mgr_update_pending_cb),
|
||||
self);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nm_clear_g_signal_handler(nm_manager_get_dns_manager(self),
|
||||
&priv->dns_mgr_update_pending_signal_id);
|
||||
|
||||
c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
|
||||
reason = nm_device_has_pending_action_reason(device);
|
||||
if (reason) {
|
||||
|
|
@ -7014,10 +7039,6 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
|
|||
guint32 route_metric_default_aspired;
|
||||
guint32 route_metric_default_effective;
|
||||
NMTernary nm_owned;
|
||||
NMDhcpConfig *dhcp_config;
|
||||
const char *next_server = NULL;
|
||||
const char *root_path = NULL;
|
||||
const char *dhcp_bootfile = NULL;
|
||||
|
||||
NM_SET_OUT(out_ifindex, 0);
|
||||
|
||||
|
|
@ -7059,15 +7080,6 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
|
|||
TRUE,
|
||||
&route_metric_default_aspired);
|
||||
|
||||
dhcp_config = nm_device_get_dhcp_config(device, AF_INET);
|
||||
if (dhcp_config) {
|
||||
root_path = nm_dhcp_config_get_option(dhcp_config, "root_path");
|
||||
next_server = nm_dhcp_config_get_option(dhcp_config, "next_server");
|
||||
dhcp_bootfile = nm_dhcp_config_get_option(dhcp_config, "filename");
|
||||
if (!dhcp_bootfile)
|
||||
dhcp_bootfile = nm_dhcp_config_get_option(dhcp_config, "bootfile_name");
|
||||
}
|
||||
|
||||
if (!nm_config_device_state_write(ifindex,
|
||||
managed_type,
|
||||
perm_hw_addr_fake,
|
||||
|
|
@ -7075,9 +7087,8 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
|
|||
nm_owned,
|
||||
route_metric_default_aspired,
|
||||
route_metric_default_effective,
|
||||
next_server,
|
||||
root_path,
|
||||
dhcp_bootfile))
|
||||
nm_device_get_dhcp_config(device, AF_INET),
|
||||
nm_device_get_dhcp_config(device, AF_INET6)))
|
||||
return FALSE;
|
||||
|
||||
NM_SET_OUT(out_ifindex, ifindex);
|
||||
|
|
@ -7790,6 +7801,28 @@ impl_manager_checkpoint_adjust_rollback_timeout(NMDBusObject
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMDnsManager *
|
||||
nm_manager_get_dns_manager(NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_MANAGER(self), NULL);
|
||||
|
||||
priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
if (G_UNLIKELY(!priv->dns_mgr)) {
|
||||
/* Initialize lazily on first use.
|
||||
*
|
||||
* But keep a reference. This is to ensure proper lifetimes between
|
||||
* singleton instances (i.e. nm_dns_manager_get() outlives NMManager). */
|
||||
priv->dns_mgr = g_object_ref(nm_dns_manager_get());
|
||||
}
|
||||
|
||||
return priv->dns_mgr;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
auth_mgr_changed(NMAuthManager *auth_manager, gpointer user_data)
|
||||
{
|
||||
|
|
@ -8250,6 +8283,9 @@ dispose(GObject *object)
|
|||
g_clear_object(&priv->concheck_mgr);
|
||||
}
|
||||
|
||||
nm_clear_g_signal_handler(priv->dns_mgr, &priv->dns_mgr_update_pending_signal_id);
|
||||
g_clear_object(&priv->dns_mgr);
|
||||
|
||||
if (priv->auth_mgr) {
|
||||
g_signal_handlers_disconnect_by_func(priv->auth_mgr, G_CALLBACK(auth_mgr_changed), self);
|
||||
g_clear_object(&priv->auth_mgr);
|
||||
|
|
|
|||
|
|
@ -200,6 +200,10 @@ NMMetered nm_manager_get_metered(NMManager *self);
|
|||
|
||||
void nm_manager_notify_device_availability_maybe_changed(NMManager *self);
|
||||
|
||||
struct _NMDnsManager;
|
||||
|
||||
struct _NMDnsManager *nm_manager_get_dns_manager(NMManager *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_manager_device_auth_request(NMManager *self,
|
||||
|
|
|
|||
|
|
@ -389,15 +389,15 @@ typedef struct {
|
|||
gint64 startup_complete_start_timestamp_msec;
|
||||
GHashTable *startup_complete_idx;
|
||||
CList startup_complete_scd_lst_head;
|
||||
guint startup_complete_timeout_id;
|
||||
GSource *startup_complete_timeout_source;
|
||||
|
||||
GSource *kf_db_flush_idle_source_timestamps;
|
||||
GSource *kf_db_flush_idle_source_seen_bssids;
|
||||
|
||||
guint connections_len;
|
||||
|
||||
guint connections_generation;
|
||||
|
||||
guint kf_db_flush_idle_id_timestamps;
|
||||
guint kf_db_flush_idle_id_seen_bssids;
|
||||
|
||||
bool kf_db_pruned_timestamps;
|
||||
bool kf_db_pruned_seen_bssid;
|
||||
|
||||
|
|
@ -541,9 +541,9 @@ _startup_complete_timeout_cb(gpointer user_data)
|
|||
NMSettings *self = user_data;
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self);
|
||||
|
||||
priv->startup_complete_timeout_id = 0;
|
||||
nm_clear_g_source_inst(&priv->startup_complete_timeout_source);
|
||||
_startup_complete_check(self, 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -567,7 +567,7 @@ _startup_complete_check(NMSettings *self, gint64 now_msec)
|
|||
return;
|
||||
}
|
||||
|
||||
nm_clear_g_source(&priv->startup_complete_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->startup_complete_timeout_source);
|
||||
|
||||
if (c_list_is_empty(&priv->startup_complete_scd_lst_head))
|
||||
goto ready;
|
||||
|
|
@ -609,8 +609,10 @@ next_with_ready:
|
|||
|
||||
timeout_msec = priv->startup_complete_start_timestamp_msec + scd_not_ready->timeout_msec
|
||||
- nm_utils_get_monotonic_timestamp_msec();
|
||||
priv->startup_complete_timeout_id =
|
||||
g_timeout_add(NM_CLAMP(0, timeout_msec, 60000), _startup_complete_timeout_cb, self);
|
||||
priv->startup_complete_timeout_source =
|
||||
nm_g_timeout_add_source(NM_CLAMP(0, timeout_msec, 60000),
|
||||
_startup_complete_timeout_cb,
|
||||
self);
|
||||
_LOGT("startup-complete: wait for suitable device for connection \"%s\" (%s) which has "
|
||||
"\"connection.wait-device-timeout\" set",
|
||||
nm_settings_connection_get_id(scd_not_ready->sett_conn),
|
||||
|
|
@ -637,7 +639,7 @@ ready:
|
|||
_LOGT("startup-complete: ready, no more profiles to wait for");
|
||||
priv->startup_complete_start_timestamp_msec = 0;
|
||||
nm_assert(!priv->startup_complete_idx);
|
||||
nm_assert(priv->startup_complete_timeout_id == 0);
|
||||
nm_assert(!priv->startup_complete_timeout_source);
|
||||
_notify(self, PROP_STARTUP_COMPLETE);
|
||||
}
|
||||
|
||||
|
|
@ -3842,13 +3844,13 @@ _kf_db_got_dirty_flush(NMSettings *self, gboolean is_timestamps)
|
|||
NMKeyFileDB *kf_db;
|
||||
|
||||
if (is_timestamps) {
|
||||
prefix = "timestamps";
|
||||
kf_db = priv->kf_db_timestamps;
|
||||
priv->kf_db_flush_idle_id_timestamps = 0;
|
||||
prefix = "timestamps";
|
||||
kf_db = priv->kf_db_timestamps;
|
||||
nm_clear_g_source_inst(&priv->kf_db_flush_idle_source_timestamps);
|
||||
} else {
|
||||
prefix = "seen-bssids";
|
||||
kf_db = priv->kf_db_seen_bssids;
|
||||
priv->kf_db_flush_idle_id_seen_bssids = 0;
|
||||
prefix = "seen-bssids";
|
||||
kf_db = priv->kf_db_seen_bssids;
|
||||
nm_clear_g_source_inst(&priv->kf_db_flush_idle_source_seen_bssids);
|
||||
}
|
||||
|
||||
if (nm_key_file_db_is_dirty(kf_db))
|
||||
|
|
@ -3859,7 +3861,7 @@ _kf_db_got_dirty_flush(NMSettings *self, gboolean is_timestamps)
|
|||
nm_key_file_db_get_filename(kf_db));
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -3880,26 +3882,27 @@ _kf_db_got_dirty_fcn(NMKeyFileDB *kf_db, gpointer user_data)
|
|||
NMSettings *self = user_data;
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self);
|
||||
GSourceFunc idle_func;
|
||||
guint *p_id;
|
||||
GSource **p_source;
|
||||
const char *prefix;
|
||||
|
||||
if (priv->kf_db_timestamps == kf_db) {
|
||||
prefix = "timestamps";
|
||||
p_id = &priv->kf_db_flush_idle_id_timestamps;
|
||||
p_source = &priv->kf_db_flush_idle_source_timestamps;
|
||||
idle_func = _kf_db_got_dirty_flush_timestamps_cb;
|
||||
} else if (priv->kf_db_seen_bssids == kf_db) {
|
||||
prefix = "seen-bssids";
|
||||
p_id = &priv->kf_db_flush_idle_id_seen_bssids;
|
||||
p_source = &priv->kf_db_flush_idle_source_seen_bssids;
|
||||
idle_func = _kf_db_got_dirty_flush_seen_bssids_cb;
|
||||
} else {
|
||||
nm_assert_not_reached();
|
||||
return;
|
||||
}
|
||||
|
||||
if (*p_id != 0)
|
||||
if (*p_source)
|
||||
return;
|
||||
_LOGT("[%s-keyfile]: schedule flushing changes to disk", prefix);
|
||||
*p_id = g_idle_add_full(G_PRIORITY_LOW, idle_func, self, NULL);
|
||||
*p_source =
|
||||
nm_g_source_attach(nm_g_idle_source_new(G_PRIORITY_LOW, idle_func, self, NULL), NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -4100,7 +4103,7 @@ dispose(GObject *object)
|
|||
nm_assert(c_list_is_empty(&priv->sce_dirty_lst_head));
|
||||
nm_assert(g_hash_table_size(priv->sce_idx) == 0);
|
||||
|
||||
nm_clear_g_source(&priv->startup_complete_timeout_id);
|
||||
nm_clear_g_source_inst(&priv->startup_complete_timeout_source);
|
||||
nm_clear_pointer(&priv->startup_complete_idx, g_hash_table_destroy);
|
||||
nm_assert(c_list_is_empty(&priv->startup_complete_scd_lst_head));
|
||||
|
||||
|
|
@ -4154,8 +4157,8 @@ finalize(GObject *object)
|
|||
|
||||
g_clear_object(&priv->agent_mgr);
|
||||
|
||||
nm_clear_g_source(&priv->kf_db_flush_idle_id_timestamps);
|
||||
nm_clear_g_source(&priv->kf_db_flush_idle_id_seen_bssids);
|
||||
nm_clear_g_source_inst(&priv->kf_db_flush_idle_source_timestamps);
|
||||
nm_clear_g_source_inst(&priv->kf_db_flush_idle_source_seen_bssids);
|
||||
_kf_db_to_file(self, TRUE, FALSE);
|
||||
_kf_db_to_file(self, FALSE, FALSE);
|
||||
nm_key_file_db_destroy(priv->kf_db_timestamps);
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@
|
|||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "libnm-core-intern/nm-keyfile-internal.h"
|
||||
|
||||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
|
||||
#include "settings/nm-settings-plugin.h"
|
||||
#include "settings/nm-settings-storage.h"
|
||||
#include "settings/nm-settings-utils.h"
|
||||
|
|
@ -1247,9 +1245,9 @@ nms_keyfile_plugin_init(NMSKeyfilePlugin *plugin)
|
|||
/* dirname_libs are a set of read-only directories with lower priority than /etc or /run.
|
||||
* There is nothing complicated about having multiple of such directories, so dirname_libs
|
||||
* is a list (which currently only has at most one directory). */
|
||||
priv->dirname_libs[0] = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_LIB));
|
||||
priv->dirname_libs[0] = nm_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_LIB));
|
||||
priv->dirname_libs[1] = NULL;
|
||||
priv->dirname_run = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_RUN));
|
||||
priv->dirname_run = nm_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_RUN));
|
||||
priv->dirname_etc = nm_config_data_get_value(NM_CONFIG_GET_DATA_ORIG,
|
||||
NM_CONFIG_KEYFILE_GROUP_KEYFILE,
|
||||
NM_CONFIG_KEYFILE_KEY_KEYFILE_PATH,
|
||||
|
|
@ -1262,9 +1260,9 @@ nms_keyfile_plugin_init(NMSKeyfilePlugin *plugin)
|
|||
} else if (!priv->dirname_etc || priv->dirname_etc[0] != '/') {
|
||||
/* either invalid path or unspecified. Use the default. */
|
||||
g_free(priv->dirname_etc);
|
||||
priv->dirname_etc = nm_sd_utils_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_ETC_DEFAULT));
|
||||
priv->dirname_etc = nm_path_simplify(g_strdup(NM_KEYFILE_PATH_NAME_ETC_DEFAULT));
|
||||
} else
|
||||
nm_sd_utils_path_simplify(priv->dirname_etc);
|
||||
nm_path_simplify(priv->dirname_etc);
|
||||
|
||||
/* no duplicates */
|
||||
if (NM_IN_STRSET(priv->dirname_libs[0], priv->dirname_etc, priv->dirname_run))
|
||||
|
|
|
|||
|
|
@ -1924,6 +1924,7 @@ test_write_bridge_main(void)
|
|||
gs_unref_object NMConnection *connection = NULL;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingBridge *s_bridge;
|
||||
NMSettingWired *s_wired;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
NMSettingIPConfig *s_ip6;
|
||||
|
||||
|
|
@ -1953,6 +1954,11 @@ test_write_bridge_main(void)
|
|||
g_assert(s_bridge);
|
||||
nm_connection_add_setting(connection, NM_SETTING(s_bridge));
|
||||
|
||||
/* Ethernet setting */
|
||||
s_wired = (NMSettingWired *) nm_setting_wired_new();
|
||||
g_assert(s_wired);
|
||||
nm_connection_add_setting(connection, NM_SETTING(s_wired));
|
||||
|
||||
/* IP4 setting */
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
||||
g_assert(s_ip4);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-core-utils.h"
|
||||
#include "libnm-systemd-core/nm-sd-utils-core.h"
|
||||
|
||||
#include "dns/nm-dns-manager.h"
|
||||
#include "nm-connectivity.h"
|
||||
|
|
@ -2314,7 +2313,6 @@ test_dns_create_resolv_conf(void)
|
|||
static void
|
||||
test_machine_id_read(void)
|
||||
{
|
||||
NMUuid machine_id_sd;
|
||||
const NMUuid *machine_id;
|
||||
char machine_id_str[33];
|
||||
gpointer logstate;
|
||||
|
|
@ -2346,27 +2344,6 @@ test_machine_id_read(void)
|
|||
== machine_id_str);
|
||||
g_assert(strlen(machine_id_str) == 32);
|
||||
g_assert_cmpstr(machine_id_str, ==, nm_utils_machine_id_str());
|
||||
|
||||
/* double check with systemd's implementation... */
|
||||
if (!nm_sd_utils_id128_get_machine(&machine_id_sd)) {
|
||||
/* if systemd failed to read /etc/machine-id, the file likely
|
||||
* is invalid. Our machine-id is fake, and we have nothing to
|
||||
* compare against. */
|
||||
|
||||
if (g_file_test(LOCALSTATEDIR "/lib/dbus/machine-id", G_FILE_TEST_EXISTS)) {
|
||||
/* Hm. So systemd failed to read /etc/machine-id, but we may have the one from D-Bus.
|
||||
* With LOCALSTATEDIR"/lib/dbus/machine-id", we don't really know whether we
|
||||
* parsed that file. Assume we don't know and skip the test on this system. */
|
||||
g_assert(!nm_utils_machine_id_is_fake());
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK, in this case, our function should have generated a random machine ID. */
|
||||
g_assert(nm_utils_machine_id_is_fake());
|
||||
} else {
|
||||
g_assert(!nm_utils_machine_id_is_fake());
|
||||
g_assert_cmpmem(&machine_id_sd, sizeof(NMUuid), machine_id, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -12,27 +12,6 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_dhcp_create(void)
|
||||
{
|
||||
sd_dhcp_client *client4 = NULL;
|
||||
int r;
|
||||
|
||||
r = sd_dhcp_client_new(&client4, FALSE);
|
||||
g_assert(r == 0);
|
||||
g_assert(client4);
|
||||
|
||||
if (/* never true */ client4 == (gpointer) &r) {
|
||||
/* we don't want to call this, but ensure that the linker
|
||||
* includes all these symbols. */
|
||||
sd_dhcp_client_start(client4);
|
||||
}
|
||||
|
||||
sd_dhcp_client_unref(client4);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_lldp_create(void)
|
||||
{
|
||||
|
|
@ -119,141 +98,6 @@ test_sd_event(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_path_equal(void)
|
||||
{
|
||||
#define _path_equal_check(path, expected) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const char *_path0 = (path); \
|
||||
const char *_expected = (expected); \
|
||||
gs_free char *_path = g_strdup(_path0); \
|
||||
const char *_path_result; \
|
||||
\
|
||||
_path_result = nm_sd_utils_path_simplify(_path); \
|
||||
g_assert(_path_result == _path); \
|
||||
g_assert_cmpstr(_path, ==, _expected); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
_path_equal_check("", "");
|
||||
_path_equal_check(".", ".");
|
||||
_path_equal_check("..", "..");
|
||||
_path_equal_check("/..", "/..");
|
||||
_path_equal_check("//..", "/..");
|
||||
_path_equal_check("/.", "/");
|
||||
_path_equal_check("./", ".");
|
||||
_path_equal_check("./.", ".");
|
||||
_path_equal_check(".///.", ".");
|
||||
_path_equal_check(".///./", ".");
|
||||
_path_equal_check(".////", ".");
|
||||
_path_equal_check("//..//foo/", "/../foo");
|
||||
_path_equal_check("///foo//./bar/.", "/foo/bar");
|
||||
_path_equal_check(".//./foo//./bar/.", "foo/bar");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_test_unbase64char(char ch, gboolean maybe_invalid)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nm_sd_utils_unbase64char(ch, FALSE);
|
||||
|
||||
if (ch == '=') {
|
||||
g_assert(!maybe_invalid);
|
||||
g_assert_cmpint(r, <, 0);
|
||||
g_assert_cmpint(nm_sd_utils_unbase64char(ch, TRUE), ==, G_MAXINT);
|
||||
} else {
|
||||
g_assert_cmpint(r, ==, nm_sd_utils_unbase64char(ch, TRUE));
|
||||
if (r >= 0)
|
||||
g_assert_cmpint(r, <=, 255);
|
||||
if (!maybe_invalid)
|
||||
g_assert_cmpint(r, >=, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_test_unbase64mem_mem(const char *base64, const guint8 *expected_arr, gsize expected_len)
|
||||
{
|
||||
gs_free char *expected_base64 = NULL;
|
||||
int r;
|
||||
nm_auto_free guint8 *exp2_arr = NULL;
|
||||
nm_auto_free guint8 *exp3_arr = NULL;
|
||||
gsize exp2_len;
|
||||
gsize exp3_len;
|
||||
gsize i;
|
||||
|
||||
expected_base64 = g_base64_encode(expected_arr, expected_len);
|
||||
|
||||
for (i = 0; expected_base64[i]; i++)
|
||||
_test_unbase64char(expected_base64[i], FALSE);
|
||||
|
||||
r = nm_sd_utils_unbase64mem(expected_base64,
|
||||
strlen(expected_base64),
|
||||
TRUE,
|
||||
&exp2_arr,
|
||||
&exp2_len);
|
||||
g_assert_cmpint(r, ==, 0);
|
||||
g_assert_cmpmem(expected_arr, expected_len, exp2_arr, exp2_len);
|
||||
|
||||
if (!nm_streq(base64, expected_base64)) {
|
||||
r = nm_sd_utils_unbase64mem(base64, strlen(base64), TRUE, &exp3_arr, &exp3_len);
|
||||
g_assert_cmpint(r, ==, 0);
|
||||
g_assert_cmpmem(expected_arr, expected_len, exp3_arr, exp3_len);
|
||||
}
|
||||
}
|
||||
|
||||
#define _test_unbase64mem(base64, expected_str) \
|
||||
_test_unbase64mem_mem(base64, (const guint8 *) "" expected_str "", NM_STRLEN(expected_str))
|
||||
|
||||
static void
|
||||
_test_unbase64mem_inval(const char *base64)
|
||||
{
|
||||
gs_free guint8 *exp_arr = NULL;
|
||||
gsize exp_len = 0;
|
||||
int r;
|
||||
|
||||
r = nm_sd_utils_unbase64mem(base64, strlen(base64), TRUE, &exp_arr, &exp_len);
|
||||
g_assert_cmpint(r, <, 0);
|
||||
g_assert(!exp_arr);
|
||||
g_assert(exp_len == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nm_sd_utils_unbase64mem(void)
|
||||
{
|
||||
gs_free char *rnd_base64 = NULL;
|
||||
guint8 rnd_buf[30];
|
||||
guint i, rnd_len;
|
||||
|
||||
_test_unbase64mem("", "");
|
||||
_test_unbase64mem(" ", "");
|
||||
_test_unbase64mem(" Y Q == ", "a");
|
||||
_test_unbase64mem(" Y WJjZGV mZ 2g = ", "abcdefgh");
|
||||
_test_unbase64mem_inval(" Y %WJjZGV mZ 2g = ");
|
||||
_test_unbase64mem_inval(" Y %WJjZGV mZ 2g = a");
|
||||
_test_unbase64mem("YQ==", "a");
|
||||
_test_unbase64mem_inval("YQ==a");
|
||||
|
||||
rnd_len = nmtst_get_rand_uint32() % sizeof(rnd_buf);
|
||||
for (i = 0; i < rnd_len; i++)
|
||||
rnd_buf[i] = nmtst_get_rand_uint32() % 256;
|
||||
rnd_base64 = g_base64_encode(rnd_buf, rnd_len);
|
||||
_test_unbase64mem_mem(rnd_base64, rnd_buf, rnd_len);
|
||||
|
||||
_test_unbase64char('=', FALSE);
|
||||
for (i = 0; i < 10; i++) {
|
||||
char ch = nmtst_get_rand_uint32() % 256;
|
||||
|
||||
if (ch != '=')
|
||||
_test_unbase64char(ch, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
|
|
@ -261,11 +105,8 @@ main(int argc, char **argv)
|
|||
{
|
||||
nmtst_init(&argc, &argv, TRUE);
|
||||
|
||||
g_test_add_func("/systemd/dhcp/create", test_dhcp_create);
|
||||
g_test_add_func("/systemd/lldp/create", test_lldp_create);
|
||||
g_test_add_func("/systemd/sd-event", test_sd_event);
|
||||
g_test_add_func("/systemd/test_path_equal", test_path_equal);
|
||||
g_test_add_func("/systemd/test_nm_sd_utils_unbase64mem", test_nm_sd_utils_unbase64mem);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,8 +234,10 @@ test_shorten_hostname(void)
|
|||
* system configuration (`getconf HOST_NAME_MAX`). On Linux
|
||||
* it's typically 64 characters, but POSIX allows up to
|
||||
* 255 characters.
|
||||
*
|
||||
* We use our own define NM_HOST_NAME_MAX, which is always 64.
|
||||
*/
|
||||
maxhost = g_strnfill(HOST_NAME_MAX, 'a');
|
||||
maxhost = g_strnfill(NM_HOST_NAME_MAX, 'a');
|
||||
|
||||
do_test_shorten_hostname("name1", TRUE, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "nm-checkpoint.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-dbus-helpers.h"
|
||||
#include "nm-wifi-p2p-peer.h"
|
||||
#include "nm-device-6lowpan.h"
|
||||
#include "nm-device-adsl.h"
|
||||
#include "nm-device-bond.h"
|
||||
|
|
@ -33,7 +34,6 @@
|
|||
#include "nm-device-macsec.h"
|
||||
#include "nm-device-macvlan.h"
|
||||
#include "nm-device-modem.h"
|
||||
#include "nm-device-olpc-mesh.h"
|
||||
#include "nm-device-ovs-bridge.h"
|
||||
#include "nm-device-ovs-interface.h"
|
||||
#include "nm-device-ovs-port.h"
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
#include "nm-device-wifi.h"
|
||||
#include "nm-device-wireguard.h"
|
||||
#include "nm-device-wpan.h"
|
||||
#include "nm-device-olpc-mesh.h"
|
||||
#include "nm-dhcp-config.h"
|
||||
#include "nm-dhcp4-config.h"
|
||||
#include "nm-dhcp6-config.h"
|
||||
|
|
@ -56,7 +57,6 @@
|
|||
#include "nm-remote-connection.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-vpn-connection.h"
|
||||
#include "nm-wifi-p2p-peer.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -8399,9 +8399,9 @@ nm_client_class_init(NMClientClass *client_class)
|
|||
*
|
||||
* Whether a connectivity checking service has been enabled.
|
||||
*
|
||||
* Since: 1.10
|
||||
*
|
||||
* The property setter is a synchronous D-Bus call. This is deprecated since 1.22.
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
obj_properties[PROP_CONNECTIVITY_CHECK_ENABLED] =
|
||||
g_param_spec_boolean(NM_CLIENT_CONNECTIVITY_CHECK_ENABLED,
|
||||
|
|
@ -8729,7 +8729,7 @@ nm_client_class_init(NMClientClass *client_class)
|
|||
G_TYPE_UINT);
|
||||
/**
|
||||
* NMClient::connection-added:
|
||||
* @client: the settings object that received the signal
|
||||
* @client: the client that received the signal
|
||||
* @connection: the new connection
|
||||
*
|
||||
* Notifies that a #NMConnection has been added.
|
||||
|
|
@ -8747,7 +8747,7 @@ nm_client_class_init(NMClientClass *client_class)
|
|||
|
||||
/**
|
||||
* NMClient::connection-removed:
|
||||
* @client: the settings object that received the signal
|
||||
* @client: the client that received the signal
|
||||
* @connection: the removed connection
|
||||
*
|
||||
* Notifies that a #NMConnection has been removed.
|
||||
|
|
@ -8765,7 +8765,7 @@ nm_client_class_init(NMClientClass *client_class)
|
|||
|
||||
/**
|
||||
* NMClient::active-connection-added:
|
||||
* @client: the settings object that received the signal
|
||||
* @client: the client that received the signal
|
||||
* @active_connection: the new active connection
|
||||
*
|
||||
* Notifies that a #NMActiveConnection has been added.
|
||||
|
|
@ -8783,7 +8783,7 @@ nm_client_class_init(NMClientClass *client_class)
|
|||
|
||||
/**
|
||||
* NMClient::active-connection-removed:
|
||||
* @client: the settings object that received the signal
|
||||
* @client: the client that received the signal
|
||||
* @active_connection: the removed active connection
|
||||
*
|
||||
* Notifies that a #NMActiveConnection has been removed.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,16 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#include "nm-version.h"
|
||||
#include "nm-dbus-interface.h"
|
||||
#include "nm-dhcp-config.h"
|
||||
#include "nm-ip-config.h"
|
||||
#include "nm-connection.h"
|
||||
#include "nm-remote-connection.h"
|
||||
#include "nm-active-connection.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-checkpoint.h"
|
||||
#include "nm-client.h"
|
||||
#include "nm-vpn-connection.h"
|
||||
#include "nm-libnm-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -120,11 +120,11 @@ nm_device_macvlan_get_tap(NMDeviceMacvlan *device)
|
|||
* Returns: the hardware address. This is the internal string used by the
|
||||
* device, and must not be modified.
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* This property is not implemented yet, and the function always return NULL.
|
||||
*
|
||||
* Deprecated: 1.24: Use nm_device_get_hw_address() instead.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
const char *
|
||||
nm_device_macvlan_get_hw_address(NMDeviceMacvlan *device)
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@
|
|||
|
||||
#include "libnm-client-impl/nm-default-libnm.h"
|
||||
|
||||
#include "nm-access-point.h"
|
||||
#include "nm-device-wifi.h"
|
||||
#include "nm-device-olpc-mesh.h"
|
||||
|
||||
#include "nm-setting-connection.h"
|
||||
#include "nm-setting-olpc-mesh.h"
|
||||
#include "nm-object-private.h"
|
||||
#include "nm-device-wifi.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ nm_device_vxlan_get_hw_address(NMDeviceVxlan *device)
|
|||
*
|
||||
* Returns: %TRUE if the device has carrier.
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* This property is not implemented yet, and the function always returns
|
||||
* FALSE.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
gboolean
|
||||
nm_device_vxlan_get_carrier(NMDeviceVxlan *device)
|
||||
|
|
@ -541,9 +541,9 @@ nm_device_vxlan_class_init(NMDeviceVxlanClass *klass)
|
|||
*
|
||||
* Whether the device has carrier.
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* This property is not implemented yet, and the property is always FALSE.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
obj_properties[PROP_CARRIER] = g_param_spec_boolean(NM_DEVICE_VXLAN_CARRIER,
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
|
||||
#include "libnm-client-impl/nm-default-libnm.h"
|
||||
|
||||
#include "nm-wifi-p2p-peer.h"
|
||||
#include "nm-device-wifi-p2p.h"
|
||||
|
||||
#include "libnm-glib-aux/nm-dbus-aux.h"
|
||||
#include "nm-setting-connection.h"
|
||||
#include "nm-setting-wifi-p2p.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-wifi-p2p-peer.h"
|
||||
#include "nm-object-private.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-dbus-helpers.h"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "libnm-client-impl/nm-default-libnm.h"
|
||||
|
||||
#include "nm-access-point.h"
|
||||
#include "nm-device-wifi.h"
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
|
|
@ -15,7 +16,6 @@
|
|||
#include "nm-setting-wireless.h"
|
||||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-access-point.h"
|
||||
#include "nm-object-private.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-dbus-helpers.h"
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
|
||||
#include "libnm-client-impl/nm-default-libnm.h"
|
||||
|
||||
#include "nm-device-wimax.h"
|
||||
|
||||
#include "nm-wimax-nsp.h"
|
||||
#include "nm-device-wimax.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,8 @@
|
|||
#define __NM_LIBNM_UTILS_H__
|
||||
|
||||
#include "c-list/src/c-list.h"
|
||||
#include "nm-device.h"
|
||||
#include "libnm-glib-aux/nm-ref-string.h"
|
||||
#include "libnm-glib-aux/nm-logging-fwd.h"
|
||||
#include "nm-types.h"
|
||||
#include "nm-object.h"
|
||||
#include "nm-client.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -8,48 +8,19 @@
|
|||
|
||||
#define __NETWORKMANAGER_H_INSIDE__
|
||||
|
||||
#include "nm-access-point.h"
|
||||
#include "nm-active-connection.h"
|
||||
#include "nm-client.h"
|
||||
#include "nm-connection.h"
|
||||
#include "nm-core-enum-types.h"
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "nm-version.h"
|
||||
#include "nm-dbus-interface.h"
|
||||
#include "nm-device-6lowpan.h"
|
||||
#include "nm-device-adsl.h"
|
||||
#include "nm-device-bond.h"
|
||||
#include "nm-device-bridge.h"
|
||||
#include "nm-device-bt.h"
|
||||
#include "nm-device-dummy.h"
|
||||
#include "nm-device-ethernet.h"
|
||||
#include "nm-device-generic.h"
|
||||
#include "nm-device-infiniband.h"
|
||||
#include "nm-device-ip-tunnel.h"
|
||||
#include "nm-device-macsec.h"
|
||||
#include "nm-device-macvlan.h"
|
||||
#include "nm-device-modem.h"
|
||||
#include "nm-device-olpc-mesh.h"
|
||||
#include "nm-device-ovs-bridge.h"
|
||||
#include "nm-device-ovs-interface.h"
|
||||
#include "nm-device-ovs-port.h"
|
||||
#include "nm-device-ppp.h"
|
||||
#include "nm-device-team.h"
|
||||
#include "nm-device-tun.h"
|
||||
#include "nm-device-veth.h"
|
||||
#include "nm-device-vlan.h"
|
||||
#include "nm-device-vxlan.h"
|
||||
#include "nm-device-wifi-p2p.h"
|
||||
#include "nm-device-wifi.h"
|
||||
#include "nm-device-wimax.h"
|
||||
#include "nm-device-wireguard.h"
|
||||
#include "nm-device-wpan.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-dhcp-config.h"
|
||||
#include "nm-enum-types.h"
|
||||
#include "nm-ethtool-utils.h"
|
||||
#include "nm-ip-config.h"
|
||||
|
||||
#include "nm-core-enum-types.h"
|
||||
|
||||
#include "nm-connection.h"
|
||||
#include "nm-simple-connection.h"
|
||||
#include "nm-keyfile.h"
|
||||
#include "nm-object.h"
|
||||
#include "nm-remote-connection.h"
|
||||
#include "nm-setting.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
#include "nm-setting-6lowpan.h"
|
||||
#include "nm-setting-8021x.h"
|
||||
#include "nm-setting-adsl.h"
|
||||
|
|
@ -102,18 +73,59 @@
|
|||
#include "nm-setting-wireless.h"
|
||||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-setting-wpan.h"
|
||||
#include "nm-setting.h"
|
||||
#include "nm-simple-connection.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-version.h"
|
||||
#include "nm-vpn-connection.h"
|
||||
|
||||
#include "nm-vpn-dbus-interface.h"
|
||||
#include "nm-vpn-editor.h"
|
||||
#include "nm-vpn-editor-plugin.h"
|
||||
#include "nm-vpn-plugin-info.h"
|
||||
#include "nm-vpn-service-plugin.h"
|
||||
#include "nm-vpn-editor-plugin.h"
|
||||
|
||||
#include "nm-enum-types.h"
|
||||
|
||||
#include "nm-ethtool-utils.h"
|
||||
|
||||
#include "nm-object.h"
|
||||
#include "nm-dhcp-config.h"
|
||||
#include "nm-ip-config.h"
|
||||
#include "nm-remote-connection.h"
|
||||
#include "nm-active-connection.h"
|
||||
#include "nm-checkpoint.h"
|
||||
#include "nm-access-point.h"
|
||||
#include "nm-wifi-p2p-peer.h"
|
||||
#include "nm-wimax-nsp.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-vpn-connection.h"
|
||||
#include "nm-vpn-editor.h"
|
||||
#include "nm-vpn-service-plugin.h"
|
||||
|
||||
#include "nm-client.h"
|
||||
|
||||
#include "nm-device-6lowpan.h"
|
||||
#include "nm-device-adsl.h"
|
||||
#include "nm-device-bond.h"
|
||||
#include "nm-device-bridge.h"
|
||||
#include "nm-device-bt.h"
|
||||
#include "nm-device-dummy.h"
|
||||
#include "nm-device-ethernet.h"
|
||||
#include "nm-device-generic.h"
|
||||
#include "nm-device-infiniband.h"
|
||||
#include "nm-device-ip-tunnel.h"
|
||||
#include "nm-device-macsec.h"
|
||||
#include "nm-device-macvlan.h"
|
||||
#include "nm-device-modem.h"
|
||||
#include "nm-device-ovs-bridge.h"
|
||||
#include "nm-device-ovs-interface.h"
|
||||
#include "nm-device-ovs-port.h"
|
||||
#include "nm-device-ppp.h"
|
||||
#include "nm-device-team.h"
|
||||
#include "nm-device-tun.h"
|
||||
#include "nm-device-veth.h"
|
||||
#include "nm-device-vlan.h"
|
||||
#include "nm-device-vxlan.h"
|
||||
#include "nm-device-wifi.h"
|
||||
#include "nm-device-wifi-p2p.h"
|
||||
#include "nm-device-olpc-mesh.h"
|
||||
#include "nm-device-wimax.h"
|
||||
#include "nm-device-wireguard.h"
|
||||
#include "nm-device-wpan.h"
|
||||
|
||||
#include "nm-autoptr.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ libnm_client_headers = files(
|
|||
'nm-object.h',
|
||||
'nm-remote-connection.h',
|
||||
'nm-secret-agent-old.h',
|
||||
'nm-types.h',
|
||||
'nm-vpn-connection.h',
|
||||
'nm-vpn-editor.h',
|
||||
'nm-vpn-plugin-old.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