#!/bin/sh
. /lib/functions.sh
. "${OMR_LIB_DIR:-/usr/share/omr/lib}/omr-vps-curl.sh"

intf=$1
timeout="$(uci -q get openmptcprouter.settings.status_vps_timeout)"
[ -z "$timeout" ] && timeout="1"

[ -z "$intf" ] && return

get_mptcp_from_server() {
	[ -n "$support" ] && return
	serverport=$(uci -q get openmptcprouter.$1.port)
	get_mptcp() {
		[ -n "$support" ] && return
		serverip=$1
		# Only called on the out-of-tree MPTCP (v0) kernel, where curl's
		# connection is MPTCP as it is (see below): no mptcpize branch here,
		# the ones for the upstream kernel could never run
		if [ "$(echo $serverip | grep :)" ]; then
			support="$(omr_vps_curl -s -k -6 -m ${timeout} --interface $intf https://[$serverip]:$serverport/mptcpsupport)"
		else
			support="$(omr_vps_curl -s -k -4 -m ${timeout} --interface $intf https://$serverip:$serverport/mptcpsupport)"
		fi
		[ -n "$support" ] && {
			support=$(echo $support | jsonfilter -e '@.mptcp')
			return
		}
	}
	config_list_foreach $1 ip get_mptcp
}

get_mptcpv0_from_website() {
	multipathip=$(dig +short A multipath-tcp.org | tr -d "\n")
	ipset add ss_rules_dst_bypass_all $multipathip > /dev/null 2>&1
	support="$(curl -s -4 -m ${timeout} --interface $intf http://www.multipath-tcp.org)"
	ipset del ss_rules_dst_bypass_all $multipathip > /dev/null 2>&1
	[ -n "$support" ] && {
		if [ "$support" = "Yay, you are MPTCP-capable! You can now rest in peace." ]; then
			support="working"
		else
			support="not working"
		fi
	}
}

get_mptcpv0_from_website6() {
	multipathip=$(dig +short AAAA multipath-tcp.org | tr -d "\n")
	ipset add ss_rules6_dst_bypass_all $multipathip > /dev/null 2>&1
	support="$(curl -s -6 -m ${timeout} --interface $intf http://www.multipath-tcp.org)"
	ipset del ss_rules6_dst_bypass_all $multipathip > /dev/null 2>&1
	[ -n "$support" ] && {
		if [ "$support" = "Yay, you are MPTCP-capable! You can now rest in peace." ]; then
			support="working"
		else
			support="not working"
		fi
	}
}

# The router's own connection to the test site must not go through the
# transparent proxy: its output chain (ss_rules_local_out, or the xr_/v2r_
# one) lets through what is in the proxy's dst_bypass set, and omr-bypass's
# omr_dst_bypass_all_4/6 when it has one. The ipsets used before don't exist
# with fw4. Only what was added is removed afterwards: an address the user
# already bypasses stays.
_proxy_bypass_added=""
_proxy_bypass_add() {
	local fam="$1" ip set
	shift
	for ip in "$@"; do
		case "$ip" in ""|*[!0-9a-fA-F.:]*) continue ;; esac
		for set in ss_rules${fam}_dst_bypass v2r_rules${fam}_dst_bypass xr_rules${fam}_dst_bypass omr_dst_bypass_all_${fam:-4}; do
			nft get element inet fw4 "$set" "{ $ip }" >/dev/null 2>&1 && continue
			nft add element inet fw4 "$set" "{ $ip }" >/dev/null 2>&1 && _proxy_bypass_added="$_proxy_bypass_added $set,$ip"
		done
	done
}
_proxy_bypass_del() {
	local e
	for e in $_proxy_bypass_added; do
		nft delete element inet fw4 "${e%%,*}" "{ ${e#*,} }" >/dev/null 2>&1
	done
	_proxy_bypass_added=""
}

get_mptcpv1_from_website() {
	# One address per line, CNAMEs (ending with a dot) left out
	_proxy_bypass_add "" $(dig +short A check.mptcp.dev | grep -v '\.$')
	support="$(mptcpize run curl -s -4 -m ${timeout} --interface $intf https://check.mptcp.dev)"
	_proxy_bypass_del
	[ -n "$support" ] && {
		if [ "$support" = "You are using MPTCP." ]; then
			support="working"
		else
			support="not working"
		fi
	}
}

get_mptcpv1_from_website6() {
	_proxy_bypass_add 6 $(dig +short AAAA check.mptcp.dev | grep -v '\.$')
	support="$(mptcpize run curl -s -6 -m ${timeout} --interface $intf https://check.mptcp.dev)"
	_proxy_bypass_del
	[ -n "$support" ] && {
		if [ "$support" = "You are using MPTCP." ]; then
			support="working"
		else
			support="not working"
		fi
	}
}

support=""
if [ ! -f /proc/sys/net/mptcp/enabled ]; then
	# For now API can't give MPTCP status as MPTCP is not correctly enabled on it
	# with the upstream kernel (/proc/sys/net/mptcp/enabled): check.mptcp.dev
	# answers then
	config_load openmptcprouter
	config_foreach get_mptcp_from_server server
fi
if [ -z "$support" ]; then
	if [ ! -f /proc/sys/net/mptcp/enabled ]; then
		[ -n "$(ip -4 a show dev $intf)" ] && get_mptcpv0_from_website
		[ -z "$support" ] && [ -n "$(ip -6 a show dev $intf)" ] && get_mptcpv0_from_website6
	else
		[ -n "$(ip -4 a show dev $intf)" ] && get_mptcpv1_from_website
		[ -z "$support" ] && [ -n "$(ip -6 a show dev $intf)" ] && get_mptcpv1_from_website6
	fi
fi
if [ "$support" = "working" ]; then
	echo "MPTCP enabled"
elif [ "$support" = "not working" ]; then
	echo "MPTCP disabled"
fi
