#!/bin/sh /etc/rc.common

START=15
. /lib/functions/network.sh
. /lib/functions.sh

proto="4"
#[ -f /proc/net/ipv6_route ] && proto="4 6"
[ -f /etc/config/olsrd ] && cfgs="olsrd"
[ -f /etc/config/olsrd6 ] && cfgs="$cfgs olsrd6"

config_load freifunk-policyrouting
config_get enable pr enable
config_get fallback pr fallback
config_get zones pr zones


olsrd_rmtables() {
	for cfg in $cfgs; do
		# Remove custom routing tables from olsrd 
		if [ "`uci -q get $cfg.@olsrd[0].RtTable`" == "111" ] || [ "`uci -q get $cfg.@olsrd[0].RtTableDefault`" == "112" ]; then
			uci delete $cfg.@olsrd[0].RtTable
			uci delete $cfg.@olsrd[0].RtTableDefault
			uci commit
		fi
	done
}

olsrd_intalltables() {
	for cfg in $cfgs; do
		if [ ! "`uci -q get $cfg.@olsrd[0].RtTable`" == "111" ] || [ ! "`uci -q get $cfg.@olsrd[0].RtTableDefault`" == "112" ]; then
			uci set $cfg.@olsrd[0].RtTable='111'
			uci set $cfg.@olsrd[0].RtTableDefault='112'
			uci commit $cfg
			/etc/init.d/$cfg restart 2&> /dev/null
		fi
	done
}

rt_tables() {
	tables="/etc/iproute2/rt_tables"
	if [ -z "`grep "110" $tables`" ]; then
		echo "110 localnets" >> $tables
	fi
	if [ -z "`grep "111" $tables`" ]; then
		echo "111 olsr" >> $tables
	fi
	if [ -z "`grep "112" $tables`" ]; then
		echo "112 olsr-default" >> $tables
	fi

}

disable_dyngw() {
	for cfg in $cfgs; do
		local dyngwlib=`uci show $cfg |grep dyn_gw.so |awk {' FS="."; print $1"."$2 '}`
		if [ -n "$dyngwlib" ]; then
			uci set $dyngwlib.ignore=1
			uci commit $cfg
		fi

		dyngwplainlib=`uci show $cfg |grep dyn_gw_plain |awk {' FS="."; print $1"."$2 '}`
		if [ -n "$dyngwplainlib" ]; then
			rttable="$(uci -q get $dyngwplainlib.RtTable)"
			if [ -z "$rttable" ] || [ "$rttable" = "254" ]; then 
				uci set $dyngwplainlib.ignore=1
				uci commit $cfg
			fi
		fi
	done
}

restart_services() {
	logger -s -t policyrouting -p info "Restarting services"
	/etc/init.d/network restart 2&> /dev/null
	for cfg in $cfgs; do
		/etc/init.d/$cfg restart 2&> /dev/null
	done
}

boot() {
	if [ "$enable" = "1" ]; then
		[ -d /var/state ] || mkdir -p /var/state
		touch /var/state/freifunk-policyrouting
		start noservicerestart
	else
		olsrd_rmtables
	fi
}

add_lookup_rule() {
	name=${1/-/_}
	lookup=$2
	prio=$3
	in=$4
	name=$name"_"${in:-allif}"_"

	if [ -z "$name" -o -z "$lookup" -o -z "$prio" ]; then
		logger -s -t policyrouting "Missing parameters for add_rule!"
	else
		for p in $proto; do
			if [ "$p" = "6" ]; then
				rule="rule6"
			else
				rule="rule"
			fi
			if [ "$(uci -q get network.${name}ipv${p})" != "$rule" ] ; then
				uci batch <<- EOF
					set network.${name}ipv${p}="$rule"
					set network.${name}ipv${p}.lookup="$lookup"
					set network.${name}ipv${p}.priority="$prio"
					set network.${name}ipv${p}.in="$in"
				EOF
				uci commit network
			fi
		done
	fi
}

add_action_rule() {
	name=${1/-/_}
	action=$2
	prio=$3
	in=$4
	name=$name"_"${in:-allif}"_"

	if [ -z "$name" -o -z "$action" -o -z "$prio" ]; then
		logger -s -t policyrouting "Missing parameters for add_action!"
	else
		for p in $proto; do
			if [ "$p" = "6" ]; then
				rule="rule6"
			else
				rule="rule"
			fi
			if [ "$(uci -q get network.${name}ipv${p})" != "$rule" ] ; then
				uci batch <<- EOF
					set network.${name}ipv${p}="$rule"
					set network.${name}ipv${p}.action="$action"
					set network.${name}ipv${p}.priority="$prio"
					set network.${name}ipv${p}.in="$in"
				EOF
				uci commit network
			fi
		done
	fi
}


del_rule() {
	name=${1/-/_}
	in=$2
	name=$name"_"${in:-allif}"_"
	for p in $proto; do
		uci -q delete network.${name}ipv${p}
	done
	uci commit network
}

start() {
	if [ $enable = "1" ]; then
		logger -s -t policyrouting "Starting policy routing."
		rt_tables
		olsrd_intalltables
		#disable_dyngw

		add_lookup_rule olsr olsr 1000
		add_lookup_rule localnets localnets 2000

		if [ "$fallback" = 1 ]; then
			add_lookup_rule olsr-default olsr-default 100000
		fi
		networks=""
		for z in $zones; do
			network_zone="$(uci -q get firewall.zone_${z}.network)"
			if [ -z "$network_zone" ]; then
				network_zone="$z"
			fi
			networks="$networks $network_zone"
		done

		sgw="$(uci -q get olsrd.@olsrd[0].SmartGateway)"
		for n in $networks; do
			# only add route for tunnel if smart gateway is enabled
			if [ "$sgw" = "yes" ]; then
				add_lookup_rule olsr-tunnel olsr-tunnel 19999 $n
			fi
			add_lookup_rule olsr-default olsr-default 20000 $n
			if [ "$strict" != 0 ]; then
				add_action_rule olsr-default_unreachable unreachable 20001 $n
			fi
		done
	fi
	uci commit network
	if [ ! "$1" = "noservicerestart" ]; then
		restart_services
	fi
}

stop() {
	logger -s -t policyrouting "Stopping policy routing"
	olsrd_rmtables
	del_rule olsr-default
	del_rule olsr
	del_rule localnets
	networks=""
	for z in $zones; do
		network_zone="$(uci -q get firewall.zone_${z}.network)"
		if [ -z "$network_zone" ]; then
			network_zone="$z"
		fi
		networks="$networks $network_zone"
	done

	sgw=$(uci -q get olsrd.@olsrd[0].SmartGateway)
	for n in $networks; do
		if [ "$sgw" = "yes" ]; then
			del_rule olsr-tunnel $n
		fi
		del_rule olsr-default $n
		if [ "$strict" != 0 ]; then
			del_rule olsr-default_unreachable $n
		fi
	done
	restart_services
	echo "Hint: To completely disable freifunk-policyrouting set enable=0 in /etc/config/freifunk-policyrouting."
}

restart() {
	logger -s -t policyrouting "Restarting policy routing"
	start
}
