#!/bin/sh
#
# Copyright (C) 2008  Eugene Prokopiev <enp@altlinux.org>
#
# fw-scripts functions
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.


IPTABLES="/sbin/iptables"

IFS_OLD=$IFS
IFS="
"

function fw_clear()
{
    $IPTABLES -F
    $IPTABLES -X
    $IPTABLES -t nat -F
    $IPTABLES -t nat -X
}

# params: policy name
function fw_policy()
{
    $IPTABLES -P INPUT   $1
    $IPTABLES -P OUTPUT  $1
    $IPTABLES -P FORWARD $1
}


function fw_define_allowed() 
{
    $IPTABLES -N allowed
    IFS=$IFS_OLD
    [ -z "$ULOG_PARAMS" ] || $IPTABLES -A allowed -j ULOG $ULOG_PARAMS --ulog-prefix allow
    $IPTABLES -A allowed -j ACCEPT
}

function fw_define_rejected()
{
    $IPTABLES -N rejected
    IFS=$IFS_OLD
    [ -z "$ULOG_PARAMS"  ] || $IPTABLES -A rejected -j ULOG $ULOG_PARAMS --ulog-prefix drop
    for LOG_PARAM in ${LOG_PARAM[@]}
    do
	LOG_CRITERIA=`echo "$LOG_PARAM" | awk -F: '{print $1}'`
	LOG_PREFIX=`echo "$LOG_PARAM" | awk -F: '{print $2}'`
	IFS=$IFS_OLD
	$IPTABLES -A rejected $LOG_CRITERIA -j LOG --log-prefix "$LOG_PREFIX"
    done
    $IPTABLES -A rejected -p tcp -j REJECT --reject-with tcp-reset
    $IPTABLES -A rejected -j REJECT --reject-with icmp-port-unreachable
}

# params: interface name
function fw_allow_interface()
{
    $IPTABLES -A INPUT  -i $1 -j allowed
    $IPTABLES -A OUTPUT -o $1 -j allowed
}

# params: incoming and outgoing interface names
function fw_forward_between_interfaces()
{
    $IPTABLES -A FORWARD  -i $1 -o $2 -j allowed
    $IPTABLES -A FORWARD  -o $1 -i $2 -j allowed
}

function fw_validate_tcp()
{
    $IPTABLES -A INPUT -p tcp ! --syn -m state --state new -j rejected
    $IPTABLES -A INPUT -p tcp -m state --state established,related -j allowed
    $IPTABLES -A OUTPUT -p tcp ! --syn -m state --state new -j rejected
    $IPTABLES -A OUTPUT -p tcp -m state --state established,related -j allowed
    $IPTABLES -A FORWARD -p tcp ! --syn -m state --state new -j rejected
    $IPTABLES -A FORWARD -p tcp -m state --state established,related -j allowed
}

function fw_allow_icmp()
{
    $IPTABLES -A INPUT  -p icmp -j allowed
    $IPTABLES -A OUTPUT -p icmp -j allowed
}

function fw_allow_client_udp()
{
    $IPTABLES -A INPUT -m multiport -p udp --port 1025:65535 -j allowed
    $IPTABLES -A OUTPUT -m multiport -p udp --port 1025:65535 -j allowed
}

# params: source address, destination address, destination port for incoming packets
#         destination address, source address, source port for outgoing packets
function fw_allow_udp()
{
    $IPTABLES -A INPUT  -p udp -s $1 -d $2 --dport $3 -j allowed
    $IPTABLES -A OUTPUT -p udp -d $1 -s $2 --sport $3 -j allowed
}

function fw_allow_client_tcp()
{
    $IPTABLES -A OUTPUT -p tcp --syn -j allowed
}

# params: source address, fake destination address, fake source address, destination address
function fw_allow_host()
{
    $IPTABLES -t nat -A PREROUTING -s $1 -d $2 -j DNAT --to-destination $4
    $IPTABLES -t nat -A POSTROUTING -s $1 -d $4 -j SNAT --to-source $3
    $IPTABLES -A FORWARD -s $1 -d $4 -j allowed
    $IPTABLES -A FORWARD -s $4 -d $1 -j allowed
}

function fw_allow_tcp()
{
    case $# in
	3)
    	    # params: source address, destination address, destination port 
	    # for new incoming packets
	    $IPTABLES -A INPUT -p tcp --syn -s $1 -d $2 --dport $3 -j allowed
	    ;;
	4)
    	    # params: source address, destination address, destination port, redirected port 
	    # for new incoming packets
	    $IPTABLES -t nat -A PREROUTING -p tcp -s $1 -d $2 --dport $3 -j DNAT --to-destination $2:$4
	    $IPTABLES -A INPUT -p tcp --syn -s $1 -d $2 --dport $4 -j allowed
	    ;;
	5)
    	    # params: source address, destination address, destination port, redirected host, redirected port 
	    # for new incoming packets
	    $IPTABLES -t nat -A PREROUTING -p tcp -s $1 -d $2 --dport $3 -j DNAT --to-destination $4:$5
	    $IPTABLES -A FORWARD -p tcp --syn -s $1 -d $4 --dport $5 -j allowed
	    ;;
	6)
	    # params: source address, destination address, destination port, redirected host, redirected port, fake source address 
	    # for new incoming packets
	    $IPTABLES -t nat -A PREROUTING -p tcp -s $1 -d $2 --dport $3 -j DNAT --to-destination $4:$5
	    $IPTABLES -A FORWARD -p tcp --syn -s $1 -d $4 --dport $5 -j allowed
	    $IPTABLES -t nat -A POSTROUTING -p tcp -s $1 -d $4 --dport $5 -j SNAT --to-source $6
	    ;;
	*)
	    echo wrong arguments count
	    ;;
    esac				
}

function fw_forward_to_interface()
{
    case $# in
	2)
	    # params: destination interface name, source address for outgoing packets
	    #         source interface name, destination address for incoming packets
	    $IPTABLES -A FORWARD -o $1 -s $2 -j allowed
	    $IPTABLES -A FORWARD -i $1 -d $2 -j allowed
	    ;;
	3)
	    # params: destination interface name, source address, fake source address for outgoing packets
	    #         source interface name, destination address for incoming packets
	    $IPTABLES -A FORWARD -o $1 -s $2 -j allowed
	    $IPTABLES -A FORWARD -i $1 -d $2 -j allowed
	    $IPTABLES -t nat -A POSTROUTING -o $1 -s $2 -j SNAT --to-source $3
	    ;;
	4)
	    # params: destination interface name, source address, fake source address, destination address for outgoing packets
	    #         source interface name, destination address for incoming packets
	    $IPTABLES -A FORWARD -o $1 -s $2 -d $4 -j allowed
	    $IPTABLES -A FORWARD -i $1 -d $2 -s $4 -j allowed
	    $IPTABLES -t nat -A POSTROUTING -o $1 -s $2 -d $4 -j SNAT --to-source $3
	    ;;
	*)
	    echo wrong arguments count
	    ;;
    esac
}

function fw_drop()
{
    $IPTABLES -A INPUT   -j rejected
    $IPTABLES -A OUTPUT  -j rejected
    $IPTABLES -A FORWARD -j rejected
}

function fw_begin()
{
    fw_clear
    fw_policy DROP
    fw_define_allowed
    fw_define_rejected
    fw_allow_interface lo
    fw_allow_icmp
    fw_allow_client_udp
    fw_allow_client_tcp
    fw_validate_tcp
}

function fw_end()
{
    fw_drop
}
