GNU bug report logs - #68675
[PATCH] Support dhcpcd in dhcp-client-service-type

Previous Next

Package: guix-patches;

Reported by: soeren <at> soeren-tempel.net

Date: Tue, 23 Jan 2024 16:14:01 UTC

Severity: normal

Tags: patch

Done: Sören Tempel <soeren <at> soeren-tempel.net>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: soeren <at> soeren-tempel.net
To: 68675 <at> debbugs.gnu.org
Subject: [bug#68675] [PATCH v2] services: dhcp: Support the dhcpcd implementation.
Date: Wed, 24 Jan 2024 20:05:13 +0100
From: Sören Tempel <soeren <at> soeren-tempel.net>

Prior to this commit, the isc-dhcp implementation was the only DHCP
implementation supported by dhcp-client-shepherd-service. This is
problematic as the ISC implementation has reached end-of-life in
2022(!). As a first step to migrate away from isc-dhcp, this commit
adds support for dhcpcd to dhcp-client-shepherd-service. Currently,
it has to be enabled explicitly via the package field of the
dhcp-client-configuration. In the future, it is intended to become
the default to migrate away from isc-dhcp.

While at it, also remove isc-dhcp from %base-packages as it is no
longer necessarily needed and it will be pulled in by the DHCP
client service if required.

See also: https://issues.guix.gnu.org/68619

* gnu/services/networking.scm (dhcp-client-shepherd-service): Add
  support for the dhcpcd client implementation.
* gnu/services/networking.scm (dhcp-client-account-service): New
  procedure.
* gnu/services/networking.scm (dhcp-client-service-type): Add optional
  account-service-type extensions (needed for dhcpcd).
* gnu/system.scm (%base-packages-networking): Remove isc-dhcp from
  %base-packages (will be pulled in by dhcp-client-shepherd-service).

Signed-off-by: Sören Tempel <soeren <at> soeren-tempel.net>
---
Changes since v1:

* Remove isc-dhcp from %base-packages

 gnu/services/networking.scm | 84 ++++++++++++++++++++++++++-----------
 gnu/system.scm              |  2 +-
 2 files changed, 61 insertions(+), 25 deletions(-)

diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index 495d049728..3621e2bda2 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -316,25 +316,21 @@ (define-record-type* <dhcp-client-configuration>
 (define dhcp-client-shepherd-service
   (match-lambda
     ((? dhcp-client-configuration? config)
-     (let ((package (dhcp-client-configuration-package config))
-           (requirement (dhcp-client-configuration-shepherd-requirement config))
-           (provision (dhcp-client-configuration-shepherd-provision config))
-           (interfaces (dhcp-client-configuration-interfaces config))
-           (pid-file "/var/run/dhclient.pid"))
+     (let* ((package (dhcp-client-configuration-package config))
+            (client-name (package-name package))
+            (requirement (dhcp-client-configuration-shepherd-requirement config))
+            (provision (dhcp-client-configuration-shepherd-provision config))
+            (interfaces (dhcp-client-configuration-interfaces config)))
        (list (shepherd-service
               (documentation "Set up networking via DHCP.")
               (requirement `(user-processes udev ,@requirement))
               (provision provision)
 
-              ;; XXX: Running with '-nw' ("no wait") avoids blocking for a minute when
-              ;; networking is unavailable, but also means that the interface is not up
-              ;; yet when 'start' completes.  To wait for the interface to be ready, one
-              ;; should instead monitor udev events.
               (start #~(lambda _
-                         (define dhclient
-                           (string-append #$package "/sbin/dhclient"))
+                         (use-modules (ice-9 popen)
+                                      (ice-9 rdelim))
 
-                         ;; When invoked without any arguments, 'dhclient' discovers all
+                         ;; When invoked without any arguments, the client discovers all
                          ;; non-loopback interfaces *that are up*.  However, the relevant
                          ;; interfaces are typically down at this point.  Thus we perform
                          ;; our own interface discovery here.
@@ -355,17 +351,40 @@ (define dhcp-client-shepherd-service
                                        (_
                                         #~'#$interfaces))))
 
-                         (false-if-exception (delete-file #$pid-file))
-                         (let ((pid (fork+exec-command
-                                     ;; By default dhclient uses a
-                                     ;; pre-standardization implementation of
-                                     ;; DDNS, which is incompatable with
-                                     ;; non-ISC DHCP servers; thus, pass '-I'.
-                                     ;; <https://kb.isc.org/docs/aa-01091>.
-                                     (cons* dhclient "-nw" "-I"
-                                            "-pf" #$pid-file ifaces))))
-                           (and (zero? (cdr (waitpid pid)))
-                                (read-pid-file #$pid-file)))))
+                         ;; Returns the execution configuration for the DHCP client
+                         ;; selected by the package field of dhcp-client-configuration.
+                         ;; The configuration is a pair of pidfile and execution command
+                         ;; where the latter is a list.
+                         (define exec-config
+                           (case (string->symbol #$client-name)
+                             ((isc-dhcp)
+                              (let ((pid-file "/var/run/dhclient.pid"))
+                                (cons
+                                  (cons* (string-append #$package "/sbin/dhclient")
+                                         "-nw" "-I" "-pf" pid-file ifaces)
+                                  pid-file)))
+                             ((dhcpcd)
+                              ;; For dhcpcd, the utilized pid-file depends on the
+                              ;; command-line arguments.  If multiple interfaces are
+                              ;; given, a different pid-file is returned.  Hence, we
+                              ;; consult dhcpcd itself to determine the pid-file.
+                              (let* ((cmd (string-append #$package "/sbin/dhcpcd"))
+                                     (arg (cons* cmd "-b" ifaces)))
+                                (cons arg
+                                  (let* ((pipe (string-join (append arg '("-P")) " "))
+                                         (port (open-input-pipe pipe))
+                                         (path (read-line port)))
+                                    (close-pipe port)
+                                    path))))
+                             (else
+                               (error (G_ "unknown 'package' value in dhcp-client-configuration")))))
+
+                         (let ((pid-file (cdr exec-config))
+                               (exec-cmd (car exec-config)))
+                           (false-if-exception (delete-file pid-file))
+                           (let ((pid (fork+exec-command exec-cmd)))
+                             (and (zero? (cdr (waitpid pid)))
+                                  (read-pid-file pid-file))))))
               (stop #~(make-kill-destructor))))))
     (package
      (warning (G_ "'dhcp-client' service now expects a \
@@ -377,10 +396,27 @@ (define dhcp-client-shepherd-service
       (dhcp-client-configuration
        (package package))))))
 
+(define (dhcp-client-account-service config)
+  (let ((package (dhcp-client-configuration-package config)))
+    ;; Contrary to other DHCP clients (e.g. dhclient), dhcpcd supports
+    ;; privilege separation.  Hence, we need to create an account here.
+    (if (string=? "dhcpcd" (package-name package))
+      (list (user-group (name "dhcpcd") (system? #t))
+            (user-account
+              (name "dhcpcd")
+              (group "dhcpcd")
+              (system? #t)
+              (comment "dhcpcd daemon user")
+              (home-directory "/var/empty")
+              (shell "/run/current-system/profile/sbin/nologin")))
+      '())))
+
 (define dhcp-client-service-type
   (service-type (name 'dhcp-client)
                 (extensions
-                 (list (service-extension shepherd-root-service-type
+                 (list (service-extension account-service-type
+                                          dhcp-client-account-service)
+                       (service-extension shepherd-root-service-type
                                           dhcp-client-shepherd-service)))
                 (default-value (dhcp-client-configuration))
                 (description "Run @command{dhcp}, a Dynamic Host Configuration
diff --git a/gnu/system.scm b/gnu/system.scm
index 3cd64a5c9f..a7676ec90e 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -917,7 +917,7 @@ (define %base-packages-interactive
 
 (define %base-packages-networking
   ;; Default set of networking packages.
-  (list inetutils isc-dhcp
+  (list inetutils
         iproute
         wget
         ;; wireless-tools is deprecated in favor of iw, but it's still what




This bug report was last modified 76 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.