diff --git a/pkgs/liminix-tools/networking/default.nix b/pkgs/liminix-tools/networking/default.nix index 57694d7..c1818fe 100644 --- a/pkgs/liminix-tools/networking/default.nix +++ b/pkgs/liminix-tools/networking/default.nix @@ -28,6 +28,7 @@ in { }; pppoe = callPackage ./pppoe.nix {}; dnsmasq = callPackage ./dnsmasq.nix {}; + hostapd = callPackage ./hostapd.nix {}; route = { name, target, via, dependencies }: oneshot { inherit name; diff --git a/pkgs/liminix-tools/networking/hostapd.nix b/pkgs/liminix-tools/networking/hostapd.nix new file mode 100644 index 0000000..62a3942 --- /dev/null +++ b/pkgs/liminix-tools/networking/hostapd.nix @@ -0,0 +1,39 @@ +# This is not a friendly interface to configuring a wireless AP: it +# just passes everything straight through to the hostapd config. When +# we've worked out what the sensible options are to expose, we'll add +# them as top-level attributes and rename params to extraParams + +{ + liminix +, hostapd +, lib +, writeText +}: +interface: +{ + params ? {} +}: +let + inherit (liminix.services) longrun; + inherit (lib) concatStringsSep mapAttrsToList; + inherit (builtins) toString; + + name = "${interface.device}.hostapd"; + defaults = { + driver = "nl80211"; + logger_syslog = "-1"; + logger_syslog_level = 1; + ctrl_interface = "/run/hostapd"; + ctrl_interface_group = 0; + }; + + conf = writeText "hostapd.conf" + (concatStringsSep + "\n" + (mapAttrsToList + (name: value: "${name}=${toString value}") + (defaults // params))); +in longrun { + inherit name; + run = "${hostapd}/bin/hostapd -d -i ${interface.device} -P /run/hostapd.pid -S ${conf}"; +} diff --git a/tests/wlan/configuration.nix b/tests/wlan/configuration.nix new file mode 100644 index 0000000..809725d --- /dev/null +++ b/tests/wlan/configuration.nix @@ -0,0 +1,43 @@ +{ config, pkgs, lib, ... } : +let + inherit (pkgs.liminix.networking) interface address hostapd route dnsmasq; + inherit (pkgs.liminix.services) oneshot longrun bundle target output; +in rec { + services.loopback = + let iface = interface { type = "loopback"; device = "lo";}; + in bundle { + name = "loopback"; + contents = [ + (address iface { family = "inet4"; address ="127.0.0.1"; prefixLength = 8;}) + (address iface { family = "inet6"; address ="::1"; prefixLength = 128;}) + ]; + }; + + services.wlan = interface { type = "hardware"; device = "wlan0"; }; + + services.hostap = hostapd (services.wlan) { + params = { + ssid = "liminix"; + country_code = "GB"; + hw_mode="g"; + channel = "2"; + wmm_enabled = 1; + ieee80211n = 1; + wpa_passphrase = "colourless green ideas"; + auth_algs = 1; # 1=wpa2, 2=wep, 3=both + wpa = 2; # 1=wpa, 2=wpa2, 3=both + wpa_key_mgmt = "WPA-PSK"; + wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?) + rsn_pairwise = "CCMP"; # auth for wpa2 + }; + }; + + services.default = target { + name = "default"; + contents = with services; [ + loopback + hostap + ]; + }; + defaultProfile.packages = with pkgs; [ tcpdump ] ; +} diff --git a/tests/wlan/run.sh b/tests/wlan/run.sh new file mode 100755 index 0000000..0c538e8 --- /dev/null +++ b/tests/wlan/run.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env sh + +cleanup(){ + if test -e foo.pid && test -d /proc/`cat foo.pid` ; then + echo "killing qemu" + kill `cat foo.pid` + fi +} +trap cleanup EXIT +fatal(){ + err=$? + echo "FAIL: command $(eval echo $BASH_COMMAND) exited with code $err" + exit $err +} +trap fatal ERR + +NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-build '' -I liminix-config=./configuration.nix --arg device "import " -A outputs.default $* + + + +../../scripts/run-qemu.sh \ + --background foo.sock \ + result/vmlinux result/squashfs \ + +nix-shell -p expect --run "expect wait-for-wlan.expect" diff --git a/tests/wlan/wait-for-wlan.expect b/tests/wlan/wait-for-wlan.expect new file mode 100644 index 0000000..4e2f8a0 --- /dev/null +++ b/tests/wlan/wait-for-wlan.expect @@ -0,0 +1,21 @@ +set timeout 60 + +spawn socat unix-connect:foo.sock - +send "\r\n" +expect "login:" { send "root\r\n" } +expect "/ #" +set FINISHED 0 +set EXIT "1" +send "ls -l /run/uncaught-logs/current\r\n" +expect "/ #" +while { $FINISHED < 10 } { + send "grep AP-ENABLED /run/uncaught-logs/current || echo not\r\n" + + expect { + "wlan0: AP-ENABLED" { set FINISHED 10; set EXIT 0; } + "not" { send_user "waiting ..." ; sleep 5 } + } + set FINISHED [ expr $FINISHED + 1 ] +} + +exit $EXIT