# The plugin configuration file
###############################
PLUGIN_CONF_FILE="parasitic-net.conf"

# Preinit return value for success
PLUGIN_RET_VAL=0

# Check sanity of environment
parasitic_net_helper_sanity_check()
{
  # Check whether chain exists
  if ! ip4tables -nL PARASITIC_NET_ACL >/dev/null 2>&1; then
    echo "** ERROR: PARASITIC_NET_ACL does not exist! **" >&2
    return 1
  fi

  return 0
}


parasitic_net_helper_do_work()
{
  local RETVAL=0

  # Flush the PARASITIC_NET_ACL
  iptables -F PARASITIC_NET_ACL

  unset IFS
  for rule in $PARASITIC_NET_HOST_DENY_TCP; do
    if parse_rule "$rule" PARASITIC_NET_HOST_DENY_TCP "hosts-ports"; then
      echo "${INDENT}Denying access to $hosts for TCP port(s): $ports"

      IFS=' ,'
      for host in `ip_range "$hosts"`; do
        if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
          echo "** WARNING: Skipping TCP deny rule(s) for unresolvable host \"$host\"! **" >&2
          RETVAL=1
          continue
        fi

        for host_ip2 in $host_ip; do
          for port in $ports; do
            if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
              ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p tcp --dport $port -m limit --limit 1/m -j LOG \
                --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
            fi

            ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p tcp --dport $port -j $PARASITIC_NET_DENY_POLICY
          done
        done
      done
    fi
  done

  unset IFS
  for rule in $PARASITIC_NET_HOST_DENY_UDP; do
    if parse_rule "$rule" PARASITIC_NET_HOST_DENY_UDP "hosts-ports"; then
      echo "${INDENT}Denying access to $hosts for UDP port(s): $ports"

      IFS=' ,'
      for host in `ip_range "$hosts"`; do
        if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
          echo "** WARNING: Skipping UDP deny rule(s) for unresolvable host \"$host\"! **" >&2
          RETVAL=1
          continue
        fi

        for host_ip2 in $host_ip; do
          for port in $ports; do
            if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
              ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p udp --dport $port -m limit --limit 1/m -j LOG \
                --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
            fi

            ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p udp --dport $port -j $PARASITIC_NET_DENY_POLICY
          done
        done
      done
    fi
  done

  IFS=' ,'
  for hosts in $PARASITIC_NET_HOST_DENY_ICMP; do
    echo "${INDENT}Denying access to $hosts for ICMP requests"

    for host in `ip_range "$hosts"`; do
      if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
        echo "** WARNING: Skipping ICMP deny rule(s) for unresolvable host \"$host\"! **" >&2
        RETVAL=1
        continue
      fi

      for host_ip2 in $host_ip; do
        if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
          ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p icmp --icmp-type echo-request -m limit --limit 1/m -j LOG \
            --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
        fi

        ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p icmp --icmp-type echo-request -j $PARASITIC_NET_DENY_POLICY
      done
    done
  done

  unset IFS
  for rule in $PARASITIC_NET_HOST_DENY_IP; do
    if parse_rule "$rule" PARASITIC_NET_HOST_DENY_IP "hosts-protos"; then
      echo "${INDENT}Denying access to $hosts for IP protocol(s): $protos"

      IFS=' ,'
      for host in `ip_range "$hosts"`; do
        if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
          echo "** WARNING: Skipping IP deny rule(s) for unresolvable host \"$host\"! **" >&2
          RETVAL=1
          continue
        fi

        for host_ip2 in $host_ip; do
          for proto in $protos; do
            if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
              ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p $proto -m limit --limit 1/m -j LOG \
                --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
            fi

            ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p $proto -j $PARASITIC_NET_DENY_POLICY
          done
        done
      done
    fi
  done

  unset IFS
  for rule in $PARASITIC_NET_HOST_OPEN_TCP; do
    if parse_rule "$rule" PARASITIC_NET_HOST_OPEN_TCP "hosts-ports"; then
      echo "${INDENT}Allowing access to $hosts for TCP port(s): $ports"

      IFS=' ,'
      for host in `ip_range "$hosts"`; do
        if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
          echo "** WARNING: Skipping TCP allow rule(s) for unresolvable host \"$host\"! **" >&2
          RETVAL=1
          continue
        fi

        for host_ip2 in $host_ip; do
          for port in $ports; do
            ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p tcp --dport $port -j ACCEPT
          done
        done
      done
    fi
  done

  unset IFS
  for rule in $PARASITIC_NET_HOST_OPEN_UDP; do
    if parse_rule "$rule" PARASITIC_NET_HOST_OPEN_UDP "hosts-ports"; then
      echo "${INDENT}Allowing access to $hosts for UDP port(s): $ports"

      IFS=' ,'
      for host in `ip_range "$hosts"`; do
        if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
          echo "** WARNING: Skipping UDP allow rule(s) for unresolvable host \"$host\"! **" >&2
          RETVAL=1
          continue
        fi

        for host_ip2 in $host_ip; do
          for port in $ports; do
            ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p udp --dport $port -j ACCEPT
          done
        done
      done
    fi
  done

  IFS=' ,'
  for hosts in $PARASITIC_NET_HOST_OPEN_ICMP; do
    echo "${INDENT}Allowing access to $hosts for ICMP requests"

    for host in `ip_range "$hosts"`; do
      if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
        echo "** WARNING: Skipping ICMP allow rule(s) for unresolvable host \"$host\"! **" >&2
        RETVAL=1
        continue
      fi

      for host_ip2 in $host_ip; do
        ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p icmp --icmp-type echo-request -j ACCEPT
      done
    done
  done

  unset IFS
  for rule in $PARASITIC_NET_HOST_OPEN_IP; do
    if parse_rule "$rule" PARASITIC_NET_HOST_OPEN_IP "hosts-protos"; then
      echo "${INDENT}Allowing access to $hosts for IP protocol(s): $protos"

      IFS=' ,'
      for host in `ip_range "$hosts"`; do
        if ! get_dynamic_host_cached $host || [ -z "$host_ip" ]; then
          echo "** WARNING: Skipping IP allow rule(s) for unresolvable host \"$host\"! **" >&2
          RETVAL=1
          continue
        fi

        for host_ip2 in $host_ip; do
          for proto in $protos; do
            ip4tables -A PARASITIC_NET_ACL -d $host_ip2 -p $proto -j ACCEPT
          done
        done
      done
    fi
  done

  # Set default policy
  if [ -z "$PARASITIC_NET_HOST_OPEN_TCP" ]; then
    ip4tables -A PARASITIC_NET_ACL -p tcp -j ACCEPT
  else
    if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
      ip4tables -A PARASITIC_NET_ACL -p tcp -m limit --limit 1/m -j LOG \
        --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
    fi

    ip4tables -A PARASITIC_NET_ACL -p tcp -j $PARASITIC_NET_DENY_POLICY
  fi

  if [ -z "$PARASITIC_NET_HOST_OPEN_UDP" ]; then
    ip4tables -A PARASITIC_NET_ACL -p udp -j ACCEPT
  else
    if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
      ip4tables -A PARASITIC_NET_ACL -p udp -m limit --limit 1/m -j LOG \
        --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
    fi

    ip4tables -A PARASITIC_NET_ACL -p udp -j $PARASITIC_NET_DENY_POLICY
  fi

  if [ -z "$PARASITIC_NET_HOST_OPEN_ICMP" ]; then
    ip4tables -A PARASITIC_NET_ACL -p icmp --icmp-type echo-request -j ACCEPT
  else
    if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
      ip4tables -A PARASITIC_NET_ACL -p icmp --icmp-type echo-request -m limit --limit 1/m -j LOG \
        --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
    fi

    ip4tables -A PARASITIC_NET_ACL -p icmp --icmp-type echo-request -j $PARASITIC_NET_DENY_POLICY
  fi

  # Drop the rest ("Other" IP protocols always need to be specified explicitly)
  if [ "$PARASITIC_NET_DENY_LOG" = "1" ]; then
    ip4tables -A PARASITIC_NET_ACL -m limit --limit 1/m -j LOG \
      --log-level $LOGLEVEL --log-prefix "AIF:Parasitic-net denied: "
  fi
  ip4tables -A PARASITIC_NET_ACL -j $PARASITIC_NET_DENY_POLICY

  return $RETVAL
}


############
# Mainline #
############

# Check where to find the config file
CONF_FILE=""
if [ -n "$PLUGIN_CONF_PATH" ]; then
  CONF_FILE="$PLUGIN_CONF_PATH/$PLUGIN_CONF_FILE"
fi

# Check if the config file exists
if [ ! -e "$CONF_FILE" ]; then
  echo "** ERROR: Config file \"$CONF_FILE\" not found! **" >&2
  PLUGIN_RET_VAL=1
else
  # Source the plugin config file
  . "$CONF_FILE"

  # Only proceed if environment ok
  if ! parasitic_net_helper_sanity_check; then
    PLUGIN_RET_VAL=1
  else
    if ! parasitic_net_helper_do_work; then
      PLUGIN_RET_VAL=1
    fi
  fi
fi
