#!/usr/bin/env bash

IPT="$(command -v ip6tables)"
NF6_CONF="/etc/net6filter-rules.conf"
NF6_CONF_DIR="/etc/net6filter-rules.d"

source_conf_file() {
  [ ! -f "${NF6_CONF}" ] && {
    echo "${NF6_CONF} missing" 1>&2
    exit 1
  }
  source "${NF6_CONF}"
}

run_extra_cmds() {
  [ ! -d "${NF6_CONF_DIR}" ] && {
    echo "${NF6_CONF_DIR} directory missing" 1>&2
    exit 1
  }
  local extra_cmds extra_cmd
  extra_cmds="$(find ${NF6_CONF_DIR} -type f -name '*.rule')"
  for extra_cmd in ${extra_cmds} ; do
    . ${extra_cmd}
  done
}

flush() {
  ${IPT} -P INPUT ACCEPT
  ${IPT} -P OUTPUT ACCEPT
  ${IPT} -P FORWARD ACCEPT

  ${IPT} -F INPUT
  ${IPT} -F OUTPUT
  ${IPT} -F FORWARD
  ${IPT} -F PREROUTING -t mangle
  ${IPT} -F POSTROUTING -t mangle
  ${IPT} -F LOGDROP -t filter > /dev/null 2>&1
  ${IPT} -X LOGDROP -t filter > /dev/null 2>&1
  ${IPT} -N LOGDROP
}

main() {
  case "${1}" in
    start)
      flush
      source_conf_file
      run_extra_cmds

      ${IPT} -t filter -A LOGDROP -j LOG --log-prefix "[DROP] "
      ${IPT} -t filter -A LOGDROP -j REJECT

      local int
      for int in ${ping} ; do
        ${IPT} -A INPUT -p icmpv6 -i ${int} -j ACCEPT
      done

      local except
      for except in ${exceptions} ; do
        ${IPT} -t filter -A INPUT -s ${except} -j ACCEPT
      done

      local int_all
      for int_all in ${all} ; do
        ${IPT} -t filter -A INPUT -i ${int_all} -j ACCEPT
      done

      OLDIFS=$IFS

      local int_t
      for int_t in ${tcpint} ; do
        IFS="+"
        set -- ${int_t}

        int_t=${1}
        shift
        nport=$#
        i=0;
        while (( ${i} < ${nport} )) ; do
          ${IPT} -t filter -A INPUT -i ${int_t} -p TCP --dport ${1} -j ACCEPT
          shift
          i=$[$i+1]
        done
      done

      IFS=$OLDIFS

      local int_u
      for int_u in ${udpint} ; do
        IFS="+"
        set -- ${int_u}

        int_u=$1
        shift
        nport=$#
        i=0;
        while (( ${i} < ${nport} )) ; do
          ${IPT} -t filter -A INPUT -i ${int_u} -p UDP --dport ${1} -j ACCEPT
          shift
          i=$[$i+1]
        done
      done

      ${IPT} -t filter -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

      [[ ${gateway} == "True" ]] && {
        ${IPT} -A FORWARD -i ${intif} -o ${extif} -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
        ${IPT} -A FORWARD -o ${intif} -i ${extif} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
      }

      [[ ${logdrop} == "True" ]] && {
        ${IPT} -t filter -A INPUT -j LOG --log-prefix "[DROP] "
      }

      IFS=$OLDIFS

      # REJECT
      ${IPT} -A INPUT -p TCP -j REJECT --reject-with icmp6-adm-prohibited # we prefer REJECT instead of DROP
      ${IPT} -A INPUT -p TCP -j REJECT --reject-with tcp-reset # we prefer REJECT instead of DROP
      ${IPT} -A INPUT -j REJECT # we prefer REJECT instead of DROP
      # To avoid the network break
      ${IPT} -P INPUT DROP
      ${IPT} -P OUTPUT ACCEPT
      ${IPT} -P FORWARD ACCEPT
    ;;

    stop)
      flush
    ;;

    restart)
      $0 start
    ;;

    *)
      echo "Usage: $0 [start|restart|stop]"
    ;;
  esac
}

main "${@}"