~ruther/guix-local

c4e1081f82c4f45e34cf6aca1e3f3347dd384c79 — Sergey Trofimov 1 year, 1 month ago e4995c9
services: networking: Add iwd-service-type.

* gnu/services/networking.scm (iwd-service-type): New service type.
(iwd-configuration), (iwd-settings), (iwd-scan-settings),
(iwd-general-settings), (iwd-network-settings): New configuration types.
* doc/guix.texi (Networking setup): Document it.

Change-Id: I852115b9c6768b3ec4eedb34a7f9e66438bd1429
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2 files changed, 411 insertions(+), 0 deletions(-)

M doc/guix.texi
M gnu/services/networking.scm
M doc/guix.texi => doc/guix.texi +162 -0
@@ 22408,6 22408,168 @@ List of additional command-line arguments to pass to the daemon.
@end table
@end deftp

@cindex IWD, Internet Wireless Daemon
@defvar iwd-service-type
This is the service type to run @acronym{IWD,Internet Wireless Daemon},
a wireless daemon required to authenticate against encrypted WiFi
networks.
@end defvar

@quotation Warning
By default @code{iwd} removes and re-creates interfaces it manages.  It
doesn't play nicely with @code{dhcp-client-service-type} that enumerates
wireless interfaces before starting the Shepherd service.  Use either
@code{dhcpcd-service-type} or the @code{iwd}'s built-in DHCP client (see
@code{enable-network-configuration} option below).
@end quotation

@quotation Warning
@code{iwd-service-type} conflicts with @code{wpa-supplicant-service-type}.
Make sure only one is configured.
@end quotation

@c %start of fragment

@deftp {Data Type} iwd-configuration
Available @code{iwd-configuration} fields are:

@table @asis
@item @code{iwd} (default: @code{iwd}) (type: file-like)
The IWD package to use.

@item @code{interfaces} (default: @code{()}) (type: list-of-strings)
If this is set, it must specify @dfn{glob patterns} matching network
interfaces that IWD will control.

@item @code{ignored-interfaces} (default: @code{()}) (type: list-of-strings)
If this is set, it must specify @dfn{glob patterns} matching network
interfaces that IWD will not manage.

@item @code{phys} (default: @code{()}) (type: list-of-strings)
If this is set, it must specify @dfn{glob patterns} matching network
PHYs names that IWD will control.

@item @code{ignored-phys} (default: @code{()}) (type: list-of-strings)
If this is set, it must specify @dfn{glob patterns} matching network
PHYs names that IWD will not manage.

@item @code{shepherd-requirement} (default: @code{()}) (type: list-of-symbols)
Shepherd requirements the service should depend on.

@item @code{shepherd-provision} (default: @code{(iwd wireless-daemon)}) (type: list-of-symbols)
The name(s) of the service.

@item @code{config} (type: iwd-settings)
Configuration settings.

@end table

@end deftp


@c %end of fragment

@c %start of fragment

@deftp {Data Type} iwd-settings
Available @code{iwd-settings} fields are:

@table @asis
@item @code{general} (type: iwd-general-settings)
General settings.

@item @code{network} (type: maybe-iwd-network-settings)
Network settings.

@item @code{scan} (type: maybe-iwd-scan-settings)
Scan settings.

@item @code{extra-config} (default: @code{()}) (type: list-of-strings)
Extra configuration values to append to the IWD configuration file.

@end table

@end deftp


@c %end of fragment

@c %start of fragment

@deftp {Data Type} iwd-general-settings
Available @code{iwd-general-settings} fields are:

@table @asis
@item @code{enable-network-configuration?} (default: @code{#f}) (type: boolean)
Setting this option to true enables @code{iwd} to configure the network
interfaces with the IP addresses.

@item @code{extra-options} (default: @code{()}) (type: alist)
An association list of option symbols/strings to string values to be
appended to the General settings group.

@end table

@end deftp


@c %end of fragment

@c %start of fragment

@deftp {Data Type} iwd-network-settings
Available @code{iwd-network-settings} fields are:

@table @asis
@item @code{enable-ipv6?} (default: @code{#t}) (type: boolean)
Sets the global default that tells @code{iwd} whether it should
configure IPv6 addresses and routes

@item @code{name-resolving-service} (default: @code{none}) (type: resolving-service)
Configures a DNS resolution method used by the system.

@item @code{extra-options} (default: @code{()}) (type: alist)
An association list of option symbols/strings to string values to be
appended to the Network settings group.

@end table

@end deftp


@c %end of fragment

@c %start of fragment

@deftp {Data Type} iwd-scan-settings
Available @code{iwd-scan-settings} fields are:

@table @asis
@item @code{disable-periodic-scan?} (default: @code{#f}) (type: boolean)
Setting this option to @code{#t} will prevent @code{iwd} from issuing
the periodic scans for the available networks while disconnected.

@item @code{initial-periodic-scan-interval} (default: @code{10}) (type: number)
The initial periodic scan interval upon disconnect (in seconds).

@item @code{maximum-periodic-scan-interval} (default: @code{300}) (type: number)
The maximum periodic scan interval (in seconds).

@item @code{disable-roaming-scan?} (default: @code{#f}) (type: boolean)
Setting this option to @code{#t} will prevent @code{iwd} from trying to
scan when roaming decisions are activated.

@item @code{extra-options} (default: @code{()}) (type: alist)
An association list of option symbols/strings to string values to be
appended to the Scan settings group.

@end table

@end deftp


@c %end of fragment

@cindex ModemManager
Some networking devices such as modems require special care, and this is
what the services below focus on.

M gnu/services/networking.scm => gnu/services/networking.scm +249 -0
@@ 41,6 41,7 @@
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu services networking)
  #:use-module (gnu home services utils)
  #:use-module (gnu services)
  #:use-module (gnu services base)
  #:use-module (gnu services configuration)


@@ 56,6 57,7 @@
  #:use-module (gnu packages bash)
  #:use-module (gnu packages cluster)
  #:use-module (gnu packages connman)
  #:use-module (gnu packages dns)
  #:use-module (gnu packages freedesktop)
  #:use-module (gnu packages linux)
  #:use-module (gnu packages tor)


@@ 80,6 82,7 @@
  #:use-module (srfi srfi-9)
  #:use-module (srfi srfi-26)
  #:use-module (srfi srfi-43)
  #:use-module ((ice-9 curried-definitions) #:select (define))
  #:use-module (ice-9 format)
  #:use-module (ice-9 match)
  #:use-module (ice-9 string-fun)


@@ 236,6 239,21 @@
            wpa-supplicant-configuration-extra-options
            wpa-supplicant-service-type

            iwd-configuration
            iwd-configuration-config
            iwd-configuration-ignored-interfaces
            iwd-configuration-ignored-phys
            iwd-configuration-interfaces
            iwd-configuration-iwd
            iwd-configuration-phys
            iwd-configuration-shepherd-provision
            iwd-configuration-shepherd-requirement
            iwd-service-type
            iwd-general-settings
            iwd-network-settings
            iwd-scan-settings
            iwd-settings

            hostapd-configuration
            hostapd-configuration?
            hostapd-configuration-package


@@ 2103,6 2121,237 @@ implements authentication, key negotiation and more for wireless networks.")


;;;
;;; IWD
;;;
(define (iwd-uglify-field-name name)
  (object->camel-case-string name 'upper))

(define (iwd-serialize-base field-name val)
  (format #f "~a=~a\n" field-name val))

(define (iwd-serialize-field field-name val)
  (iwd-serialize-base (iwd-uglify-field-name field-name) val))

(define iwd-serialize-number iwd-serialize-field)

(define (iwd-serialize-boolean field-name value)
  (iwd-serialize-field
   (string-trim-right (symbol->string field-name) #\?)
   (if value "true" "false")))

(define (iwd-serialize-alist field-name value)
  (if (null? value)
      ""
      #~(string-append #$@(generic-serialize-alist list
                                                   iwd-serialize-base
                                                   value))))

(define-enumerated-field-type resolving-service
  (none systemd resolvconf)
  (prefix iwd-))

(define-configuration iwd-general-settings
  (enable-network-configuration?
   (boolean #f)
   "Setting this option to true enables @code{iwd} to configure the network
interfaces with the IP addresses.")
  (extra-options
   (alist '())
   "An association list of option symbols/strings to string values to be
appended to the General settings group.")

  (prefix iwd-))

(define-configuration iwd-network-settings
  (enable-ipv6?
   (boolean #t)
   "Sets the global default that tells @code{iwd} whether it should configure
IPv6 addresses and routes")

  (name-resolving-service
   (resolving-service 'none)
   "Configures a DNS resolution method used by the system.")

  (extra-options
   (alist '())
   "An association list of option symbols/strings to string values to be
appended to the Network settings group.")

  (prefix iwd-))

(define-configuration iwd-scan-settings
  (disable-periodic-scan?
   (boolean #f)
   "Setting this option to @code{#t} will prevent @code{iwd} from issuing the
periodic scans for the available networks while disconnected.")

  (initial-periodic-scan-interval
   (number 10)
   "The initial periodic scan interval upon disconnect (in seconds).")

  (maximum-periodic-scan-interval
   (number 300)
   "The maximum periodic scan interval (in seconds).")

  (disable-roaming-scan?
   (boolean #f)
   "Setting this option to @code{#t} will prevent @code{iwd} from trying to scan
when roaming decisions are activated.")

  (extra-options
   (alist '())
   "An association list of option symbols/strings to string values to be
appended to the Scan settings group.")

  (prefix iwd-))

(define-maybe iwd-network-settings)
(define-maybe iwd-scan-settings)

(define ((iwd-serialize-config-section fields) name cfg)
  #~(format #f "[~a]\n~a\n"
            #$(string-upcase (object->string name) 0 1)
            #$(serialize-configuration cfg fields)))

(define serialize-iwd-network-settings
  (iwd-serialize-config-section iwd-network-settings-fields))

(define serialize-iwd-scan-settings
  (iwd-serialize-config-section iwd-scan-settings-fields))

(define serialize-iwd-general-settings
  (iwd-serialize-config-section iwd-general-settings-fields))

(define-configuration iwd-settings
  (general
   (iwd-general-settings (iwd-general-settings))
   "General settings.")

  (network
   maybe-iwd-network-settings
   "Network settings.")

  (scan
   maybe-iwd-scan-settings
   "Scan settings.")

  (extra-config
   (list-of-strings '())
   "Extra configuration values to append to the IWD configuration file."
   (serializer (lambda (_ value) (string-join value "\n" 'suffix)))))

(define-configuration/no-serialization iwd-configuration
  (iwd
   (file-like iwd)
   "The IWD package to use.")

  (interfaces
   (list-of-strings '())
   "If this is set, it must specify @dfn{glob patterns} matching network
interfaces that IWD will control.")

  (ignored-interfaces
   (list-of-strings '())
   "If this is set, it must specify @dfn{glob patterns} matching network
interfaces that IWD will not manage.")

  (phys
   (list-of-strings '())
   "If this is set, it must specify @dfn{glob patterns} matching network
PHYs names that IWD will control.")

  (ignored-phys
   (list-of-strings '())
   "If this is set, it must specify @dfn{glob patterns} matching network
PHYs names that IWD will not manage.")

  (shepherd-requirement
   (list-of-symbols '())
   "Shepherd requirements the service should depend on.")

  (shepherd-provision
   (list-of-symbols '(iwd wireless-daemon))
   "The name(s) of the service.")

  (config
   (iwd-settings (iwd-settings))
   "Configuration settings."))

(define (iwd-generate-documentation)
  (configuration->documentation 'iwd-configuration)
  (configuration->documentation 'iwd-settings)
  (configuration->documentation 'iwd-general-settings)
  (configuration->documentation 'iwd-network-settings)
  (configuration->documentation 'iwd-scan-settings))

(define (iwd-config-file config)
  "Return an IWD configuration file."
  (mixed-text-file "main.conf"
                   (serialize-configuration
                    (iwd-configuration-config config)
                    iwd-settings-fields)))

(define (iwd-environment config)
  (let ((resolver
         (and=> (iwd-settings-network (iwd-configuration-config config))
                iwd-network-settings-name-resolving-service)))

    (if (eq? resolver 'resolvconf)
        #~(list (string-append "PATH=" #$openresolv "/sbin"))
        '())))

(define (iwd-shepherd-service config)
  (match-record config <iwd-configuration>
                (iwd interfaces ignored-interfaces
                     phys ignored-phys
                     shepherd-requirement shepherd-provision)

    (list (shepherd-service
           (documentation "Run Internet Wireless Daemon")
           (provision shepherd-provision)
           (requirement `(user-processes dbus-system loopback ,@shepherd-requirement))
           (start #~(make-forkexec-constructor
                     (list (string-append #$iwd "/libexec/iwd")
                           "--logger=syslog"
                           #$@(if (null? interfaces) '()
                                  (list (string-append "--interfaces="
                                                       (string-join interfaces ","))))
                           #$@(if (null? ignored-interfaces) '()
                                  (list (string-append "--nointerfaces="
                                                       (string-join ignored-interfaces ","))))
                           #$@(if (null? phys) '()
                                  (list (string-append "--phys="
                                                       (string-join phys ","))))
                           #$@(if (null? ignored-phys) '()
                                  (list (string-append "--nophys="
                                                       (string-join ignored-phys ",")))))

                     #:environment-variables
                     #$(iwd-environment config)))
           (stop #~(make-kill-destructor))))))

(define (iwd-etc-service config)
  `(("iwd/main.conf" ,(iwd-config-file config))))

(define iwd-service-type
  (let ((add-iwd-package (compose list iwd-configuration-iwd)))
    (service-type (name 'iwd)
                  (extensions
                   (list (service-extension shepherd-root-service-type
                                            iwd-shepherd-service)
                         (service-extension etc-service-type
                                            iwd-etc-service)
                         (service-extension dbus-root-service-type
                                            add-iwd-package)
                         (service-extension profile-service-type
                                            add-iwd-package)))
                  (default-value (iwd-configuration))
                  (description
                   "Run @url{https://iwd.wiki.kernel.org/,Iwd},
a network connection manager."))))


;;;
;;; Hostapd.
;;;