#!/bin/sh /etc/rc.common
# Copyright (C) 2008  Alina Friedrichsen <x-alina@gmx.net>
START=50

DHCP6S_INTERFACE_STRING_OPTIONS='rapidcommit addresspool prefer_time lease_time lease_assign'

DHCP6S_PREFIX_STRING_OPTIONS='prefix'

DHCP6S_DNSS_STRING_OPTIONS='domain_name_servers domain_name'

. /lib/functions.sh

get_ifname() {
	local interface=$1
	local cfgt
	local ifname

	scan_interfaces
	config_get cfgt "$interface" TYPE
	[ "$cfgt" != "interface" ] && return 1
	config_get ifname "$interface" ifname
	printf '%s\n' "$ifname"

	return 0
}

get_ip6addr() {
	local ifname=$1
	local scope=$2
	local iproute2_scope
	local ifconfig_scope
	local ip6addr

	case "$scope" in
		host) iproute2_scope=host ifconfig_scope=Host;;
		link) iproute2_scope=link ifconfig_scope=Link;;
		site) iproute2_scope=site ifconfig_scope=Site;;
		global) iproute2_scope=global ifconfig_scope=Global;;
		"") get_ip6addr "$ifname" global || get_ip6addr "$ifname" site; return;;
		*) return 1;;
	esac

	ip6addr=$(LANG=C ip -f inet6 -- addr show dev "$ifname" 2> /dev/null | sed -n -e 's/^  *inet6 \([A-Fa-f0-9.:]*[/][0-9]*\) scope '"$iproute2_scope"' $/\1/p' | head -n 1)
	if [ -z "$ip6addr" ]; then
		ip6addr=$(LANG=C ifconfig "$ifname" 2> /dev/null | sed -n -e 's/^  *inet6 addr: \([A-Fa-f0-9.:]*[/][0-9]*\) Scope:'"$ifconfig_scope"'$/\1/p' | tail -n 1)
		[ -z "$ip6addr" ] && return 1
	fi

	printf '%s\n' "$ip6addr"

	return 0
}

dhcp6s_find_config_file() {
	local cfg=$1

	config_get_bool ignore "$cfg" ignore 0
	[ "$ignore" -ne 0 ] && return 0
	config_get DHCP6S_CONFIG_FILE "$cfg" config_file

	return 0
}

dhcp6s_add_interface() {
	local cfg=$1
	local ignore
	local interfaces
	local interface
	local list_interface
	local exist

	config_get interfaces "$cfg" interface
	for interface in $interfaces; do
		exist=0
		for list_interface in $DHCP6S_INTERFACES; do
			[ "x$interface" = "x$list_interface" ] && exist=1
		done
		[ "$exist" -eq 0 ] && DHCP6S_INTERFACES="$DHCP6S_INTERFACES $interface"
	done

	return 0
}

dhcp6s_write_interface() {
	local cfg=$1
	local ignore
	local interfaces
	local interface
	local name
	local value
	local prefer_time
	local lease_time

	config_get_bool ignore "$cfg" ignore 0
	[ "$ignore" -ne 0 ] && return 0

	config_get interfaces "$cfg" interface
	exist=0
	for interface in $interfaces; do
		[ "$INTERFACE" = "$interface" ] && exist=1
	done
	[ "$exist" -eq 0 ] && return 0

	for name in $DHCP6S_INTERFACE_STRING_OPTIONS; do
		config_get value "$cfg" "$name"
		if [ "$name" = "rapidcommit" ]; then
			printf '\t%s rapid-commit;\n' "$value"
		elif [ "$name" = "addresspool" ]; then
			config_get prefer_time "$cfg" "prefer_time"
			config_get lease_time "$cfg" "lease_time"
			printf '\t%s %s %s %s;\n' "address-pool" "$value" "$prefer_time" "$lease_time"
		elif [ "$name" = "lease_assign" ]; then
			config_get disabled_assign "$cfg" "$name"
		fi
	done

	return 0
}

dhcp6s_write_pool() {
	local cfg=$1
	local ignore
	local interfaces
	local interface
	local prefixes
	local prefix
	local name
	local value
	local cfgt
	local pool_name
	local prefix

	config_get_bool ignore "$cfg" ignore 0
	[ "$ignore" -ne 0 ] && return 0

	config_get interfaces "$cfg" interface
	exist=0
	for interface in $interfaces; do
		[ "$INTERFACE" = "$interface" ] && exist=1
	done
	[ "$exist" -eq 0 ] && return 0

#	config_get prefixes "$cfg" prefix
#	if [ -z "$prefixes" ]; then
#		prefixes=$(get_ip6addr "$IFNAME") || return 0
#	fi

	config_get pool_name "$cfg" "pool_name"
	printf 'pool %s {\n' "$pool_name"
	for name in $DHCP6S_PREFIX_STRING_OPTIONS; do
		config_get value "$cfg" "$name"
		if [ "$name" = "prefix" ]; then
			printf '\t\trange %s2 to %s40;\n' "$value" "$value"
		fi
	done

	printf '\t};\n'

	return 0
}

dhcp6s_write_dnss() {
	local cfg=$1
	local ignore
	local interfaces
	local interface
	local addrs
	local addr
	local addr_list
	local name
	local value
	local i

	config_get_bool ignore "$cfg" ignore 0
	[ "$ignore" -ne 0 ] && return 0

	config_get interfaces "$cfg" interface
	exist=0
	for interface in $interfaces; do
		[ "$INTERFACE" = "$interface" ] && exist=1
	done
	[ "$exist" -eq 0 ] && return 0

	for name in $DHCP6S_DNSS_STRING_OPTIONS; do
		config_get value "$cfg" "$name"
		if [ "$name" = "domain_name_servers" -a "x$value" != "x" ]; then
			printf 'option %s %s;\n' "domain-name-servers" "$value"
		elif [ "$name" = "domain_name" -a "x$value" != "x" ]; then
			printf 'option %s %s;\n' "domain-name" "$value"
		fi
	done

	return 0
}

dhcp6s_write_config() {
	include /lib/network

	DHCP6S_INTERFACES=
	config_foreach dhcp6s_add_interface interface
	config_foreach dhcp6s_add_interface dns

	for INTERFACE in $DHCP6S_INTERFACES; do
		IFNAME=$(get_ifname "$INTERFACE") || continue
		printf 'interface %s{\n' "$IFNAME"
		config_foreach dhcp6s_write_interface interface
		printf '};\n\n'
		config_foreach dhcp6s_write_pool pool
		config_foreach dhcp6s_write_dnss dns
	done

	return 0
}

start() {
	local opts
	config_load dhcp6s
	DHCP6S_CONFIG_FILE=
	config_foreach dhcp6s_find_config_file dhcp6s
	if [ -z "$DHCP6S_CONFIG_FILE" ]; then
		mkdir -p -- /var/etc/
		dhcp6s_write_config > /var/etc/dhcp6s.conf
		if [ -s "/var/etc/dhcp6s.conf" ]; then
			DHCP6S_CONFIG_FILE=/var/etc/dhcp6s.conf
		fi
	fi

	[ -z "$DHCP6S_CONFIG_FILE" ] && return 1

	append opts "-3"
	[ -n "$DHCP6S_CONFIG_FILE" ] && append opts "-c $DHCP6S_CONFIG_FILE"
	[ "$disabled_assign" = "0" ] && append opts "-i $IFNAME" || append opts "$IFNAME"

	/usr/sbin/dhcp6s $opts
}

reload() {
	local opts
	config_load dhcp6s
	DHCP6S_CONFIG_FILE=
	config_foreach dhcp6s_find_config_file dhcp6s
	if [ -z "$DHCP6S_CONFIG_FILE" ]; then
		mkdir -p -- /var/etc/
		dhcp6s_write_config > /var/etc/dhcp6s.conf
		if [ -s "/var/etc/dhcp6s.conf" ]; then
			DHCP6S_CONFIG_FILE=/var/etc/dhcp6s.conf
		fi
	fi

	[ -z "$DHCP6S_CONFIG_FILE" ] && return 1

	/usr/sbin/dhcp6ctl -S reload
}

stop() {
	killall dhcp6s
}
