#!/bin/sh

<< COPYRIGHT

 LibreMesh
 Copyright (C) 2019-2023  Gioacchino Mazzurco <gio@altermundi.net>
 Copyright (C) 2023  Asociación Civil Altermundi <info@altermundi.net>

 SPDX-License-Identifier: AGPL-3.0-only

COPYRIGHT

get_uptime()
{
	awk '{print $1}' /proc/uptime | awk -F. '{print $1}'
}

cacheFile="/tmp/shared-state-get_candidates_neigh.cache"
lastRunFile="/tmp/shared-state-get_candidates_neigh.lastrun"
lastRun=$(if [ -s $lastRunFile ]; then echo $(cat $lastRunFile); else  echo -9999; fi)
currUptime="$(get_uptime)"

[ "$(($currUptime - $lastRun))" -lt "30" ] &&
{
	cat "$cacheFile"
	exit 0
}

batmanNonMeshCandidateAddresses="$(
for iface in $(ls /sys/class/net/) ; do
	ls /sys/class/net/${iface}/upper_bat? &> /dev/null || continue

	echo "${iface}" | grep -E "mesh|adhoc" &> /dev/null && continue

#[Doc] ping6 from busybox doesn't support float intervals iputils-ping does
	ping -i 0.1 -c 2 ff02::1%${iface} 2> /dev/null | \
		awk '{if ($3 == "from") print substr($4, 1, length($4)-1)'"\"%${iface}\""'}'
done | sort -u -r)"

babelCandidateAddresses="$([ -e /var/etc/babeld.conf ] &&
for iface in $(grep interface /var/etc/babeld.conf | awk '{print $2}'); do
	ping -i 0.1 -c 2 ff02::1%${iface} 2> /dev/null | \
		awk '{if ($3 == "from") print substr($4, 1, length($4)-1)'"\"%${iface}\""'}'
done | sort -u -r)"

wifi_get_macs="
wireless = require('lime.wireless')
iwinfo = require('iwinfo')
utils = require('lime.utils')

for _, ifc in ipairs(wireless.mesh_ifaces()) do
	for mac, sta in  pairs(iwinfo.nl80211.assoclist(ifc)) do
		if sta.inactive < 5000 then
			print(utils.mac2ipv6linklocal(mac) .. '%' .. ifc)
		end
	end
end
"

wirelessCandidateAddresses=$(echo "$wifi_get_macs" | lua -  | sort -u -r)

candidateAddresses="$batmanNonMeshCandidateAddresses
$babelCandidateAddresses
$wirelessCandidateAddresses
$(ping -i 0.1 -c 2 ff02::1%br-lan | \
	awk '{if ($3 == "from" && substr($7,6)+0 < 2) print substr($4, 1, length($4)-1)"%br-lan" }' | sort -u)"

for ownAddr in $(ip -6 address show | awk '{if ($1 == "inet6") print $2}' | awk -F/ '{print $1}') ; do
	candidateAddresses="$(echo "$candidateAddresses" | grep -v "^$ownAddr%.*$")"
done

#[Doc] Deduplicate addresses visible from muliple interfaces
for cAddr in $(echo "$candidateAddresses"); do
	cIp="$(echo "$cAddr" | awk -F% '{print $1}')"
	cIface="$(echo "$cAddr" | awk -F% '{print $2}')"

#[Doc] Use ${cIp}%${cIface} instead of $cAddr to avoid duplicate interface with
#[Doc] newer iputils-ping
	candidateAddresses="${cIp}%${cIface}
$(echo "$candidateAddresses" | grep -v "$cIp")"

done

echo "$candidateAddresses" | grep -v "^$" | tee "$cacheFile"
get_uptime > "$lastRunFile"
