hackbox-hostapd/patch-fix-disconnect

101 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# patch_hotspot_apmode.sh
# Make wlan0 persistent AP-mode and ensure hostapd can use it.
# Run as root: sudo ./patch_hotspot_apmode.sh
set -euo pipefail
AP_IF="wlan0"
NM_CONF="/etc/NetworkManager/conf.d/unmanaged-wlan0.conf"
UDEV_RULE="/etc/udev/rules.d/90-wlan0-apmode.rules"
IW_PATH="$(command -v iw || true)"
if [ "$(id -u)" -ne 0 ]; then
echo "Please run as root (sudo)."
exit 2
fi
echo "== patch_hotspot_apmode: starting =="
echo
# 1) Tell NetworkManager to ignore wlan0 (idempotent)
if [ -f "$NM_CONF" ] && grep -q "interface-name:${AP_IF}" "$NM_CONF"; then
echo "[+] NetworkManager already configured to ignore $AP_IF ($NM_CONF)"
else
echo "[*] Writing NetworkManager unmanaged conf -> $NM_CONF"
mkdir -p "$(dirname "$NM_CONF")"
cat > "$NM_CONF" <<EOF
[keyfile]
unmanaged-devices=interface-name:$AP_IF
EOF
echo "[*] Restarting NetworkManager..."
systemctl restart NetworkManager || true
fi
# 2) Create udev rule to set wlan0 to AP mode when added (idempotent)
if [ -f "$UDEV_RULE" ] && grep -q "iw $AP_IF set type ap" "$UDEV_RULE"; then
echo "[+] udev rule already exists -> $UDEV_RULE"
else
echo "[*] Writing udev rule -> $UDEV_RULE"
cat > "$UDEV_RULE" <<EOF
ACTION=="add", SUBSYSTEM=="net", KERNEL=="$AP_IF", RUN+="${IW_PATH:-/usr/sbin/iw} $AP_IF set type ap"
EOF
echo "[*] Reloading udev rules..."
udevadm control --reload-rules || true
udevadm trigger --action=add --subsystem-match=net || true
fi
# 3) Stop services/processes that may hold wlan0 right now
echo "[*] Stopping services that might grab $AP_IF (NetworkManager, wpa_supplicant) for the moment..."
systemctl stop NetworkManager || true
# Try stopping wpa_supplicant systemd instance for the iface, but tolerate failure
systemctl stop "wpa_supplicant@${AP_IF}.service" >/dev/null 2>&1 || true
# Kill any lingering wpa_supplicant processes bound to the interface
pkill -f "wpa_supplicant.*${AP_IF}" >/dev/null 2>&1 || true
# 4) Force interface down -> ap mode -> up (immediate)
if [ -z "$IW_PATH" ]; then
echo "[!] 'iw' command not found. Please install 'iw' and re-run this script."
exit 3
fi
echo "[*] Forcing $AP_IF to AP mode now..."
ip link set "$AP_IF" down || true
# set type ap (if already ap this is harmless)
$IW_PATH "$AP_IF" set type ap || {
echo "[!] Failed to set $AP_IF to AP via iw. Check driver support (iw list)."
# continue so hostapd restart attempt still happens
}
ip link set "$AP_IF" up || true
# 5) Restart hostapd + dnsmasq (so hostapd binds to AP-mode iface)
echo "[*] Starting hostapd and dnsmasq (or restarting if already running)..."
systemctl unmask hostapd >/dev/null 2>&1 || true
systemctl restart hostapd || echo "[!] hostapd restart returned non-zero (check sudo journalctl -u hostapd)"
systemctl restart dnsmasq || echo "[!] dnsmasq restart returned non-zero (check sudo journalctl -u dnsmasq)"
# 6) Re-enable NetworkManager (but it will ignore wlan0 now)
echo "[*] Re-enabling NetworkManager (it should ignore $AP_IF per conf)..."
systemctl start NetworkManager || true
# 7) Persist iptables if netfilter-persistent exists
if command -v netfilter-persistent >/dev/null 2>&1; then
echo "[*] Saving iptables rules via netfilter-persistent..."
netfilter-persistent save || echo "[!] netfilter-persistent save failed (check rules)"
else
echo "[*] netfilter-persistent not installed; skipping iptables save."
fi
# 8) Final status + verification commands
echo
echo "== done =="
echo "Quick checks you can run now:"
echo " iw dev"
echo " sudo systemctl status hostapd dnsmasq NetworkManager"
echo " sudo journalctl -u hostapd -n 50"
echo
echo "If you reboot, udev will attempt to set $AP_IF to AP mode automatically and NetworkManager will ignore $AP_IF."
echo "If anything goes wrong, paste the output of: sudo journalctl -u hostapd -n 100"
echo