#!/bin/bash
# wml-carrier-watcher - real-time NIC plug/unplug watchdog.
#
# Runs forever as a systemd service. Uses `ip monitor link` to watch for
# carrier-up events. When a NIC's carrier goes up:
#   - If we don't have a WAN with a valid DHCP lease yet, re-run wml-firstboot
#     WAN detection on the newly-connected NIC.
#   - If WAN already has a lease and this is a different NIC, mark it LAN.
#
# This is the firewall equivalent of "hot-plug an Ethernet cable" - it should
# Just Work, no reboot required.

set -u

LOG=/var/log/wml/carrier-watcher.log
mkdir -p /var/log/wml

log() {
    echo "$(date -Is) $*" >> "$LOG"
}

# Re-detect WAN by probing for DHCP. Same logic as wml-firstboot but runs
# whenever a new NIC comes up.
redetect_wan() {
    local iface="$1"
    # FIXED interface roles — NO auto re-detection. eth0=WAN, eth1=LAN.
    # On a link-up we never probe DHCP or reclassify ports; we only nudge the
    # network stack so the fixed-role interface re-acquires its config.
    log "Carrier UP on $iface (fixed roles: eth0=WAN, eth1=LAN — no re-detect)"
    case "$iface" in
        eth0)
            log "WAN ($iface) link up - renewing via networkd"
            systemctl restart --no-block systemd-networkd 2>/dev/null || true
            ;;
        eth1)
            log "LAN ($iface) link up - nothing to reassign"
            ;;
        *)
            log "$iface link up - extra NIC, treated as LAN, no action"
            ;;
    esac
    return 0
}

log "wml-carrier-watcher started"

# Use `ip monitor link` to stream link-state events. Each event line looks like:
#   3: eth1: <BROADCAST,...,UP,LOWER_UP> mtu 1500 ...
# LOWER_UP appearing = carrier just went up.
ip monitor link 2>/dev/null | while read -r line; do
    # Extract interface name and check if LOWER_UP just appeared
    if echo "$line" | grep -qE 'LOWER_UP'; then
        iface=$(echo "$line" | sed -E 's/^[0-9]+: ([^:@]+).*/\1/' | head -1)
        if [[ -n "$iface" ]] && [[ -e "/sys/class/net/$iface/device" ]]; then
            # Debounce: wait 2 sec then verify carrier is actually up
            sleep 2
            if [[ "$(cat /sys/class/net/$iface/carrier 2>/dev/null)" == "1" ]]; then
                redetect_wan "$iface"
            fi
        fi
    fi
done
