#!/bin/sh
#

INTRA_DEV=eth0
INTRA_IP=195.168.47.129
INET_DEV=eth1
INET_IP=195.168.26.93

B_INTRA=100Mbit
B_INET=10Mbit
IBANDW=128Kbit
BSYN=4Kbit
BICMP=4Kbit
BSMTP=56Kbit

CLASSFILE=/etc/sysconfig/cbq-classes

# Source function library.
. /etc/rc.d/init.d/functions

if [ ! -f /etc/sysconfig/network ]; then
    exit 0
fi

. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

[ -x /sbin/iptables ] || exit 0
[ "`uname -r | cut -f1,2 -d.`" = "2.2" ] && exit 0

case "$1" in
  start)
	# start ping -f prevention and SYN flooding prevention

	tc qdisc del dev ${INET_DEV} root 2> /dev/null
	tc qdisc del dev ${INTRA_DEV} root 2> /dev/null

	tc qdisc add dev ${INET_DEV} root handle 10: cbq \
		bandwidth ${B_INET} avpkt 1000
	tc qdisc add dev ${INTRA_DEV} root handle 20: cbq \
		bandwidth ${B_INTRA} avpkt 1000

	tc class add dev ${INET_DEV} parent 10:0 classid 10:1 cbq \
		bandwidth ${B_INET} rate ${B_INET} allot 1514 cell 8 prio 8 \
		maxburst 20 avpkt 1000
	tc class add dev ${INET_DEV} parent 10:1 classid 10:2 cbq \
		bandwidth ${B_INET} rate ${IBANDW} allot 1514 cell 8 prio 7 \
		maxburst 20 avpkt 1000 bounded

	tc class add dev ${INTRA_DEV} parent 20:0 classid 20:1 cbq \
		bandwidth ${B_INTRA} rate ${B_INTRA} allot 1514 cell 8 prio 8 \
		maxburst 20 avpkt 1000
	tc class add dev ${INTRA_DEV} parent 20:1 classid 20:2 cbq \
		bandwidth ${B_INTRA} rate ${IBANDW} allot 1514 cell 8 prio 7 \
		maxburst 20 avpkt 1000 bounded

	tc qdisc add dev ${INET_DEV} parent 10:2 handle 11: \
		cbq bandwidth ${IBANDW} rate ${IBANDW} \
		allot 1514 cell 8 avpkt 1000 mpu 64
	tc qdisc add dev ${INTRA_DEV} parent 20:2 handle 21: \
		cbq bandwidth ${IBANDW} rate ${IBANDW} \
		allot 1514 cell 8 avpkt 1000 mpu 64

	tc class add dev ${INET_DEV} parent 11:0 classid 11:1 cbq \
		bandwidth ${IBANDW} rate ${IBANDW} cell 8 allot 1514 prio 5 \
		maxburst 20 avpkt 1000 bounded
	tc class add dev ${INTRA_DEV} parent 21:0 classid 21:1 cbq \
		bandwidth ${IBANDW} rate ${IBANDW} cell 8 allot 1514 prio 5 \
		maxburst 20 avpkt 1000 bounded

	tc class add dev ${INET_DEV} parent 11:1 classid 11:100 cbq \
		bandwidth ${IBANDW} rate ${BICMP} allot 1514 \
		prio 5 maxburst 20 avpkt 250 bounded
	tc class add dev ${INTRA_DEV} parent 21:1 classid 21:100 cbq \
		bandwidth ${IBANDW} rate ${BICMP} allot 1514 \
		prio 5 maxburst 20 avpkt 250 bounded

	tc class add dev ${INET_DEV} parent 11:1 classid 11:101 cbq \
		bandwidth ${IBANDW} rate ${BSYN} allot 1514 \
		prio 5 maxburst 20 avpkt 320 bounded
	tc class add dev ${INTRA_DEV} parent 21:1 classid 21:101 cbq \
		bandwidth ${IBANDW} rate ${BSYN} allot 1514 \
		prio 5 maxburst 20 avpkt 320 bounded

	tc class add dev ${INET_DEV} parent 11:1 classid 11:102 cbq \
		bandwidth ${IBANDW} rate ${BSMTP} allot 1514 \
		prio 3 maxburst 20 avpkt 1000
	tc class add dev ${INTRA_DEV} parent 21:1 classid 21:102 cbq \
		bandwidth ${IBANDW} rate ${BSMTP} allot 1514 \
		prio 3 maxburst 20 avpkt 1000

	tc filter add dev ${INET_DEV} parent 11:0 protocol ip prio 1 \
		u32 match ip protocol 1 0xFF flowid 11:100
	tc filter add dev ${INTRA_DEV} parent 21:0 protocol ip prio 1 \
		u32 match ip protocol 1 0xFF flowid 21:100

	tc filter add dev ${INET_DEV} parent 11:0 protocol ip prio 2 handle 1 \
		fw flowid 11:101
	tc filter add dev ${INTRA_DEV} parent 21:0 protocol ip prio 2 handle 1 \
		fw flowid 21:101

	tc filter add dev ${INET_DEV} parent 11:0 protocol ip prio 3 handle 2 \
		fw flowid 11:102
	tc filter add dev ${INET_DEV} parent 11:0 protocol ip prio 3 handle 3 \
		fw flowid 11:102

	tc filter add dev ${INTRA_DEV} parent 21:0 protocol ip prio 3 handle 2 \
		fw flowid 21:102
	tc filter add dev ${INTRA_DEV} parent 20:0 protocol ip prio 4 \
		u32 match ip src ${INTRA_IP} flowid 20:1
	tc filter add dev ${INTRA_DEV} parent 21:0 protocol ip prio 5 handle 3 \
		fw flowid 21:102

	# here should classes go
        cid=1001
	grep -v '^#' < ${CLASSFILE} | grep -v '^[ \t]*$' | \
		while read type rate ips; do

		if [ "${type}" = "none" ]; then
			type=
		fi

		tc class add dev ${INET_DEV} parent 11:1 classid 11:$cid cbq \
			bandwidth ${IBANDW} rate ${rate} allot 1514 \
			prio 6 maxburst 20 avpkt 250 ${type}

		tc class add dev ${INTRA_DEV} parent 21:1 classid 21:$cid cbq \
			bandwidth ${IBANDW} rate ${rate} allot 1514 \
			prio 6 maxburst 20 avpkt 250 ${type}

		for i in $ips; do

			tc filter add dev ${INET_DEV} parent 11:0 protocol ip \
				prio 6 \
				u32 match ip src $i flowid 11:$cid
			tc filter add dev ${INET_DEV} parent 11:0 protocol ip \
				prio 6 \
				u32 match ip dst $i flowid 11:$cid

			tc filter add dev ${INTRA_DEV} parent 21:0 protocol ip \
				prio 6 \
				u32 match ip dst $i flowid 21:$cid
			tc filter add dev ${INTRA_DEV} parent 21:0 protocol ip \
				prio 6 \
				u32 match ip src $i flowid 21:$cid

		done

		cid=`expr $cid + 1`
	done

	tc filter add dev ${INET_DEV} parent 11:0 protocol ip prio 8 \
		u32 match ip src 0/0 flowid 11:1

	echo Scheduling started.

        touch /var/lock/subsys/psched
        ;;
  stop)
	# stop ping -f prevention
	tc qdisc del dev ${INET_DEV} root
        tc qdisc del dev ${INTRA_DEV} root

	echo Scheduling stopped.

        rm -f /var/lock/subsys/psched
        ;;
  restart)
	$0 stop
	$0 start
	;;
  *)
        echo "Usage: firewall {start|stop|restart}"
        exit
esac
