mirror of
https://github.com/alexhopeoconnor/WiFiManager.git
synced 2026-10-22 10:42:10 +10:00
test: containerize portal hardware contract
This commit is contained in:
Executable
+152
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shared host-side helpers for the WiFiManager portal hardware contract.
|
||||
# They never modify a network interface other than the explicit client adapter.
|
||||
|
||||
wm_portal_state_root() {
|
||||
printf '%s/wifimanager-portal-hardware' "${XDG_STATE_HOME:-$HOME/.local/state}"
|
||||
}
|
||||
|
||||
wm_require() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "Required command not found: $1" >&2
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
wm_default_route_interface() {
|
||||
ip route show default 2>/dev/null | awk '/^default/{print $5; exit}'
|
||||
}
|
||||
|
||||
wm_acquire_hardware_lock() {
|
||||
local lock_file="${WM_HARDWARE_LOCK_FILE:-/tmp/wifimanager-hardware.lock}"
|
||||
exec 9>"$lock_file"
|
||||
flock -n 9 || {
|
||||
echo "Another WiFiManager hardware task is already running; wait for it to finish." >&2
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
wm_require_client_adapter() {
|
||||
local interface="$1" allow_takeover="$2" default_interface active_connection
|
||||
ip link show "$interface" >/dev/null 2>&1 || {
|
||||
echo "Wi-Fi interface not found: $interface" >&2
|
||||
return 1
|
||||
}
|
||||
default_interface="$(wm_default_route_interface)"
|
||||
[[ "$interface" != "$default_interface" ]] || {
|
||||
echo "Refusing to use the host default-route interface: $interface" >&2
|
||||
return 1
|
||||
}
|
||||
active_connection="$(nmcli -g GENERAL.CONNECTION device show "$interface" 2>/dev/null || true)"
|
||||
if [[ -n "$active_connection" && "$active_connection" != "--" && "$allow_takeover" != "yes" ]]; then
|
||||
echo "Client adapter $interface already has connection '$active_connection'." >&2
|
||||
echo "Pass --take-over-client-adapter to replace only that adapter's connection." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
wm_portal_ssid() {
|
||||
case "$1" in
|
||||
esp8266) printf '%s\n' 'WM Contract ESP8266' ;;
|
||||
esp32) printf '%s\n' 'WM Contract ESP32' ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
wm_wait_for_portal_ssid() {
|
||||
local interface="$1" ssid="$2" attempt
|
||||
nmcli device wifi rescan ifname "$interface" >/dev/null 2>&1 || true
|
||||
for attempt in $(seq 1 45); do
|
||||
if nmcli -t -f SSID device wifi list ifname "$interface" | grep -Fxq "$ssid"; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
nmcli device wifi rescan ifname "$interface" >/dev/null 2>&1 || true
|
||||
done
|
||||
echo "Portal SSID not detected on $interface: $ssid" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
wm_remove_connection_by_name() {
|
||||
local name="$1"
|
||||
[[ -n "$name" ]] || return 0
|
||||
nmcli connection down "$name" >/dev/null 2>&1 || true
|
||||
nmcli connection delete "$name" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
wm_create_portal_connection() {
|
||||
local interface="$1" ssid="$2" password="$3" name uuid
|
||||
name="wifimanager-portal-${RANDOM}-$(date +%s)"
|
||||
nmcli device disconnect "$interface" >/dev/null 2>&1 || true
|
||||
wm_wait_for_portal_ssid "$interface" "$ssid"
|
||||
if ! nmcli connection add type wifi ifname "$interface" con-name "$name" ssid "$ssid" \
|
||||
ipv4.method auto ipv4.never-default yes ipv6.method ignore connection.autoconnect no >/dev/null; then
|
||||
return 1
|
||||
fi
|
||||
if ! nmcli connection modify "$name" wifi-sec.key-mgmt wpa-psk wifi-sec.psk "$password"; then
|
||||
wm_remove_connection_by_name "$name"
|
||||
return 1
|
||||
fi
|
||||
if ! nmcli connection up "$name" ifname "$interface"; then
|
||||
wm_remove_connection_by_name "$name"
|
||||
return 1
|
||||
fi
|
||||
uuid="$(nmcli -g connection.uuid connection show "$name")"
|
||||
if [[ -z "$uuid" || "$uuid" == "--" ]]; then
|
||||
wm_remove_connection_by_name "$name"
|
||||
echo "NetworkManager did not return a UUID for the portal connection." >&2
|
||||
return 1
|
||||
fi
|
||||
WM_PORTAL_CONNECTION_UUID="$uuid"
|
||||
WM_PORTAL_CONNECTION_NAME="$name"
|
||||
export WM_PORTAL_CONNECTION_UUID WM_PORTAL_CONNECTION_NAME
|
||||
}
|
||||
|
||||
wm_verify_portal_route() {
|
||||
local interface="$1" route
|
||||
route="$(ip route get 192.168.4.1 2>/dev/null || true)"
|
||||
[[ "$route" == *" dev $interface "* ]] || {
|
||||
echo "Portal route does not use the selected adapter: $route" >&2
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
wm_remove_connection() {
|
||||
local uuid="$1"
|
||||
[[ -n "$uuid" ]] || return 0
|
||||
nmcli connection down uuid "$uuid" >/dev/null 2>&1 || true
|
||||
nmcli connection delete uuid "$uuid" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
wm_state_file() {
|
||||
printf '%s/session.env\n' "$(wm_portal_state_root)"
|
||||
}
|
||||
|
||||
wm_write_state() {
|
||||
local interface="$1" platform="$2" uuid="$3" name="$4" root file
|
||||
root="$(wm_portal_state_root)"
|
||||
file="$(wm_state_file)"
|
||||
install -d -m 700 "$root"
|
||||
umask 077
|
||||
printf 'WM_PORTAL_INTERFACE=%q\nWM_PORTAL_PLATFORM=%q\nWM_PORTAL_CONNECTION_UUID=%q\nWM_PORTAL_CONNECTION_NAME=%q\n' \
|
||||
"$interface" "$platform" "$uuid" "$name" >"$file"
|
||||
chmod 600 "$file"
|
||||
}
|
||||
|
||||
wm_load_state() {
|
||||
local file
|
||||
file="$(wm_state_file)"
|
||||
[[ -f "$file" ]] || {
|
||||
echo "No active WiFiManager portal session was found." >&2
|
||||
return 1
|
||||
}
|
||||
# The state file is created above using shell-escaped values and mode 0600.
|
||||
# shellcheck disable=SC1090
|
||||
source "$file"
|
||||
}
|
||||
|
||||
wm_clear_state() {
|
||||
local file
|
||||
file="$(wm_state_file)"
|
||||
rm -f "$file"
|
||||
}
|
||||
Reference in New Issue
Block a user