#!/bin/sh
#
# Copyright (C) 2026 iopsys Software Solutions AB
#
# See LICENSE file for license related information.
#
# ND probe — TR-181 Method "ND" (Layer-2 reachability of the IPv6 default
# gateway via Neighbor Solicitation / Neighbor Advertisement). Ports the old
# connmon daemon's `ndisc6 -w <t> -1 <gw6> <dev>` check.
#
# Positional contract (see Ping):
#   $1 interface  $2 dest  $3 ipversion  $4 timeout  $5 dscp  $6 priority
# Exit 0 = neighbour answered (Up), non-zero = no reply (Unresponsive).

. /usr/share/connmon/functions.sh

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

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

command -v ndisc6 >/dev/null 2>&1 || {
	log_err "ndisc6 not installed for iface '$iface'"
	exit 1
}

# The IPv6 interface is usually a sibling logical iface ("<iface>6"); fall back
# to the base interface's l3 device.
l3dev="$(ubus call network.interface."${iface}6" status 2>/dev/null | jsonfilter -e '@.l3_device' 2>/dev/null)"
[ -z "$l3dev" ] && l3dev="$(ubus call network.interface."$iface" status 2>/dev/null | jsonfilter -e '@.l3_device' 2>/dev/null)"
[ -z "$l3dev" ] && exit 1

# Default to the IPv6 default-route gateway when no explicit address is set.
# A device can carry multiple routes with target "::" (e.g. one per delegated
# prefix); jsonfilter emits one line per match, so `head -n1` is needed to
# collapse that back to the single nexthop ndisc6 expects — otherwise $dest
# ends up holding several newline-joined copies, which ndisc6 fails to parse
# as a valid target (silently reported as Unresponsive, not a real failure).
if [ -z "$dest" ]; then
	dest="$(ubus call network.interface."${iface}6" status 2>/dev/null | jsonfilter -e '@.route[@.target="::"].nexthop' 2>/dev/null | head -n1)"
	[ -z "$dest" ] && dest="$(ubus call network.interface."$iface" status 2>/dev/null | jsonfilter -e '@.route[@.target="::"].nexthop' 2>/dev/null | head -n1)"
fi
[ -z "$dest" ] && exit 1

# ndisc6: -1 stop after the first advertisement, -w wait in milliseconds.
ndisc6 -1 -w "$((timeout * 1000))" "$dest" "$l3dev" >/dev/null 2>&1 && exit 0
exit 1
