summary refs log blame commit diff
path: root/modules/services/networking/hostapd.nix
blob: 712b1a6824ccb07c4f4a14cda6b648abc6b911e4 (plain) (tree)

























































































































































                                                                                                                                   
{ config, pkgs, ... }:

# TODO:
#
# asserts 
#   ensure that the nl80211 module is loaded/compiled in the kernel
#   hwMode must be a/b/g
#   channel must be between 1 and 13 (maybe)
#   wpa_supplicant and hostapd on the same wireless interface doesn't make any sense
#   perhaps an assertion that there is a dhcp server and a dns server on the IP address serviced by the hostapd?

with pkgs.lib;

let

  cfg = config.services.hostapd;
  
  configFile = pkgs.writeText "hostapd.conf"  
    ''
    interface=${cfg.interface}
    driver=${cfg.driver}
    ssid=${cfg.ssid}
    hw_mode=${cfg.hwMode}
    channel=${toString cfg.channel}

    # logging (debug level)
    logger_syslog=-1
    logger_syslog_level=2
    logger_stdout=-1
    logger_stdout_level=2

    ctrl_interface=/var/run/hostapd
    ctrl_interface_group=${cfg.group}

    ${if cfg.wpa then ''
      wpa=1
      wpa_passphrase=${cfg.wpaPassphrase}
      '' else ""}

    ${cfg.extraCfg}
    '' ;

in

{
  ###### interface

  options = {

    services.hostapd = {

      enable = mkOption {
        default = false;
        description = ''
          enable putting a wireless interface into infrastructure mode,
          allowing other wireless devices to associate with the wireless interface and do
          wireless networking. A simple access point will enable hostapd.wpa, and
          hostapd.wpa_passphrase, hostapd.ssid, dhcpd on the wireless interface to
          provide IP addresses to the associated stations, and nat (from the wireless
          interface to an upstream interface). 
        '';
      };

      interface = mkOption {
        default = "";
        example = "wlan0";
        description = ''
          The interfaces <command>hostapd</command> will use. 
        '';
      };

      driver = mkOption {
        default = "nl80211";
        example = "hostapd";
        type = types.string;
        description = "Which driver hostapd will use. Most things will probably use the default.";
      };

      ssid = mkOption {
        default = "nixos";
        example = "mySpecialSSID";
        type = types.string;
        description = "SSID to be used in IEEE 802.11 management frames.";
      };

      hwMode = mkOption {
        default = "b";
        example = "g";
        type = types.string;
        description = "Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g";
      };

      channel = mkOption { 
        default = 7;
        example = 11;
        type = types.int;
        description = 
          ''
          Channel number (IEEE 802.11)
          Please note that some drivers do not use this value from hostapd and the
          channel will need to be configured separately with iwconfig.
          '';
      };

      group = mkOption {
        default = "wheel";
        example = "network";
        type = types.string;
        description = "members of this group can control hostapd";
        };

      wpa = mkOption {
        default = true;
        description = "enable WPA (IEEE 802.11i/D3.0) to authenticate to the access point";
        };

      wpaPassphrase = mkOption {
        default = "my_sekret";
        example = "any_64_char_string";
        type = types.string;
        description = "WPA-PSK (pre-shared-key) passphrase. Clients will need this passphrase to associate with this access point";
        };

      extraCfg = mkOption {
        default = "";
        example = ''
          auth_algo=0
          ieee80211n=1
          ht_capab=[HT40-][SHORT-GI-40][DSSS_CCK-40]
          '';
        type = types.string;
        description = "Extra configuration options to put in the hostapd.conf";
        };
      };
    };


  ###### implementation

  config = mkIf cfg.enable {

    environment.systemPackages =  [ pkgs.hostapd ];

    jobs.hostapd =
      { startOn = "started network-interfaces";
        stopOn = "stopping network-interfaces";

        script =
          ''
            exec ${pkgs.hostapd}/bin/hostapd ${configFile}
          '';
      };
  };
}