#!/bin/sh
# shellcheck disable=SC1091
# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 :

. /lib/functions.sh

uci -q batch <<EOF
set firewall.tun=zone
set firewall.tun.name=tun
set firewall.tun.input=REJECT
set firewall.tun.output=ACCEPT
set firewall.tun.forward=REJECT
set firewall.tun.masq=1
set firewall.tun.mtu_fix=1
set firewall.tun.family='ipv4'

set firewall.lan_tun=forwarding
set firewall.lan_tun.src=lan
set firewall.lan_tun.dest=tun

set firewall.tun_lan=forwarding
set firewall.tun_lan.src=tun
set firewall.tun_lan.dest=lan

del_list firewall.wan.network=tun0
del_list firewall.wan.network=xtun0

del_list firewall.tun.masq_dest='!10.0.0.0/8'
del_list firewall.tun.masq_dest='!172.16.0.0/12'
del_list firewall.tun.masq_dest='!192.168.0.0/16'
del_list firewall.tun.masq_src='!151.127.0.0/16'
del_list firewall.tun.masq_src='!109.190.0.0/16'

add_list firewall.tun.masq_dest='!10.0.0.0/8'
add_list firewall.tun.masq_dest='!172.16.0.0/12'
add_list firewall.tun.masq_dest='!192.168.0.0/16'
add_list firewall.tun.masq_src='!151.127.0.0/16'
add_list firewall.tun.masq_src='!109.190.0.0/16'

set firewall.tunv6=zone
set firewall.tunv6.name=tunv6
set firewall.tunv6.input=REJECT
set firewall.tunv6.output=ACCEPT
set firewall.tunv6.forward=REJECT
set firewall.tunv6.mtu_fix=1
set firewall.tunv6.family=ipv6

set firewall.lan_tunv6=forwarding
set firewall.lan_tunv6.src=lan
set firewall.lan_tunv6.dest=tunv6
EOF

_setup() {
	name=
	config_get name "$1" name

	case "$name" in
	lan|wan)
		uci -q rename "firewall.$1=$name"
		;;
	mptcp)
		interface_list=
		config_get interface_list "$1" network
		for interface in $interface_list; do
			uci -q del_list firewall.wan.network="$interface"
			uci -q add_list firewall.wan.network="$interface"
		done
		uci -q delete firewall."$1"
		;;
	esac
}

_delete_mptcp_forwarding() {
	src=
	dest=
	config_get src "$1" src
	config_get dest "$1" dest

	if [ "$src" = "mptcp" ] || [ "$dest" = "mptcp" ]; then
		uci -q delete "firewall.$1"
	fi
}

_update_network_list() {
	# according to fw4 default config get the real zone.
	if [ "$1" = "tun" ]; then
		cfg="$1"
	else
		cfg=$(uci get "firewall.$1.name")
	fi

	interface_list=
	config_get interface_list "$cfg" network

	# Delete this interface
	uci -q delete "firewall.$cfg.network"

	# Add each interfaces individually
	for interface in $interface_list; do
		uci -q del_list "firewall.$cfg.network=$interface"
		uci -q add_list "firewall.$cfg.network=$interface"
	done
}

_lowercase_proto() {
	cfg="$1"
	proto=
	config_get proto "$cfg" proto

	# shellcheck disable=SC2018,2019
	lcProto=$(echo "$proto" | tr 'A-Z' 'a-z')

	[ "$proto" != "$lcProto" ] && uci -q set "firewall.$cfg.proto=$lcProto"
}

_zone_tun_redirect() {
	# Change wan -> lan into tun -> lan
	# Change wan -> wan into tun -> wan
	cfg="$1"
	src=
	dest=
	config_get src "$cfg" src
	config_get dest "$cfg" dest

	[ "$src" = "wan" ] || return
	[ "$dest" = "lan" ] || [ "$dest" = "wan" ] || return

	uci -q set "firewall.$cfg.src=tun"
}

config_load firewall
config_foreach _update_network_list zone
config_foreach _setup zone
config_foreach _delete_mptcp_forwarding forwarding
config_foreach _lowercase_proto rule
config_foreach _lowercase_proto redirect
config_foreach _zone_tun_redirect redirect

uci -q batch <<-EOF
set firewall.lan.mtu_fix=1
del_list firewall.lan.network=if0
del_list firewall.wan.network=if0
add_list firewall.wan.network=if0

set firewall.allow_dhcp_request=rule
set firewall.allow_dhcp_request.name=Allow-DHCP-Request
set firewall.allow_dhcp_request.src=wan
set firewall.allow_dhcp_request.proto=udp
set firewall.allow_dhcp_request.dest_port=67
set firewall.allow_dhcp_request.target=ACCEPT
set firewall.allow_dhcp_request.family=ipv4

set firewall.allow_ping_tun=rule
set firewall.allow_ping_tun.name=Allow-Ping-tun
set firewall.allow_ping_tun.src=tun
set firewall.allow_ping_tun.proto=icmp
set firewall.allow_ping_tun.icmp_type='echo-request'
set firewall.allow_ping_tun.family=ipv4
set firewall.allow_ping_tun.target=ACCEPT
EOF
