summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/doc/manual/configuration/wireless.xml14
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix160
2 files changed, 87 insertions, 87 deletions
diff --git a/nixos/doc/manual/configuration/wireless.xml b/nixos/doc/manual/configuration/wireless.xml
index 13e4283d241c..373a9168cc87 100644
--- a/nixos/doc/manual/configuration/wireless.xml
+++ b/nixos/doc/manual/configuration/wireless.xml
@@ -18,18 +18,8 @@ NixOS will start wpa_supplicant for you if you enable this setting:
 networking.wireless.enable = true;
 </programlisting>
 
-NixOS lets you specify networks for wpa_supplicant declaratively:
-<programlisting>
-networking.wireless.networks = {
-  echelon = {
-    psk = "abcdefgh";
-  };
-  "free.wifi" = {};
-}
-</programlisting>
-
-When no networks are set it will default to using a configuration file at
-<literal>/etc/wpa_supplicant.conf</literal>. You should edit this file
+NixOS currently does not generate wpa_supplicant's
+configuration file, <literal>/etc/wpa_supplicant.conf</literal>. You should edit this file
 yourself to define wireless networks, WPA keys and so on (see
 wpa_supplicant.conf(5)).
 </para>
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index 397811f96266..9e04bd401906 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -3,30 +3,51 @@
 with lib;
 
 let
+
   cfg = config.networking.wireless;
-  configFile = if cfg.networks != {} then pkgs.writeText "wpa_supplicant.conf" ''
-    ${optionalString cfg.userControlled.enable ''
-      ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}
-      update_config=1''}
-    ${concatStringsSep "\n" (mapAttrsToList (ssid: networkConfig: ''
-      network={
-        ssid="${ssid}"
-        ${optionalString (networkConfig.psk != null) ''psk="${networkConfig.psk}"''}
-        ${optionalString (networkConfig.psk == null) ''key_mgmt=NONE''}
-      }
-    '') cfg.networks)}
-  '' else "/etc/wpa_supplicant.conf";
-in {
+  configFile = "/etc/wpa_supplicant.conf";
+
+  ifaces =
+    cfg.interfaces ++
+    optional (config.networking.WLANInterface != "") config.networking.WLANInterface;
+
+in
+
+{
+
+  ###### interface
+
   options = {
+
+    networking.WLANInterface = mkOption {
+      default = "";
+      description = "Obsolete. Use <option>networking.wireless.interfaces</option> instead.";
+    };
+
     networking.wireless = {
-      enable = mkEnableOption "wpa_supplicant";
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to start <command>wpa_supplicant</command> to scan for
+          and associate with wireless networks.  Note: NixOS currently
+          does not manage <command>wpa_supplicant</command>'s
+          configuration file, <filename>${configFile}</filename>.  You
+          should edit this file yourself to define wireless networks,
+          WPA keys and so on (see
+          <citerefentry><refentrytitle>wpa_supplicant.conf</refentrytitle>
+          <manvolnum>5</manvolnum></citerefentry>), or use
+          networking.wireless.userControlled.* to allow users to add entries
+          through <command>wpa_cli</command> and <command>wpa_gui</command>.
+        '';
+      };
 
       interfaces = mkOption {
         type = types.listOf types.str;
         default = [];
         example = [ "wlan0" "wlan1" ];
         description = ''
-          The interfaces <command>wpa_supplicant</command> will use. If empty, it will
+          The interfaces <command>wpa_supplicant</command> will use.  If empty, it will
           automatically use all wireless interfaces.
         '';
       };
@@ -37,34 +58,6 @@ in {
         description = "Force a specific wpa_supplicant driver.";
       };
 
-      networks = mkOption {
-        type = types.attrsOf (types.submodule {
-          options = {
-            psk = mkOption {
-              type = types.nullOr types.str;
-              default = null;
-              description = ''
-                The network's pre-shared key in plaintext defaulting
-                to being a network without any authentication.
-              '';
-            };
-          };
-        });
-        description = ''
-          The network definitions to automatically connect to when
-           <command>wpa_supplicant</command> is running. If this
-           parameter is left empty wpa_supplicant will use
-          /etc/wpa_supplicant.conf as the configuration file.
-        '';
-        default = {};
-        example = literalExample ''
-          echelon = {
-            psk = "abcdefgh";
-          };
-          "free.wifi" = {};
-        '';
-      };
-
       userControlled = {
         enable = mkOption {
           type = types.bool;
@@ -75,8 +68,10 @@ in {
             to depend on a large package such as NetworkManager just to pick nearby
             access points.
 
-            When using a declarative network specification you cannot persist any
-            settings via wpa_gui or wpa_cli.
+            When you want to use this, make sure ${configFile} doesn't exist.
+            It will be created for you.
+
+            Currently it is also necessary to explicitly specify networking.wireless.interfaces.
           '';
         };
 
@@ -90,49 +85,64 @@ in {
     };
   };
 
-  config = mkMerge [
-    (mkIf cfg.enable {
-      environment.systemPackages =  [ pkgs.wpa_supplicant ];
 
-      services.dbus.packages = [ pkgs.wpa_supplicant ];
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages =  [ pkgs.wpa_supplicant ];
+
+    services.dbus.packages = [ pkgs.wpa_supplicant ];
 
-      # FIXME: start a separate wpa_supplicant instance per interface.
-      systemd.services.wpa_supplicant = let
-        ifaces = cfg.interfaces;
-      in {
-        description = "WPA Supplicant";
+    # FIXME: start a separate wpa_supplicant instance per interface.
+    jobs.wpa_supplicant =
+      { description = "WPA Supplicant";
 
         wantedBy = [ "network.target" ];
 
         path = [ pkgs.wpa_supplicant ];
 
-        script = ''
-          ${if ifaces == [] then ''
-            for i in $(cd /sys/class/net && echo *); do
-              DEVTYPE=
-              source /sys/class/net/$i/uevent
-              if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
-                ifaces="$ifaces''${ifaces:+ -N} -i$i"
-              fi
-            done
-          '' else ''
-            ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
-          ''}
-          exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
+        preStart = ''
+          touch -a ${configFile}
+          chmod 600 ${configFile}
+        '' + optionalString cfg.userControlled.enable ''
+          if [ ! -s ${configFile} ]; then
+            echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}" >> ${configFile}
+            echo "update_config=1" >> ${configFile}
+          fi
         '';
+
+        script =
+          ''
+            ${if ifaces == [] then ''
+              for i in $(cd /sys/class/net && echo *); do
+                DEVTYPE=
+                source /sys/class/net/$i/uevent
+                if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
+                  ifaces="$ifaces''${ifaces:+ -N} -i$i"
+                fi
+              done
+            '' else ''
+              ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
+            ''}
+            exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
+          '';
       };
 
-      powerManagement.resumeCommands = ''
+    powerManagement.resumeCommands =
+      ''
         ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant
       '';
 
-      # Restart wpa_supplicant when a wlan device appears or disappears.
-      services.udev.extraRules = ''
+    assertions = [{ assertion = !cfg.userControlled.enable || cfg.interfaces != [];
+                    message = "user controlled wpa_supplicant needs explicit networking.wireless.interfaces";}];
+
+    # Restart wpa_supplicant when a wlan device appears or disappears.
+    services.udev.extraRules =
+      ''
         ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service"
       '';
-    })
-    {
-      meta.maintainers = with lib.maintainers; [ globin ];
-    }
-  ];
+
+  };
+
 }