#!/bin/sh
#
# Copyright (C) 2026 iopsys Software Solutions AB
#
# See LICENSE file for license related information.
#
# ARP probe — TR-181 Method "ARP" (Layer-2 reachability of the IPv4 gateway).
#
# Positional contract (see Ping):
#   $1 interface  $2 dest  $3 ipversion  $4 timeout  $5 dscp  $6 priority
# Exit 0 = gateway answered (Up), non-zero = no reply (Unresponsive).

iface="$1"; dest="$2"; timeout="${4:-1}"

[ "$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)"
[ -z "$l3dev" ] && exit 1

# Default to the IPv4 default gateway when no explicit address is configured.
# A device can carry multiple routes matching the same target; jsonfilter
# emits one line per match, so `head -n1` collapses that back to the single
# nexthop expected here — otherwise $dest ends up holding several
# newline-joined copies of the address, which arping/ping would fail to
# parse as a valid target.
if [ -z "$dest" ]; then
	dest="$(ubus call network.interface."$iface" status 2>/dev/null | jsonfilter -e '@.route[@.target="0.0.0.0"].nexthop' 2>/dev/null | head -n1)"
fi
[ -z "$dest" ] && exit 1

if command -v arping >/dev/null 2>&1; then
	arping -c 1 -w "$timeout" -I "$l3dev" "$dest" >/dev/null 2>&1 && exit 0
	exit 1
fi

# Fallback when arping is absent: kick the neighbour with a ping, then check the
# ARP cache for a resolved (non-FAILED/INCOMPLETE) entry for the gateway.
ping -c 1 -W "$timeout" -I "$l3dev" "$dest" >/dev/null 2>&1
if ip neigh show "$dest" dev "$l3dev" 2>/dev/null | grep -qE 'REACHABLE|STALE|DELAY|PROBE|PERMANENT'; then
	exit 0
fi

exit 1
