Skip to content

Commit

Permalink
dhcpcd: fix to work with systemd
Browse files Browse the repository at this point in the history
Currently, dhcpcd does not work well with systemd. When using dhcpcd
to configure network, the /etc/resolv.conf contents are not correct.
This issue could easily be reproduced by using 'qemu + slirp' to
start a systemd based image and using dhcpcd to configure network.
The expected 'nameserver 10.0.2.3' is not in /etc/resolv.conf.

The root cause of this problem is that dhcpcd assumes the resolvconf
should recognize .protocol suffix[1]. But systemd's resolvconf (which
is a symlink to resolvectl) has a limited support for traditional
resolvconf interface[2], and "may not work with all clients"[3]. This
of cource includes the clients that use the .protocol suffix.

The current situation is:
1. systemd is not going to support the .protocol suffix in the foreseeable
   near future[4].
2. dhcpcd does not want to merge systemd specific patch and insists
   systemd needs to consider the .protocol suffix[5][6].

It's a normal thing that people have different opinions. As a build system
that supports such combination, however, we do need to come up with a
solution to fix this typical integration problem, making dhcpcd and systemd
work together.

This patch solves this integration problem by relying on dhcpcd's ability
to manage its own resolv.conf contents. But instead of letting it to write
to /etc/resolv.conf directly, we supply the generated contents to resolvconf.
In this way, the resolvconf still stands in the central place and dhcpcd remains
a supplier to it. And the /etc/resolv.conf can get the correct contents.
With this patch, dhcpcd could work with both sysvinit and systemd.

[1] https://man.archlinux.org/man/resolvconf.8.en
[2] https://man.archlinux.org/man/resolvectl.1#COMPATIBILITY_WITH_RESOLVCONF(8)
[3] https://wiki.archlinux.org/title/systemd-resolved
[4] systemd/systemd#25032
[5] NetworkConfiguration/dhcpcd#152
[6] NetworkConfiguration/dhcpcd#146

(From OE-Core rev: ab4cc3bc44a9cf5f15fcf1f5dcda1aa5b61b325a)

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
  • Loading branch information
ChenQi1989 authored and alexandrebelloni committed Nov 18, 2022
1 parent ab4bd28 commit 98134b0
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
1 change: 1 addition & 0 deletions meta/recipes-connectivity/dhcpcd/dhcpcd_9.4.1.bb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ UPSTREAM_CHECK_URI = "https://roy.marples.name/downloads/dhcpcd/"

SRC_URI = "https://roy.marples.name/downloads/${BPN}/${BPN}-${PV}.tar.xz \
file://0001-remove-INCLUDEDIR-to-prevent-build-issues.patch \
file://0001-20-resolv.conf-improve-the-sitation-of-working-with-.patch \
file://dhcpcd.service \
file://dhcpcd@.service \
"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
From 02acc4d875ee81e6fd19ef66d69c9f55b4b4a7e7 Mon Sep 17 00:00:00 2001
From: Chen Qi <Qi.Chen@windriver.com>
Date: Wed, 9 Nov 2022 16:33:18 +0800
Subject: [PATCH] 20-resolv.conf: improve the sitation of working with systemd

systemd's resolvconf implementation ignores the protocol part.
See https://github.com/systemd/systemd/issues/25032.

When using 'dhcp server + dns server + dhcpcd + systemd', we
get an integration issue, that is dhcpcd runs 'resolvconf -d eth0.ra',
yet systemd's resolvconf treats it as eth0. This will delete the
DNS information set by 'resolvconf -a eth0.dhcp'.

Fortunately, 20-resolv.conf has the ability to build the resolv.conf
file contents itself. We can just pass the generated contents to
systemd's resolvconf. This way, the DNS information is not incorrectly
deleted. Also, it does not cause behavior regression for dhcpcd
in other cases.

Upstream-Status: Inappropriate [OE Specific]
This patch has been rejected by dhcpcd upstream.
See details in https://github.com/NetworkConfiguration/dhcpcd/pull/152

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
---
hooks/20-resolv.conf | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/hooks/20-resolv.conf b/hooks/20-resolv.conf
index 504a6c53..eb6e5845 100644
--- a/hooks/20-resolv.conf
+++ b/hooks/20-resolv.conf
@@ -11,8 +11,12 @@ nocarrier_roaming_dir="$state_dir/roaming"
NL="
"
: ${resolvconf:=resolvconf}
+resolvconf_from_systemd=false
if type "$resolvconf" >/dev/null 2>&1; then
have_resolvconf=true
+ if [ $(basename $(readlink -f $(which $resolvconf))) = resolvectl ]; then
+ resolvconf_from_systemd=true
+ fi
else
have_resolvconf=false
fi
@@ -69,8 +73,13 @@ build_resolv_conf()
else
echo "# /etc/resolv.conf.tail can replace this line" >> "$cf"
fi
- if change_file /etc/resolv.conf "$cf"; then
- chmod 644 /etc/resolv.conf
+ if $resolvconf_from_systemd; then
+ [ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
+ "$resolvconf" -a "$ifname" <"$cf"
+ else
+ if change_file /etc/resolv.conf "$cf"; then
+ chmod 644 /etc/resolv.conf
+ fi
fi
rm -f "$cf"
}
@@ -170,7 +179,7 @@ add_resolv_conf()
for x in ${new_domain_name_servers}; do
conf="${conf}nameserver $x$NL"
done
- if $have_resolvconf; then
+ if $have_resolvconf && ! $resolvconf_from_systemd; then
[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
printf %s "$conf" | "$resolvconf" -a "$ifname"
return $?
@@ -186,7 +195,7 @@ add_resolv_conf()

remove_resolv_conf()
{
- if $have_resolvconf; then
+ if $have_resolvconf && ($if_down || ! $resolvconf_from_systemd); then
"$resolvconf" -d "$ifname" -f
else
if [ -e "$resolv_conf_dir/$ifname" ]; then
--
2.17.1

0 comments on commit 98134b0

Please sign in to comment.