#!/bin/sh
# Meshvirt Networking: restore anything missing after an upgrade, and, if
# the old version used kernel networking, note that the new meshvirtd binary
# has lost its file capabilities (set by "meshvirt configure-host"), so the
# next start uses userspace networking until the boot task runs again.
# Meshvirt Networking: shared helpers for the DSM package scripts.
# Inlined into each script at packaging time in place of its "@include common"
# line (release/dist/synology/meshvirt_package.go); POSIX sh only.

PKGNAME="MeshvirtNetworking"
DEFAULT_SERVER_URL="https://mesh.meshvirt.io"

# meshvirt_pkgvar prints the directory holding state, config and logs.
meshvirt_pkgvar() {
    if [ "${SYNOPKG_DSM_VERSION_MAJOR:-7}" = "6" ]; then
        echo "/var/packages/${PKGNAME}/etc"
    elif [ -n "${SYNOPKG_PKGVAR}" ]; then
        echo "${SYNOPKG_PKGVAR}"
    else
        echo "/var/packages/${PKGNAME}/var"
    fi
}

# meshvirt_quote prints $1 single-quoted for a shell/env file.
meshvirt_quote() {
    printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"
}

# meshvirt_valid_url succeeds if $1 is https://host[:port][/path].
meshvirt_valid_url() {
    printf '%s' "$1" | grep -Eq '^https://[A-Za-z0-9.-]+(:[0-9]{1,5})?(/[^[:space:]?#]*)?$'
}

# meshvirt_valid_hostname succeeds if $1 is a DNS label.
meshvirt_valid_hostname() {
    printf '%s' "$1" | grep -Eq '^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?$'
}

# meshvirt_valid_code succeeds if $1 looks like a pre-auth key (8-512
# characters). The length is checked separately: bounds above RE_DUP_MAX
# (255) are rejected by BSD grep.
meshvirt_valid_code() {
    [ ${#1} -ge 8 ] && [ ${#1} -le 512 ] && printf '%s' "$1" | grep -Eq '^[A-Za-z0-9_.:+=/-]+$'
}

# meshvirt_has_net_caps DAEMON succeeds if DAEMON carries cap_net_admin.
# Uses getcap when DSM has it; otherwise the marker "meshvirt configure-host"
# writes after setcap, valid only while it is newer than the binary (an
# upgrade replaces the binary and drops its capabilities).
meshvirt_has_net_caps() {
    for g in /bin/getcap /usr/bin/getcap /sbin/getcap /usr/sbin/getcap; do
        if [ -x "$g" ]; then
            "$g" "$1" 2>/dev/null | grep -q "cap_net_admin"
            return $?
        fi
    done
    marker="$(meshvirt_pkgvar)/net-caps"
    [ -f "${marker}" ] && [ "${marker}" -nt "$1" ]
}

# meshvirt_log appends a line to the package log.
meshvirt_log() {
    echo "$(date '+%Y-%m-%dT%H:%M:%S%z') $*" >>"$(meshvirt_pkgvar)/meshvirt-package.log" 2>/dev/null
}

# meshvirt_notify shows $1 in DSM's result dialog (if DSM gave us a log
# file), the package log and stderr, without failing the operation.
meshvirt_notify() {
    [ -n "${SYNOPKG_TEMP_LOGFILE}" ] && echo "$1" >>"${SYNOPKG_TEMP_LOGFILE}"
    meshvirt_log "$1"
    echo "$1" >&2
}

# meshvirt_fail reports $1 to the DSM wizard and exits non-zero.
meshvirt_fail() {
    [ -n "${SYNOPKG_TEMP_LOGFILE}" ] && echo "$1" >"${SYNOPKG_TEMP_LOGFILE}"
    echo "$1" >&2
    exit 1
}

PKGVAR="$(meshvirt_pkgvar)"
BACKUP="${SYNOPKG_TEMP_UPGRADE_FOLDER:-}/meshvirt"
if [ -n "${SYNOPKG_TEMP_UPGRADE_FOLDER}" ] && [ -d "${BACKUP}" ]; then
    for f in meshvirtd.state config.env enroll.key; do
        if [ ! -f "${PKGVAR}/${f}" ] && [ -f "${BACKUP}/${f}" ]; then
            cp -p "${BACKUP}/${f}" "${PKGVAR}/${f}"
            meshvirt_log "postupgrade: restored ${f}"
        fi
    done
fi
# Only when the old version used kernel networking (recorded by preupgrade;
# networking-mode survives in var as a fallback) does the UI say the upgrade
# removed the permissions; otherwise it shows the usual "not enabled yet".
had_caps=""
if [ -n "${SYNOPKG_TEMP_UPGRADE_FOLDER}" ] && [ -f "${BACKUP}/had-net-caps" ]; then
    had_caps=1
elif grep -q '^MODE=kernel$' "${PKGVAR}/networking-mode" 2>/dev/null; then
    had_caps=1
fi
if [ -n "${had_caps}" ]; then
    umask 077
    echo "UPGRADED=1" >"${PKGVAR}/upgraded"
    meshvirt_log "postupgrade: meshvirtd capabilities are reset by the upgrade; run the 'Enable full networking' boot task again (or reboot) for kernel networking"
else
    rm -f "${PKGVAR}/upgraded"
fi
exit 0
