#!/bin/sh
[ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = ifdown -o "$ACTION" = iflink -o "$ACTION" = link-up -o "$ACTION" = link-down ] || exit 0
#[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0


/etc/init.d/mptcp enabled || exit 0

# A DHCPv6 companion "<intf>_6" (wizard IPv6 SLAAC/DHCPv6 option on a DHCP
# WAN, #4329) shares its parent's device and is kept at multipath=off so it
# never counts as a WAN of its own (status page, MPTCP pages, trackers).
# Its events still matter for the shared device: a new SLAAC address must
# refresh the MPTCP endpoints, and its ifup must re-run the parent's IPv6
# routing (mptcp reload reads the gateway from "<intf>_6" status), so the
# multipath decision is keyed on the parent interface instead.
MP_INTERFACE="$INTERFACE"
case "$INTERFACE" in
	*_6)
		if [ "$(uci -q get network.$INTERFACE.proto)" = "dhcpv6" ] && [ -n "$(uci -q get network.${INTERFACE%_6})" ]; then
			MP_INTERFACE="${INTERFACE%_6}"
		fi
	;;
esac
MULTIPATH="$(uci -q get network.$MP_INTERFACE.multipath)"

# Re-add the endpoint in the mode the interface is configured for, not always
# as an active subflow: a WAN set to "backup" was promoted to a normal subflow
# on every DHCP renew / RA refresh of its interface. "master" has no endpoint
# flag of its own, it is an active subflow like "on" (see mptcp's init script).
# The explicit endpoint id keeps the id of a WAN stable across those events, so
# the peer can still pin traffic to it by the subflow remote_id.
case "$MULTIPATH" in
	backup)  MULTIPATH_MODE="backup" ;;
	*)       MULTIPATH_MODE="on" ;;
esac
MULTIPATH_ID="$(uci -q get network.$MP_INTERFACE.metric)"

# An update gives the endpoint the new address, unless omr-tracker has the
# interface down: as in mptcp's init script, the endpoint then stays out of
# MPTCP, and 003-up adds it back once the tracker sees the interface up again
_tracker_down() {
	[ "$(uci -q -P /var/state get openmptcprouter.$MP_INTERFACE.state)" = "down" ] || return 1
	logger -t "mptcp" "$DEVICE tracker state is down, not adding it back to MPTCP"
}

# netifd exports DEVICE on ifup/ifupdate only: on iflink "mptcp reload" got
# no device and reloaded every interface, on each carrier-up of any WAN.
# Resolve it as the init script matches its argument to an interface, and
# leave it to the ifup that follows when the interface has no device yet.
if [ -z "$DEVICE" ] && { [ "$ACTION" = iflink ] || [ "$ACTION" = link-up ]; }; then
	. /lib/functions/network.sh
	network_get_device DEVICE "$MP_INTERFACE"
	[ -n "$DEVICE" ] || network_get_physdev DEVICE "$MP_INTERFACE"
	[ -n "$DEVICE" ] || exit 0
fi

if [ "$ACTION" = ifupdate -a -n "$IFUPDATE_ADDRESSES" ] && [ -n "$MULTIPATH" ] && [ "$MULTIPATH" != "off" ]; then
	logger -t "mptcp" "New IP ($IFUPDATE_ADDRESSES) for $INTERFACE ($DEVICE)"
	multipath $DEVICE off >/dev/null 2>&1 || exit 0
	_tracker_down && exit 0
	multipath $DEVICE $MULTIPATH_MODE $MULTIPATH_ID >/dev/null 2>&1 || exit 0
elif [ "$ACTION" = ifupdate ] && [ -n "$MULTIPATH" ] && [ "$MULTIPATH" != "off" ]; then
	logger -t "mptcp" "Update of $INTERFACE ($DEVICE)"
	multipath $DEVICE off >/dev/null 2>&1 || exit 0
	_tracker_down && exit 0
	multipath $DEVICE $MULTIPATH_MODE $MULTIPATH_ID >/dev/null 2>&1 || exit 0
elif [ "$ACTION" = ifup -o "$ACTION" = iflink  -o "$ACTION" = link-up ] && [ -n "$DEVICE" ] && [ -z "$(echo $DEVICE | grep oip | grep gre)" ] && [ -n "$MULTIPATH" ] && [ "$MULTIPATH" != "off" ]; then
	logger -t "mptcp" "Reloading mptcp config due to $ACTION of $INTERFACE ($DEVICE)"
	/etc/init.d/mptcp reload "$DEVICE" >/dev/null || exit 0
elif [ "$ACTION" = ifdown -o "$ACTION" = link-down ]; then
	multipath $DEVICE off >/dev/null 2>&1 || exit 0
fi
