mirror of
https://gitlab.com/hacklab01/pivilion.git
synced 2026-08-06 16:08:22 +00:00
Activate offline mode changes on next boot
This commit is contained in:
parent
eda151065c
commit
b5e19f08f6
9 changed files with 94 additions and 14 deletions
|
|
@ -5,6 +5,7 @@
|
|||
PIVILION_CONFIG=""
|
||||
PIVILION_STATE_DIR=${PIVILION_STATE_DIR:-/run/pivilion}
|
||||
PIVILION_STATE_FILE=${PIVILION_STATE_FILE:-$PIVILION_STATE_DIR/status.tsv}
|
||||
PIVILION_SELECTED_MODE_FILE=${PIVILION_SELECTED_MODE_FILE:-$PIVILION_STATE_DIR/selected-mode}
|
||||
|
||||
# Stable command exit codes. Keep these public so scripts and monitoring can
|
||||
# distinguish configuration, hardware, service, captive portal, and Tor faults.
|
||||
|
|
@ -158,6 +159,12 @@ pivilion_current_mode() {
|
|||
printf '%s\n' "$PIVILION_MODE"
|
||||
}
|
||||
|
||||
pivilion_selected_mode() {
|
||||
local mode
|
||||
mode=$(head -n1 "$PIVILION_SELECTED_MODE_FILE" 2>/dev/null || true)
|
||||
case "$mode" in hotspot|onion) printf '%s\n' "$mode" ;; *) return 1 ;; esac
|
||||
}
|
||||
|
||||
pivilion_require_root() {
|
||||
[ "$(id -u)" -eq 0 ] || { echo "This operation must run as root (use sudo)." >&2; return 1; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ EOF
|
|||
}
|
||||
|
||||
write_canonical() {
|
||||
local tmp
|
||||
local tmp mode_tmp
|
||||
require_writable_boot
|
||||
tmp=$(mktemp "$BOOT_ROOT/.pivilion-conf.XXXXXX")
|
||||
render_config > "$tmp"
|
||||
|
|
@ -134,6 +134,10 @@ write_canonical() {
|
|||
sync -f "$BOOT_ROOT" 2>/dev/null || sync
|
||||
atomic_copy "$BOOT_CONFIG" "$LAST_GOOD" 0600
|
||||
atomic_copy "$BOOT_CONFIG" /run/pivilion/effective.conf 0600
|
||||
mode_tmp=$(mktemp)
|
||||
printf '%s\n' "$PIVILION_MODE" > "$mode_tmp"
|
||||
atomic_copy "$mode_tmp" "$PIVILION_SELECTED_MODE_FILE" 0644
|
||||
rm -f "$mode_tmp"
|
||||
rm -f "$BOOT_ERROR"
|
||||
}
|
||||
|
||||
|
|
@ -255,11 +259,18 @@ set_value() {
|
|||
|
||||
case "$ACTION" in
|
||||
apply|initialize)
|
||||
if [ "$ACTION" = apply ]; then
|
||||
rm -f /run/pivilion/effective.conf "$PIVILION_SELECTED_MODE_FILE"
|
||||
fi
|
||||
if ! load_boot_or_detect; then
|
||||
fail_boot "Invalid pivilion.conf; the last-known-good settings were retained"
|
||||
[ -r "$LAST_GOOD" ] || exit "$PIVILION_E_CONFIG"
|
||||
PIVILION_CONFIG_PATHS=$LAST_GOOD pivilion_load_config || exit "$PIVILION_E_CONFIG"
|
||||
atomic_copy "$LAST_GOOD" /run/pivilion/effective.conf 0600
|
||||
mode_tmp=$(mktemp)
|
||||
printf '%s\n' "$PIVILION_MODE" > "$mode_tmp"
|
||||
atomic_copy "$mode_tmp" "$PIVILION_SELECTED_MODE_FILE" 0644
|
||||
rm -f "$mode_tmp"
|
||||
[ "$ACTION" = initialize ] || apply_runtime
|
||||
exit 0
|
||||
fi
|
||||
|
|
@ -282,5 +293,9 @@ case "$ACTION" in
|
|||
sync-status)
|
||||
PIVILION_CONFIG_PATHS=$BOOT_CONFIG pivilion_load_config || exit "$PIVILION_E_CONFIG"
|
||||
write_canonical ;;
|
||||
*) echo "Usage: config-sync.sh apply|initialize|set KEY VALUE|set-wifi SSID PASSWORD|sync-status" >&2; exit 2 ;;
|
||||
record-error)
|
||||
shift
|
||||
[ "$#" -gt 0 ] || { echo "Usage: config-sync.sh record-error MESSAGE" >&2; exit 2; }
|
||||
fail_boot "$*" ;;
|
||||
*) echo "Usage: config-sync.sh apply|initialize|set KEY VALUE|set-wifi SSID PASSWORD|sync-status|record-error MESSAGE" >&2; exit 2 ;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -5,8 +5,30 @@ source /usr/local/lib/pivilion/common.sh
|
|||
pivilion_require_root
|
||||
pivilion_load_config || exit "$PIVILION_E_CONFIG"
|
||||
|
||||
MODE=${1:-$(pivilion_current_mode)}
|
||||
if [ "${1:---boot-selected}" = --boot-selected ]; then
|
||||
MODE=$(pivilion_selected_mode) || {
|
||||
echo "No validated boot mode was produced by pivilion-config.service" >&2
|
||||
/usr/local/lib/pivilion/config-sync.sh record-error "No validated boot mode was produced during startup" >/dev/null 2>&1 || true
|
||||
exit "$PIVILION_E_CONFIG"
|
||||
}
|
||||
[ "$MODE" = "$(pivilion_current_mode)" ] || {
|
||||
echo "Validated boot mode does not match the effective configuration" >&2
|
||||
/usr/local/lib/pivilion/config-sync.sh record-error "Validated boot mode does not match the effective configuration" >/dev/null 2>&1 || true
|
||||
exit "$PIVILION_E_CONFIG"
|
||||
}
|
||||
else
|
||||
MODE=$1
|
||||
fi
|
||||
case "$MODE" in hotspot|onion) ;; *) echo "Unknown Pivilion mode: $MODE" >&2; exit 2 ;; esac
|
||||
|
||||
mode_exit() {
|
||||
local rc=$? failure
|
||||
[ "$rc" -eq 0 ] && return
|
||||
failure=$(pivilion_state_value failure "activation exited with status $rc")
|
||||
/usr/local/lib/pivilion/config-sync.sh record-error "Failed to activate $MODE mode: $failure (exit $rc)" >/dev/null 2>&1 || true
|
||||
logger -t pivilion-mode "Failed to activate $MODE mode: $failure (exit $rc)" 2>/dev/null || true
|
||||
}
|
||||
trap mode_exit EXIT
|
||||
IFACE=$(pivilion_wifi_interface)
|
||||
[ -n "$IFACE" ] && [ -d "/sys/class/net/$IFACE" ] || {
|
||||
pivilion_write_state none none failed "Wi-Fi interface not found"
|
||||
|
|
@ -32,9 +54,12 @@ refresh_login_banner() {
|
|||
}
|
||||
|
||||
activation_error() {
|
||||
local rc=$? line=${BASH_LINENO[0]:-unknown}
|
||||
local rc=$? line=${BASH_LINENO[0]:-unknown} existing
|
||||
trap - ERR
|
||||
pivilion_write_state none "$BACKEND" failed "Activation failed at line $line (exit $rc)" || true
|
||||
existing=$(pivilion_state_value failure none)
|
||||
if [ "$existing" = none ] || [ "$existing" = unknown ]; then
|
||||
pivilion_write_state none "$BACKEND" failed "Activation failed at line $line (exit $rc)" || true
|
||||
fi
|
||||
refresh_login_banner || true
|
||||
logger -t pivilion-mode "Failed to activate $MODE mode at line $line (exit $rc)" 2>/dev/null || true
|
||||
exit "$rc"
|
||||
|
|
@ -152,6 +177,15 @@ wait_for_default_route() {
|
|||
return 1
|
||||
}
|
||||
|
||||
wait_for_diagnostics() {
|
||||
local mode=$1 i
|
||||
for i in $(seq 1 10); do
|
||||
/usr/local/lib/pivilion/diagnose.sh --mode "$mode" --quiet && return 0
|
||||
sleep 1
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
restart_tor() {
|
||||
if systemctl cat tor@default.service >/dev/null 2>&1; then systemctl restart tor@default.service; else systemctl restart tor.service; fi
|
||||
}
|
||||
|
|
@ -196,6 +230,7 @@ start_hotspot() {
|
|||
rfkill unblock wifi 2>/dev/null || true
|
||||
systemctl start apache2
|
||||
if [ "$BACKEND" = networkmanager ]; then
|
||||
nmcli device disconnect "$IFACE" >/dev/null 2>&1 || true
|
||||
nmcli connection add type wifi ifname "$IFACE" con-name "$NM_HOTSPOT" ssid "$PIVILION_HOTSPOT_SSID"
|
||||
nmcli connection modify "$NM_HOTSPOT" 802-11-wireless.mode ap 802-11-wireless.band bg \
|
||||
802-11-wireless.channel "$PIVILION_HOTSPOT_CHANNEL" \
|
||||
|
|
@ -209,11 +244,12 @@ start_hotspot() {
|
|||
fi
|
||||
systemctl restart pivilion-dnsmasq.service
|
||||
apply_firewall
|
||||
if /usr/local/lib/pivilion/diagnose.sh --mode hotspot --quiet; then
|
||||
if wait_for_diagnostics hotspot; then
|
||||
pivilion_write_state hotspot "$BACKEND" healthy none
|
||||
else
|
||||
pivilion_write_state hotspot "$BACKEND" degraded "Post-start captive portal diagnostics failed"
|
||||
logger -t pivilion-mode "Hotspot active but degraded; run pivilion diagnose" || true
|
||||
pivilion_write_state none "$BACKEND" failed "Post-start captive portal diagnostics failed"
|
||||
refresh_login_banner
|
||||
return "$PIVILION_E_CAPTIVE"
|
||||
fi
|
||||
refresh_login_banner
|
||||
/usr/local/lib/pivilion/config-sync.sh sync-status || logger -t pivilion-mode "Could not mirror hotspot status to the boot partition"
|
||||
|
|
@ -235,11 +271,12 @@ start_onion() {
|
|||
systemctl start apache2
|
||||
restart_tor
|
||||
update_torname || failure="${failure:+$failure; }Tor did not produce a valid hostname; retained previous value"
|
||||
if [ -z "$failure" ] && /usr/local/lib/pivilion/diagnose.sh --mode onion --quiet; then
|
||||
if [ -z "$failure" ] && wait_for_diagnostics onion; then
|
||||
pivilion_write_state onion "$BACKEND" healthy none
|
||||
else
|
||||
pivilion_write_state onion "$BACKEND" degraded "${failure:-Onion diagnostics failed}"
|
||||
logger -t pivilion-mode "Onion mode active but degraded: ${failure:-diagnostics failed}" || true
|
||||
pivilion_write_state none "$BACKEND" failed "${failure:-Onion diagnostics failed}"
|
||||
refresh_login_banner
|
||||
return "$PIVILION_E_TOR"
|
||||
fi
|
||||
refresh_login_banner
|
||||
/usr/local/lib/pivilion/config-sync.sh sync-status || logger -t pivilion-mode "Could not mirror onion status to the boot partition"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue