#! /bin/bash
#
# Bandwidth management script by Marno van der Molen
#
# #     #  # # # # #  # # #
# #     #      #      #    #   F
# # # # #      #      # # #    T
# #     #      #      #    #   W
# #     #      #      # # #
#
# - Makes use of HTB & SFQ qdiscs
# - It needs sch_htb & cls_u32 & sch_sfq
# - Does not use CBQ (as it is slow and inaccurate)
# - Implements 3 bandwidth classes:
#
# Classes
#
# 1. Unlimited (local) traffic
# 2. Limited PRIORITY traffic
# 3. Limited BULK traffic
#
# 1 = LAN
# 2 = FTP Control Channel & the website
# 3 = FTP Data channels and remaining stuff
#

# Read config & functions file (Arch Linux specific)
. /etc/rc.conf
. /etc/rc.d/functions

if [ -f /etc/pure-ftpd.conf ]
then
	. /etc/pure-ftpd.conf
else
	echo "Config file not found!"
	exit
fi

#echo $PASV1 : $PASV2

case $1 in
start)
	stat_busy "Starting Bandwidth Management"
	if ! ck_daemon bandwidth
	then
		stat_fail
		echo "Bandwidth Management is allready active."
	else
		tc qdisc del dev eth0 root > /dev/null 2>&1
		# ROOT Classes
		tc qdisc add dev eth0 root handle 1: htb default 20
		# Max bandwidth for Inbound is 99Mbit
		tc class add dev eth0 parent 1: classid 1:1 htb rate 99Mbit burst 15k
		# Max bandwidth for Outbound is 950Kbit = 118K/s
		tc class add dev eth0 parent 1: classid 1:2 htb rate 950Kbit ceil 1350Kbit burst 20k

		# Inbound
		# Unrestricted SSH & Local browsing (99Mbit)
		tc class add dev eth0 parent 1:1 classid 1:10 htb rate 99Mbit burst 20k prio 4
		
		# Outbound
		# The throttled FTP / Default if not classified: (60K/s & 70K/s)
		tc class add dev eth0 parent 1:2 classid 1:20 htb rate 200Kbit ceil 760Kbit burst 15k prio 3
		# The webserver / FTP Control Channel: (60K/s & 100K/s)
		tc class add dev eth0 parent 1:2 classid 1:30 htb rate 470Kbit ceil 760Kbit burst 20k prio 2
		# SSH (Interactive)
		tc class add dev eth0 parent 1:2 classid 1:40 htb rate 470Kbit ceil 950Kbit burst 20k prio 1
				
		# SFQ
		tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
		tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
		tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
		tc qdisc add dev eth0 parent 1:40 handle 40: sfq perturb 10
				
		# Filters
		U32="tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32"

		# Allow the local network to go as fast as possible
#		$U32 match ip dst 192.168.2.0/24 flowid 1:10
		
		# Allow SSH to go as fast as possible
#		$U32 match ip tos 0x10 0xff flowid 1:40
		
		# Set up all the rules for the FTP Data Ports
		for PORT in 62000 62001 62002 62003 62004 62005 62006 62007 62008 62009 62010 62011 62012 62013 62014 62015 62016 62017 62018 62019 62020
		do
		  $U32 match ip sport $PORT 0xffff flowid 1:20
		done
		
		# Set up the rules for the FTP Server Control Ports
		$U32 match ip sport 443 0xffff flowid 1:30
		$U32 match ip sport 444 0xffff flowid 1:30
		
		# The webserver
		$U32 match ip sport 80 0xffff flowid 1:30
		
		# Local Network at Full Speed
#		$U32 match ip dst 192.168.2.0/24 flowid 1:10
		$U32 match ip dst 192.168.3.0/24 flowid 1:10
		$U32 match ip dst 192.168.2.0/24 flowid 1:10
		$U32 match ip dst 192.168.1.0/24 flowid 1:10
#		$U32 match ip src 192.168.2.0/24 flowid 1:10
		
		# SSH
		$U32 match ip tos 0x10 0xff flowid 1:40
		
		add_daemon bandwidth
		stat_done
	fi
;;
stop)
	stat_busy "Stopping Bandwidth Management"
	if ! ck_daemon bandwidth
	then
#		tc qdisc del dev eth0 root > /dev/null 2>&1
#		
#		# ROOT Classes
#		tc qdisc add dev eth0 root handle 1: htb default 20
#		# Max bandwidth for Inbound is 99Mbit
#		tc class add dev eth0 parent 1: classid 1:1 htb rate 99Mbit burst 20k
#		# Max bandwidth for Outbound is 950Kbit = 118K/s
#		tc class add dev eth0 parent 1: classid 1:2 htb rate 950Kbit ceil 950Kbit burst 20k
#		
#		# Inbound
#		# SSH / Local browsing (99Mbit)
#		tc class add dev eth0 parent 1:1 classid 1:10 htb rate 99Mbit burst 20k prio 4
#		
#		# Outbound
#		# The throttled FTP / Default if not classified: (65K/s & 118K/s) #rate 525
#		tc class add dev eth0 parent 1:2 classid 1:20 htb rate 200Kbit ceil 950Kbit burst 15k prio 3
#		# The webserver / FTP Control Channel: (65K/s & 118K/s) # 525
#		tc class add dev eth0 parent 1:2 classid 1:30 htb rate 280Kbit ceil 950Kbit burst 20k prio 2
#		# SSH
#		tc class add dev eth0 parent 1:2 classid 1:40 htb rate 470Kbit ceil 600Kbit burst 20k prio 1
#						
#		# SFQ
#		tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
#		tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
#		tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
#		tc qdisc add dev eth0 parent 1:40 handle 40: sfq perturb 10
#				
#		# Filters
#		U32="tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32"
#
#		# Allow the local network to go as fast as possible
#		$U32 match ip dst 192.168.2.0/24 flowid 1:10
#		
#		# Allow SSH to go as fast as possible
#		$U32 match ip tos 0x10 0xff flowid 1:10
#		
#		# Set up all the rules for the FTP Data Ports
#		for PORT in 62000 62001 62002 62003 62004 62005 62006 62007 62008 62009 62010 62011 62012 62013 62014 62015 62016 62017 62018 62019 62020
#		do
#		  $U32 match ip sport $PORT 0xffff flowid 1:40
#		done
#		
#		# Set up the rules for the FTP Server Control Ports
#		$U32 match ip sport 443 0xffff flowid 1:30
#		$U32 match ip sport 444 0xffff flowid 1:30
#		
#		# The webserver
#		$U32 match ip sport 80 0xffff flowid 1:30
#		
#		
		tc qdisc del dev eth0 root > /dev/null 2>&1
		tc qdisc del dev eth0 root > /dev/null 2>&1
		rm_daemon bandwidth
		stat_done
	else
		stat_fail
		echo "Bandwidth Management is not active."
	fi
;;
restart)
	/etc/rc.d/bandwidth stop && /etc/rc.d/bandwidth start
;;
*)
	echo "usage: $0 (start|stop|restart)"
;;
esac

