#!/bin/sh /etc/rc.common
START=55

include /lib/network
include /usr/lib/gargoyle_firewall_util

backup_script_dir="/tmp/bw_backup"
backup_script="$backup_script_dir/do_bw_backup.sh"
tmp_cron="/tmp/tmp.cron"
download_table=filter
download_chain=bw_ingress
upload_table=mangle
upload_chain=bw_egress

bw_restore()
{
	bw_id="$1"
	backup_to_tmp="$2"
	
	if [ -e "/usr/data/bwmon/$bw_id.bw" ] ; then
		bw_set -i "$bw_id" -h -f /usr/data/bwmon/$bw_id.bw >/dev/null 2>&1
	elif [ -e "/tmp/data/bwmon/$bw_id.bw" ] ; then
		bw_set -i "$bw_id" -h -f /tmp/data/bwmon/$bw_id.bw >/dev/null 2>&1
	elif [ -e "/usr/data/bwmon/$bw_id" ] ; then
		bw_convert "/usr/data/bwmon/$bw_id" "/usr/data/bwmon/$bw_id.bw"
		rm "/usr/data/bwmon/$bw_id"
		bw_set -i "$bw_id" -h -f /usr/data/bwmon/$bw_id.bw >/dev/null 2>&1
	elif [ -e "/tmp/data/bwmon/$bw_id" ] ; then
		bw_convert "/tmp/data/bwmon/$bw_id" "/usr/data/bwmon/$bw_id.bw"
		rm "/tmp/data/bwmon/$bw_id"
		bw_set -i "$bw_id" -h -f /tmp/data/bwmon/$bw_id.bw >/dev/null 2>&1
	fi

	if [ -e "$tmp_cron" ] ; then
		if [ "$backup_to_tmp" = "1" ] ; then
			echo "bw_get -i \"$bw_id\" -h -f \"/tmp/data/bwmon/$bw_id.bw\" >/dev/null 2>&1" >> "$backup_script"
		else
			echo "bw_get -i \"$bw_id\" -h -f \"/usr/data/bwmon/$bw_id.bw\" >/dev/null 2>&1" >> "$backup_script"
		fi
	fi
}

update_cron()
{
	old_md5=$(md5sum /etc/crontabs/root)
	old_md5=${old_md5% *}
	new_md5=$(md5sum "$tmp_cron")
	new_md5=${new_md5% *}
	if [ "$old_md5" = "$new_md5" ] ; then
		rm "$tmp_cron"
	else
		mv "$tmp_cron" /etc/crontabs/root
		if pidof crond > /dev/null 2>&1; then
			/etc/init.d/cron restart
		fi
	fi
}


start()
{

	define_wan_if
	wan_ip=""
	bw_if="$wan_if"
	if [ -z "$bw_if" ] ; then
		bw_if=$(uci -P "/var/state" get network.lan.ifname)	
		bwg_if=$(uci -P "/var/state" get network.guest.ifname)	
	else
		wan_ip=$(uci -P "/var/state" get network.wan.ipaddr)
	fi
	



	if [ ! -d /tmp/data/bwmon ] ; then
		rm -rf /tmp/data/bwmon
		mkdir -p /tmp/data/bwmon
 	fi
	if [ ! -d /usr/data/bwmon ] ; then 
		rm -rf /usr/data/bwmon
		mkdir -p /usr/data/bwmon
	fi

	delete_chain_from_table $download_table $download_chain
	iptables -t $download_table -N $download_chain
	iptables -t $download_table -I INPUT $filter_insert_index  -i $bw_if -j $download_chain
	iptables -t $download_table -I FORWARD $filter_insert_index -i $bw_if -j $download_chain
	iptables -t $download_table -I INPUT $filter_insert_index  -i $bwg_if -j $download_chain
	iptables -t $download_table -I FORWARD $filter_insert_index -i $bwg_if -j $download_chain


	
	delete_chain_from_table $upload_table $upload_chain
	iptables -t $upload_table -N $upload_chain
	iptables -t $upload_table -A POSTROUTING -o $bw_if -j $upload_chain
	iptables -t $upload_table -A POSTROUTING -o $bwg_if -j $upload_chain
	

	lan_mask=$(uci -p /tmp/state get network.lan.netmask 2>/dev/null)
	lan_ip=$(uci -p /tmp/state get network.lan.ipaddr 2>/dev/null)
	lan_subnet="$lan_ip/$lan_mask"
	lan_bits=$( mask_to_cidr $lan_mask )
	guest_mask=$(uci -p /tmp/state get network.guest.netmask 2>/dev/null)
	guest_ip=$(uci -p /tmp/state get network.guest.ipaddr 2>/dev/null)
	guest_subnet="$guest_ip/$guest_mask"
	guest_bits=$( mask_to_cidr $guest_mask )

	# code to help filter out bogons on distribution monitors, 
	# which make up really small amount of bandwidth, but screw up monitoring
	ipset --create  local_addr_set nethash >/dev/null 2>&1 #may die if set already exists
	ipset -F local_addr_set
	ipset --add local_addr_set $lan_ip/$lan_bits
	ipset --add local_addr_set $guest_ip/$guest_bits
	ipset --add local_addr_set $wan_ip/31 #minimum netmask allowed, good enough





	minute_s=60
	hour_s=3600
	day_s=86400

	total1_interval=2
	total1_num_intervals=449
	total1_reset_time=2

	total2_interval="minute"
	total2_num_intervals=359

	total3_interval=$((3*$minute_s))
	total3_num_intervals=479
	total3_reset_time=$((3*$minute_s))

	total4_interval=$((2*$hour_s))
	total4_num_intervals=359
	total4_reset_time=$((2*$hour_s))
	
	total5_interval="day"
	total5_num_intervals=365

	bdist0_interval=$total1_interval
	bdist0_num_intervals=$total1_num_intervals
	bdist0_reset_time=$total1_reset_time

	bdist1_interval="minute"
	bdist1_num_intervals=15

	bdist2_interval=$((15*$minute_s))
	bdist2_num_intervals=24
	bdist2_reset_time=$((15*$minute_s))

	bdist3_interval="hour"
	bdist3_num_intervals=24

	bdist4_interval="day"
	bdist4_num_intervals=31

	bdist5_interval="month"
	bdist5_num_intervals=12

	ids=""


	high_res_15m=$(uci get gargoyle.bandwidth_display.high_res_15m 2>/dev/null)
	#echo "high res 15m = $high_res_15m"
	if [ "$high_res_15m" = "1" ] ; then
		n=0
		bdist_interval=$(eval "echo \$bdist"$n"_interval")
		bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
		bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
		if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi
		if [ -n "$lan_mask" ] && [ -n "$lan_ip" ] ; then
			iptables -t $download_table -A $download_chain -m set --match-set local_addr_set dst -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			iptables -t $upload_table   -A $upload_chain   -m set --match-set local_addr_set src -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ids="bdist"$n"-download-$bdist_interval-$bdist_num_intervals bdist"$n"-upload-$bdist_interval-$bdist_num_intervals" 
		fi
		if [ -n "$guest_mask" ] && [ -n "$guest_ip" ] ; then
			iptables -t $download_table -A $download_chain -m set --match-set local_addr_set dst -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			iptables -t $upload_table   -A $upload_chain   -m set --match-set local_addr_set src -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ids="bdist"$n"-download-$bdist_interval-$bdist_num_intervals bdist"$n"-upload-$bdist_interval-$bdist_num_intervals" 
		fi

	else
		rm -rf /tmp/data/bwmon/bdist0*
		rm -rf /tmp/data/bwmon/qos0*
	fi
	
	mon_nums="1 2 3 4 5"
	for n in $mon_nums ; do
		total_interval=$(eval "echo \$total"$n"_interval")
		total_num_intervals=$(eval "echo \$total"$n"_num_intervals")
		total_reset_time=$(eval "echo \$total"$n"_reset_time")
		if [ -n "$total_reset_time" ] ; then total_reset_time="--reset_time $total_reset_time" ; fi

		bdist_interval=$(eval "echo \$bdist"$n"_interval")
		bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
		bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
		if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi

		
		iptables -t $download_table -A $download_chain -m bandwidth --id "total"$n"-download-$total_interval-$total_num_intervals" --reset_interval $total_interval --intervals_to_save $total_num_intervals $total_reset_time
		iptables -t $upload_table   -A $upload_chain   -m bandwidth --id "total"$n"-upload-$total_interval-$total_num_intervals"   --reset_interval $total_interval --intervals_to_save $total_num_intervals $total_reset_time

		next_ids="total"$n"-download-$total_interval-$total_num_intervals total"$n"-upload-$total_interval-$total_num_intervals"
		if [ -z "$ids" ] ; then
			ids="$next_ids"
		else
			ids="$ids $next_ids"
		fi

		if [ -n "$lan_mask" ] && [ -n "$lan_ip" ] ; then
			iptables -t $download_table -A $download_chain -m set --match-set local_addr_set dst -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			iptables -t $upload_table   -A $upload_chain   -m set --match-set local_addr_set src -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ids="$ids bdist"$n"-download-$bdist_interval-$bdist_num_intervals bdist"$n"-upload-$bdist_interval-$bdist_num_intervals" 
		fi
		if [ -n "$guest_mask" ] && [ -n "$guest_ip" ] ; then
			iptables -t $download_table -A $download_chain -m set --match-set local_addr_set dst -m bandwidth --id "bdist"$n"-download-$bdist_interval-$bdist_num_intervals" --type "individual_dst" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			iptables -t $upload_table   -A $upload_chain   -m set --match-set local_addr_set src -m bandwidth --id "bdist"$n"-upload-$bdist_interval-$bdist_num_intervals"   --type "individual_src" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
			ids="$ids bdist"$n"-download-$bdist_interval-$bdist_num_intervals bdist"$n"-upload-$bdist_interval-$bdist_num_intervals" 
		fi

	done

	if [ "$high_res_15m" = "1" ] ; then
		mon_nums="0 1 2 3 4 5"
	fi
	qos_enabled=$(ls /etc/rc.d/*qos_gargoyle 2>/dev/null)
	if [ -n "$qos_enabled" ] && [ -e /etc/qos_class_marks ] ; then
		qos_table="mangle"
		qos_upload_chain="qos_egress"
		qos_download_chain="qos_ingress"

		upload_data=$(awk ' { if($1 == "upload"){print "up-"$2":"$3"/"$4};}' /etc/qos_class_marks )
		download_data=$(awk ' { if($1 == "download"){print "down-"$2":"$3"/"$4};}' /etc/qos_class_marks )

		for upload_info in $upload_data ; do
			mark=$(echo $upload_info | awk ' BEGIN { FS=":";} { print $2; }')
			class=$(echo $upload_info | awk ' BEGIN { FS=":";} { print $1; }')
			for n in $mon_nums ; do
				bdist_interval=$(eval "echo \$bdist"$n"_interval")
				bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
				bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
				if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi

				iptables -t $upload_table -A $upload_chain -m connmark --mark $mark -m bandwidth --id "qos"$n"-$class-$bdist_interval-$bdist_num_intervals" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
				ids="$ids qos"$n"-$class-$bdist_interval-$bdist_num_intervals"
			done
		done
		
		
		for download_info in $download_data ; do
			mark=$(echo $download_info | awk ' BEGIN { FS=":";} { print $2; }')
			class=$(echo $download_info | awk ' BEGIN { FS=":";} { print $1; }')
			for n in $mon_nums ; do
				bdist_interval=$(eval "echo \$bdist"$n"_interval")
				bdist_num_intervals=$(eval "echo \$bdist"$n"_num_intervals")
				bdist_reset_time=$(eval "echo \$bdist"$n"_reset_time")
				if [ -n "$bdist_reset_time" ] ; then bdist_reset_time="--reset_time $bdist_reset_time" ; fi

				iptables -t $download_table -A $download_chain -m connmark --mark $mark -m bandwidth --id "qos"$n"-$class-$bdist_interval-$bdist_num_intervals" --reset_interval $bdist_interval --intervals_to_save $bdist_num_intervals $bdist_reset_time
				ids="$ids qos"$n"-$class-$bdist_interval-$bdist_num_intervals"
			done
		done
	fi

	touch /etc/crontabs/root
	grep -v "$backup_script" /etc/crontabs/root > "$tmp_cron"
	echo "0 0,4,8,12,16,20 * * * $backup_script" >> "$tmp_cron"
	
	mkdir -p "$backup_script_dir"
	echo "#!/bin/sh" > "$backup_script"
	chmod 700 "$backup_script"
	

	for i in $ids ; do
		is_total123=$(echo "$i" | egrep "total[123]")
		is_bdist123=$(echo "$i" | egrep "bdist[0123]")
		is_qos123=$(echo "$i" | egrep "qos[0123]")
		if [ -n "$is_total123" ] || [ -n "$is_bdist123" ] || [ -n "$is_qos123" ]  ; then
			bw_restore "$i" 1
		else
			bw_restore "$i" 0
		fi
	done

	update_cron 
}

stop()
{
	touch /etc/crontabs/root

	sh "$backup_script" 2>/dev/null
	rm -rf "$backup_script"

	grep -v "$backup_script" /etc/crontabs/root > "$tmp_cron"
	update_cron
	
	delete_chain_from_table $download_table $download_chain >/dev/null 2>&1
	delete_chain_from_table $upload_table $upload_chain >/dev/null 2>&1
}

restart()
{
	stop
	start
}

boot()
{
	#Do nothing during init.  Start is called by hotplug.
	return
}
