#!/bin/sh
#
# Maximilian Wilhelm <max@sdn.clinic>
#  --  Wed 26 Aug 2020 08:15:58 PM CEST
#
# This executor is responsible for setting up the main B.A.T.M.A.N. adv. interface (eg. bat0)
# as well as managing settings of the underlying interfaces (hardifs).
#
# Known options for the main interface are:
#  IF_BATMAN_IFACES			Space separated list of interfaces to be part of this B.A.T.M.A.N. adv. instance
#  IF_BATMAN_IFACES_IGNORE_REGEX	Interfaces to ignore when verifying configuration (regexp)
#  IF_BATMAN_DISTRIBUTED_ARP_TABLE	'enable' or 'disable' DAT of this B.A.T.M.A.N. adv. instance
#  IF_BATMAN_MULTICAST_MODE		'enable' or 'disable' the multicast mode of this B.A.T.M.A.N. adv. instance
#  IF_BATMAN_GW_MODE			Set the gateway mode of this B.A.T.M.A.N. adv. instance
#  IF_BATMAN_HOP_PENALTY		Set the hop penalty of this B.A.T.M.A.N. adv. instance
#
# Known options for underlying interfaces are:
#  IF_BATMAN_IFACE_PENALTY		Set the hop penalty of this B.A.T.M.A.N. adv. interface
#
set -e

if [ "$VERBOSE" ]; then
	set -x
fi

if [ "${IF_BATMAN_IFACES}" -o "${IF_BATMAN_IFACE_PENALTY}" ]; then
	if ! which batctl >/dev/null 2>&1; then
		echo "Error: batctl utility not found!" >&2
		exit 1
	fi
fi

#
# Compatiblity glue: Newer versions of batctl print a deprecation
# warning when called with -m <batif>. Avoid spamming the log and
# producting SPAM by silently handling this here.
mesh_if_param="-m"
if batctl -h 2>&1 | grep -q "meshif"; then
        mesh_if_param="meshif"
fi

#
# Functions to manage main B.A.T.M.A.N. adv. interface
batctl_if () {
	for iface in ${IF_BATMAN_IFACES}; do
		${MOCK} batctl "${mesh_if_param}" "${IFACE}" interface "$1" "${iface}"
	done
}

set_batman_params () {
	[ "${IF_BATMAN_DISTRIBUTED_ARP_TABLE}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" distributed_arp_table "${IF_BATMAN_DISTRIBUTED_ARP_TABLE}"
	[ "${IF_BATMAN_MULTICAST_MODE}" ]        && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" multicast_mode "${IF_BATMAN_MULTICAST_MODE}"
	[ "${IF_BATMAN_HOP_PENALTY}" ]           && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" hop_penalty "${IF_BATMAN_HOP_PENALTY}"
	[ "${IF_BATMAN_GW_MODE}" ]               && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" gw_mode "${IF_BATMAN_GW_MODE}"
}

#
# Functions to manage B.A.T.M.A.N. adv. underlying interfaces
set_iface_penalty () {
	${MOCK} batctl hardif "${IFACE}" hop_penalty "${IF_BATMAN_IFACE_PENALTY}"
}


case "${PHASE}" in
	depend)
		if [ "${IF_BATMAN_IFACES}" ]; then
			echo "${IF_BATMAN_IFACES}"
		fi
		;;

	create)
		# Main B.A.T.M.A.N. adv. interface
		if [ "${IF_BATMAN_IFACES}" ]; then
			if [ ! -d "/sys/class/net/${IFACE}" ]; then
				batctl "${mesh_if_param}" "${IFACE}" interface create || true
			fi
		fi
		;;

	pre-up)
		# Main B.A.T.M.A.N. adv. interface
		if [ "${IF_BATMAN_IFACES}" ]; then
			batctl_if add
			set_batman_params

		# B.A.T.M.A.N. adv. underlying interface
		elif [ "${IF_BATMAN_IFACE_PENALTY}" ]; then
			set_iface_penalty
		fi
		;;

	destroy)
		if [ "${IF_BATMAN_IFACES}" -a -d "/sys/class/net/${IFACE}" ]; then
			# Newer versions of batctl provide the "interface destroy" API, try to use it
			if ! batctl "${mesh_if_param}" "${IFACE}" interface destroy 2>/dev/null; then
				# Fall back to old style member interface removal
				batctl_if del
			fi
		fi
		;;

	*)
		exit 0
		;;
esac