at 16.09-beta 5.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.networking.wireless; 7 configFile = if cfg.networks != {} then pkgs.writeText "wpa_supplicant.conf" '' 8 ${optionalString cfg.userControlled.enable '' 9 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group} 10 update_config=1''} 11 ${concatStringsSep "\n" (mapAttrsToList (ssid: networkConfig: let 12 psk = if networkConfig.psk != null 13 then ''"${networkConfig.psk}"'' 14 else networkConfig.pskRaw; 15 in '' 16 network={ 17 ssid="${ssid}" 18 ${optionalString (psk != null) ''psk=${psk}''} 19 ${optionalString (psk == null) ''key_mgmt=NONE''} 20 } 21 '') cfg.networks)} 22 '' else "/etc/wpa_supplicant.conf"; 23in { 24 options = { 25 networking.wireless = { 26 enable = mkEnableOption "wpa_supplicant"; 27 28 interfaces = mkOption { 29 type = types.listOf types.str; 30 default = []; 31 example = [ "wlan0" "wlan1" ]; 32 description = '' 33 The interfaces <command>wpa_supplicant</command> will use. If empty, it will 34 automatically use all wireless interfaces. 35 ''; 36 }; 37 38 driver = mkOption { 39 type = types.str; 40 default = "nl80211,wext"; 41 description = "Force a specific wpa_supplicant driver."; 42 }; 43 44 networks = mkOption { 45 type = types.attrsOf (types.submodule { 46 options = { 47 psk = mkOption { 48 type = types.nullOr types.str; 49 default = null; 50 description = '' 51 The network's pre-shared key in plaintext defaulting 52 to being a network without any authentication. 53 54 Be aware that these will be written to the nix store 55 in plaintext! 56 57 Mutually exclusive with <varname>pskRaw</varname>. 58 ''; 59 }; 60 61 pskRaw = mkOption { 62 type = types.nullOr types.str; 63 default = null; 64 description = '' 65 The network's pre-shared key in hex defaulting 66 to being a network without any authentication. 67 68 Mutually exclusive with <varname>psk</varname>. 69 ''; 70 }; 71 }; 72 }); 73 description = '' 74 The network definitions to automatically connect to when 75 <command>wpa_supplicant</command> is running. If this 76 parameter is left empty wpa_supplicant will use 77 /etc/wpa_supplicant.conf as the configuration file. 78 ''; 79 default = {}; 80 example = literalExample '' 81 { echelon = { 82 psk = "abcdefgh"; 83 }; 84 "free.wifi" = {}; 85 } 86 ''; 87 }; 88 89 userControlled = { 90 enable = mkOption { 91 type = types.bool; 92 default = false; 93 description = '' 94 Allow normal users to control wpa_supplicant through wpa_gui or wpa_cli. 95 This is useful for laptop users that switch networks a lot and don't want 96 to depend on a large package such as NetworkManager just to pick nearby 97 access points. 98 99 When using a declarative network specification you cannot persist any 100 settings via wpa_gui or wpa_cli. 101 ''; 102 }; 103 104 group = mkOption { 105 type = types.str; 106 default = "wheel"; 107 example = "network"; 108 description = "Members of this group can control wpa_supplicant."; 109 }; 110 }; 111 }; 112 }; 113 114 config = mkIf cfg.enable { 115 assertions = flip mapAttrsToList cfg.networks (name: cfg: { 116 assertion = cfg.psk == null || cfg.pskRaw == null; 117 message = ''networking.wireless."${name}".psk and networking.wireless."${name}".pskRaw are mutually exclusive''; 118 }); 119 120 environment.systemPackages = [ pkgs.wpa_supplicant ]; 121 122 services.dbus.packages = [ pkgs.wpa_supplicant ]; 123 124 # FIXME: start a separate wpa_supplicant instance per interface. 125 systemd.services.wpa_supplicant = let 126 ifaces = cfg.interfaces; 127 deviceUnit = interface: [ "sys-subsystem-net-devices-${interface}.device" ]; 128 in { 129 description = "WPA Supplicant"; 130 131 after = [ "network-interfaces.target" ] ++ lib.concatMap deviceUnit ifaces; 132 requires = lib.concatMap deviceUnit ifaces; 133 wantedBy = [ "network.target" ]; 134 135 path = [ pkgs.wpa_supplicant ]; 136 137 script = '' 138 ${if ifaces == [] then '' 139 for i in $(cd /sys/class/net && echo *); do 140 DEVTYPE= 141 source /sys/class/net/$i/uevent 142 if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then 143 ifaces="$ifaces''${ifaces:+ -N} -i$i" 144 fi 145 done 146 '' else '' 147 ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}" 148 ''} 149 exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces 150 ''; 151 }; 152 153 powerManagement.resumeCommands = '' 154 ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant 155 ''; 156 157 # Restart wpa_supplicant when a wlan device appears or disappears. 158 services.udev.extraRules = '' 159 ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service" 160 ''; 161 }; 162 163 meta.maintainers = with lib.maintainers; [ globin ]; 164}