#!/bin/sh
#
#	@author Forrest Lin
#

TMPFILE=/tmp/radvd.conf.$$
CONFILE=/tmp/radvd.conf
PIDFILE=/var/run/radvd.pid
LOCKFILE=/var/run/radvd.lock

# Primitives
usage() {
	echo "Usage: $0 {start|stop|reload|ipup|ipchg|ipdown|trans}"
}

lock() {
	set -o noclobber
	while ! echo PID $$ @ $(date) > ${LOCKFILE} ; do
		sleep 1
	done
	set +o noclobber        
}

unlock() {
	rm -f ${LOCKFILE} > /dev/null 2>&1
}

trans() {
	# 
	# Configuration
	#
	eval `sncfg mget LanIf6 WanIf6 RADVD_IsRouter RADVD_AdvSendAdvert RADVD_UnicastOnly RADVD_MaxRtrAdvInterval RADVD_MinRtrAdvInterval RADVD_AdvManagedFlag RADVD_AdvOtherConfigFlag RADVD_AdvLinkMTU RADVD_AdvReachableTime RADVD_AdvRetransTimer RADVD_AdvCurHopLimit RADVD_AdvDefaultLifetime RADVD_AdvDefaultPreference RADVD_AdvSourceLLAddress RADVD_PREFIX RADVD_DNS_MODE RADVD_RDNSS_NUM RADVD_RDNSS RADVD_DNSSL_NUM RADVD_DNSSL tWAN6_TYPE NAT64_ENABLE WanIp`
	#
	# Reset
	#
	echo -n "" > ${TMPFILE}
	#
	# Interfaces
	#
	for LanIf in ${LanIf6//,/ } ; do
		LanIp6=$(sncfg get ${LanIf}.Ip6 | awk -F "=" '{ print $2 }' | sed -n 's/"//gp');
		LanPrefix6=$(sncfg get ${LanIf}.Prefix6 | awk -F "=" '{ print $2 }' | sed -n 's/"//gp');
		# 
		# Interface Specific Options
		#
		echo "interface ${LanIf}" >> ${TMPFILE}
		echo "{" >> ${TMPFILE}
		echo "  IgnoreIfMissing on ;" >> ${TMPFILE}
		if [ "${RADVD_AdvSendAdvert}" == "1" ] ; then
			echo "  AdvSendAdvert on ;" >> ${TMPFILE}
		fi
		#if [ "${RADVD_UnicastOnly}" == "1" ] ; then
		#	echo "  UnicastOnly on ;" >> ${TMPFILE}
		#fi
		case "${RADVD_UnicastOnly}" in
			1) echo "  UnicastOnly 1 ;" >> ${TMPFILE} ;;
			2) echo "  UnicastOnly 2 ;" >> ${TMPFILE} ;;
			*) echo "  UnicastOnly 0 ;" >> ${TMPFILE} ;;
		esac
		echo "  MaxRtrAdvInterval ${RADVD_MaxRtrAdvInterval} ;" >> ${TMPFILE}
		echo "  MinRtrAdvInterval ${RADVD_MinRtrAdvInterval} ;" >> ${TMPFILE}
		if [ "${RADVD_AdvManagedFlag}" == "1" ] ; then
			echo "  AdvManagedFlag on ;" >> ${TMPFILE}
		fi
		if [ "${RADVD_AdvOtherConfigFlag}" == "1" ] ; then
			echo "  AdvOtherConfigFlag on ;" >> ${TMPFILE}
		fi
		if [ "${RADVD_AdvLinkMTU}" != "0" ] ; then
			echo "  AdvLinkMTU ${RADVD_AdvLinkMTU} ;" >> ${TMPFILE}
		fi
		echo "  AdvReachableTime ${RADVD_AdvReachableTime} ;" >> ${TMPFILE}
		echo "  AdvRetransTimer ${RADVD_AdvRetransTimer} ;" >> ${TMPFILE}
		echo "  AdvCurHopLimit ${RADVD_AdvCurHopLimit} ;" >> ${TMPFILE}
		case "${RADVD_IsRouter}" in
			0) echo "  AdvDefaultLifetime 0 ;" >> ${TMPFILE} ;;
			1) echo "  AdvDefaultLifetime ${RADVD_AdvDefaultLifetime} ;" >> ${TMPFILE} ;;
			*)
				# 
				# RFC6204 : G-4, G-5, L-4
				#
				isRouter=0;
				for WanIf in ${WanIf6//,/ } ; do
					WanDefRtr6=$(sncfg get ${WanIf}.DefRtr6 | awk -F "=" '{ print $2 }' | sed -n 's/"//gp');
					WanPrefix6=$(sncfg get ${WanIf}.Prefix6 | awk -F "=" '{ print $2 }' | sed -n 's/"//gp');
					if [ -n "${WanDefRtr6}" ] && [ -n "${LanPrefix6}" ] && [ -n "${WanPrefix6}" ] ; then
						isRouter=1
						WanPreferPeriod=$(sncfg get ${WanIf}.Prefix6 | awk -F " "  '{ print $2 }');	
						echo "  AdvDefaultLifetime ${WanPreferPeriod} ;" >> ${TMPFILE}
						break
					fi
				done
				if [ "${isRouter}" == 0 ] ; then
					if [ "${WanIp}" == "" ] ; then
						echo "  AdvDefaultLifetime 0 ;" >> ${TMPFILE}
					else
						if [ "${tWAN6_TYPE}" == 1000 ] || [ "${tWAN6_TYPE}" == 1001 ] || [ "${NAT64_ENABLE}" == 1 ] ; then
							echo "  AdvDefaultLifetime 4294967295;" >> ${TMPFILE}
						else
							echo "  AdvDefaultLifetime 0 ;" >> ${TMPFILE}
						fi
					fi
				fi
			;;
		esac
		case "${RADVD_AdvDefaultPreference}" in
			0) echo "  AdvDefaultPreference medium ;" >> ${TMPFILE} ;;
			1) echo "  AdvDefaultPreference high ;" >> ${TMPFILE} ;;
			2) echo "  AdvDefaultPreference low ;" >> ${TMPFILE} ;;
		esac
		if [ "${RADVD_AdvSourceLLAddress}" == "0" ] ; then
			echo "  AdvSourceLLAddress off ;" >> ${TMPFILE}
		fi
		# 
		# Prefix Specific Options
		#
		echo "${LanPrefix6}" | awk -F "," '{
			for (i=1; i<=NF; i++) {
				split($i, prefix, " ")
				printf("  prefix %s\n", prefix[1]) >> file
				printf("  {\n") >> file
				if (prefix[4] == "0") {
					printf("    AdvOnLink off ;\n") >> file
				}
				if (prefix[5] == "0") {
					printf("    AdvAutonomous off ;\n") >> file
				}
				printf("    AdvPreferredLifetime %d ;\n", prefix[2]) >> file
				printf("    AdvValidLifetime %d ;\n", prefix[3]) >> file
				printf("  } ;\n") >> file
			}
		}' -v file="${TMPFILE}"
		echo "${RADVD_PREFIX}" | awk -F ";" '{
			for (i=1; i<=NF; i++) {
				split($i, prefix, ",")
				printf("  prefix %s\n", prefix[5]) >> file
				printf("  {\n") >> file
				if (prefix[1] == "0") {
					printf("    AdvOnLink off ;\n") >> file
				}
				if (prefix[2] == "0") {
					printf("    AdvAutonomous off ;\n") >> file
				}
				printf("    AdvValidLifetime %d ;\n", prefix[3]) >> file
				printf("    AdvPreferredLifetime %d ;\n", prefix[4]) >> file
				printf("  } ;\n") >> file
			}
		}' -v file="${TMPFILE}"		
		#
		# RDNSS Specific Options
		# RFC6204 : L-11
		#
		if [ "${RADVD_DNS_MODE}" = "0" ] ; then
			echo "${LanIp6}" | awk -F "," '{
				for (i=1; i<=NF; i++) {
					printf("  RDNSS %s\n", $i) >> file
					printf("  {\n") >> file
					printf("    AdvRDNSSLifetime %d ;\n", lifetime) >> file
					printf("  } ;\n") >> file
				}
			}' -v lifetime="${RADVD_MaxRtrAdvInterval}" -v file="${TMPFILE}"
		else
			for WanIf in ${WanIf6//,/ } ; do
				WanRDNSS=$(sncfg get ${WanIf}.DNS6 | awk -F "=" '{ print $2 }' | sed -n 's/"//gp');
				echo "${WanRDNSS}" | awk -F "," '{
					for (i=1; i<=NF; i++) {
						printf("  RDNSS %s\n", $i) >> file
						printf("  {\n") >> file
						printf("    AdvRDNSSLifetime %d ;\n", lifetime) >> file
						printf("  } ;\n") >> file
					}
				}' -v lifetime="${RADVD_MaxRtrAdvInterval}" -v file="${TMPFILE}"
			done	
			echo "${RADVD_RDNSS}" | awk -F ";" '{
				for (i=1; i<=NF; i++) {
					split($i, rdnss, ",")
					printf("  RDNSS %s\n", rdnss[1]) >> file
					printf("  {\n") >> file
					printf("    AdvRDNSSLifetime %d ;\n", rdnss[2]) >> file
					printf("  } ;\n") >> file
				}
			}' -v file="${TMPFILE}"
		fi
		#
		# DNSSL Specific Options
		# RFC6204 : L-11
		#
		for WanIf in ${WanIf6//,/ } ; do
			WanDNSSL=$(sncfg get ${WanIf}.Domain6 | awk -F "=" '{ print $2 }' | sed -n 's/"//gp');
			echo "${WanDNSSL}" | awk -F "," '{
				for (i=1; i<=NF; i++) {
					printf("  DNSSL %s\n", $i) >> file
					printf("  {\n") >> file
					printf("    AdvDNSSLLifetime %d ;\n", lifetime) >> file
					printf("  } ;\n") >> file
				}
			}' -v lifetime="${RADVD_MaxRtrAdvInterval}" -v file="${TMPFILE}"
		done			
		echo "${RADVD_DNSSL}" | awk -F ";" '{
			for (i=1; i<=NF; i++) {
				split($i, dnssl, ",")
				printf("  DNSSL %s\n", dnssl[1]) >> file
				printf("  {\n") >> file
				printf("    AdvDNSSLLifetime %d ;\n", dnssl[2]) >> file
				printf("  } ;\n") >> file
			}
		}' -v file="${TMPFILE}"
		# 
		# RFC6204 : L-3
		#
		echo "${LanPrefix6}" | awk -F "," '{
			for (i=1; i<=NF; i++) {
				split($i, route, " ")
				printf("  route %s\n", route[1]) >> file
				printf("  {\n") >> file
				printf("    AdvRouteLifetime %d ;\n", route[2]) >> file
				printf("  } ;\n") >> file
			}
		}' -v file="${TMPFILE}"
		# 
		# Final
		#
		echo "} ;" >> ${TMPFILE}
	done
	#
	# Update
	#
	mv ${TMPFILE} ${CONFILE}
	chmod 644 ${CONFILE}
}

start() {
	local pid=`cat ${PIDFILE} 2> /dev/null`
	if grep radvd /proc/${pid}/stat > /dev/null 2>&1 ; then
		echo -n "radvd was already running ... "
		ret=0
		return
	fi
	trans
	eval `sncfg mget RADVD_DEBUG`
	if [ "${RADVD_DEBUG}" == "1" ] ; then
		echo -n "radvd -p ${PIDFILE} -C ${CONFILE} -d 5 & ... "
		radvd -p ${PIDFILE} -C ${CONFILE} -d 5 &
	else
		echo -n "radvd -p ${PIDFILE} -C ${CONFILE} ... "
		radvd -p ${PIDFILE} -C ${CONFILE}
	fi
	ret=$?
}

stop() {
	local pid=`cat ${PIDFILE} 2> /dev/null`
	if grep radvd /proc/${pid}/stat > /dev/null 2>&1 ; then
		echo -n "kill ${pid} ... "
		kill ${pid} > /dev/null 2>&1
		rm -f ${PIDFILE} > /dev/null 2>&1
		sleep 1
		ret=0
	else
		ret=1
	fi
}

if echo "$0" | grep "trans" ; then
	lock
	trans
	unlock
	exit 0
fi
if [ $# != 1 ] ; then
	usage
	exit 1
fi
case "$1" in
	start)
		echo -n "[Starting] radvd ... "
		lock
		start
		unlock
	;;
	stop)
		echo -n "[Stopping] radvd ... "
		lock
		stop
		unlock
	;;
	reload|ipup|ipchg|ipdown)
		echo -n "[Reloading] radvd ... "
		lock
		stop
		start
		unlock
	;;
	trans)
		echo -n "[Translating] radvd configuration ... "
		lock
		trans
		unlock
		ret=0
	;;
	*)
		usage
		exit 1
	;;
esac
if [ $ret == 0 ] ; then
	echo "OK"
	exit 0
else
	echo "FAIL"
	exit 1
fi
