#!/usr/bin/env bash

# Version 1.6.2
#
# Blocking connectivity gate. This unit is a Type=oneshot service that stays
# "activating" until a remote HTTPS host answers; it exits 0 ONLY on a
# successful probe. Units that need the internet declare
#     Wants=netcheck.service
#     After=netcheck.service
# (never Requires=, which is a lifetime coupling: a later netcheck failure or
# stop would tear down running gateways).
#
# Changes from 1.6.1 (rationale in docs/package-changes.v2.md):
#   * 1.6.1 ran `wget --tries 10` inside a 9-pass loop (~90 attempts, ~45 s),
#     then EXITED NON-ZERO when the link was down. With Requires= that made
#     every dependent service fail to start on an offline box (the "broken on
#     armhf" report). 1.6.2 loops forever, so the gate stays closed until the
#     internet is actually up, and the only exit is 0.
#   * Target is configurable via /opt/dvswitch/netcheck.conf
#     (NETCHECK_TARGET=...), default www.google.com. Gateways resolve FQDNs at
#     startup, so the probe exercises DNS through the same resolver path they
#     will use.
#   * --output-document dropped: --spider sends HEAD and writes nothing.
#   * ERRNO=101 notification dropped (1.6.1 change, kept).
#   * Diagnostics only, never gating: getent ahosts (is DNS broken?) and a TCP
#     connect to 1.1.1.1:443 (is there a route at all?). TCP alone must NOT
#     open the gate — the daemons need getaddrinfo to succeed.
#   * Runs once per boot (RemainAfterExit=yes in the unit); a later
#     `systemctl restart <gateway>` does not re-run this gate.
#   * TimeoutStartSec=infinity in the unit: the wait is unbounded by design,
#     so systemd's 90 s default must not kill the probe mid-loop.

TARGET="${NETCHECK_TARGET:-www.google.com}"
PROBE_URL="https://${TARGET}/robots.txt"

echo >>/var/log/netcheck
echo "NetCheck starting: [`date +%T.%3N`] target=${TARGET}" >> /var/log/netcheck

attempt=0
while :; do
    attempt=$((attempt + 1))

    # --- probe (this is what opens the gate) -------------------------------
    wget --spider --tries=1 --timeout=8 --append-output=/dev/null \
         "$PROBE_URL" 2>&1 | grep -vE '^(Resolving|Connecting|HTTP request|HTTP response|  HTTP)' \
         >> /var/log/netcheck
    wget_exit_code=${PIPESTATUS[0]}

    if [ "$wget_exit_code" -eq 0 ]; then
        echo "attempt $attempt: probe OK via $TARGET [`date +%T.%3N`]" \
            >> /var/log/netcheck
        echo >>/var/log/netcheck
        echo "NetCheck: Success [`date +%T.%3N`] (attempts=$attempt)" \
            >> /var/log/netcheck
        systemd-notify --status="Network connectivity is available" 2>/dev/null || true
        exit 0
    fi

    # --- diagnostics (logged, never gate) ----------------------------------
    if ! getent ahosts "$TARGET" >/dev/null 2>&1; then
        diag="DNS: cannot resolve ${TARGET}"
    elif ! timeout 5 bash -c 'exec 3<>/dev/tcp/1.1.1.1/443' 2>/dev/null; then
        diag="DNS OK, but no route to 1.1.1.1:443"
    else
        diag="route + DNS OK; HTTPS probe failed (wget exit ${wget_exit_code})"
    fi

    echo "attempt $attempt: $TARGET unreachable (wget exit ${wget_exit_code}) — ${diag} [`date +%T.%3N`]" \
        >> /var/log/netcheck
    sleep 5
done
