#!/bin/sh
#
# Copyright (C) 2026 iopsys Software Solutions AB
#
# See LICENSE file for license related information.
#
# Ping probe — TR-181 Method "Ping" (Layer-3 ICMP Echo).
#
# Contract (shared by every methods/* script; all inputs positional so this script
# can be replaced per deployment without touching connmon or the data model):
#   $1 interface   IP.Interface Name (logical, e.g. "wan")
#   $2 dest        destination IP/FQDN, or "" to use the interface gateway
#   $3 ipversion   4 | 6 | -1
#   $4 timeout     max response time, seconds
#   $5 dscp        DSCP mark (0-63)   [best effort]
#   $6 priority    802.1p priority    [unused here]
# Exit 0 = reachable (Up), non-zero = unreachable (Unresponsive).

iface="$1"; dest="$2"; ipver="$3"; timeout="${4:-1}"; dscp="$5"

[ "$timeout" -ge 1 ] 2>/dev/null || timeout=1

l3dev="$(ubus call network.interface."$iface" status 2>/dev/null | jsonfilter -e '@.l3_device' 2>/dev/null)"

DEV_ARG=""
[ -n "$l3dev" ] && DEV_ARG="-I $l3dev"
DSCP_ARG=""
[ -n "$dscp" ] && [ "$dscp" -ge 0 ] 2>/dev/null && DSCP_ARG="-Q $((dscp << 2))"

gw4() { ubus call network.interface."$iface" status 2>/dev/null | jsonfilter -e '@.route[@.target="0.0.0.0"].nexthop' 2>/dev/null | head -n1; }
gw6() { ubus call network.interface."${iface}6" status 2>/dev/null | jsonfilter -e '@.route[@.target="::"].nexthop' 2>/dev/null | head -n1; }

# $1 = ip version flag (-4|-6) — this platform's `ping` is the unified
# iputils build (no separate `ping6` binary), so the family is selected via
# flag, not a different command. $2 = destination (explicit dest, or "" to
# use the matching-family default gateway).
try_ping() {
	local ipflag="$1" target="$2"

	if [ -z "$target" ]; then
		if [ "$ipflag" = "-6" ]; then
			target="$(gw6)"
		else
			target="$(gw4)"
		fi
	fi
	[ -n "$target" ] || return 1

	# shellcheck disable=SC2086
	ping "$ipflag" -c 1 -W "$timeout" $DEV_ARG $DSCP_ARG "$target" >/dev/null 2>&1
}

case "$ipver" in
	6)
		try_ping -6 "$dest" && exit 0
		;;
	4)
		try_ping -4 "$dest" && exit 0
		;;
	*)
		# -1: no specific IP version required. Per spec: "it will try to use
		# IPv6 first, and if that fails, it will fall back to IPv4."
		try_ping -6 "$dest" && exit 0
		try_ping -4 "$dest" && exit 0
		;;
esac

exit 1
