#!/bin/sh

alterator_api_version=1
. alterator-sh-functions
. alterator-net-functions
. shell-config
. shell-var
. shell-quote

ETCNET_FWOPTIONS=/etc/net/ifaces/default/fw/options
ETCNET_DEFAUILT_OPTIONS=/etc/net/ifaces/default/options

get_status()
{
  local ipv="$1"
  local config_fw= iptables= config_ip=

  if [ "$ipv" = 6 ]; then
      iptables='ip6tables'
  else
      iptables='iptables'
  fi
  config_fw="$(shell_config_get "$ETCNET_DEFAUILT_OPTIONS" CONFIG_FW)"
  config_ip="$(shell_config_get "$ETCNET_FWOPTIONS" CONFIG_IPV$ipv)"
  if [ -z "$config_ip" ]; then
      config_ip="$(shell_config_get "$ETCNET_DEFAUILT_OPTIONS" CONFIG_IPV$ipv)"
  fi

  grep -qs "^FW_TYPE=.*$iptables.*" "$ETCNET_FWOPTIONS" &&
    shell_var_is_yes "$config_fw" &&
    shell_var_is_yes "$config_ip" &&
    echo true || echo false
}

set_status()
{
  local ipv="$1"; shift
  local status="$1"; shift

  if [ "$ipv" = 6 ]; then
      iptables='ip6tables'
  else
      iptables='iptables'
  fi
  if test_bool "$status"; then
      grep -qs "^FW_TYPE=.*$iptables.*" "$ETCNET_FWOPTIONS" ||
          sed -i -r "s;^FW_TYPE=\"?([[:alnum:][:blank:]]*)\"?;FW_TYPE=\"\1 $iptables\";" "$ETCNET_FWOPTIONS"

      shell_config_set "$ETCNET_DEFAUILT_OPTIONS" CONFIG_FW yes

      # Dirty hack: set CONFIG_IPV6=yes in the $ETCNET_FWOPTIONS.
      # Normally there shouldn't be such option, but we need
      # set it for 'default' fw and we don't want
      # to set it in the /etc/net/ifaces/default/options.
      if [ "$ipv" = 6 ]; then
          shell_config_set "$ETCNET_FWOPTIONS" CONFIG_IPV6 yes
      fi
  else
      /etc/net/scripts/contrib/efw --$iptables default all stop >/dev/null 2>&1
      sed -i -r -e "/^FW_TYPE=/s;$iptables;;" -e "/^FW_TYPE=/s;[[:blank:]]*\"[[:blank:]]*;\";g" "$ETCNET_FWOPTIONS"
  fi
}

on_message()
{
  case "$in_action" in
    type)
        write_type_item 'status'      'boolean'
        write_type_item 'commit_mode' 'boolean'
        write_type_item 'ipv'         'integer'
        write_type_item 'opened_tcp_ports' 'tcp-port-list'
        write_type_item 'opened_udp_ports' 'tcp-port-list'
        ;;
    
    list)
      set_locale
      case "$in__objects" in
        ipv)
            write_enum_item "4" "`_ "IPv4"`"
            if is_ipv6_enabled; then
                write_enum_item "6" "`_ "IPv6"`"
            fi
        ;;
        ifaces)
          list_iface |
          while read ifname; do
            local ifinfo="$(netdev_read_info "$ifname")"
              local ip="$(read_iface_current_addresses "$ifname" $in_ipv)"
              write_enum_item "$ifname" "$ifname${ifinfo:+ ($ifinfo)}${ip:+ $ip}"
            done
        ;;
        services) iptables_helper -"$in_ipv" list | cut -f1,3 | write_enum ;;
        modes)    write_enum_item "router"  "`_ "router"`"
                  [ "$in_ipv" = "6" ] || write_enum_item "gateway" "`_ "gateway (NAT)"`"
                  write_enum_item "host" "`_ "host (Workstation)"`"
      esac
    ;;
    read)
        write_string_param "ipv"    "$in_ipv"
        write_bool_param 'commit_mode' "$(iptables_helper -"$in_ipv" show -c)"
        write_bool_param   "status" "$(get_status "$in_ipv")"
        _keys="external_ifaces/e opened_services/s opened_tcp_ports/t opened_udp_ports/u mode/m"
        for _kk in $_keys; do
            _k="${_kk%/*}"; _opt="${_kk##*/}"
            _v="$(iptables_helper -"$in_ipv" show -$_opt | tr '\n' ';')"
	    _v="${_v%;}"
            quote_shell_variable "$_k" "$_v"
            write_string_param "$_k" "$_v"
        done
    ;;
    write)
      set_locale
      local ans="$(iptables_helper -"$in_ipv" write \
        -m "${in_mode:-router}"   \
        -e "$in_external_ifaces"  \
        -s "$in_opened_services"  \
        -t "$in_opened_tcp_ports" \
        -u "$in_opened_udp_ports" 2>&1)"
      [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"
      # call set_status *after* iptables_helper:
      # it always enables firewalling and we can't
      # set commit_mode to 'false' because it currently
      # means 'manually edit' mode
      set_status "$in_ipv" "$in_status"
    ;;
    firsttime)
      set_locale
      local ans="$(iptables_helper -"$in_ipv" write \
        -e "$in_external_ifaces" 2>&1)"
      [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"
    ;;
  esac
}

message_loop
