The DNS manager used to apply a selection by writing system/etc/hosts into the live module directory and asking for a reboot, so the root manager would pick it up while assembling /system. That put the module's own tree in the path of whatever the manager does between boots: KernelSU v3 moved that assembly into a separate metamodule, a second hosts module publishing the same path raced it silently, and an upgrade replaced the tree and discarded the user's selection with it. The published file now lives in /data/adb/zapret2-hosts and the module bind-mounts it over /system/etc/hosts from post-fs-data.sh, which is the same mechanism on Magisk, KernelSU and APatch. hosts-overlay.sh owns that mount: it snapshots the untouched system file before covering it, carries a pre-2.3.0 in-tree overlay over and takes it out of the tree, relabels the source so netd can still read it, and yields to another enabled hosts module instead of fighting it for the path. Because the module publishes the mount itself, an edit now takes effect immediately: publication is still an atomic rename, and --apply republishes the mount rather than waiting for a reboot. A rename leaves the live mount on the replaced inode, so the mount identity is recorded when it is published and consulted only against a live mount — a foreign mount is never released. Rollback, uninstall and purge follow the file to its new home, and the installer carries an existing selection across the upgrade that would otherwise drop it. Also releases the tethering runtime key and owner state v9, and lifts the packaged lifecycle contract to 9.
333 lines
14 KiB
Shell
Executable file
333 lines
14 KiB
Shell
Executable file
#!/system/bin/sh
|
|
# In-process replacement for a validated preset whose capture topology changed.
|
|
#
|
|
# The caller holds the lifecycle lock, has authenticated the running process
|
|
# and owner receipt, and has already dry-run the candidate argv. This layer
|
|
# audits the exact old chains once, snapshots both rule generations in memory,
|
|
# then replaces only the contents of the stable private chains. Every family
|
|
# commit is atomic. Any later failure restores those old rules and relaunches
|
|
# the preserved old argv before the outer transaction restores runtime data.
|
|
|
|
Z2_TOPOLOGY_OLD_PORTS_TCP=
|
|
Z2_TOPOLOGY_OLD_PORTS_UDP=
|
|
Z2_TOPOLOGY_OLD_TCP_PKT_OUT=
|
|
Z2_TOPOLOGY_OLD_TCP_PKT_IN=
|
|
Z2_TOPOLOGY_OLD_UDP_PKT_OUT=
|
|
Z2_TOPOLOGY_OLD_UDP_PKT_IN=
|
|
Z2_TOPOLOGY_OLD_DESYNC_MARK=
|
|
Z2_TOPOLOGY_OLD_IPV4_CONNBYTES=0
|
|
Z2_TOPOLOGY_OLD_IPV4_MULTIPORT=0
|
|
Z2_TOPOLOGY_OLD_IPV4_MARK=0
|
|
Z2_TOPOLOGY_OLD_IPV6_ACTIVE=0
|
|
Z2_TOPOLOGY_OLD_IPV6_CONNBYTES=0
|
|
Z2_TOPOLOGY_OLD_IPV6_MULTIPORT=0
|
|
Z2_TOPOLOGY_OLD_IPV6_MARK=0
|
|
Z2_TOPOLOGY_OLD_IPV4_RULES=0
|
|
Z2_TOPOLOGY_OLD_IPV6_RULES=0
|
|
Z2_TOPOLOGY_OLD_IPV4_SPEC=
|
|
Z2_TOPOLOGY_OLD_IPV6_SPEC=
|
|
Z2_TOPOLOGY_OLD_FIREWALL_FINGERPRINT=
|
|
|
|
Z2_TOPOLOGY_NEW_PORTS_TCP=
|
|
Z2_TOPOLOGY_NEW_PORTS_UDP=
|
|
Z2_TOPOLOGY_NEW_TCP_PKT_OUT=
|
|
Z2_TOPOLOGY_NEW_TCP_PKT_IN=
|
|
Z2_TOPOLOGY_NEW_UDP_PKT_OUT=
|
|
Z2_TOPOLOGY_NEW_UDP_PKT_IN=
|
|
Z2_TOPOLOGY_NEW_DESYNC_MARK=
|
|
Z2_TOPOLOGY_NEW_IPV4_CONNBYTES=0
|
|
Z2_TOPOLOGY_NEW_IPV4_MULTIPORT=0
|
|
Z2_TOPOLOGY_NEW_IPV4_MARK=0
|
|
Z2_TOPOLOGY_NEW_IPV6_ACTIVE=0
|
|
Z2_TOPOLOGY_NEW_IPV6_CONNBYTES=0
|
|
Z2_TOPOLOGY_NEW_IPV6_MULTIPORT=0
|
|
Z2_TOPOLOGY_NEW_IPV6_MARK=0
|
|
Z2_TOPOLOGY_NEW_IPV4_RULES=0
|
|
Z2_TOPOLOGY_NEW_IPV6_RULES=0
|
|
Z2_TOPOLOGY_NEW_IPV4_SPEC=
|
|
Z2_TOPOLOGY_NEW_IPV6_SPEC=
|
|
Z2_TOPOLOGY_NEW_FIREWALL_FINGERPRINT=
|
|
Z2_TOPOLOGY_FIREWALL_STAGE=START_FIREWALL_IPV4
|
|
|
|
topology_snapshot_old_generation() {
|
|
Z2_TOPOLOGY_OLD_PORTS_TCP="$OWNER_STATE_PORTS_TCP"
|
|
Z2_TOPOLOGY_OLD_PORTS_UDP="$OWNER_STATE_PORTS_UDP"
|
|
Z2_TOPOLOGY_OLD_TCP_PKT_OUT="$OWNER_STATE_TCP_PKT_OUT"
|
|
Z2_TOPOLOGY_OLD_TCP_PKT_IN="$OWNER_STATE_TCP_PKT_IN"
|
|
Z2_TOPOLOGY_OLD_UDP_PKT_OUT="$OWNER_STATE_UDP_PKT_OUT"
|
|
Z2_TOPOLOGY_OLD_UDP_PKT_IN="$OWNER_STATE_UDP_PKT_IN"
|
|
Z2_TOPOLOGY_OLD_DESYNC_MARK="$OWNER_STATE_DESYNC_MARK"
|
|
Z2_TOPOLOGY_OLD_IPV4_CONNBYTES="$OWNER_STATE_IPV4_CONNBYTES"
|
|
Z2_TOPOLOGY_OLD_IPV4_MULTIPORT="$OWNER_STATE_IPV4_MULTIPORT"
|
|
Z2_TOPOLOGY_OLD_IPV4_MARK="$OWNER_STATE_IPV4_MARK"
|
|
Z2_TOPOLOGY_OLD_IPV6_ACTIVE="$OWNER_STATE_IPV6_ACTIVE"
|
|
Z2_TOPOLOGY_OLD_IPV6_CONNBYTES="$OWNER_STATE_IPV6_CONNBYTES"
|
|
Z2_TOPOLOGY_OLD_IPV6_MULTIPORT="$OWNER_STATE_IPV6_MULTIPORT"
|
|
Z2_TOPOLOGY_OLD_IPV6_MARK="$OWNER_STATE_IPV6_MARK"
|
|
Z2_TOPOLOGY_OLD_IPV4_RULES="$OWNER_STATE_IPV4_RULES"
|
|
Z2_TOPOLOGY_OLD_IPV6_RULES="$OWNER_STATE_IPV6_RULES"
|
|
Z2_TOPOLOGY_OLD_IPV4_SPEC="$OWNER_STATE_IPV4_SPEC"
|
|
Z2_TOPOLOGY_OLD_IPV6_SPEC="$OWNER_STATE_IPV6_SPEC"
|
|
Z2_TOPOLOGY_OLD_FIREWALL_FINGERPRINT="$OWNER_STATE_FIREWALL_FINGERPRINT"
|
|
}
|
|
|
|
topology_snapshot_new_generation() {
|
|
Z2_TOPOLOGY_NEW_PORTS_TCP="$OWNER_WRITE_PORTS_TCP"
|
|
Z2_TOPOLOGY_NEW_PORTS_UDP="$OWNER_WRITE_PORTS_UDP"
|
|
Z2_TOPOLOGY_NEW_TCP_PKT_OUT="$OWNER_WRITE_TCP_PKT_OUT"
|
|
Z2_TOPOLOGY_NEW_TCP_PKT_IN="$OWNER_WRITE_TCP_PKT_IN"
|
|
Z2_TOPOLOGY_NEW_UDP_PKT_OUT="$OWNER_WRITE_UDP_PKT_OUT"
|
|
Z2_TOPOLOGY_NEW_UDP_PKT_IN="$OWNER_WRITE_UDP_PKT_IN"
|
|
Z2_TOPOLOGY_NEW_DESYNC_MARK="$OWNER_WRITE_DESYNC_MARK"
|
|
Z2_TOPOLOGY_NEW_IPV4_CONNBYTES="$OWNER_WRITE_IPV4_CONNBYTES"
|
|
Z2_TOPOLOGY_NEW_IPV4_MULTIPORT="$OWNER_WRITE_IPV4_MULTIPORT"
|
|
Z2_TOPOLOGY_NEW_IPV4_MARK="$OWNER_WRITE_IPV4_MARK"
|
|
Z2_TOPOLOGY_NEW_IPV6_ACTIVE="$OWNER_WRITE_IPV6_ACTIVE"
|
|
Z2_TOPOLOGY_NEW_IPV6_CONNBYTES="$OWNER_WRITE_IPV6_CONNBYTES"
|
|
Z2_TOPOLOGY_NEW_IPV6_MULTIPORT="$OWNER_WRITE_IPV6_MULTIPORT"
|
|
Z2_TOPOLOGY_NEW_IPV6_MARK="$OWNER_WRITE_IPV6_MARK"
|
|
Z2_TOPOLOGY_NEW_IPV4_RULES="$OWNER_WRITE_IPV4_RULES"
|
|
Z2_TOPOLOGY_NEW_IPV6_RULES="$OWNER_WRITE_IPV6_RULES"
|
|
Z2_TOPOLOGY_NEW_IPV4_SPEC="$OWNER_WRITE_IPV4_SPEC"
|
|
Z2_TOPOLOGY_NEW_IPV6_SPEC="$OWNER_WRITE_IPV6_SPEC"
|
|
Z2_TOPOLOGY_NEW_FIREWALL_FINGERPRINT="$OWNER_WRITE_FIREWALL_FINGERPRINT"
|
|
}
|
|
|
|
topology_load_generation() {
|
|
local which="$1"
|
|
case "$which" in
|
|
old)
|
|
PORTS_TCP="$Z2_TOPOLOGY_OLD_PORTS_TCP"
|
|
PORTS_UDP="$Z2_TOPOLOGY_OLD_PORTS_UDP"
|
|
TCP_PKT_OUT="$Z2_TOPOLOGY_OLD_TCP_PKT_OUT"
|
|
TCP_PKT_IN="$Z2_TOPOLOGY_OLD_TCP_PKT_IN"
|
|
UDP_PKT_OUT="$Z2_TOPOLOGY_OLD_UDP_PKT_OUT"
|
|
UDP_PKT_IN="$Z2_TOPOLOGY_OLD_UDP_PKT_IN"
|
|
DESYNC_MARK="$Z2_TOPOLOGY_OLD_DESYNC_MARK"
|
|
IPV4_CONNBYTES="$Z2_TOPOLOGY_OLD_IPV4_CONNBYTES"
|
|
IPV4_MULTIPORT="$Z2_TOPOLOGY_OLD_IPV4_MULTIPORT"
|
|
IPV4_MARK="$Z2_TOPOLOGY_OLD_IPV4_MARK"
|
|
IPV6_ACTIVE="$Z2_TOPOLOGY_OLD_IPV6_ACTIVE"
|
|
IPV6_CONNBYTES="$Z2_TOPOLOGY_OLD_IPV6_CONNBYTES"
|
|
IPV6_MULTIPORT="$Z2_TOPOLOGY_OLD_IPV6_MULTIPORT"
|
|
IPV6_MARK="$Z2_TOPOLOGY_OLD_IPV6_MARK"
|
|
IPV4_RULES="$Z2_TOPOLOGY_OLD_IPV4_RULES"
|
|
IPV6_RULES="$Z2_TOPOLOGY_OLD_IPV6_RULES"
|
|
OWNER_WRITE_IPV4_SPEC="$Z2_TOPOLOGY_OLD_IPV4_SPEC"
|
|
OWNER_WRITE_IPV6_SPEC="$Z2_TOPOLOGY_OLD_IPV6_SPEC"
|
|
OWNER_WRITE_FIREWALL_FINGERPRINT="$Z2_TOPOLOGY_OLD_FIREWALL_FINGERPRINT"
|
|
;;
|
|
new)
|
|
PORTS_TCP="$Z2_TOPOLOGY_NEW_PORTS_TCP"
|
|
PORTS_UDP="$Z2_TOPOLOGY_NEW_PORTS_UDP"
|
|
TCP_PKT_OUT="$Z2_TOPOLOGY_NEW_TCP_PKT_OUT"
|
|
TCP_PKT_IN="$Z2_TOPOLOGY_NEW_TCP_PKT_IN"
|
|
UDP_PKT_OUT="$Z2_TOPOLOGY_NEW_UDP_PKT_OUT"
|
|
UDP_PKT_IN="$Z2_TOPOLOGY_NEW_UDP_PKT_IN"
|
|
DESYNC_MARK="$Z2_TOPOLOGY_NEW_DESYNC_MARK"
|
|
IPV4_CONNBYTES="$Z2_TOPOLOGY_NEW_IPV4_CONNBYTES"
|
|
IPV4_MULTIPORT="$Z2_TOPOLOGY_NEW_IPV4_MULTIPORT"
|
|
IPV4_MARK="$Z2_TOPOLOGY_NEW_IPV4_MARK"
|
|
IPV6_ACTIVE="$Z2_TOPOLOGY_NEW_IPV6_ACTIVE"
|
|
IPV6_CONNBYTES="$Z2_TOPOLOGY_NEW_IPV6_CONNBYTES"
|
|
IPV6_MULTIPORT="$Z2_TOPOLOGY_NEW_IPV6_MULTIPORT"
|
|
IPV6_MARK="$Z2_TOPOLOGY_NEW_IPV6_MARK"
|
|
IPV4_RULES="$Z2_TOPOLOGY_NEW_IPV4_RULES"
|
|
IPV6_RULES="$Z2_TOPOLOGY_NEW_IPV6_RULES"
|
|
OWNER_WRITE_IPV4_SPEC="$Z2_TOPOLOGY_NEW_IPV4_SPEC"
|
|
OWNER_WRITE_IPV6_SPEC="$Z2_TOPOLOGY_NEW_IPV6_SPEC"
|
|
OWNER_WRITE_FIREWALL_FINGERPRINT="$Z2_TOPOLOGY_NEW_FIREWALL_FINGERPRINT"
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
IPV4_ACTIVE=1
|
|
IPV4_BUILT=1
|
|
IPV6_BUILT="$IPV6_ACTIVE"
|
|
OWNER_WRITE_FIREWALL_TAG="$OWNER_STATE_FIREWALL_TAG"
|
|
OWNER_WRITE_OUT_CHAIN="$OWNER_STATE_OUT_CHAIN"
|
|
OWNER_WRITE_IN_CHAIN="$OWNER_STATE_IN_CHAIN"
|
|
OWNER_WRITE_TETHERING="$OWNER_STATE_TETHERING"
|
|
OWNER_WRITE_QNUM="$OWNER_STATE_QNUM"
|
|
OWNER_WRITE_PORTS_TCP="$PORTS_TCP"
|
|
OWNER_WRITE_PORTS_UDP="$PORTS_UDP"
|
|
OWNER_WRITE_STUN_PORTS=0
|
|
OWNER_WRITE_TCP_PKT_OUT="$TCP_PKT_OUT"
|
|
OWNER_WRITE_TCP_PKT_IN="$TCP_PKT_IN"
|
|
OWNER_WRITE_UDP_PKT_OUT="$UDP_PKT_OUT"
|
|
OWNER_WRITE_UDP_PKT_IN="$UDP_PKT_IN"
|
|
OWNER_WRITE_DESYNC_MARK="$DESYNC_MARK"
|
|
OWNER_WRITE_IPV4_ACTIVE=1
|
|
OWNER_WRITE_IPV6_ACTIVE="$IPV6_ACTIVE"
|
|
OWNER_WRITE_IPV4_CONNBYTES="$IPV4_CONNBYTES"
|
|
OWNER_WRITE_IPV4_MULTIPORT="$IPV4_MULTIPORT"
|
|
OWNER_WRITE_IPV4_MARK="$IPV4_MARK"
|
|
OWNER_WRITE_IPV6_CONNBYTES="$IPV6_CONNBYTES"
|
|
OWNER_WRITE_IPV6_MULTIPORT="$IPV6_MULTIPORT"
|
|
OWNER_WRITE_IPV6_MARK="$IPV6_MARK"
|
|
OWNER_WRITE_IPV4_RULES="$IPV4_RULES"
|
|
OWNER_WRITE_IPV6_RULES="$IPV6_RULES"
|
|
OWNER_WRITE_INSTALL_GENERATION="$INSTALL_META_GENERATION"
|
|
OWNER_WRITE_INSTALL_ARCHIVE_SHA256="$INSTALL_META_ARCHIVE_SHA256"
|
|
OWNER_WRITE_SOURCE_GENERATION=
|
|
OWNER_WRITE_READY=1
|
|
}
|
|
|
|
topology_replace_prepare() {
|
|
local multiport_fits=0
|
|
[ "${Z2_DAEMON_REPLACE_TOPOLOGY_CHANGED:-0}" = 1 ] || return 1
|
|
[ -n "${Z2_DAEMON_REPLACE_ROLLBACK_ARTIFACT:-}" ] &&
|
|
state_file_is_secure "$Z2_DAEMON_REPLACE_ROLLBACK_ARTIFACT" &&
|
|
path_mode_is_0600 "$Z2_DAEMON_REPLACE_ROLLBACK_ARTIFACT" || return 1
|
|
z2_load_firewall_reconciler || return 1
|
|
[ "$OWNER_STATE_OUT_CHAIN" = "$Z2_FW_OUT_CHAIN" ] &&
|
|
[ "$OWNER_STATE_IN_CHAIN" = "$Z2_FW_IN_CHAIN" ] || return 1
|
|
# Hot replacement repopulates the owned chains inside one COMMIT and never
|
|
# rewrites an anchor, so a changed tethering setting has no representation
|
|
# on this path. Refusing it here sends that change down the full
|
|
# publication path instead of publishing rules the anchors contradict.
|
|
[ "${TETHERING:-0}" = "$OWNER_STATE_TETHERING" ] || return 1
|
|
owner_family_generation_healthy iptables ipv4 || return 1
|
|
if command -v ip6tables >/dev/null 2>&1; then
|
|
owner_family_generation_healthy ip6tables ipv6 || return 1
|
|
else
|
|
[ "$OWNER_STATE_IPV6_ACTIVE" = 0 ] || return 1
|
|
fi
|
|
topology_snapshot_old_generation
|
|
|
|
z2_fw_multiport_fits && multiport_fits=1
|
|
IPV4_CONNBYTES="$OWNER_STATE_IPV4_CONNBYTES"
|
|
IPV4_MULTIPORT="$OWNER_STATE_IPV4_MULTIPORT"
|
|
[ "$multiport_fits" = 1 ] || IPV4_MULTIPORT=0
|
|
IPV4_MARK="$OWNER_STATE_IPV4_MARK"
|
|
IPV6_ACTIVE="$OWNER_STATE_IPV6_ACTIVE"
|
|
IPV6_BUILT="$IPV6_ACTIVE"
|
|
IPV6_CONNBYTES="$OWNER_STATE_IPV6_CONNBYTES"
|
|
IPV6_MULTIPORT="$OWNER_STATE_IPV6_MULTIPORT"
|
|
[ "$multiport_fits" = 1 ] || IPV6_MULTIPORT=0
|
|
IPV6_MARK="$OWNER_STATE_IPV6_MARK"
|
|
FIREWALL_TAG="$OWNER_STATE_FIREWALL_TAG"
|
|
ZAPRET2_OUT="$OWNER_STATE_OUT_CHAIN"
|
|
ZAPRET2_IN="$OWNER_STATE_IN_CHAIN"
|
|
prepare_new_firewall_identity || return 1
|
|
prepare_owner_generation_spec 1 "$IPV6_ACTIVE" || return 1
|
|
topology_snapshot_new_generation
|
|
return 0
|
|
}
|
|
|
|
topology_reconfigure_loaded_generation() {
|
|
Z2_TOPOLOGY_FIREWALL_STAGE=START_FIREWALL_IPV4
|
|
z2_fw_reconfigure_family iptables "$IPV4_CONNBYTES" "$IPV4_MULTIPORT" ||
|
|
return 1
|
|
if [ "$IPV6_ACTIVE" = 1 ]; then
|
|
Z2_TOPOLOGY_FIREWALL_STAGE=START_FIREWALL_IPV6
|
|
z2_fw_reconfigure_family ip6tables "$IPV6_CONNBYTES" "$IPV6_MULTIPORT" ||
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
topology_restore_old_firewall() {
|
|
topology_load_generation old || return 1
|
|
topology_reconfigure_loaded_generation
|
|
}
|
|
|
|
topology_stop_partial_candidate() {
|
|
local rc=0
|
|
if [ "$Z2_DAEMON_REPLACE_NEW_PID" = 1 ]; then
|
|
PROCESS_CLEANUP_PREFLIGHT_PROVEN=0
|
|
preflight_owned_process_cleanup && stop_pidfile_process || rc=1
|
|
elif [ -n "$Z2_DAEMON_REPLACE_LAUNCHED_PID" ]; then
|
|
stop_all_exact_owned_nfqws >/dev/null 2>&1 || rc=1
|
|
rm -f "$PIDFILE" "$OWNER_STATE" 2>/dev/null || rc=1
|
|
retire_owner_read_cache
|
|
fi
|
|
Z2_DAEMON_REPLACE_NEW_PID=0
|
|
Z2_DAEMON_REPLACE_LAUNCHED_PID=
|
|
return "$rc"
|
|
}
|
|
|
|
topology_relaunch_old_generation() {
|
|
local candidate_artifact="$COMPILED_ARGV_FILE"
|
|
topology_load_generation old || return 1
|
|
COMPILED_ARGV_FILE="$Z2_DAEMON_REPLACE_ROLLBACK_ARTIFACT"
|
|
Z2_DAEMON_REPLACE_PREVALIDATED=1
|
|
daemon_replace_launch
|
|
local rc=$?
|
|
COMPILED_ARGV_FILE="$candidate_artifact"
|
|
[ "$rc" -eq 0 ] || return 1
|
|
[ "$PUBLISHED_PID" = "$STARTED_PID" ] &&
|
|
[ "$PUBLISHED_START" = "$STARTED_PID_START" ] &&
|
|
[ "$PUBLISHED_FIREWALL_FINGERPRINT" = "$Z2_TOPOLOGY_OLD_FIREWALL_FINGERPRINT" ]
|
|
}
|
|
|
|
topology_rollback_live_generation() {
|
|
local rc=0
|
|
topology_stop_partial_candidate || rc=1
|
|
topology_restore_old_firewall || rc=1
|
|
[ "$rc" -ne 0 ] || topology_relaunch_old_generation || rc=1
|
|
if [ "$rc" -eq 0 ]; then
|
|
Z2_DAEMON_REPLACE_STATUS_DIAGNOSTICS="topology replacement failed; previous daemon and firewall generation restored"
|
|
daemon_replace_write_ok_status >/dev/null 2>&1 || :
|
|
Z2_DAEMON_REPLACE_LAUNCHED_PID=
|
|
log_msg "Topology replacement rolled back; previous daemon and firewall restored"
|
|
return 0
|
|
fi
|
|
daemon_replace_converge_stopped >/dev/null 2>&1 || :
|
|
daemon_replace_write_error_status >/dev/null 2>&1 || :
|
|
return 1
|
|
}
|
|
|
|
replace_topology_in_locked_transaction() {
|
|
topology_replace_prepare || {
|
|
daemon_replace_set_error FIREWALL FIREWALL_CLEANUP_FAILED START_CLEANUP \
|
|
"the authenticated firewall generation is not eligible for in-transaction reconfiguration"
|
|
return 1
|
|
}
|
|
|
|
Z2_DAEMON_REPLACE_CONTROLLED=1
|
|
stop_pidfile_process || {
|
|
daemon_replace_set_error PROCESS PROCESS_STOP_FAILED START_CLEANUP \
|
|
"the authenticated previous daemon could not be stopped"
|
|
return 1
|
|
}
|
|
|
|
topology_load_generation new || {
|
|
daemon_replace_set_error FIREWALL PREFLIGHT_FAILED START_IDENTITY \
|
|
"the candidate firewall generation could not be loaded"
|
|
topology_rollback_live_generation || :
|
|
return 1
|
|
}
|
|
if ! topology_reconfigure_loaded_generation; then
|
|
daemon_replace_set_error FIREWALL FIREWALL_PUBLICATION_FAILED \
|
|
"$Z2_TOPOLOGY_FIREWALL_STAGE" \
|
|
"atomic firewall reconfiguration failed: ${Z2_FW_ERROR_DETAIL:-unknown backend failure}"
|
|
topology_rollback_live_generation ||
|
|
Z2_DAEMON_REPLACE_ERROR_DETAIL="$Z2_DAEMON_REPLACE_ERROR_DETAIL; previous generation rollback is incomplete"
|
|
return 1
|
|
fi
|
|
|
|
topology_load_generation new || return 1
|
|
if ! daemon_replace_launch; then
|
|
daemon_replace_set_error PROCESS PROCESS_LAUNCH_FAILED START_LAUNCH \
|
|
"nfqws2 launch failed after firewall reconfiguration"
|
|
topology_rollback_live_generation ||
|
|
Z2_DAEMON_REPLACE_ERROR_DETAIL="$Z2_DAEMON_REPLACE_ERROR_DETAIL; previous generation rollback is incomplete"
|
|
return 1
|
|
fi
|
|
[ "$PUBLISHED_PID" = "$STARTED_PID" ] &&
|
|
[ "$PUBLISHED_START" = "$STARTED_PID_START" ] &&
|
|
[ "$PUBLISHED_FIREWALL_FINGERPRINT" = "$Z2_TOPOLOGY_NEW_FIREWALL_FINGERPRINT" ] ||
|
|
{
|
|
daemon_replace_set_error LIFECYCLE POSTCONDITION_FAILED START_COMMIT \
|
|
"the topology replacement owner receipt is inconsistent"
|
|
topology_rollback_live_generation ||
|
|
Z2_DAEMON_REPLACE_ERROR_DETAIL="$Z2_DAEMON_REPLACE_ERROR_DETAIL; previous generation rollback is incomplete"
|
|
return 1
|
|
}
|
|
Z2_DAEMON_REPLACE_STATUS_DIAGNOSTICS="validated daemon and capture-topology replacement; stable private chain anchors retained"
|
|
daemon_replace_write_ok_status ||
|
|
log_msg "WARNING: topology replacement committed but its status snapshot could not be refreshed"
|
|
Z2_DAEMON_REPLACE_LAUNCHED_PID=
|
|
log_msg "Daemon and firewall topology replaced with verified PID $STARTED_PID; anchors retained"
|
|
return 0
|
|
}
|