#!/bin/sh # Revoke the PPPoE dial lease. Runs every 5s. Only ever takes the WAN AWAY. # # vrrp-wan-reconcile is the single writer and runs every 30s; this is the # watcher, and it exists because `may-dial` must be a LEASE, not a flag. # ConditionPathExists is evaluated at START only -- it can prevent a dial, it can # never revoke one. So if the reconciler stops running (timer masked, box wedged, # someone stops it during maintenance) and the box is then demoted, nothing would # ever hang up: it would keep the one ISP session while the new master tries to # take it. # # Two conditions revoke, both biased the safe way: # - this box does not hold the management VIP # - the lease has not been renewed within LEASE_TTL (the reconciler is dead) # # Deliberately tiny: no config mode, no flock, no commit. It cannot wedge the # router's configuration system, which is what earns it a 5s timer. Running at # 5s rather than the reconciler's 30s is also what shrinks the double-dial # window on a demotion from up to 30s down to about 5. CONF=/config/vrrp-wan.conf [ -r "$CONF" ] && . "$CONF" VIP="${VRRP_WAN_VIP:-192.168.1.1}" LEASE_TTL="${LEASE_TTL:-75}" STATE=/run/vrrp-wan revoke() { rm -f "$STATE/may-dial" systemctl is-active --quiet ppp@pppoe0 2>/dev/null || return 0 logger -t vrrp-wan "GUARD: $1 -- hanging up pppoe0" systemctl stop ppp@pppoe0 2>/dev/null } if ! ip -4 -o addr show 2>/dev/null | grep -q " ${VIP}/"; then revoke "does not hold ${VIP}" exit 0 fi # Holds the VIP, so it is entitled to dial -- but only while something is # actively renewing the lease on its behalf. if [ -f "$STATE/may-dial" ]; then age=$(( $(date +%s) - $(stat -c %Y "$STATE/may-dial" 2>/dev/null || echo 0) )) [ "$age" -gt "$LEASE_TTL" ] && revoke "lease stale (${age}s > ${LEASE_TTL}s; is vrrp-wan-reconcile.timer running?)" fi exit 0