services: connman: Redirect output to a log file.
[jackhill/guix/guix.git] / gnu / services / networking.scm
index b0c23aa..03b2c6e 100644 (file)
@@ -1,10 +1,14 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016, 2018 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 John Darrington <jmd@gnu.org>
 ;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
 ;;; Copyright © 2017 Thomas Danckaert <post@thomasdanckaert.be>
+;;; Copyright © 2017, 2018 Marius Bakke <mbakke@fastmail.com>
+;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
+;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
+;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
 
 (define-module (gnu services networking)
   #:use-module (gnu services)
+  #:use-module (gnu services base)
   #:use-module (gnu services shepherd)
   #:use-module (gnu services dbus)
   #:use-module (gnu system shadow)
   #:use-module (gnu system pam)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages connman)
+  #:use-module (gnu packages freedesktop)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages tor)
   #:use-module (gnu packages messaging)
   #:use-module (guix gexp)
   #:use-module (guix records)
   #:use-module (guix modules)
+  #:use-module (guix deprecation)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
+  #:re-export (static-networking-service
+               static-networking-service-type)
   #:export (%facebook-host-aliases
-            static-networking
-
-            static-networking?
-            static-networking-interface
-            static-networking-ip
-            static-networking-netmask
-            static-networking-gateway
-
-            static-networking-service
-            static-networking-service-type
             dhcp-client-service
+            dhcp-client-service-type
+
+            dhcpd-service-type
+            dhcpd-configuration
+            dhcpd-configuration?
+            dhcpd-configuration-package
+            dhcpd-configuration-config-file
+            dhcpd-configuration-version
+            dhcpd-configuration-run-directory
+            dhcpd-configuration-lease-file
+            dhcpd-configuration-pid-file
+            dhcpd-configuration-interfaces
+
             %ntp-servers
 
             ntp-configuration
             ntp-service
             ntp-service-type
 
+            openntpd-configuration
+            openntpd-configuration?
+            openntpd-service-type
+
             inetd-configuration
             inetd-entry
             inetd-service-type
             tor-service
             tor-service-type
 
-            bitlbee-configuration
-            bitlbee-configuration?
-            bitlbee-service
-            bitlbee-service-type
-
             wicd-service-type
             wicd-service
 
             connman-configuration?
             connman-service-type
 
+            modem-manager-configuration
+            modem-manager-configuration?
+            modem-manager-service-type
+
+            <wpa-supplicant-configuration>
+            wpa-supplicant-configuration
+            wpa-supplicant-configuration?
+            wpa-supplicant-configuration-wpa-supplicant
+            wpa-supplicant-configuration-pid-file
+            wpa-supplicant-configuration-dbus?
+            wpa-supplicant-configuration-interface
+            wpa-supplicant-configuration-config-file
+            wpa-supplicant-configuration-extra-options
             wpa-supplicant-service-type
 
             openvswitch-service-type
-            openvswitch-configuration))
+            openvswitch-configuration
+
+            iptables-configuration
+            iptables-configuration?
+            iptables-configuration-iptables
+            iptables-configuration-ipv4-rules
+            iptables-configuration-ipv6-rules
+            iptables-service-type))
 
 ;;; Commentary:
 ;;;
@@ -133,152 +164,6 @@ fe80::1%lo0 connect.facebook.net
 fe80::1%lo0 www.connect.facebook.net
 fe80::1%lo0 apps.facebook.com\n")
 
-
-(define-record-type* <static-networking>
-  static-networking make-static-networking
-  static-networking?
-  (interface static-networking-interface)
-  (ip static-networking-ip)
-  (netmask static-networking-netmask
-           (default #f))
-  (gateway static-networking-gateway              ;FIXME: doesn't belong here
-           (default #f))
-  (provision static-networking-provision
-             (default #f))
-  (name-servers static-networking-name-servers    ;FIXME: doesn't belong here
-                (default '())))
-
-(define static-networking-shepherd-service
-  (match-lambda
-    (($ <static-networking> interface ip netmask gateway provision
-                            name-servers)
-     (let ((loopback? (and provision (memq 'loopback provision))))
-       (shepherd-service
-
-        ;; Unless we're providing the loopback interface, wait for udev to be up
-        ;; and running so that INTERFACE is actually usable.
-        (requirement (if loopback? '() '(udev)))
-
-        (documentation
-         "Bring up the networking interface using a static IP address.")
-        (provision (or provision
-                       (list (symbol-append 'networking-
-                                            (string->symbol interface)))))
-
-        (start #~(lambda _
-                   ;; Return #t if successfully started.
-                   (let* ((addr     (inet-pton AF_INET #$ip))
-                          (sockaddr (make-socket-address AF_INET addr 0))
-                          (mask     (and #$netmask
-                                         (inet-pton AF_INET #$netmask)))
-                          (maskaddr (and mask
-                                         (make-socket-address AF_INET
-                                                              mask 0)))
-                          (gateway  (and #$gateway
-                                         (inet-pton AF_INET #$gateway)))
-                          (gatewayaddr (and gateway
-                                            (make-socket-address AF_INET
-                                                                 gateway 0))))
-                     (configure-network-interface #$interface sockaddr
-                                                  (logior IFF_UP
-                                                          #$(if loopback?
-                                                                #~IFF_LOOPBACK
-                                                                0))
-                                                  #:netmask maskaddr)
-                     (when gateway
-                       (let ((sock (socket AF_INET SOCK_DGRAM 0)))
-                         (add-network-route/gateway sock gatewayaddr)
-                         (close-port sock))))))
-        (stop #~(lambda _
-                  ;; Return #f is successfully stopped.
-                  (let ((sock (socket AF_INET SOCK_STREAM 0)))
-                    (when #$gateway
-                      (delete-network-route sock
-                                            (make-socket-address
-                                             AF_INET INADDR_ANY 0)))
-                    (set-network-interface-flags sock #$interface 0)
-                    (close-port sock)
-                    #f)))
-        (respawn? #f))))))
-
-(define (static-networking-etc-files interfaces)
-  "Return a /etc/resolv.conf entry for INTERFACES or the empty list."
-  (match (delete-duplicates
-          (append-map static-networking-name-servers
-                      interfaces))
-    (()
-     '())
-    ((name-servers ...)
-     (let ((content (string-join
-                     (map (cut string-append "nameserver " <>)
-                          name-servers)
-                     "\n" 'suffix)))
-       `(("resolv.conf"
-          ,(plain-file "resolv.conf"
-                       (string-append "\
-# Generated by 'static-networking-service'.\n"
-                                      content))))))))
-
-(define (static-networking-shepherd-services interfaces)
-  "Return the list of Shepherd services to bring up INTERFACES, a list of
-<static-networking> objects."
-  (define (loopback? service)
-    (memq 'loopback (shepherd-service-provision service)))
-
-  (let ((services (map static-networking-shepherd-service interfaces)))
-    (match (remove loopback? services)
-      (()
-       ;; There's no interface other than 'loopback', so we assume that the
-       ;; 'networking' service will be provided by dhclient or similar.
-       services)
-      ((non-loopback ...)
-       ;; Assume we're providing all the interfaces, and thus, provide a
-       ;; 'networking' service.
-       (cons (shepherd-service
-              (provision '(networking))
-              (requirement (append-map shepherd-service-provision
-                                       services))
-              (start #~(const #t))
-              (stop #~(const #f))
-              (documentation "Bring up all the networking interfaces."))
-             services)))))
-
-(define static-networking-service-type
-  ;; The service type for statically-defined network interfaces.
-  (service-type (name 'static-networking)
-                (extensions
-                 (list
-                  (service-extension shepherd-root-service-type
-                                     static-networking-shepherd-services)
-                  (service-extension etc-service-type
-                                     static-networking-etc-files)))
-                (compose concatenate)
-                (extend append)
-                (description
-                 "Turn up the specified network interfaces upon startup,
-with the given IP address, gateway, netmask, and so on.  The value for
-services of this type is a list of @code{static-networking} objects, one per
-network interface.")))
-
-(define* (static-networking-service interface ip
-                                    #:key
-                                    netmask gateway provision
-                                    (name-servers '()))
-  "Return a service that starts @var{interface} with address @var{ip}.  If
-@var{netmask} is true, use it as the network mask.  If @var{gateway} is true,
-it must be a string specifying the default network gateway.
-
-This procedure can be called several times, one for each network
-interface of interest.  Behind the scenes what it does is extend
-@code{static-networking-service-type} with additional network interfaces
-to handle."
-  (simple-service 'static-network-interface
-                  static-networking-service-type
-                  (list (static-networking (interface interface) (ip ip)
-                                           (netmask netmask) (gateway gateway)
-                                           (provision provision)
-                                           (name-servers name-servers)))))
-
 (define dhcp-client-service-type
   (shepherd-service-type
    'dhcp-client
@@ -318,26 +203,82 @@ to handle."
                              (cons* #$dhclient "-nw"
                                     "-pf" #$pid-file ifaces))))
                    (and (zero? (cdr (waitpid pid)))
-                        (let loop ()
-                          (catch 'system-error
-                            (lambda ()
-                              (call-with-input-file #$pid-file read))
-                            (lambda args
-                              ;; 'dhclient' returned before PID-FILE was created,
-                              ;; so try again.
-                              (let ((errno (system-error-errno args)))
-                                (if (= ENOENT errno)
-                                    (begin
-                                      (sleep 1)
-                                      (loop))
-                                    (apply throw args))))))))))
-      (stop #~(make-kill-destructor))))))
-
-(define* (dhcp-client-service #:key (dhcp isc-dhcp))
+                        (read-pid-file #$pid-file)))))
+      (stop #~(make-kill-destructor))))
+   isc-dhcp))
+
+(define-deprecated (dhcp-client-service #:key (dhcp isc-dhcp))
+  dhcp-client-service-type
   "Return a service that runs @var{dhcp}, a Dynamic Host Configuration
 Protocol (DHCP) client, on all the non-loopback network interfaces."
   (service dhcp-client-service-type dhcp))
 
+(define-record-type* <dhcpd-configuration>
+  dhcpd-configuration make-dhcpd-configuration
+  dhcpd-configuration?
+  (package   dhcpd-configuration-package ;<package>
+             (default isc-dhcp))
+  (config-file   dhcpd-configuration-config-file ;file-like
+                 (default #f))
+  (version dhcpd-configuration-version ;"4", "6", or "4o6"
+              (default "4"))
+  (run-directory dhcpd-configuration-run-directory
+                 (default "/run/dhcpd"))
+  (lease-file dhcpd-configuration-lease-file
+              (default "/var/db/dhcpd.leases"))
+  (pid-file dhcpd-configuration-pid-file
+            (default "/run/dhcpd/dhcpd.pid"))
+  ;; list of strings, e.g. (list "enp0s25")
+  (interfaces dhcpd-configuration-interfaces
+              (default '())))
+
+(define dhcpd-shepherd-service
+  (match-lambda
+    (($ <dhcpd-configuration> package config-file version run-directory
+                              lease-file pid-file interfaces)
+     (unless config-file
+       (error "Must supply a config-file"))
+     (list (shepherd-service
+            ;; Allow users to easily run multiple versions simultaneously.
+            (provision (list (string->symbol
+                              (string-append "dhcpv" version "-daemon"))))
+            (documentation (string-append "Run the DHCPv" version " daemon"))
+            (requirement '(networking))
+            (start #~(make-forkexec-constructor
+                      '(#$(file-append package "/sbin/dhcpd")
+                        #$(string-append "-" version)
+                        "-lf" #$lease-file
+                        "-pf" #$pid-file
+                        "-cf" #$config-file
+                        #$@interfaces)
+                      #:pid-file #$pid-file))
+            (stop #~(make-kill-destructor)))))))
+
+(define dhcpd-activation
+  (match-lambda
+    (($ <dhcpd-configuration> package config-file version run-directory
+                              lease-file pid-file interfaces)
+     (with-imported-modules '((guix build utils))
+       #~(begin
+           (unless (file-exists? #$run-directory)
+             (mkdir #$run-directory))
+           ;; According to the DHCP manual (man dhcpd.leases), the lease
+           ;; database must be present for dhcpd to start successfully.
+           (unless (file-exists? #$lease-file)
+             (with-output-to-file #$lease-file
+               (lambda _ (display ""))))
+           ;; Validate the config.
+           (invoke
+            #$(file-append package "/sbin/dhcpd") "-t" "-cf"
+            #$config-file))))))
+
+(define dhcpd-service-type
+  (service-type
+   (name 'dhcpd)
+   (extensions
+    (list (service-extension shepherd-root-service-type dhcpd-shepherd-service)
+          (service-extension activation-service-type dhcpd-activation)))))
+
 (define %ntp-servers
   ;; Default set of NTP servers. These URLs are managed by the NTP Pool project.
   ;; Within Guix, Leo Famulari <leo@famulari.name> is the administrative contact
@@ -358,7 +299,8 @@ Protocol (DHCP) client, on all the non-loopback network interfaces."
   ntp-configuration?
   (ntp      ntp-configuration-ntp
             (default ntp))
-  (servers  ntp-configuration-servers)
+  (servers  ntp-configuration-servers
+            (default %ntp-servers))
   (allow-large-adjustment? ntp-allow-large-adjustment?
                            (default #f)))
 
@@ -431,11 +373,13 @@ restrict -6 ::1\n"))
                 (description
                  "Run the @command{ntpd}, the Network Time Protocol (NTP)
 daemon of the @uref{http://www.ntp.org, Network Time Foundation}.  The daemon
-will keep the system clock synchronized with that of the given servers.")))
+will keep the system clock synchronized with that of the given servers.")
+                (default-value (ntp-configuration))))
 
-(define* (ntp-service #:key (ntp ntp)
-                      (servers %ntp-servers)
-                      allow-large-adjustment?)
+(define-deprecated (ntp-service #:key (ntp ntp)
+                                (servers %ntp-servers)
+                                allow-large-adjustment?)
+  ntp-service-type
   "Return a service that runs the daemon from @var{ntp}, the
 @uref{http://www.ntp.org, Network Time Protocol package}.  The daemon will
 keep the system clock synchronized with that of @var{servers}.
@@ -448,6 +392,104 @@ make an initial adjustment of more than 1,000 seconds."
                                allow-large-adjustment?))))
 
 \f
+;;;
+;;; OpenNTPD.
+;;;
+
+(define-record-type* <openntpd-configuration>
+  openntpd-configuration make-openntpd-configuration
+  openntpd-configuration?
+  (openntpd                openntpd-configuration-openntpd
+                           (default openntpd))
+  (listen-on               openntpd-listen-on
+                           (default '("127.0.0.1"
+                                      "::1")))
+  (query-from              openntpd-query-from
+                           (default '()))
+  (sensor                  openntpd-sensor
+                           (default '()))
+  (server                  openntpd-server
+                           (default %ntp-servers))
+  (servers                 openntpd-servers
+                           (default '()))
+  (constraint-from         openntpd-constraint-from
+                           (default '()))
+  (constraints-from        openntpd-constraints-from
+                           (default '()))
+  (allow-large-adjustment? openntpd-allow-large-adjustment?
+                           (default #f))) ; upstream default
+
+(define (openntpd-shepherd-service config)
+  (match-record config <openntpd-configuration>
+    (openntpd listen-on query-from sensor server servers constraint-from
+              constraints-from allow-large-adjustment?)
+    (let ()
+      (define config
+        (string-join
+          (filter-map
+            (lambda (field value)
+              (string-join
+                (map (cut string-append field <> "\n")
+                     value)))
+            '("listen on " "query from " "sensor " "server " "servers "
+              "constraint from ")
+            (list listen-on query-from sensor server servers constraint-from))
+          ;; The 'constraints from' field needs to be enclosed in double quotes.
+          (string-join
+            (map (cut string-append "constraints from \"" <> "\"\n")
+                 constraints-from))))
+
+      (define ntpd.conf
+        (plain-file "ntpd.conf" config))
+
+      (list (shepherd-service
+              (provision '(ntpd))
+              (documentation "Run the Network Time Protocol (NTP) daemon.")
+              (requirement '(user-processes networking))
+              (start #~(make-forkexec-constructor
+                         (list (string-append #$openntpd "/sbin/ntpd")
+                               "-f" #$ntpd.conf
+                               "-d" ;; don't daemonize
+                               #$@(if allow-large-adjustment?
+                                    '("-s")
+                                    '()))
+                         ;; When ntpd is daemonized it repeatedly tries to respawn
+                         ;; while running, leading shepherd to disable it.  To
+                         ;; prevent spamming stderr, redirect output to logfile.
+                         #:log-file "/var/log/ntpd"))
+              (stop #~(make-kill-destructor)))))))
+
+(define (openntpd-service-activation config)
+  "Return the activation gexp for CONFIG."
+  (with-imported-modules '((guix build utils))
+    #~(begin
+        (use-modules (guix build utils))
+
+        (mkdir-p "/var/db")
+        (mkdir-p "/var/run")
+        (unless (file-exists? "/var/db/ntpd.drift")
+          (with-output-to-file "/var/db/ntpd.drift"
+                               (lambda _
+                                 (format #t "0.0")))))))
+
+(define openntpd-service-type
+  (service-type (name 'openntpd)
+                (extensions
+                 (list (service-extension shepherd-root-service-type
+                                          openntpd-shepherd-service)
+                       (service-extension account-service-type
+                                          (const %ntp-accounts))
+                       (service-extension profile-service-type
+                                          (compose list openntpd-configuration-openntpd))
+                       (service-extension activation-service-type
+                                          openntpd-service-activation)))
+                (default-value (openntpd-configuration))
+                (description
+                 "Run the @command{ntpd}, the Network Time Protocol (NTP)
+daemon, as implemented by @uref{http://www.openntpd.org, OpenNTPD}.  The
+daemon will keep the system clock synchronized with that of the given servers.")))
+
+\f
 ;;;
 ;;; Inetd.
 ;;;
@@ -548,7 +590,9 @@ demand.")))
   (config-file      tor-configuration-config-file
                     (default (plain-file "empty" "")))
   (hidden-services  tor-configuration-hidden-services
-                    (default '())))
+                    (default '()))
+  (socks-socket-type tor-configuration-socks-socket-type ; 'tcp or 'unix
+                     (default 'tcp)))
 
 (define %tor-accounts
   ;; User account and groups for Tor.
@@ -570,7 +614,7 @@ demand.")))
 (define (tor-configuration->torrc config)
   "Return a 'torrc' file for CONFIG."
   (match config
-    (($ <tor-configuration> tor config-file services)
+    (($ <tor-configuration> tor config-file services socks-socket-type)
      (computed-file
       "torrc"
       (with-imported-modules '((guix build utils))
@@ -581,10 +625,15 @@ demand.")))
             (call-with-output-file #$output
               (lambda (port)
                 (display "\
-# The beginning was automatically added.
+### These lines were generated from your system configuration:
 User tor
 DataDirectory /var/lib/tor
+PidFile /var/run/tor/tor.pid
 Log notice syslog\n" port)
+                (when (eq? 'unix '#$socks-socket-type)
+                  (display "\
+SocksPort unix:/var/run/tor/socks-sock
+UnixSocksGroupWritable 1\n" port))
 
                 (for-each (match-lambda
                             ((service (ports hosts) ...)
@@ -601,6 +650,9 @@ HiddenServicePort ~a ~a~%"
                                      (cons name mapping)))
                                   services))
 
+                (display "\
+### End of automatically generated lines.\n\n" port)
+
                 ;; Append the user's config file.
                 (call-with-input-file #$config-file
                   (lambda (input)
@@ -608,7 +660,7 @@ HiddenServicePort ~a ~a~%"
                 #t))))))))
 
 (define (tor-shepherd-service config)
-  "Return a <shepherd-service> running TOR."
+  "Return a <shepherd-service> running Tor."
   (match config
     (($ <tor-configuration> tor)
      (let ((torrc (tor-configuration->torrc config)))
@@ -634,12 +686,17 @@ HiddenServicePort ~a ~a~%"
                                             (writable? #t))
                                            (file-system-mapping
                                             (source "/dev/log") ;for syslog
-                                            (target source)))))
+                                            (target source))
+                                           (file-system-mapping
+                                            (source "/var/run/tor")
+                                            (target source)
+                                            (writable? #t)))
+                          #:pid-file "/var/run/tor/tor.pid"))
                 (stop #~(make-kill-destructor))
                 (documentation "Run the Tor anonymous network overlay."))))))))
 
-(define (tor-hidden-service-activation config)
-  "Return the activation gexp for SERVICES, a list of hidden services."
+(define (tor-activation config)
+  "Set up directories for Tor and its hidden services, if any."
   #~(begin
       (use-modules (guix build utils))
 
@@ -655,6 +712,15 @@ HiddenServicePort ~a ~a~%"
           ;; The daemon bails out if we give wider permissions.
           (chmod directory #o700)))
 
+      ;; Allow Tor to write its PID file.
+      (mkdir-p "/var/run/tor")
+      (chown "/var/run/tor" (passwd:uid %user) (passwd:gid %user))
+      ;; Set the group permissions to rw so that if the system administrator
+      ;; has specified UnixSocksGroupWritable=1 in their torrc file, members
+      ;; of the "tor" group will be able to use the SOCKS socket.
+      (chmod "/var/run/tor" #o750)
+
+      ;; Allow Tor to access the hidden services' directories.
       (mkdir-p "/var/lib/tor")
       (chown "/var/lib/tor" (passwd:uid %user) (passwd:gid %user))
       (chmod "/var/lib/tor" #o700)
@@ -674,7 +740,7 @@ HiddenServicePort ~a ~a~%"
                        (service-extension account-service-type
                                           (const %tor-accounts))
                        (service-extension activation-service-type
-                                          tor-hidden-service-activation)))
+                                          tor-activation)))
 
                 ;; This can be extended with hidden services.
                 (compose concatenate)
@@ -689,9 +755,10 @@ HiddenServicePort ~a ~a~%"
                  "Run the @uref{https://torproject.org, Tor} anonymous
 networking daemon.")))
 
-(define* (tor-service #:optional
-                      (config-file (plain-file "empty" ""))
-                      #:key (tor tor))
+(define-deprecated (tor-service #:optional
+                                (config-file (plain-file "empty" ""))
+                                #:key (tor tor))
+  tor-service-type
   "Return a service to run the @uref{https://torproject.org, Tor} anonymous
 networking daemon.
 
@@ -733,114 +800,6 @@ project's documentation} for more information."
            (hidden-service name mapping)))
 
 \f
-;;;
-;;; BitlBee.
-;;;
-
-(define-record-type* <bitlbee-configuration>
-  bitlbee-configuration make-bitlbee-configuration
-  bitlbee-configuration?
-  (bitlbee bitlbee-configuration-bitlbee
-           (default bitlbee))
-  (interface bitlbee-configuration-interface
-             (default "127.0.0.1"))
-  (port bitlbee-configuration-port
-        (default 6667))
-  (extra-settings bitlbee-configuration-extra-settings
-                  (default "")))
-
-(define bitlbee-shepherd-service
-  (match-lambda
-    (($ <bitlbee-configuration> bitlbee interface port extra-settings)
-     (let ((conf (plain-file "bitlbee.conf"
-                             (string-append "
-  [settings]
-  User = bitlbee
-  ConfigDir = /var/lib/bitlbee
-  DaemonInterface = " interface "
-  DaemonPort = " (number->string port) "
-" extra-settings))))
-
-       (with-imported-modules (source-module-closure
-                               '((gnu build shepherd)
-                                 (gnu system file-systems)))
-         (list (shepherd-service
-                (provision '(bitlbee))
-
-                ;; Note: If networking is not up, then /etc/resolv.conf
-                ;; doesn't get mapped in the container, hence the dependency
-                ;; on 'networking'.
-                (requirement '(user-processes networking))
-
-                (modules '((gnu build shepherd)
-                           (gnu system file-systems)))
-                (start #~(make-forkexec-constructor/container
-                          (list #$(file-append bitlbee "/sbin/bitlbee")
-                                "-n" "-F" "-u" "bitlbee" "-c" #$conf)
-
-                          #:pid-file "/var/run/bitlbee.pid"
-                          #:mappings (list (file-system-mapping
-                                            (source "/var/lib/bitlbee")
-                                            (target source)
-                                            (writable? #t)))))
-                (stop  #~(make-kill-destructor)))))))))
-
-(define %bitlbee-accounts
-  ;; User group and account to run BitlBee.
-  (list (user-group (name "bitlbee") (system? #t))
-        (user-account
-         (name "bitlbee")
-         (group "bitlbee")
-         (system? #t)
-         (comment "BitlBee daemon user")
-         (home-directory "/var/empty")
-         (shell (file-append shadow "/sbin/nologin")))))
-
-(define %bitlbee-activation
-  ;; Activation gexp for BitlBee.
-  #~(begin
-      (use-modules (guix build utils))
-
-      ;; This directory is used to store OTR data.
-      (mkdir-p "/var/lib/bitlbee")
-      (let ((user (getpwnam "bitlbee")))
-        (chown "/var/lib/bitlbee"
-               (passwd:uid user) (passwd:gid user)))))
-
-(define bitlbee-service-type
-  (service-type (name 'bitlbee)
-                (extensions
-                 (list (service-extension shepherd-root-service-type
-                                          bitlbee-shepherd-service)
-                       (service-extension account-service-type
-                                          (const %bitlbee-accounts))
-                       (service-extension activation-service-type
-                                          (const %bitlbee-activation))))
-                (default-value (bitlbee-configuration))
-                (description
-                 "Run @url{http://bitlbee.org,BitlBee}, a daemon that acts as
-a gateway between IRC and chat networks.")))
-
-(define* (bitlbee-service #:key (bitlbee bitlbee)
-                          (interface "127.0.0.1") (port 6667)
-                          (extra-settings ""))
-  "Return a service that runs @url{http://bitlbee.org,BitlBee}, a daemon that
-acts as a gateway between IRC and chat networks.
-
-The daemon will listen to the interface corresponding to the IP address
-specified in @var{interface}, on @var{port}.  @code{127.0.0.1} means that only
-local clients can connect, whereas @code{0.0.0.0} means that connections can
-come from any networking interface.
-
-In addition, @var{extra-settings} specifies a string to append to the
-configuration file."
-  (service bitlbee-service-type
-           (bitlbee-configuration
-            (bitlbee bitlbee)
-            (interface interface) (port port)
-            (extra-settings extra-settings))))
-
-\f
 ;;;
 ;;; Wicd.
 ;;;
@@ -899,6 +858,17 @@ and @command{wicd-curses} user interfaces."
   (service wicd-service-type wicd))
 
 \f
+;;;
+;;; ModemManager
+;;;
+
+(define-record-type* <modem-manager-configuration>
+  modem-manager-configuration make-modem-manager-configuration
+  modem-manager-configuration?
+  (modem-manager modem-manager-configuration-modem-manager
+                   (default modem-manager)))
+
+\f
 ;;;
 ;;; NetworkManager
 ;;;
@@ -1015,7 +985,14 @@ wireless networking."))))
                       (list (string-append #$connman
                                            "/sbin/connmand")
                             "-n" "-r"
-                            #$@(if disable-vpn? '("--noplugin=vpn") '()))))
+                            #$@(if disable-vpn? '("--noplugin=vpn") '()))
+
+                      ;; As connman(8) notes, when passing '-n', connman
+                      ;; "directs log output to the controlling terminal in
+                      ;; addition to syslog."  Redirect stdout and stderr
+                      ;; to avoid spamming the console (XXX: for some reason
+                      ;; redirecting to /dev/null doesn't work.)
+                      #:log-file "/var/log/connman.log"))
             (stop #~(make-kill-destructor)))))))
 
 (define connman-service-type
@@ -1024,6 +1001,8 @@ wireless networking."))))
                   (extensions
                    (list (service-extension shepherd-root-service-type
                                             connman-shepherd-service)
+                         (service-extension polkit-service-type
+                                            connman-package)
                          (service-extension dbus-root-service-type
                                             connman-package)
                          (service-extension activation-service-type
@@ -1031,37 +1010,97 @@ wireless networking."))))
                          ;; Add connman to the system profile.
                          (service-extension profile-service-type
                                             connman-package)))
+                  (default-value (connman-configuration))
                   (description
                    "Run @url{https://01.org/connman,Connman},
 a network connection manager."))))
 
 \f
 ;;;
-;;; WPA supplicant
+;;; Modem manager
 ;;;
 
+(define modem-manager-service-type
+  (let ((config->package
+         (match-lambda
+          (($ <modem-manager-configuration> modem-manager)
+           (list modem-manager)))))
+    (service-type (name 'modem-manager)
+                  (extensions
+                   (list (service-extension dbus-root-service-type
+                                            config->package)
+                         (service-extension udev-service-type
+                                            config->package)
+                         (service-extension polkit-service-type
+                                            config->package)))
+                  (default-value (modem-manager-configuration))
+                  (description
+                   "Run @uref{https://wiki.gnome.org/Projects/ModemManager,
+ModemManager}, a modem management daemon that aims to simplify dialup
+networking."))))
 
-(define (wpa-supplicant-shepherd-service wpa-supplicant)
-  "Return a shepherd service for wpa_supplicant"
-  (list (shepherd-service
-         (documentation "Run WPA supplicant with dbus interface")
-         (provision '(wpa-supplicant))
-         (requirement '(user-processes dbus-system loopback))
-         (start #~(make-forkexec-constructor
-                   (list (string-append #$wpa-supplicant
-                                        "/sbin/wpa_supplicant")
-                         "-u" "-B" "-P/var/run/wpa_supplicant.pid")
-                   #:pid-file "/var/run/wpa_supplicant.pid"))
-         (stop #~(make-kill-destructor)))))
+\f
+;;;
+;;; WPA supplicant
+;;;
+
+(define-record-type* <wpa-supplicant-configuration>
+  wpa-supplicant-configuration make-wpa-supplicant-configuration
+  wpa-supplicant-configuration?
+  (wpa-supplicant     wpa-supplicant-configuration-wpa-supplicant ;<package>
+                      (default wpa-supplicant))
+  (pid-file           wpa-supplicant-configuration-pid-file       ;string
+                      (default "/var/run/wpa_supplicant.pid"))
+  (dbus?              wpa-supplicant-configuration-dbus?          ;Boolean
+                      (default #t))
+  (interface          wpa-supplicant-configuration-interface      ;#f | string
+                      (default #f))
+  (config-file        wpa-supplicant-configuration-config-file    ;#f | <file-like>
+                      (default #f))
+  (extra-options      wpa-supplicant-configuration-extra-options  ;list of strings
+                      (default '())))
+
+(define wpa-supplicant-shepherd-service
+  (match-lambda
+    (($ <wpa-supplicant-configuration> wpa-supplicant pid-file dbus? interface
+                                       config-file extra-options)
+     (list (shepherd-service
+            (documentation "Run the WPA supplicant daemon")
+            (provision '(wpa-supplicant))
+            (requirement '(user-processes dbus-system loopback syslogd))
+            (start #~(make-forkexec-constructor
+                      (list (string-append #$wpa-supplicant
+                                           "/sbin/wpa_supplicant")
+                            (string-append "-P" #$pid-file)
+                            "-B"        ;run in background
+                            "-s"        ;log to syslogd
+                            #$@(if dbus?
+                                   #~("-u")
+                                   #~())
+                            #$@(if interface
+                                   #~((string-append "-i" #$interface))
+                                   #~())
+                            #$@(if config-file
+                                   #~((string-append "-c" #$config-file))
+                                   #~())
+                            #$@extra-options)
+                      #:pid-file #$pid-file))
+            (stop #~(make-kill-destructor)))))))
 
 (define wpa-supplicant-service-type
-  (service-type (name 'wpa-supplicant)
-                (extensions
-                 (list (service-extension shepherd-root-service-type
-                                          wpa-supplicant-shepherd-service)
-                       (service-extension dbus-root-service-type list)
-                       (service-extension profile-service-type list)))
-                (default-value wpa-supplicant)))
+  (let ((config->package
+         (match-lambda
+           (($ <wpa-supplicant-configuration> wpa-supplicant)
+            (list wpa-supplicant)))))
+    (service-type (name 'wpa-supplicant)
+                  (extensions
+                   (list (service-extension shepherd-root-service-type
+                                            wpa-supplicant-shepherd-service)
+                         (service-extension dbus-root-service-type config->package)
+                         (service-extension profile-service-type config->package)))
+                  (description "Run the WPA Supplicant daemon, a service that
+implements authentication, key negotiation and more for wireless networks.")
+                  (default-value (wpa-supplicant-configuration)))))
 
 \f
 ;;;
@@ -1123,6 +1162,53 @@ a network connection manager."))))
    (description
     "Run @uref{http://www.openvswitch.org, Open vSwitch}, a multilayer virtual
 switch designed to enable massive network automation through programmatic
-extension.")))
+extension.")
+   (default-value (openvswitch-configuration))))
+
+;;;
+;;; iptables
+;;;
+
+(define %iptables-accept-all-rules
+  (plain-file "iptables-accept-all.rules"
+              "*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+COMMIT
+"))
+
+(define-record-type* <iptables-configuration>
+  iptables-configuration make-iptables-configuration iptables-configuration?
+  (iptables iptables-configuration-iptables
+            (default iptables))
+  (ipv4-rules iptables-configuration-ipv4-rules
+              (default %iptables-accept-all-rules))
+  (ipv6-rules iptables-configuration-ipv6-rules
+              (default %iptables-accept-all-rules)))
+
+(define iptables-shepherd-service
+  (match-lambda
+    (($ <iptables-configuration> iptables ipv4-rules ipv6-rules)
+     (let ((iptables-restore (file-append iptables "/sbin/iptables-restore"))
+           (ip6tables-restore (file-append iptables "/sbin/ip6tables-restore")))
+       (shepherd-service
+        (documentation "Packet filtering framework")
+        (provision '(iptables))
+        (start #~(lambda _
+                   (invoke #$iptables-restore #$ipv4-rules)
+                   (invoke #$ip6tables-restore #$ipv6-rules)))
+        (stop #~(lambda _
+                  (invoke #$iptables-restore #$%iptables-accept-all-rules)
+                  (invoke #$ip6tables-restore #$%iptables-accept-all-rules))))))))
+
+(define iptables-service-type
+  (service-type
+   (name 'iptables)
+   (description
+    "Run @command{iptables-restore}, setting up the specified rules.")
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             (compose list iptables-shepherd-service))))))
 
 ;;; networking.scm ends here