#!/bin/bash

# Copyright: 2023 Virtuozzo International GmbH

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.



inherit default os net;
include log vzexec virtuozzo;

DESCRIPTION="Manipulate DNAT iptables rules";
VERSION="1.2"
DEFAULT_ACTION="Usage";


$PROGRAM 'iptables';
$PROGRAM 'tail';
$PROGRAM 'sed';
$PROGRAM 'grep';

FORWARD_RANGE_START=50000
FORWARD_RANGE_END=55000
NAT_ACTION='dnat'

EXEC="/bin/bash -c "
FIREWALL_RULES_DIR="/etc/jelastic/iptables"

function doUsage() {
    showUsageMessage
}


function onModLoadCallback() {
    local args=$(getopt -o c:i:p:s:a: -l "ctid:,ip:,dport:,sport:,proto:,net:,action" -- "$@");
    [[ $? != 0 ]] && die -q "Terminating...";

    eval set -- "${args}";

    while true ; do
        case "${1}" in
            -i|--ip)
                case "${2}" in
                    "") die -q "Please specify IP address param." ;;
                    *) __IP=${2}; shift 2 ;;
                esac ;;
            -p|--dport)
                case "${2}" in
                    "") die -q "Please specify destination port param." ;;
                    *) __PORT=${2}; shift 2 ;;
                esac ;;
            -s|--sport)
                case "${2}" in
                    "") die -q "Please specify source port param." ;;
                    *) __SPORT=${2}; shift 2 ;;
                esac ;;
            --proto)
                case "${2}" in
                    "") die -q "Please specify proto param." ;;
                    *) __PROTO=`echo ${2} | tr A-Z a-z`; shift 2 ;;
                esac ;;
             --net)
                case "${2}" in
                    "") die -q "Please specify network param." ;;
                    *) __NETWORK=${2}; shift 2 ;;
                esac ;;

            -a | --action)
                case "${2}" in
                    "") die -q "Please specify action param." ;;
                    *) NAT_ACTION=`echo ${2} | tr A-Z a-z`; shift 2 ;;
                esac ;;
            -c|--ctid)
                CTID=$2
                vzexecSetCTID $CTID
                shift 2;;
            --) shift ; break ;;
            *) die -q "ROUTER.MODULE (onModLoadCallback) Internal error!";
        esac;
    done
    [ -z "$__PROTO" ] && __PROTO=tcp ;

    if [[ ! -z "${CTID}" ]] ; then
        populateVEVarsVZ $CTID
        res=$?
        if [[ "$res" -eq 3 ]] ; then
            writeJSONResponseErr "result=>4003" "message=>ctid $CTID not found"
            die -q;
        fi
        VZ_CTID_ROOT=$VZ_VEID_ROOT
    else
        local issue_file="/etc/issue"
        local release_files="/etc/*-release"
        issue_string=$(set +f; cat $release_files $issue_file 2>/dev/null)
        VZ_VEID_OS=$(detectOS "$issue_string")
        VZ_VEID_OS_VER=$(getOSVersion "$issue_string")
        VZ_VEID_OS_VER=${VZ_VEID_OS_VER%%.*}
    fi


    if [ "x$VZ_VEID_OS" == "xalmalinux" -a "$VZ_VEID_OS_VER" -ge "9" ] ; then
        inherit nftables
    else
        inherit iptables
    fi

    return 0
}

function getFreePort() {
    __SPORT=$1
    [ ! -z "$__SPORT" ] && { echo $__SPORT ; return ; }
    local usedPorts=($(getUsedPorts))
    eval "availablePorts=($(seq ${FORWARD_RANGE_START} ${FORWARD_RANGE_END}| sed -re 's/([0-9]+)/[\1]="0"/g'))"
    for port in "${!usedPorts[@]}"; do
        availablePorts[${usedPorts[$port]}]=1
    done;
    freePorts=($(
        for key in "${!availablePorts[@]}"; do
            [[ ${availablePorts["${key}"]} -eq 0 ]] &&  echo "$key"; done | sort -n
        ))
    echo ${freePorts[0]}
}

function describeForward() {
    echo "Get and add free port for DNAT for specified local IP:Port";
}

function describeForwardParameters() {
    echo "--ip <IP> --dport <Port> [--sport <Port>] [--proto <PROTOCOL>]";
}

function describeForwardOptions() {
   echo "--ip: destination IP address";
   echo "--dport: destination port";
   echo "--sport: source port";
   echo "--proto: protocol";
}

function doRedirect() {
    : ${__PORT?  "Missing  destination port" }
    : ${__SPORT? "Missing source port" }
    : ${__PROTO? "Missing protocol" }

    echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction performing redirect" >>$JEM_CALLS_LOG
    isFunction "netfilterRedirect" && netfilterRedirect $__PORT $__SPORT $__PROTO

}

function doForward() {
    echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction performing forward" >>$JEM_CALLS_LOG
    isFunction "netfilterForward" && netfilterForward $__IP $__PORT $__PROTO $__SPORT
}

function describeSNAT() {
    echo "Add SNAT";
}

function describeForwardParameters() {
    echo "--ip <IP> --net <NETWORK> [--proto <PROTOCOL>]";
}

function describeForwardOptions() {
   echo "--ip: destination IP address";
   echo "--net: network";
   echo "--proto: protocol";
}

function doSNAT() {
    : ${__IP? "Missing IP address" }
    : ${__NETWORK? "Missing network" }

    echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction performing SNAT" >>$JEM_CALLS_LOG
    isFunction "netfilterSNAT" && netfilterSNAT $__IP $__NETWORK $__PROTO
}

function describeUnbind() {
    echo "Delete specified IP[:Port] binding for DNAT";
}

function describeUnbindParameters() {
    echo "--ip <IP> [--dport <Port>]  [--proto <PROTOCOL>]";
}

function describeUnbindOptions {
    echo "--ip: destination IP address";
    echo "--dport: destination port";
    echo "--proto: protocol";
}

function doUnbind() {
    : ${__IP? "Missing IP address" }
    : ${__PROTO? "Missing protocol" }

    echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction performing unbind" >>$JEM_CALLS_LOG
    isFunction "netfilterUnbind" && netfilterUnbind $__IP $__PORT $__PROTO
}

# vim: syntax=sh
