#!/bin/sh

SERVICE_RECORD_FILE=/tmp/syno_disable_early_accept_service_records
SERVICE_RECORD_FILE_LOCK=/tmp/syno_disable_early_accept_service_records.lock
LOCK_TIMEOUT=5
ARGS=$(getopt -o r:d:lRh -l "register:,deregister:,list,reset,help" -n "syno_disable_early_accept" -- "$@");

#Bad arguments
if [ $? -ne 0 ];
then
  exit 1
fi

eval set -- "$ARGS";


print_usage() {
	echo "Copyright (c) 2003-2016 Synology Inc. All rights reserved."
	echo -e "\nUsage:"
	echo -e "\t$0 -h, --help"
	echo -e "\t$0 -r, --register SERVNAME"
	echo -e "\t$0 -d, --deregister SERVNAME"
	echo -e "\t$0 -l, --list"
	echo -e "\t$0 -R, --reset"
}

register_service() {
	local service=$1

	[ -f "${SERVICE_RECORD_FILE}" ] || touch ${SERVICE_RECORD_FILE}
	grep -q "^\<${service}\>$" ${SERVICE_RECORD_FILE}
	if [ $? -ne 0 ]; then
		echo ${service} >> ${SERVICE_RECORD_FILE}
	fi
	remove_early_accept_rules
}

remove_early_accept_rules() {
	/sbin/iptables -F FORWARD_EARLY_ACCEPT
	/sbin/iptables -F INPUT_EARLY_ACCEPT
	/sbin/ip6tables -F FORWARD_EARLY_ACCEPT
	/sbin/ip6tables -F INPUT_EARLY_ACCEPT
}

deregister_service() {
  service=$1

  [ -f "${SERVICE_RECORD_FILE}" ] || touch ${SERVICE_RECORD_FILE}
  sed -i "/^\<${service}\>$/d" ${SERVICE_RECORD_FILE}

  left_registered_service_cnt=`wc -l < ${SERVICE_RECORD_FILE}`
  if [ ${left_registered_service_cnt} -eq 0 ]; then
    add_early_accept_rules
  fi
}

add_early_accept_rules() {
	/sbin/iptables -A FORWARD_EARLY_ACCEPT -m state --state RELATED,ESTABLISHED -j SYNO_FORWARD_ACCEPT
	/sbin/iptables -A INPUT_EARLY_ACCEPT -m state --state RELATED,ESTABLISHED -j ACCEPT
	/sbin/ip6tables -A FORWARD_EARLY_ACCEPT -m state --state RELATED,ESTABLISHED -j SYNO_FORWARD_ACCEPT
	/sbin/ip6tables -A INPUT_EARLY_ACCEPT -m state --state RELATED,ESTABLISHED -j ACCEPT
}

list_services() {
  [ -f "${SERVICE_RECORD_FILE}" ] && cat ${SERVICE_RECORD_FILE}
}

reset_services() {
  [ -f "${SERVICE_RECORD_FILE}" ] && rm ${SERVICE_RECORD_FILE}
  add_early_accept_rules
}

do_main() {
  case "$1" in
    -r|--register)
      register_service $2
      ;;
    -d|--deregister)
      deregister_service $2
      ;;
    -l|--list)
      list_services
      ;;
    -R|--reset)
      reset_services
      ;;
    -h|--help)
      print_usage
      ;;
    --)
      print_usage
      ;;
  esac
}

(
  ELAPSED_TIME=0
  while true; do
    if ! flock -n 9 && [ "${ELAPSED_TIME}" -lt "${LOCK_TIMEOUT}" ]; then
      sleep 1
      ELAPSED_TIME=$((ELAPSED_TIME + 1))
      continue
    else
      break;
    fi
  done

  if [ "${ELAPSED_TIME}" -lt "${LOCK_TIMEOUT}" ]; then
    do_main $@
  else
    exit 1
  fi
) 9> ${SERVICE_RECORD_FILE_LOCK}
