
IP_CMD="ip"
IPT_CMD=`which iptables-legacy`
if [ $? -ne 0 ]; then
    IPT_CMD=`which iptables`
    if [ $? -ne 0 ]; then
        echo " Error! Iptables doesn't exists" >&2
        exit 1
    fi
fi

IPT_ALLOWED_HOSTS_CHAIN="${NAME}_allowed_hosts"
IPT_BLLIST_CHAIN="${NAME}_blacklist"
IPT_ACTION_CHAIN="${NAME}_action"
IPT_FIRST_CHAIN="PREROUTING"
VPN_ROUTE_TABLE_ID=99

case "$ALLOWED_HOSTS_MODE" in
    "1")
        IPT_ALLOWED_HOSTS_RULE="-m set --match-set ${IPSET_ALLOWED_HOSTS} src -j ${IPT_BLLIST_CHAIN}"
    ;;
    "2")
        IPT_ALLOWED_HOSTS_RULE="-m set ! --match-set ${IPSET_ALLOWED_HOSTS} src -j ${IPT_BLLIST_CHAIN}"
    ;;
    *)
        IPT_ALLOWED_HOSTS_RULE="-j ${IPT_BLLIST_CHAIN}"
    ;;
esac

if [ "$PROXY_MODE" = "2" ]; then
    IPT_TABLE="mangle"
else
    IPT_TABLE="nat"
fi

IptCmdWrapper() {
    local _i=0 _attempts=10 _return_code=1
    while [ $_i -lt $_attempts ]
    do
        if $*; then
            _return_code=$?
            break
        fi
        _i=`expr $_i + 1`
    done
    return $_return_code
}

IptVpnRouteAdd() {
    VPN_IP=`$IP_CMD addr list dev $IF_VPN 2> /dev/null | $AWK_CMD '/inet/{sub("/[0-9]{1,2}$", "", $2); print $2; exit}'`
    if [ -n "$VPN_IP" ]; then
        echo 0 > /proc/sys/net/ipv4/conf/$IF_VPN/rp_filter
        IptVpnRouteDel 2> /dev/null
        $IP_CMD rule add fwmark $VPN_PKTS_MARK table $VPN_ROUTE_TABLE_ID priority 1000
        $IP_CMD route add default via $VPN_IP table $VPN_ROUTE_TABLE_ID
    fi
}

IptVpnRouteDel() {
    $IP_CMD route flush table $VPN_ROUTE_TABLE_ID
    $IP_CMD rule del table $VPN_ROUTE_TABLE_ID
}

IptVpnRouteStatus() {
    [ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0
    return 1
}

IptMainAdd() {
    local _set
    $IPT_CMD -t "$IPT_TABLE" -N "$IPT_ACTION_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -N "$IPT_BLLIST_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -N "$IPT_ALLOWED_HOSTS_CHAIN"
    IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ALLOWED_HOSTS_CHAIN" $IPT_ALLOWED_HOSTS_RULE
    IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -I "$IPT_FIRST_CHAIN" 1 -j "$IPT_ALLOWED_HOSTS_CHAIN"

    if [ "$PROXY_MODE" = "2" ]; then
        IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -j MARK --set-mark $VPN_PKTS_MARK
        IPT_IPSETS="${IPSET_CIDR} ${IPSET_IP} ${IPSET_DNSMASQ}"
    elif [ "$PROXY_MODE" = "3" ]; then
        IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p tcp -j REDIRECT --to-ports ${T_PROXY_PORT_TCP}
        if [ "$T_PROXY_ALLOW_UDP" = "1" ]; then
            IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p udp -j REDIRECT --to-ports ${T_PROXY_PORT_UDP}
        fi
        IPT_IPSETS="${IPSET_CIDR} ${IPSET_IP} ${IPSET_DNSMASQ}"
    else
        IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p tcp -j REDIRECT --to-ports ${TOR_TRANS_PORT}
        if [ "$TOR_ALLOW_UDP" = "1" ]; then
            IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p udp -j REDIRECT --to-ports ${TOR_TRANS_PORT}
        fi
        IPT_IPSETS="${IPSET_ONION} ${IPSET_CIDR} ${IPSET_IP} ${IPSET_DNSMASQ}"
    fi

    for _set in $IPT_IPSETS
    do
        IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_BLLIST_CHAIN" -m set --match-set "$_set" dst -j "$IPT_ACTION_CHAIN"
    done
    if [ "$PROXY_MODE" = "2" ]; then
        IptVpnRouteAdd
    fi
}

IptMainDel() {
    IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -D "$IPT_FIRST_CHAIN" -j "$IPT_ALLOWED_HOSTS_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -F "$IPT_ALLOWED_HOSTS_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -X "$IPT_ALLOWED_HOSTS_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -F "$IPT_BLLIST_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -X "$IPT_BLLIST_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -F "$IPT_ACTION_CHAIN"
    $IPT_CMD -t "$IPT_TABLE" -X "$IPT_ACTION_CHAIN"
    if [ "$PROXY_MODE" = "2" ]; then
        IptVpnRouteDel 2> /dev/null
    fi
}

IPT_OUTPUT_FIRST_RULE="-j ${IPT_BLLIST_CHAIN}"

IptLocalClientsAdd() {
    IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -I OUTPUT 1 $IPT_OUTPUT_FIRST_RULE
}

IptLocalClientsDel() {
    IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -D OUTPUT $IPT_OUTPUT_FIRST_RULE
}

IptListBllistChain() {
    $IPT_CMD -t "$IPT_TABLE" -v -L "$IPT_BLLIST_CHAIN"
}
