#!/bin/sh
. /etc/utils

#set -x

routing_table()
{
route -n | rgrep -v 127.0.0 | rgrep . | rgrep -v default |
while read dest gw mask flag mss window use int 
do
echo "$dest/$mask ($int)"
done 
}

my_ip()
{
local ip
for i in eth0 eth1 ppp0 ppp1 plip0 plip1 lo
do
ip=`get_ip $i`
if [ "$ip" ] && [ "$ip" != "0.0.0.0" ] ; then
	echo "$ip/255.255.255.255 (myself)"
fi
done
}

relevant_ip()
{
routing_table
my_ip
}

# pick row,col

pick()
{
rc=$1
row=`Array $rc 1`
col=`Array $rc 2`
if [ $row -eq 0 ] ; then
	echo "0/0"; return
fi

skip=`expr $row - 1`
relevant_ip | tail +$skip | (read line; set -- $line; eval echo \$${col} )
}

do_masq()
{
read -p "Enter x-y (0 means ALL): " pair
save=$IFS; IFS="-"
set -- $pair
IFS=$save
from=`pick $1,1`; to=`pick $2,1`
mkdir -p $DIR/m
echo "-S $from -D $to" > $DIR/m/${pair} 
}

do_block()
{
read -p "Enter x-y[,port] (0 means ALL): " pair_port
pair=`Array ${pair_port} 1`
port=`Array ${pair_port} 2`
save=$IFS; IFS="-"
set -- $pair
IFS=$save
from=`pick $1,1`; to=`pick $2,1`
ifrom=`pick $1,2`; ito=`pick $2,2`

if [ "$ifrom" = "(myself)" ] || [ "$ito" = "(myself)" ]; then
	kind="i"
else
	kind="f"
fi

opt=
opt="$port ${port:+-P tcp}"
mkdir -p $DIR/$kind
echo "-S $from -D $to ${opt}" > $DIR/$kind/${pair_port} 
}

format()
{
cat -n | 
while read n net int
do
list=$( cd $DIR; /bin/ls -1q */* 2>/dev/null |
sed -n /$n/P |
tr '\012' ' ' )

printf "%2s %-30s %8s %-30s" $n $net $int "$list"
echo
done
}

menu()
{
echo "---------------------------------------"
relevant_ip | format 
echo "---------------------------------------"
echo
read -p "Command h)elp,q)uit  m)asq,b)lock: " cmd
[ -z "$cmd" ] && cmd=h
}

configure()
{
rm -r $DIR/* 2>/dev/null # clear cache
echo "All rules in the cache cleaned."
while [ 1 ] ; do
menu
case $cmd in
q)
	echo "bye"; exit ;;
h)	help;;
m)
	do_masq
	;;
b)
	do_block
	;;
*)	echo "command unknown" ;;
esac
done
}

start()
{
stop
if cd $DIR/m 2>/dev/null
then
        for c in *
        do
        ipfwadm -F -i m `cat $c`
        done
fi

if cd $DIR/f 2>/dev/null
then
        for c in *
        do
        ipfwadm -F -i reject `cat $c`
        done
fi

if cd $DIR/i 2>/dev/null
then
        for c in *
        do
        ipfwadm -I -i reject `cat $c`
        done
fi


}

# remove cache

undo()
{
rm -r $DIR/* 2>/dev/null
}

flush()
{
group="-I -O -F"
for g in $group
do
        ipfwadm $g -f; ipfwadm $g -p accept
done
}

stop()
{
flush
}

help()
{
clear
cat <<END
ipf: rustic IP filtering/masquerading utility, (C) M. Andreoli 2000
The interface is similar to 'fdisk'. ipf manipulate a cache in /etc/ipfw.
To enstablish real rules, use "ipf start", in second stage. 

All actives network destinations are numbered 1,2,3, .... (You will see 
all network/host active at *this* moment). The network number '0' means
ALL destinations. Blocking is performed using "forward" chain; if 
destinations is (myself), using "input" chain. 

Ex 1: if you want masquerade the network 1 and you act as
      Internet gateway to him, please specify 1-0 (from-to)
Ex 2: if you want block "telnet" connections from 1 to 3,
      please specify "1-3,23" or "1-3,telnet".
 Ex 3: to block all forwading, specify 0-0.

ipf start:	enstablish rules
ipf stop:	stop rules
ipf status:	shows rules

END
read -p "press -ENTER-" enter
}

status()
{
ipfwadm -I -l
ipfwadm -O -l
ipfwadm -F -l
}

stat()
{
status
}
# Main


DIR=/etc/ipfw
mkdir -p $DIR

case "Z$1Z" in
Z-hZ)
	echo "Usage: ipf help|configure|start|stop|status"
	exit	
	;;
esac

eval ${1:-configure}

# End
