#!/bin/sh /etc/rc.common

START=99
USE_PROCD=1
# PROCD_DEBUG=1
config_load 'dockerd'
# config_get daemon_ea "dockerman" daemon_ea
_DOCKERD=/etc/init.d/dockerd

docker_running(){
	docker version > /dev/null 2>&1
	return $?
}

add_ports() {
	[ $# -eq 0 ] && return
	$($_DOCKERD running) && docker_running || return 1
	ids=$@
	for id in $ids; do
		id=$(docker ps --filter "ID=$id" --quiet)
		[ -z "$id" ] && {
			 echo "Docker containner not running"; 
			 return 1;
		}
		ports=$(docker ps --filter "ID=$id" --format "{{.Ports}}")
		# echo "$ports"
		for port in $ports; do
				echo "$port" | grep -qE "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:.*$" || continue;
				[ "${port: -1}" == "," ] && port="${port:0:-1}"
				local protocol=""
				[ "${port%tcp}" != "$port" ] && protocol="/tcp"
				[ "${port%udp}" != "$port" ] && protocol="/udp"
				[ "$protocol" == "" ] && continue
				port="${port%%->*}"
				port="${port##*:}"
				uci_add_list dockerd dockerman ac_allowed_ports "${port}${protocol}"
		done
	done
	uci_commit dockerd
}


convert() {
	_convert() {
		_id=$1
		_id=$(docker ps --all --filter "ID=$_id" --quiet)
		if [ -z "$_id" ]; then
			uci_remove_list dockerd dockerman ac_allowed_container "$1"
			return
		fi
		if /etc/init.d/dockerman add_ports "$_id"; then
			uci_remove_list dockerd dockerman ac_allowed_container "$_id"
		fi
	}
	config_list_foreach dockerman ac_allowed_container _convert
	uci_commit dockerd
}

iptables_append(){
	# Wait for a maximum of 10 second per command, retrying every millisecond
	local iptables_wait_args="--wait 10 --wait-interval 1000"
	if ! iptables ${iptables_wait_args} --check $@ 2>/dev/null; then
		iptables ${iptables_wait_args} -A $@ 2>/dev/null
	fi
}

init_dockerman_chain(){
	iptables -N DOCKER-MAN >/dev/null 2>&1
	iptables -F DOCKER-MAN >/dev/null 2>&1
	iptables -D DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1
	iptables -I DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1
}

delete_dockerman_chain(){
	iptables -D DOCKER-USER -j DOCKER-MAN >/dev/null 2>&1
	iptables -F DOCKER-MAN >/dev/null 2>&1
	iptables -X DOCKER-MAN >/dev/null 2>&1
}

add_allowed_interface(){
	iptables_append DOCKER-MAN -i $1 -o docker0 -j RETURN
}

add_allowed_ports(){
	port=$1
	if [ "${port%/tcp}" != "$port" ]; then
		iptables_append DOCKER-MAN -p tcp -m conntrack --ctorigdstport ${port%/tcp} --ctdir ORIGINAL -j RETURN
	elif [ "${port%/udp}" != "$port" ]; then
		iptables_append DOCKER-MAN -p udp -m conntrack --ctorigdstport ${port%/udp} --ctdir ORIGINAL -j RETURN
	fi
}

handle_allowed_ports(){
	config_list_foreach "dockerman" "ac_allowed_ports" add_allowed_ports
}

handle_allowed_interface(){
	config_list_foreach "dockerman" "ac_allowed_interface" add_allowed_interface
	iptables_append DOCKER-MAN -m conntrack --ctstate ESTABLISHED,RELATED -o docker0 -j RETURN >/dev/null 2>&1
	iptables_append DOCKER-MAN -m conntrack --ctstate NEW,INVALID -o docker0 -j DROP >/dev/null 2>&1
	iptables_append DOCKER-MAN -j RETURN >/dev/null 2>&1
}

start_service(){
	[ -x "$_DOCKERD" ] && $($_DOCKERD enabled) || return 0
	delete_dockerman_chain
	$($_DOCKERD running) && docker_running || return 0
	init_dockerman_chain
	handle_allowed_ports
	handle_allowed_interface
}

stop_service(){
	delete_dockerman_chain
}

service_triggers() {
	procd_add_reload_trigger 'dockerd'
}

reload_service() {
	start
}

boot() {
	sleep 5s
	start
}

extra_command "add_ports" "Add allowed ports based on the container ID(s)"
extra_command "convert" "Convert Ac allowed container to AC allowed ports"
