#!/bin/sh

alterator_api_version=1
. alterator-sh-functions
. /usr/lib/alterator-net-iptables/srv.sh

po_domain="alterator-net-iptables"

TCCONF="/etc/alterator/net-tc.conf"

get_mac(){
  local data="${1:-}"
  echo "$data" |
    sed -r -n 's/^[[:space:]]*[0-9\.[:xdigit:]:]+=([[:xdigit:]:]+)[[:space:]]*$/\1/p'
}

on_message()
{
  case "$in_action" in
    list) # list all rules
      set_locale
      local ipmac ip mac services
      write_enum_item "default" "`_ "Default"`"
      iptables_helper -"$in_ipv" ir list |
        while read ipmac services comm; do
          local ip=${ipmac%%=*}
          [ -z "$ip" ] || echo "$ip $ip ${comm:+($comm)}"
        done | grep -v "^default" | write_enum
    ;;
    read) # read data for selected ip=mac
      write_bool_param "status" "$(iptables_helper -"$in_ipv" ir status)"
      write_string_param commit_mode "$(iptables_helper -"$in_ipv" show -c)"
      local ifaces="$(iptables_helper -"$in_ipv" show -i | tr -s '\n' ',')"
      write_string_param "ifaces"  "${ifaces%,}"
      [ -n "$in_name" ] || return
      iptables_helper -"$in_ipv" ir show "$in_name" | (
        local key srv comm
        read  key srv comm
        srv="$(echo "$srv" | tr ';, ' '\n')"
        write_string_param "services"  "$(echo "$srv" | srv_extract srv)"
        write_string_param "tcp_ports" "$(echo "$srv" | srv_extract tcp)"
        write_string_param "udp_ports" "$(echo "$srv" | srv_extract udp)"
        write_string_param "mac"       "$(get_mac "$key")"
        write_string_param "comm"      "$comm"
      )
      if [ "$in_ipv" = 4 ]; then
          local ip i o
          grep "^[[:space:]]*$in_name[[:space:]]" "$TCCONF" | (
            read ip i o
            write_string_param "ikbps" "${i:-0}"
            write_string_param "okbps" "${o:-0}"
          )
      fi
    ;;
    add)
      set_locale
      local ans="$(iptables_helper -"$in_ipv" ir add "$in_new_ip" 2>&1)"
      [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"
    ;;
    switch)
      set_locale
      local status
      if [ "$in_status" = "#t" ]; then
        local ans="$(iptables_helper -"$in_ipv" ir on  2>&1)"
        [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"

        if [ "$in_ipv" = 4 -a "$(iptables_helper -"$in_ipv" show -c)" != "off" ]; then
          ans="$(alterator-net-tc restart > /dev/null 2>&1)"
          [ -z "$ans" ] || write_error "${ans#alterator-net-tc*:}"
        fi

      else
        local ans="$(iptables_helper -"$in_ipv" ir off  2>&1)"
        [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"

        if [ "$in_ipv" = 4 -a "$(iptables_helper -"$in_ipv" show -c)" != "off" ]; then
          ans="$(alterator-net-tc stop)"
          [ -z "$ans" ] || write_error "${ans#alterator-net-tc*:}"
        fi
      fi
    ;;
    resolve)
      local ping=
      [ "$in_ipv" = 4 ] && ping=ping || ping=ping6
      $ping -w1 -c1 -q "$in_name" &>/dev/null
      local mac="$(ip -"$in_ipv" n |\
          sed -r -n "s/^$in_name dev [[:alnum:]]+ lladdr ([[:xdigit:]:]+) .*$/\1/p")"
      write_string_param "mac" "$mac"
    ;;
    del)
      [ -n "$in_name" ] || return
      set_locale
      local ans="$(iptables_helper -"$in_ipv" ir del "$in_name" 2>&1)"
      [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"
      if [ "$in_ipv" = 4 ]; then
        sed -i "/^[[:space:]]*$in_name[[:space:]].*/d" "$TCCONF"
      fi
    ;;
    write)
      set_locale
      local ans
      local services="$(srv_compile "$in_services" "$in_tcp_ports" "$in_udp_ports")"

      [ -n "$in_name" ] || {
        write_error "`_ "IP-address is not specified"`"
        return
      }

      ans="$(iptables_helper -"$in_ipv" ir add "$in_name${in_mac:+=$in_mac} $services" "$in_comm" 2>&1)"
      [ -z "$ans" ] || write_error "${ans#iptables_helper*:}"

      if [ "$in_ipv" = 4 -a "$in_name" != default ]; then
        if grep -s "^[[:space:]]*$in_name[[:space:]]" "$TCCONF"; then
          sed -i "s/^\([[:space:]]*$in_name[[:space:]]\+\).*/\1${in_ikbps:-0} ${in_okbps:-0}/" "$TCCONF"
        else
          echo "$in_name ${in_ikbps:-0} ${in_okbps:-0}" >> "$TCCONF"
        fi
        ans="$(alterator-net-tc restart >/dev/null 2>&1)"
        [ -z "$ans" ] || write_error "${ans#alterator-net-tc*:}"
      fi
    ;;
  esac
}

message_loop
