#!/bin/sh

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

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
    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"`"
                  write_enum_item "gateway" "`_ "gateway (NAT)"`"
      esac
    ;;
    read)
      unset external_ifaces opened_services opened_tcp_ports opened_udp_ports mode
      eval $(iptables_helper -"$in_ipv" show)
      write_string_param "ipv"              "$in_ipv"
      write_bool_param   "status"           "$(get_status "$in_ipv")"
      write_string_param "external_ifaces"  "$external_ifaces"
      write_string_param "opened_services"  "$opened_services"
      write_string_param "opened_tcp_ports" "$opened_tcp_ports"
      write_string_param "opened_udp_ports" "$opened_udp_ports"
      write_string_param "mode"             "$mode"
      write_string_param "commit_mode"      "$commit_mode"
    ;;
    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
