From a023cca8d90cfdc7114bbdaa886c52b324075fb6 Mon Sep 17 00:00:00 2001
From: Ludovic Courtès <ludo@gnu.org>
Date: Sun, 14 Sep 2014 23:01:23 +0200
Subject: services: Add 'dhcp-client-service'.

* gnu/services/networking.scm (dhcp-client-service): New procedure.
* doc/guix.texi (Networking Services): Document it.
---
 doc/guix.texi               |  6 ++++++
 gnu/services/networking.scm | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/doc/guix.texi b/doc/guix.texi
index 8c68c1a743..1c1a04c75c 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3449,6 +3449,12 @@ Run @var{udev}, which populates the @file{/dev} directory dynamically.
 The @code{(gnu system networking)} module provides services to configure
 the network interface.
 
+@cindex DHCP, networking service
+@deffn {Monadic Procedure} dhcp-client-service [#:dhcp @var{isc-dhcp}]
+Return a service that runs @var{dhcp}, a Dynamic Host Configuration
+Protocol (DHCP) client, on all the non-loopback network interfaces.
+@end deffn
+
 @deffn {Monadic Procedure} static-networking-service @var{interface} @var{ip} @
        [#:gateway #f] [#:name-services @code{'()}]
 Return a service that starts @var{interface} with address @var{ip}.  If
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index ce924a55bf..ff7bd7fde9 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -25,6 +25,7 @@ (define-module (gnu services networking)
   #:use-module (guix gexp)
   #:use-module (guix monads)
   #:export (static-networking-service
+            dhcp-client-service
             tor-service))
 
 ;;; Commentary:
@@ -94,6 +95,38 @@ (define* (static-networking-service interface ip
                                 #t)))))
       (respawn? #f)))))
 
+(define* (dhcp-client-service #:key (dhcp isc-dhcp))
+  "Return a service that runs @var{dhcp}, a Dynamic Host Configuration
+Protocol (DHCP) client, on all the non-loopback network interfaces."
+
+  (define dhclient
+    #~(string-append #$dhcp "/sbin/dhclient"))
+
+  (define pid-file
+    "/var/run/dhclient.pid")
+
+  (with-monad %store-monad
+    (return (service
+             (documentation
+              "Set up networking via DHCP.")
+             (requirement '(user-processes udev))
+             (provision '(networking))
+             (start #~(lambda _
+                        ;; When invoked without any arguments, 'dhclient'
+                        ;; 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.
+                        (let* ((valid? (negate loopback-network-interface?))
+                               (ifaces (filter valid?
+                                               (all-network-interfaces)))
+                               (pid    (fork+exec-command
+                                        (cons* #$dhclient "-pf" #$pid-file
+                                               ifaces))))
+                          (and (zero? (cdr (waitpid pid)))
+                               (call-with-input-file #$pid-file read)))))
+             (stop #~(make-kill-destructor))))))
+
 (define* (tor-service #:key (tor tor))
   "Return a service to run the @uref{https://torproject.org,Tor} daemon.
 
-- 
cgit v1.2.3