commit: 6945571fce4bf7557248af07f6d2e22a7ea56efb Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Sat Apr 19 00:10:50 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sat Apr 19 00:10:50 2025 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=6945571f
net-misc/dhcpcd: backport IPv6 fix Closes: https://bugs.gentoo.org/953895 Signed-off-by: Sam James <sam <AT> gentoo.org> net-misc/dhcpcd/dhcpcd-10.2.2-r1.ebuild | 173 ++++++++++++++ net-misc/dhcpcd/files/dhcpcd-10.2.2-ipv6.patch | 312 +++++++++++++++++++++++++ 2 files changed, 485 insertions(+) diff --git a/net-misc/dhcpcd/dhcpcd-10.2.2-r1.ebuild b/net-misc/dhcpcd/dhcpcd-10.2.2-r1.ebuild new file mode 100644 index 000000000000..481da7cf2047 --- /dev/null +++ b/net-misc/dhcpcd/dhcpcd-10.2.2-r1.ebuild @@ -0,0 +1,173 @@ +# Copyright 1999-2025 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit systemd optfeature toolchain-funcs + +if [[ ${PV} == 9999 ]]; then + inherit git-r3 + EGIT_REPO_URI="https://github.com/NetworkConfiguration/dhcpcd.git" +else + MY_P="${P/_alpha/-alpha}" + MY_P="${MY_P/_beta/-beta}" + MY_P="${MY_P/_rc/-rc}" + SRC_URI="https://github.com/NetworkConfiguration/dhcpcd/releases/download/v${PV}/${MY_P}.tar.xz" + S="${WORKDIR}/${MY_P}" + + KEYWORDS="~alpha amd64 arm arm64 hppa ~loong ~m68k ~mips ppc ppc64 ~riscv ~s390 sparc x86 ~amd64-linux ~x86-linux" +fi + +DESCRIPTION="A fully featured, yet light weight RFC2131 compliant DHCP client" +HOMEPAGE="https://github.com/NetworkConfiguration/dhcpcd/ https://roy.marples.name/projects/dhcpcd/" + +LICENSE="BSD-2 BSD ISC MIT" +SLOT="0" +IUSE="debug +embedded ipv6 privsep +udev" + +DEPEND=" + app-crypt/libmd + udev? ( virtual/udev ) +" +RDEPEND=" + ${DEPEND} + privsep? ( + acct-group/dhcpcd + acct-user/dhcpcd + ) +" + +QA_CONFIG_IMPL_DECL_SKIP=( + # These don't exist on Linux/glibc (bug #900264) + memset_explicit + memset_s + setproctitle + strtoi + consttime_memequal + SHA256_Init + hmac + # These may exist on some glibc versions, but the checks fail due to + # -Werror / undefined reference no matter what. bug #924825 + arc4random + arc4random_uniform +) + +PATCHES=( + "${FILESDIR}"/${PN}-10.0.6-fix-lib-check.patch + "${FILESDIR}"/${P}-ipv6.patch +) + +src_configure() { + local myeconfargs=( + --dbdir="${EPREFIX}/var/lib/dhcpcd" + --libexecdir="${EPREFIX}/lib/dhcpcd" + --localstatedir="${EPREFIX}/var" + --prefix="${EPREFIX}" + --with-hook=ntp.conf + $(use_enable debug) + $(use_enable embedded) + $(use_enable ipv6) + $(use_enable privsep) + $(usex elibc_glibc '--with-hook=yp.conf' '') + --rundir=$(usex kernel_linux "${EPREFIX}/run/dhcpcd" "${EPREFIX}/var/run/dhcpcd") + $(usex privsep '--privsepuser=dhcpcd' '') + $(usex udev '' '--without-dev --without-udev') + CC="$(tc-getCC)" + ) + econf "${myeconfargs[@]}" +} + +src_install() { + default + keepdir /var/lib/dhcpcd + newinitd "${FILESDIR}"/dhcpcd.initd-r1 dhcpcd + systemd_newunit "${FILESDIR}"/dhcpcd.service-r1 dhcpcd.service +} + +pkg_postinst() { + local dbdir="${EROOT}"/var/lib/dhcpcd old_files=() + + local old_old_duid="${EROOT}"/var/lib/dhcpcd/dhcpcd.duid + local old_duid="${EROOT}"/etc/dhcpcd.duid + local new_duid="${dbdir}"/duid + if [[ -e "${old_old_duid}" ]] ; then + # Upgrade the duid file to the new format if needed + if ! grep -q '..:..:..:..:..:..' "${old_old_duid}"; then + sed -i -e 's/\(..\)/\1:/g; s/:$//g' "${old_old_duid}" + fi + + # Move the duid to /etc, a more sensible location + if [[ ! -e "${old_duid}" ]] ; then + cp -p "${old_old_duid}" "${new_duid}" + fi + old_files+=( "${old_old_duid}" ) + fi + + # dhcpcd-7 moves the files out of /etc + if [[ -e "${old_duid}" ]] ; then + if [[ ! -e "${new_duid}" ]] ; then + cp -p "${old_duid}" "${new_duid}" + fi + old_files+=( "${old_duid}" ) + fi + local old_secret="${EROOT}"/etc/dhcpcd.secret + local new_secret="${dbdir}"/secret + if [[ -e "${old_secret}" ]] ; then + if [[ ! -e "${new_secret}" ]] ; then + cp -p "${old_secret}" "${new_secret}" + fi + old_files+=( "${old_secret}" ) + fi + + # dhcpcd-7 renames some files in /var/lib/dhcpcd + local old_rdm="${dbdir}"/dhcpcd-rdm.monotonic + local new_rdm="${dbdir}"/rdm_monotonic + if [[ -e "${old_rdm}" ]] ; then + if [[ ! -e "${new_rdm}" ]] ; then + cp -p "${old_rdm}" "${new_rdm}" + fi + old_files+=( "${old_rdm}" ) + fi + local lease= + for lease in "${dbdir}"/dhcpcd-*.lease*; do + [[ -f "${lease}" ]] || continue + old_files+=( "${lease}" ) + local new_lease=$(basename "${lease}" | sed -e "s/dhcpcd-//") + [[ -e "${dbdir}/${new_lease}" ]] && continue + cp "${lease}" "${dbdir}/${new_lease}" + done + + # Warn about removing stale files + if [[ -n "${old_files[@]}" ]] ; then + elog + elog "dhcpcd-7 has copied dhcpcd.duid and dhcpcd.secret from" + elog "${EROOT}/etc to ${dbdir}" + elog "and copied leases in ${dbdir} to new files with the dhcpcd-" + elog "prefix dropped." + elog + elog "You should remove these files if you don't plan on reverting" + elog "to an older version:" + local old_file= + for old_file in ${old_files[@]}; do + elog " ${old_file}" + done + fi + + if [ -z "${REPLACING_VERSIONS}" ]; then + elog + elog "dhcpcd has zeroconf support active by default." + elog "This means it will always obtain an IP address even if no" + elog "DHCP server can be contacted, which will break any existing" + elog "failover support you may have configured in your net configuration." + elog "This behaviour can be controlled with the noipv4ll configuration" + elog "file option or the -L command line switch." + elog "See the dhcpcd and dhcpcd.conf man pages for more details." + + elog + elog "Dhcpcd has duid enabled by default, and this may cause issues" + elog "with some dhcp servers. For more information, see" + elog "https://bugs.gentoo.org/show_bug.cgi?id=477356" + fi + + optfeature "lookup-hostname hook" net-dns/bind-tools +} diff --git a/net-misc/dhcpcd/files/dhcpcd-10.2.2-ipv6.patch b/net-misc/dhcpcd/files/dhcpcd-10.2.2-ipv6.patch new file mode 100644 index 000000000000..1a42788d23d9 --- /dev/null +++ b/net-misc/dhcpcd/files/dhcpcd-10.2.2-ipv6.patch @@ -0,0 +1,312 @@ +https://bugs.gentoo.org/953895 +https://github.com/NetworkConfiguration/dhcpcd/issues/492 + +From 664952372f0965da16ef24abe079bea1ad87a166 Mon Sep 17 00:00:00 2001 +From: Roy Marples <[email protected]> +Date: Fri, 28 Mar 2025 19:44:48 +0000 +Subject: [PATCH] route: Don't spam route changes for lifetime + +Fixes #459 +--- + src/route.c | 134 +++++++++++++++++++++++++++------------------------- + 1 file changed, 70 insertions(+), 64 deletions(-) + +diff --git a/src/route.c b/src/route.c +index 865d50a5..0037dda4 100644 +--- a/src/route.c ++++ b/src/route.c +@@ -33,6 +33,7 @@ + #include <stddef.h> + #include <stdlib.h> + #include <string.h> ++#include <syslog.h> + #include <unistd.h> + + #include "config.h" +@@ -255,7 +256,7 @@ rt_is_default(const struct rt *rt) + } + + static void +-rt_desc(const char *cmd, const struct rt *rt) ++rt_desc(int loglevel, const char *cmd, const struct rt *rt) + { + char dest[INET_MAX_ADDRSTRLEN], gateway[INET_MAX_ADDRSTRLEN]; + int prefix; +@@ -273,25 +274,25 @@ rt_desc(const char *cmd, const struct rt *rt) + + if (rt->rt_flags & RTF_HOST) { + if (gateway_unspec) +- loginfox("%s: %s host route to %s", ++ logmessage(loglevel, "%s: %s host route to %s", + ifname, cmd, dest); + else +- loginfox("%s: %s host route to %s via %s", ++ logmessage(loglevel, "%s: %s host route to %s via %s", + ifname, cmd, dest, gateway); + } else if (rt_is_default(rt)) { + if (gateway_unspec) +- loginfox("%s: %s default route", ++ logmessage(loglevel, "%s: %s default route", + ifname, cmd); + else +- loginfox("%s: %s default route via %s", ++ logmessage(loglevel, "%s: %s default route via %s", + ifname, cmd, gateway); + } else if (gateway_unspec) +- loginfox("%s: %s%s route to %s/%d", ++ logmessage(loglevel, "%s: %s%s route to %s/%d", + ifname, cmd, + rt->rt_flags & RTF_REJECT ? " reject" : "", + dest, prefix); + else +- loginfox("%s: %s%s route to %s/%d via %s", ++ logmessage(loglevel, "%s: %s%s route to %s/%d via %s", + ifname, cmd, + rt->rt_flags & RTF_REJECT ? " reject" : "", + dest, prefix, gateway); +@@ -490,7 +491,7 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid) + + rb_tree_remove_node(&ctx->routes, f); + snprintf(buf, sizeof(buf), "pid %d deleted", pid); +- rt_desc(buf, f); ++ rt_desc(LOG_WARNING, buf, f); + rt_free(f); + } + break; +@@ -503,8 +504,8 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid) + } + + /* Compare miscellaneous route details */ +-static bool +-rt_cmp_misc(struct rt *nrt, struct rt *ort) ++static int ++rt_cmp_mtu(struct rt *nrt, struct rt *ort) + { + #if defined(__FreeBSD__) || defined(__DragonFly__) + /* FreeBSD puts the interface MTU into the route MTU +@@ -514,13 +515,19 @@ rt_cmp_misc(struct rt *nrt, struct rt *ort) + nmtu = nrt->rt_mtu ? nrt->rt_mtu : (unsigned int)nrt->rt_ifp->mtu; + omtu = ort->rt_mtu ? ort->rt_mtu : (unsigned int)ort->rt_ifp->mtu; + if (omtu != nmtu) +- return false; ++ return 1; + #else + if (ort->rt_mtu != nrt->rt_mtu) +- return false; ++ return 1; + #endif + ++ return 0; ++} ++ + #ifdef HAVE_ROUTE_LIFETIME ++static int ++rt_cmp_lifetime(struct rt *nrt, struct rt *ort) ++{ + /* There might be a minor difference between kernel route + * lifetime and our lifetime due to processing times. + * We allow a small deviation to avoid needless route changes. +@@ -533,23 +540,25 @@ rt_cmp_misc(struct rt *nrt, struct rt *ort) + if (ts.tv_sec < 0) + ts.tv_sec = -ts.tv_sec; + if (ts.tv_sec > RTLIFETIME_DEV_MAX) +- return false; ++ return 1; + if (nrt->rt_lifetime > ort->rt_lifetime) + deviation = nrt->rt_lifetime - ort->rt_lifetime; + else + deviation = ort->rt_lifetime - nrt->rt_lifetime; + if (deviation > RTLIFETIME_DEV_MAX) +- return false; +-#endif ++ return 1; + +- return true; ++ return 0; + } ++#endif + + static bool + rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort) + { + struct dhcpcd_ctx *ctx; +- bool change, kroute, result; ++ struct rt *krt; ++ int loglevel = LOG_INFO; ++ bool change, result; + + assert(nrt != NULL); + ctx = nrt->rt_ifp->ctx; +@@ -569,46 +578,40 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort) + sa_is_unspecified(&nrt->rt_netmask)) + return false; + +- rt_desc(ort == NULL ? "adding" : "changing", nrt); +- +- change = kroute = result = false; +- if (ort == NULL) { +- ort = rb_tree_find_node(kroutes, nrt); +- if (ort != NULL && +- ((ort->rt_flags & RTF_REJECT && +- nrt->rt_flags & RTF_REJECT) || +- (ort->rt_ifp == nrt->rt_ifp && ++ krt = rb_tree_find_node(kroutes, nrt); ++ if (krt != NULL && ++ krt->rt_ifp == nrt->rt_ifp && ++ /* Only test flags dhcpcd controls */ ++ (krt->rt_flags & (RTF_HOST | RTF_REJECT)) == nrt->rt_flags && + #ifdef HAVE_ROUTE_METRIC +- ort->rt_metric == nrt->rt_metric && ++ krt->rt_metric == nrt->rt_metric && + #endif +- sa_cmp(&ort->rt_gateway, &nrt->rt_gateway) == 0))) +- { +- if (rt_cmp_misc(nrt, ort)) +- return true; +- change = true; +- kroute = true; +- } +- } else if (ort->rt_dflags & RTDF_FAKE && +- !(nrt->rt_dflags & RTDF_FAKE) && +- ort->rt_ifp == nrt->rt_ifp && +-#ifdef HAVE_ROUTE_METRIC +- ort->rt_metric == nrt->rt_metric && +-#endif +- sa_cmp(&ort->rt_dest, &nrt->rt_dest) == 0 && +- rt_cmp_netmask(ort, nrt) == 0 && +- sa_cmp(&ort->rt_gateway, &nrt->rt_gateway) == 0) ++ sa_cmp(&krt->rt_dest, &nrt->rt_dest) == 0 && ++ rt_cmp_netmask(krt, nrt) == 0 && ++ sa_cmp(&krt->rt_gateway, &nrt->rt_gateway) == 0 && ++ rt_cmp_mtu(krt, nrt) == 0) + { +- if (rt_cmp_misc(nrt, ort)) ++#ifdef HAVE_ROUTE_LIFETIME ++ if (rt_cmp_lifetime(krt, nrt) == 0) { ++ rt_desc(LOG_DEBUG, "keeping", krt); + return true; +- change = true; ++ } else ++ loglevel = LOG_DEBUG; ++#else ++ rt_desc(LOG_DEBUG, "keeping", krt); ++ return true; ++#endif + } + ++ rt_desc(loglevel, ort == NULL ? "adding" : "changing", nrt); ++ ++ change = krt != NULL; + #ifdef RTF_CLONING + /* BSD can set routes to be cloning routes. + * Cloned routes inherit the parent flags. + * As such, we need to delete and re-add the route to flush children + * to correct the flags. */ +- if (change && ort != NULL && ort->rt_flags & RTF_CLONING) ++ if (change && krt != NULL && krt->rt_flags & RTF_CLONING) + change = false; + #endif + +@@ -625,8 +628,8 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort) + /* With route metrics, we can safely add the new route before + * deleting the old route. */ + if (if_route(RTM_ADD, nrt) != -1) { +- if (ort != NULL) { +- if (if_route(RTM_DELETE, ort) == -1 && errno != ESRCH) ++ if (krt != NULL) { ++ if (if_route(RTM_DELETE, krt) == -1 && errno != ESRCH) + logerr("if_route (DEL)"); + } + result = true; +@@ -644,19 +647,17 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort) + #ifdef ROUTE_PER_GATEWAY + errno = 0; + #endif +- if (ort != NULL) { +- if (if_route(RTM_DELETE, ort) == -1 && errno != ESRCH) ++ if (krt != NULL) { ++ if (if_route(RTM_DELETE, krt) == -1 && errno != ESRCH) + logerr("if_route (DEL)"); +- else +- kroute = false; + } + #ifdef ROUTE_PER_GATEWAY + /* The OS allows many routes to the same dest with different gateways. + * dhcpcd does not support this yet, so for the time being just keep on + * deleting the route until there is an error. */ +- if (ort != NULL && errno == 0) { ++ if (krt != NULL && errno == 0) { + for (;;) { +- if (if_route(RTM_DELETE, ort) == -1) ++ if (if_route(RTM_DELETE, krt) == -1) + break; + } + } +@@ -675,9 +676,9 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort) + logerr("if_route (ADD)"); + + out: +- if (kroute) { +- rb_tree_remove_node(kroutes, ort); +- rt_free(ort); ++ if (krt != NULL) { ++ rb_tree_remove_node(kroutes, krt); ++ rt_free(krt); + } + return result; + } +@@ -687,22 +688,24 @@ rt_delete(struct rt *rt) + { + int retval; + +- rt_desc("deleting", rt); ++ rt_desc(LOG_INFO, "deleting", rt); + retval = if_route(RTM_DELETE, rt) == -1 ? false : true; + if (!retval && errno != ENOENT && errno != ESRCH) + logerr(__func__); + return retval; + } + +-static bool ++static int + rt_cmp(const struct rt *r1, const struct rt *r2) + { + +- return (r1->rt_ifp == r2->rt_ifp && ++ if (r1->rt_ifp == r2->rt_ifp && + #ifdef HAVE_ROUTE_METRIC + r1->rt_metric == r2->rt_metric && + #endif +- sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0); ++ sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0) ++ return 0; ++ return 1; + } + + static bool +@@ -718,10 +721,13 @@ rt_doroute(rb_tree_t *kroutes, struct rt *rt) + if (rt->rt_dflags & RTDF_FAKE) + return true; + if (or->rt_dflags & RTDF_FAKE || +- !rt_cmp(rt, or) || ++ rt_cmp(rt, or) != 0 || + (rt->rt_ifa.sa_family != AF_UNSPEC && + sa_cmp(&or->rt_ifa, &rt->rt_ifa) != 0) || +- !rt_cmp_misc(rt, or)) ++#ifdef HAVE_ROUTE_LIFETIME ++ rt_cmp_lifetime(rt, or) != 0 || ++#endif ++ rt_cmp_mtu(rt, or) != 0) + { + if (!rt_add(kroutes, rt, or)) + return false; +@@ -733,7 +739,7 @@ rt_doroute(rb_tree_t *kroutes, struct rt *rt) + or = rb_tree_find_node(kroutes, rt); + if (or == NULL) + return false; +- if (!rt_cmp(rt, or)) ++ if (rt_cmp(rt, or) == 0) + return false; + } else { + if (!rt_add(kroutes, rt, NULL)) +
