Merge pull request #123 from outis1one/claude/laughing-sagan-2oo2mx
Claude/laughing sagan 2oo2mx
This commit is contained in:
@@ -242,6 +242,9 @@ provision_install_wifi_helper() {
|
|||||||
log_warning "Couldn't set up the kiosk WiFi screen's permission - Ctrl+Alt+Super+W won't be able to connect"
|
log_warning "Couldn't set up the kiosk WiFi screen's permission - Ctrl+Alt+Super+W won't be able to connect"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp"
|
rm -f "$tmp"
|
||||||
|
# Flaky cheap dongles (RTL8188CUS...) need WiFi power saving off.
|
||||||
|
provision_install_file "etc/udev/rules.d/70-kiosk-wifi-power.rules" /etc/udev/rules.d/70-kiosk-wifi-power.rules
|
||||||
|
sudo udevadm control --reload-rules 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
provision_configure_firewall() {
|
provision_configure_firewall() {
|
||||||
|
|||||||
+84
-3
@@ -57,17 +57,91 @@ try:
|
|||||||
del w[n]
|
del w[n]
|
||||||
if not w:
|
if not w:
|
||||||
del d["network"]["wifis"]
|
del d["network"]["wifis"]
|
||||||
|
# Not "optional" = the boot waits (up to ~2 min) for it to get an address.
|
||||||
|
opt = [n for n, v in w.items() if isinstance(v, dict) and not v.get("optional")]
|
||||||
|
for n in opt:
|
||||||
|
w[n]["optional"] = True
|
||||||
|
if stale or opt:
|
||||||
|
if not stale:
|
||||||
|
shutil.copy2(p, p + ".kiosk-bak")
|
||||||
mode = os.stat(p).st_mode & 0o777
|
mode = os.stat(p).st_mode & 0o777
|
||||||
with open(p, "w") as fh:
|
with open(p, "w") as fh:
|
||||||
yaml.safe_dump(d, fh, default_flow_style=False)
|
yaml.safe_dump(d, fh, default_flow_style=False)
|
||||||
os.chmod(p, mode)
|
os.chmod(p, mode)
|
||||||
print("Removed stale WiFi entries from %s: %s" % (p, ", ".join(map(str, stale))))
|
print("Fixed WiFi entries in %s (removed: %s)" % (p, ", ".join(map(str, stale)) or "none"))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
PYEOF
|
PYEOF
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Why a connect attempt failed, from wpa_supplicant's own log lines in
|
||||||
|
# the journal (netplan runs it as netplan-wpa-<iface>.service). Prints a
|
||||||
|
# short human-readable reason, or nothing if the log says nothing useful.
|
||||||
|
wifi_diagnose() {
|
||||||
|
local log
|
||||||
|
log=$(journalctl -b -u "netplan-wpa-$1" -n 150 --no-pager 2>/dev/null) || return 0
|
||||||
|
if grep -q "reason=WRONG_KEY\|pre-shared key may be incorrect" <<< "$log"; then
|
||||||
|
echo "wrong password (the network rejected the key)"
|
||||||
|
elif grep -q "CTRL-EVENT-NETWORK-NOT-FOUND" <<< "$log"; then
|
||||||
|
echo "network not found - wrong name, or out of range of this adapter"
|
||||||
|
elif grep -q "CTRL-EVENT-ASSOC-REJECT\|CTRL-EVENT-AUTH-REJECT" <<< "$log"; then
|
||||||
|
echo "the access point refused the connection (MAC filter, or WPA3-only/unsupported security)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Every wireless interface, one per line.
|
||||||
|
wifi_list_ifaces() {
|
||||||
|
local d
|
||||||
|
for d in /sys/class/net/*; do
|
||||||
|
if [[ -d "$d/wireless" || -e "$d/phy80211" ]]; then
|
||||||
|
basename "$d"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# "USB" / "PCI" / "" - what an interface hangs off, to tell a dongle
|
||||||
|
# from a built-in card when there are two.
|
||||||
|
wifi_iface_bus() {
|
||||||
|
local sub
|
||||||
|
sub=$(readlink -f "/sys/class/net/$1/device/subsystem" 2>/dev/null) || return 0
|
||||||
|
case "$sub" in
|
||||||
|
*/usb) echo "USB" ;;
|
||||||
|
*/pci) echo "PCI" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# The interface to configure: the only one, or the user's pick when there
|
||||||
|
# are several (e.g. built-in card plus a USB dongle).
|
||||||
|
wifi_choose_iface() {
|
||||||
|
local -a ifaces
|
||||||
|
mapfile -t ifaces < <(wifi_list_ifaces)
|
||||||
|
if (( ${#ifaces[@]} == 0 )); then
|
||||||
|
wifi_detect_iface
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if (( ${#ifaces[@]} == 1 )); then
|
||||||
|
echo "${ifaces[0]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo "Several WiFi adapters found:"
|
||||||
|
local i bus
|
||||||
|
for i in "${!ifaces[@]}"; do
|
||||||
|
bus=$(wifi_iface_bus "${ifaces[$i]}")
|
||||||
|
printf ' %d. %s%s\n' "$((i + 1))" "${ifaces[$i]}" "${bus:+ ($bus)}"
|
||||||
|
done
|
||||||
|
} >&2
|
||||||
|
local choice
|
||||||
|
read -r -p "Which one? [1]: " choice </dev/tty >&2
|
||||||
|
choice=${choice:-1}
|
||||||
|
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#ifaces[@]} )); then
|
||||||
|
echo "${ifaces[$((choice - 1))]}"
|
||||||
|
else
|
||||||
|
echo "${ifaces[0]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
wifi_menu() {
|
wifi_menu() {
|
||||||
local rc=0
|
local rc=0
|
||||||
wifi_configure || rc=$?
|
wifi_configure || rc=$?
|
||||||
@@ -165,7 +239,7 @@ wifi_configure() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local wifi_iface
|
local wifi_iface
|
||||||
if ! wifi_iface=$(wifi_detect_iface); then
|
if ! wifi_iface=$(wifi_choose_iface); then
|
||||||
log_warning "No WiFi hardware detected"
|
log_warning "No WiFi hardware detected"
|
||||||
echo "Network interfaces found: $(ls /sys/class/net 2>/dev/null | tr '\n' ' ')"
|
echo "Network interfaces found: $(ls /sys/class/net 2>/dev/null | tr '\n' ' ')"
|
||||||
echo "If you have a USB WiFi adapter, make sure it's plugged in. A built-in"
|
echo "If you have a USB WiFi adapter, make sure it's plugged in. A built-in"
|
||||||
@@ -344,7 +418,14 @@ WATCHEOF
|
|||||||
[[ -n "${SSH_CONNECTION:-}" ]] && echo "Connection successful - watchdog will not revert"
|
[[ -n "${SSH_CONNECTION:-}" ]] && echo "Connection successful - watchdog will not revert"
|
||||||
else
|
else
|
||||||
log_warning "Config applied but $wifi_iface has no address yet"
|
log_warning "Config applied but $wifi_iface has no address yet"
|
||||||
echo "Wrong password or network name is the usual cause. Details:"
|
local why
|
||||||
|
why=$(wifi_diagnose "$wifi_iface")
|
||||||
|
if [[ -n "$why" ]]; then
|
||||||
|
log_error "Couldn't connect to $ssid: $why"
|
||||||
|
else
|
||||||
|
echo "Wrong password or network name is the usual cause."
|
||||||
|
fi
|
||||||
|
echo "Details:"
|
||||||
echo " sudo journalctl -b -u 'netplan-wpa-*' -u systemd-networkd -n 30 --no-pager"
|
echo " sudo journalctl -b -u 'netplan-wpa-*' -u systemd-networkd -n 30 --no-pager"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Keep WiFi adapters awake. Power saving (the adapter dozing between
|
||||||
|
# packets, and the USB port suspending an idle dongle) is what makes
|
||||||
|
# cheap dongles like the Realtek RTL8188CUS drop or stall a connection.
|
||||||
|
# Both are ordinary software settings, so nothing here can harm the
|
||||||
|
# hardware: the cost is a fraction of a watt.
|
||||||
|
|
||||||
|
# Radio power save off on every WiFi interface as it appears.
|
||||||
|
ACTION=="add", SUBSYSTEM=="net", KERNEL=="wl*", RUN+="/usr/sbin/iw dev $name set power_save off"
|
||||||
|
|
||||||
|
# No USB autosuspend for the common RTL8188/8192 CU/CUS/RU dongles.
|
||||||
|
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0bda", ATTR{idProduct}=="8176|8177|8178|8179|817a|817b|817c|817d|817e|8191", TEST=="power/control", ATTR{power/control}="on"
|
||||||
@@ -107,8 +107,40 @@ except Exception:
|
|||||||
pass' "$WIFI_NETPLAN_FILE" 2>/dev/null
|
pass' "$WIFI_NETPLAN_FILE" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Why a connect attempt failed, from wpa_supplicant's own log lines in
|
||||||
|
# the journal (netplan runs it as netplan-wpa-<iface>.service). Prints a
|
||||||
|
# short human-readable reason, or nothing if the log says nothing useful.
|
||||||
|
diagnose_failure() {
|
||||||
|
local log
|
||||||
|
log=$(journalctl -b -u "netplan-wpa-$1" -n 150 --no-pager 2>/dev/null) || return 0
|
||||||
|
if grep -q "reason=WRONG_KEY\|pre-shared key may be incorrect" <<< "$log"; then
|
||||||
|
echo "wrong password (the network rejected the key)"
|
||||||
|
elif grep -q "CTRL-EVENT-NETWORK-NOT-FOUND" <<< "$log"; then
|
||||||
|
echo "network not found - wrong name, or out of range of this adapter"
|
||||||
|
elif grep -q "CTRL-EVENT-ASSOC-REJECT\|CTRL-EVENT-AUTH-REJECT" <<< "$log"; then
|
||||||
|
echo "the access point refused the connection (MAC filter, or WPA3-only/unsupported security)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prefer the adapter our netplan file already configures (if it's still
|
||||||
|
# there) over "first one found", so a built-in card plus a USB dongle
|
||||||
|
# don't swap places between calls.
|
||||||
|
prefer_configured_iface() {
|
||||||
|
[[ -f "$WIFI_NETPLAN_FILE" ]] || return 1
|
||||||
|
python3 -I -c '
|
||||||
|
import sys, os, yaml
|
||||||
|
try:
|
||||||
|
d = yaml.safe_load(open(sys.argv[1]))
|
||||||
|
for n in (d.get("network", {}).get("wifis") or {}):
|
||||||
|
if os.path.exists(sys.argv[2] + "/net/" + str(n)):
|
||||||
|
print(n); sys.exit(0)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
sys.exit(1)' "$WIFI_NETPLAN_FILE" "$SYS_CLASS" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
need_iface() {
|
need_iface() {
|
||||||
IFACE=$(detect_iface) || reply_error "No WiFi adapter found. If it's a USB adapter, check it's plugged in."
|
IFACE=$(prefer_configured_iface || detect_iface) || reply_error "No WiFi adapter found. If it's a USB adapter, check it's plugged in."
|
||||||
command -v iw >/dev/null || reply_error "WiFi support (iw, wpasupplicant) isn't installed - run Core Settings -> WiFi once from the admin menu"
|
command -v iw >/dev/null || reply_error "WiFi support (iw, wpasupplicant) isn't installed - run Core Settings -> WiFi once from the admin menu"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,11 +223,18 @@ try:
|
|||||||
del w[n]
|
del w[n]
|
||||||
if not w:
|
if not w:
|
||||||
del d["network"]["wifis"]
|
del d["network"]["wifis"]
|
||||||
|
# Not "optional" = the boot waits (up to ~2 min) for it to get an address.
|
||||||
|
opt = [n for n, v in w.items() if isinstance(v, dict) and not v.get("optional")]
|
||||||
|
for n in opt:
|
||||||
|
w[n]["optional"] = True
|
||||||
|
if stale or opt:
|
||||||
|
if not stale:
|
||||||
|
shutil.copy2(p, p + ".kiosk-bak")
|
||||||
mode = os.stat(p).st_mode & 0o777
|
mode = os.stat(p).st_mode & 0o777
|
||||||
with open(p, "w") as fh:
|
with open(p, "w") as fh:
|
||||||
yaml.safe_dump(d, fh, default_flow_style=False)
|
yaml.safe_dump(d, fh, default_flow_style=False)
|
||||||
os.chmod(p, mode)
|
os.chmod(p, mode)
|
||||||
print("Removed stale WiFi entries from %s: %s" % (p, ", ".join(map(str, stale))))
|
print("Fixed WiFi entries in %s (removed: %s)" % (p, ", ".join(map(str, stale)) or "none"))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
PYEOF
|
PYEOF
|
||||||
@@ -271,6 +310,11 @@ do_connect() {
|
|||||||
|
|
||||||
if [[ -z "$addr" ]]; then
|
if [[ -z "$addr" ]]; then
|
||||||
restore "$backup"
|
restore "$backup"
|
||||||
|
local why
|
||||||
|
why=$(diagnose_failure "$IFACE")
|
||||||
|
if [[ -n "$why" ]]; then
|
||||||
|
reply_error "Couldn't connect to \"$ssid\": $why."
|
||||||
|
fi
|
||||||
if [[ -n "$backup" ]]; then
|
if [[ -n "$backup" ]]; then
|
||||||
reply_error "Couldn't connect to \"$ssid\" - wrong password, or out of range. The previous WiFi setting was put back."
|
reply_error "Couldn't connect to \"$ssid\" - wrong password, or out of range. The previous WiFi setting was put back."
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user