#!/bin/bash

set -f

FILE_MAX=16000
INODE_MAX=48000

#DBG="echo"

#ICMP_MIN="destination-unreachable source-quench redirect \
#	router-advertisement router-solicitation time-exceeded \
#	parameter-problem timestamp-request timestamp-reply \
#	address-mask-request address-mask-reply"

ICMP_MIN="destination-unreachable source-quench time-exceeded \
	  parameter-problem"


function icmp_res
{
    for type in $ICMP_MIN; do
	$DBG /sbin/ipchains -A icmp -p ICMP --icmp-type $type -j ACCEPT
    done
    $DBG /sbin/ipchains -A icmp -j DENY
}

function icmp_ping
{
    for type in $ICMP_MIN ping pong; do
	$DBG /sbin/ipchains -A icmp -p ICMP --icmp-type $type -j ACCEPT
    done

    $DBG /sbin/ipchains -A icmp -j DENY
}

function icmp_all
{
    $DBG /sbin/ipchains -A icmp -j ACCEPT;
}


$DBG /sbin/ipchains -F
$DBG /sbin/ipchains -X
$DBG /sbin/ipchains -N icmp
$DBG /sbin/ipchains -A input -p ICMP -j icmp

(while read -r line;do
    unset forward masq ipcopts SrcDev DstDev global syn action input proto
    unset protoarg  srcport dstport
    # Remove comments
    line=$(echo $line|(IFS="#" read a b; echo $a))

    set -- $line
    while test $# -gt 0; do
        if test -n "$DBG" ;then  echo "$@" '>>>' "$ipcopts";fi
	case "$1" in 
	    Global)
		global=true
		while test $# -gt 0; do
		shift
		case $1 in 
		    ICMP)
			shift
			case $1 in 
			    restricted)
				icmp_res
				;;
			    ping)
				icmp_ping
				;;
			    all)
				icmp_all
				;;
			esac;;
		    Input)
			shift
			$DBG /sbin/ipchains -P input $1
			;;
		    Forward)
			shift
			$DBG /sbin/ipchains -P forward $1
			;;
		    Output)
			shift
			$DBG /sbin/ipchains -P output $1
			;;
		esac
		done
		;;
	    Chain)
		shift
		case $1 in 
		    Input)
			input="true"
			;;
		    Forward)
			forward="true"
			;;
		    Masq)
			forward="true"
			masq="true"
			do_masq="true"
			;;
		    InForward)
			input="true"
			forward="true"
			;;
		    InMasq)
			input="true"
			forward="true"
			masq="true"
			do_masq="true"
			;;
		esac
		;;
	    Action)
		shift
		action="-j $1"
#		case $1 in 
# 		    ACCEPT)
#			;;
#		    DENY)
#			;;
#		    REJECT)
#			;;
#		    REDIRECT)
#			;;
#		esac
		;;
	    SrcDev)
		shift
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		if test "$1" != "*";then
		    SrcDev="-i $not $1"
		fi
		;;
	    SrcIP)
		shift
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		if test "$1" != "*";then
		    ipcopts="$ipcopts -s $not $1"
		fi
		;;
	    SrcPorts)
		shift
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		if test "$1" != "*";then
		    ipcopts="$ipcopts --source-port $not $1"
                fi
		;;
	    DstDev)
		shift
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		if test "$1" != "*";then
		    DstDev="-i $not $1"
                fi
		;;
	    DstIP)
		shift
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		if test "$1" != "*";then
		    ipcopts="$ipcopts -d $not $1"
		fi
		;;
	    DstPorts)
		shift
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		if test "$1" != "*";then
		    ipcopts="$ipcopts --destination-port $not $1"
                fi
		;;
	    Proto)
                if test "X$1" = 'X!'; then
                    shift
                    not='!'
		else
                    not=''
		fi
		shift
		if test "$1" != "*";then
		    protoarg="-p $not $1"
                fi
		proto="$not$1"
		;;
	    RePort)
		shift
		if test "$action" = "-j REDIRECT";then		
		    action="$action $1";
		fi
		;;
	    Option)
		shift
		case $1 in 
		    SOC)
			syn="-y"
			;;
		    OC)
			syn="! -y"
			;;
		    Log)
			ipcopts="$ipcopts -l"
			;;
		    BiDir)
			ipcopts="$ipcopts -b"
			;;
		esac
		;;
	esac;

	if test $# -gt 0;then
	    shift
	fi
    done
    if test "$global" != "true"; then

	# Forward Chain
	if test "$forward" = "true"; then
	    if test "$masq" = "true"; then
	        if test "$proto" = "*"; then
		   $DBG /sbin/ipchains -A forward -p tcp $DstDev $ipcopts -j MASQ
		   $DBG /sbin/ipchains -A forward -p udp $DstDev $ipcopts -j MASQ
		else
		   $DBG /sbin/ipchains -A forward $DstDev $ipcopts $protoarg -j MASQ
		fi
	    else
	        if test "$proto" = "*"; then
		   $DBG /sbin/ipchains -A forward -p tcp $DstDev $ipcopts $action
		   $DBG /sbin/ipchains -A forward -p udp $DstDev $ipcopts $action
		else
		   $DBG /sbin/ipchains -A forward $DstDev $ipcopts $protoarg $action
		fi
	    fi
	fi    

	# Input Chain
	if test "$input" = "true"; then
	    if test -n "$syn";then
		# SOC or OC
		$DBG /sbin/ipchains -A input $SrcDev $ipcopts \
			-p tcp $syn $action
		if test "$proto" != "tcp"; then 
		    if test "$proto" = "*"; then
			$DBG /sbin/ipchains -A input $SrcDev $ipcopts \
			    -p udp $action
	            else
			$DBG /sbin/ipchains -A input $SrcDev $ipcopts \
			   $protoarg $action
		    fi
		fi
	    else
	        if test "$proto" = "*"; then
		   # Normal input chain
		   $DBG /sbin/ipchains -A input $SrcDev \
		       $ipcopts -p tcp $action
		   # Normal input chain
		   $DBG /sbin/ipchains -A input $SrcDev \
		       $ipcopts -p udp $action
		else
		   # Normal input chain
		   $DBG /sbin/ipchains -A input $SrcDev \
		       $ipcopts $protoarg $action
		fi
	    fi
	fi

	# Output chain
	if test "$proto" = "*"; then
		$DBG /sbin/ipchains -A output $DstDev \
                	$ipcopts -p tcp $action
		$DBG /sbin/ipchains -A output $DstDev \
                        $ipcopts -p udp $action
	else
		$DBG /sbin/ipchains -A output $DstDev \
                        $ipcopts $protoarg $action
	fi
    fi
done

) < /etc/sysconfig/firewall

/sbin/service ipchains save

