#!/bin/sh

. /lib/functions.sh

IDENTIFIER="UI-REMOTE-ACCESS-WAN"
ZONE_NAME_FILE="/tmp/ui_fw_zone"

log() {
	echo "${@}"|logger -t firewall.userinterface -p info
}

if [ ! -f "/etc/config/userinterface" ] || [ ! -f "/etc/config/nginx" ]; then
	exit 0;
fi

exec_cmd() {
	if ! "$@"; then
		log "Failed to run [$*]"
	fi
}

collect_zone_name() {
	local name network

	config_get name "${1}" name ""
	if [ -z "${name}" ]; then
		return
	fi

	config_get network "${1}" network ""
	for i in ${network}; do
		var="${i}_zone"
		echo "${var}=${name}" >> "${ZONE_NAME_FILE}"
	done
}

load_zone_names() {
	rm -f "${ZONE_NAME_FILE}"
	config_load firewall
	config_foreach collect_zone_name zone
}

get_firewall_zone() {
	if [ ! -f "${ZONE_NAME_FILE}" ]; then
		echo ""
		return
	fi

	var="${1}_zone="
	name="$(cat ${ZONE_NAME_FILE} | grep ${var} | head -n 1 | cut -d'=' -f 2)"
	echo "${name}"
}

delete_ui_firewall_rules() {
	input_chains=$(iptables -w 1 -S | grep -E "^-N zone[a-zA-Z0-9_]+input$" | cut -d' ' -f 2)
	output_chains=$(iptables -w 1 -S | grep -E "^-N zone[a-zA-Z0-9_]+output$" | cut -d' ' -f 2)

	for chain in ${input_chains}; do
		CMD="iptables -w 1 -t filter -nL ${chain} --line-numbers"
		while ${CMD} 2>/dev/null | grep "${IDENTIFIER}"; do
			rule_num="$(${CMD} | grep "${IDENTIFIER}" | head -1|awk '{print $1}')"
			if [ -n "${rule_num}" ]; then
				exec_cmd iptables -w 1 -t filter -D "${chain}" "${rule_num}";
			fi
		done
	done

	for chain in ${output_chains}; do
		CMD="iptables -w 1 -t filter -nL ${chain} --line-numbers"
		while ${CMD} 2>/dev/null | grep "${IDENTIFIER}"; do
			rule_num="$(${CMD} | grep "${IDENTIFIER}" | head -1|awk '{print $1}')"
			if [ -n "${rule_num}" ]; then
				exec_cmd iptables -w 1 -t filter -D "${chain}" "${rule_num}";
			fi
		done
	done

	input6_chains=$(ip6tables -w 1 -S | grep -E "^-N zone[a-zA-Z0-9_]+input$" | cut -d' ' -f 2)
	output6_chains=$(ip6tables -w 1 -S | grep -E "^-N zone[a-zA-Z0-9_]+output$" | cut -d' ' -f 2)

	for chain in ${input6_chains}; do
		CMD="ip6tables -w 1 -t filter -nL ${chain} --line-numbers"
		while ${CMD} 2>/dev/null | grep "${IDENTIFIER}"; do
			rule_num="$(${CMD} | grep "${IDENTIFIER}" | head -1|awk '{print $1}')"
			if [ -n "${rule_num}" ]; then
				exec_cmd ip6tables -w 1 -t filter -D "${chain}" "${rule_num}";
			fi
		done
	done

	for chain in ${output6_chains}; do
		CMD="ip6tables -w 1 -t filter -nL ${chain} --line-numbers"
		while ${CMD} 2>/dev/null | grep "${IDENTIFIER}"; do
			rule_num="$(${CMD} | grep "${IDENTIFIER}" | head -1|awk '{print $1}')"
			if [ -n "${rule_num}" ]; then
				exec_cmd ip6tables -w 1 -t filter -D "${chain}" "${rule_num}";
			fi
		done
	done
}

configure_ui_firewall_rule() {
	local sec="${1}"
	local enabled access interface
	local port=""

	config_get_bool enabled "${sec}" enable '1'
	config_get access "${sec}" access ""
	config_get interface "${sec}" interface ""
	config_get port "${sec}" port ""

	if [ "${enabled}" -eq "1" ] && [ "${access}" == "remote" ] && [ -n "${interface}" ]; then
		if [ -z "${port}" ]; then
			return 0
		fi

		zone_name="$(get_firewall_zone ${interface})"
		if [ -z "${zone_name}" ]; then
			return 0
		fi

		chain="zone_${zone_name}_input"
		iptables -w 1 -t filter -nL ${chain} 2>/dev/null 1>&2
		if [ "$?" -eq 0 ]; then
			iptables -w 1 -I "${chain}" -p tcp -m multiport --dports "${port}" -m conntrack --ctstate NEW,ESTABLISHED -m comment --comment "${IDENTIFIER}" -j ACCEPT
		fi

		ip6tables -w 1 -t filter -nL ${chain} 2>/dev/null 1>&2
		if [ "$?" -eq 0 ]; then
			ip6tables -w 1 -I "${chain}" -p tcp -m multiport --dports "${port}" -m conntrack --ctstate NEW,ESTABLISHED -m comment --comment "${IDENTIFIER}" -j ACCEPT
		fi

		chain="zone_${zone_name}_output"
		iptables -w 1 -t filter -nL "${chain}" 2>/dev/null 1>&2
		if [ "$?" -eq 0 ]; then
			iptables -w 1 -I "${chain}" -p tcp -m multiport --dports "${port}" -m conntrack --ctstate ESTABLISHED -m comment --comment "${IDENTIFIER}" -j ACCEPT
		fi

		ip6tables -w 1 -t filter -nL "${chain}" 2>/dev/null 1>&2
		if [ "$?" -eq 0 ]; then
			ip6tables -w 1 -I "${chain}" -p tcp -m multiport --dports "${port}" -m conntrack --ctstate ESTABLISHED -m comment --comment "${IDENTIFIER}" -j ACCEPT
		fi
	fi
}

# Delete existing remote access rules
delete_ui_firewall_rules

load_zone_names

config_load userinterface
config_get_bool serv_enable global enable 1

if [ "${serv_enable}" -eq "1" ]; then
	# Configure the User Interface rule
	config_foreach configure_ui_firewall_rule http_access
fi

rm -f "${ZONE_NAME_FILE}"
