dotfiles/system/modules/router/hostapd.nix

85 lines
3.3 KiB
Nix
Raw Normal View History

2023-06-20 15:11:01 +07:00
{ lib
, config
, pkgs
, utils
, ... }:
let
cfg = config.router;
in {
config = lib.mkIf (cfg.enable && builtins.any (x: x.hostapd.enable) (builtins.attrValues cfg.interfaces)) {
environment.systemPackages = with pkgs; [ hostapd wirelesstools ];
services.udev.packages = with pkgs; [ crda ];
hardware.wirelessRegulatoryDatabase = true;
systemd.services = lib.mapAttrs' (interface: icfg: let
escapedInterface = utils.escapeSystemdPath interface;
compileValue = k: v:
if builtins.isBool v then (if v then "1" else "0")
else if builtins.isList v then builtins.concatStringsSep " " (map (compileValue k) v)
else if k == "ssid2" then "P${builtins.toJSON (toString v)}"
else toString v;
compileSettings = x:
let
y = builtins.removeAttrs x [ "ssid" ];
z = if y?ssid2 then y else y // { ssid2 = x.ssid; };
in
if !x?ssid && !x?ssid2 then
throw "Must specify ssid for hostapd"
else if x.wpa_key_mgmt == defaultSettings.wpa_key_mgmt && !x?wpa_passphrase && !x?sae_password then
throw "Either change authentication methods or specify wpa_passphrase for hostapd"
else builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k}=${compileValue k v}") z);
forceSettings = {
inherit interface;
};
defaultSettings = {
driver = "nl80211";
logger_syslog = -1;
logger_syslog_level = 2;
logger_stdout = -1;
logger_stdout_level = 2;
# not sure if enabling it when it isn't supported is gonna break anything?
ieee80211n = true; # wifi 4
ieee80211ac = true; # wifi 5
ieee80211ax = true; # wifi 6
ieee80211be = true; # wifi 7
ctrl_interface = "/run/hostapd";
disassoc_low_ack = true;
wmm_enabled = true;
uapsd_advertisement_enabled = true;
utf8_ssid = true;
sae_require_mfp = true;
ieee80211w = 1; # optional mfp
sae_pwe = 2;
auth_algs = 1;
wpa = 2;
wpa_pairwise = [ "CCMP" ];
wpa_key_mgmt = [ "WPA-PSK" "WPA-PSK-SHA256" "SAE" ];
okc = true;
group_mgmt_cipher = "AES-128-CMAC";
qos_map_set = "0,0,2,16,1,1,255,255,18,22,24,38,40,40,44,46,48,56"; # from openwrt
# ap_isolate = true; # to isolate clients
} // lib.optionalAttrs (icfg.hostapd.settings?country_code) {
ieee80211d = true;
} // lib.optionalAttrs (icfg.bridge != null) {
inherit (icfg) bridge;
};
settings = defaultSettings // icfg.hostapd.settings // forceSettings;
configFile = pkgs.writeText "hostapd.conf" (compileSettings settings);
in {
name = "hostapd-${escapedInterface}";
value = lib.mkIf icfg.hostapd.enable {
description = "hostapd wireless AP (${interface})";
path = [ pkgs.hostapd ];
after = [ "sys-subsystem-net-devices-${escapedInterface}.device" ];
bindsTo = [ "sys-subsystem-net-devices-${escapedInterface}.device" ];
requiredBy = [ "network-link-${escapedInterface}.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.hostapd}/bin/hostapd ${configFile}";
Restart = "always";
};
};
}) cfg.interfaces;
};
}