
#-----------------------------------------------------------------------
# Copyright (C) 2000-2001, Jean-Sebastien Morisset <jsmoriss@mvlan.net>
#-----------------------------------------------------------------------
# $Id: hostports.sh,v 1.5 2001/08/11 17:01:20 jsmoriss Exp $
#-----------------------------------------------------------------------
#  $RCSfile: hostports.sh,v $
#   $Author: jsmoriss $
# $Revision: 1.5 $
#     $Date: 2001/08/11 17:01:20 $
#   $Locker:  $ 
#     $Name:  $
#-----------------------------------------------------------------------
#
# This program 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 <http://www.gnu.org/copyleft/gpl.txt>.
# 
# 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 (LICENSE file in archive) for more details.
#
#-----------------------------------------------------------------------
# README
#-----------------------------------------------------------------------
#
# A bourne shell function used by rcf; a very secure, fast, and complete
# firewall for linux <http://jsmoriss.mvlan.net/linux/rcf.html>.
#
#-----------------------------------------------------------------------
# FUNCTION
#-----------------------------------------------------------------------

Hostports () {
	#
	# This function expects each host to have an accompanying port number.
	#
	# Syntax:
	#   Hostports [accept|deny|ignore] [local|remote] {prot} {description} {hosts and ports}
	#
	# Examples:
	#   Hostports accept local tcp "HTTP" any/0 www
	#   Hostports accept local tcp "My Game" first.friend.com 1234:1240 1666, second.friend.com 1234
	#
	
	lcase_action_arg="`echo $1|To_Lower`"
	case $lcase_action_arg in
		accept|ignore)
			action_log="$LOG"
			action_log_msg="$LOG_MSG"
			;;
		deny)
			action_log="-l"
			action_log_msg="(logged)"
			;;
		*)	echo "Hostports [accept|deny|ignore] [local|remote] {prot} {description} {hosts and ports}"
			return
			;;
	esac
	
	lcase_loc_arg="`echo $2|To_Lower`"
	case $lcase_loc_arg in
		local)
			case $lcase_action_arg in
				accept) desc_action="Accept" ;;
				deny|ignore) desc_action="Deny" ;;
			esac
			;;
		remote)
			case $lcase_action_arg in
				accept) desc_action="Accept" ;;
				deny|ignore) desc_action="Reject" ;;
			esac
			;;
		*)	echo "Hostports [accept|deny|ignore] [local|remote] {prot} {description} {hosts and ports}"
			return
			;;
	esac

	prot_arg="$3"
	desc_arg="$4"
	shift 4		# $1 should now be a host and $2 a port, etc.

	# Make sure there's at least one host ($1) and one port ($2)
	if [ "$2" ]
	then
		lcase_prot_arg="`echo $prot_arg|To_Lower`"
		hostports_arg="`echo $*|sed -e 's/,/ *separator* /g'`"
		host_field=""

		for field in $hostports_arg
		do
			if [ "$field" = "*separator*" ]
			then
				host_field=""
			elif [ ! "$host_field" ]
			then
				host_field="$field"
			else
				port_field="$field"
				
				# Display the port number only if it's numerical.
				[ "`echo $port_field|grep '^[0-9][0-9]*'`" ] \
					&& showport=" Port# ${port_field}" || showport=""

				case $lcase_prot_arg in
					tcp)	synopt="! -y";;
					*)		synopt="";;
				esac

				# If this is a rule for a cluster, we need access *through* the Interface.
				# This means the INCHAIN/OUTCHAIN variables must be reversed
				if [ "$CLUSTER_NAME" ]
				then
					inchain="$OUTCHAIN"
					outchain="$INCHAIN"
				else
					inchain="$INCHAIN"
					outchain="$OUTCHAIN"
				fi

				case $lcase_loc_arg in
					local)
						[ "$desc_arg" ] && \
						echo "$desc_action $INTOPT $IPADDR ${desc_arg}${showport}/$lcase_prot_arg <- $host_field $action_log_msg"
						
						case $lcase_action_arg in
							accept)
								ipchains -A $inchain  -j ACCEPT -p $lcase_prot_arg \
									-s $host_field $UNPRIVPORTS -d $IPADDR $port_field $action_log
								ipchains -A $outchain -j ACCEPT -p $lcase_prot_arg \
									$synopt -s $IPADDR $port_field -d $host_field $UNPRIVPORTS $action_log
								;;
							deny|ignore)
								ipchains -A $inchain  -j DENY -p $lcase_prot_arg \
									-s $host_field $UNPRIVPORTS -d $IPADDR $port_field $action_log
								;;
						esac
						;;
					remote)
						[ "$desc_arg" ] && \
						echo "Accept $INTOPT $IPADDR/$lcase_prot_arg -> $host_field ${desc_arg}${showport} $action_log_msg"
						
						case $lcase_action_arg in
							accept)
								ipchains -A $inchain  -j ACCEPT -p $lcase_prot_arg \
									$synopt -s $host_field $port_field -d $IPADDR $UNPRIVPORTS $action_log
								ipchains -A $outchain -j ACCEPT -p $lcase_prot_arg \
									-s $IPADDR $UNPRIVPORTS -d $host_field $port_field $action_log
								;;
							deny|ignore)
								ipchains -A $outchain -j REJECT -p $lcase_prot_arg \
									-s $IPADDR $UNPRIVPORTS -d $host_field $port_field $action_log
								;;
						esac
						;;
				esac
			fi
			unset synopt
		done
		unset lcase_prot_arg hostports_arg field host_field port_field
	fi
	unset lcase_action_arg action_log action_log_msg
	unset lcase_loc_arg prot_arg desc_arg
}

