#!/bin/sh

alterator_api_version=1
dhcp_config_file=/etc/alterator/dhcp/general

. alterator-sh-functions
. ddns-sh-functions



## domain

list_ddns_domain()
{
    ddns_list_domain|write_enum
}

## ns

read_ddns_ns()
{
    local zone="$1";shift
    local ns="$(ddns_domain_list_ns "$zone"|grep -v "ns.$zone"|tr '\n' ' ')"
    echo "${ns% }"
}

write_ddns_ns()
{
    local zone="$1";shift
    local hostlist="$1";shift

    local nslist="ns.$zone $hostlist"

    [ -n "$nslist" ] || return 0

    local state1="$(mktemp -t alterator-bind.XXXXXX)"
    local state2="$(mktemp -t alterator-bind.XXXXXX)"

    ddns_domain_list_ns "$zone"|sort >"$state1"
    echo "$nslist"|tr ' ' '\n'|sed '/^[[:space:]]*$/d'|sort >"$state2"

    comm -13 "$state1" "$state2"|
	while read host; do
	    ddns_domain_add_ns "$zone" "$host"
	done

    comm -23 "$state1" "$state2"|
	while read host;do
	    ddns_domain_del_ns "$zone" "$host"
	done

    rm -f -- "$state1" "$state2"
}

## network

read_ddns_network()
{
    local zone="$1";shift
    local ddns_network="$(ddns_domain_list_net "$zone"|tr '\n' ';')"
    echo "${ddns_network%;}"
}

write_ddns_network()
{
    local zone="$1";shift

    local state1="$(mktemp -t alterator-bind.XXXXXX)"
    local state2="$(mktemp -t alterator-bind.XXXXXX)"
    local ip=

    ddns_domain_list_net "$zone"|sort >"$state1"
    [ -z "$1" ] || echo "$1"|tr ';' '\n'|sort >"$state2"

    comm -13 "$state1" "$state2"|
	while read ip; do
	    ddns_domain_add_net "$zone" "$ip"
	done

    local dhcp_ip="$(shell_config_get "$dhcp_config_file" ip_start)"

    comm -23 "$state1" "$state2"|
	while read ip;do
	    [ -n "$dhcp_ip" ] && [ "$zone" = "$(ddns_system_zone)" ] && ipv4addr_is_in_subnet "$dhcp_ip" "$ip" ||
		ddns_domain_del_net "$zone" "$ip"
	done

    rm -f -- "$state1" "$state2"
}

list_ddns_network()
{
    local ip
    local iface
    local dhcp_iface="$(shell_config_get "$dhcp_config_file" iface)"

    ddns_net_list_all|
    while read ip iface; do
	local comment="$iface ($ip)"
	[ "$iface" != "$dhcp_iface" ] || comment="$comment `_ "managed by DHCP server"`"
        write_enum_item "$ip" "$comment"
    done
}

list_ddns_host()
{
    local zone="$1";shift
    local ip
    local name
    ddns_domain_list_host "$zone"|
	while read ip name; do
	    write_table_item ip "$ip" host "$name" name "${ip}:${name}"
	done
}

del_ddns_host()
{
    local zone="$1";shift
    local IFS=';'
    local host
    local ip

    [ -z "$1" ] ||
	for i in $1;do
	    host="${i#*:}"
	    ip="${i%%:*}"
	    ddns_domain_is_reserved_host "$host" || ddns_domain_del_host "$zone" "$ip" "$host"
	done
}


on_message()
{
    case "$in_action" in
	type)
	    write_type_item	ddns_master	ipv4-address-list
	    write_type_item	ddns_ns		hostname-list
	    write_type_item	ddns_mx		hostname-list
	    write_type_item	new_ddns_ip	ipv4-address
	    write_type_item	new_ddns_host	system-computer-name
	    write_type_item	new_ddns_domain	hostname
	    ;;
	list)
	    case "$in__objects" in
		ddns_type)
			write_enum_item "master" "`_ "master"`"
			write_enum_item "slave" "`_ "slave"`"
			;;
		ddns_network) list_ddns_network ;;
		ddns_host) [ -z "$in_ddns_domain" ] || list_ddns_host "$in_ddns_domain";;
		ddns_domain) list_ddns_domain ;;
	    esac
	    ;;
	read)
	    [ -n "$in_ddns_domain" ] || return
	    write_string_param ddns_network "$(read_ddns_network "$in_ddns_domain")"
	    write_string_param ddns_ns "$(read_ddns_ns "$in_ddns_domain")"
	    write_string_param ddns_mx "$(ddns_domain_read_mx "$in_ddns_domain")"
	    write_string_param ddns_type "$(ddns_domain_read_type "$in_ddns_domain")"
	    write_string_param ddns_master "$(ddns_domain_read_master "$in_ddns_domain")"
	    ! ddns_key_exist "$in_ddns_domain-transfer-key"
	    write_string_param ddns_has_key "$?"
	    ;;
	write)
	    [ -n "$in_ddns_domain" -a -n "$in_ddns_type" ] || return
	    case "$in_ddns_type" in
		master)
		    write_ddns_network "$in_ddns_domain" "$in_ddns_network"
		    write_ddns_ns "$in_ddns_domain" "$in_ddns_ns"
		    ddns_domain_write_mx "$in_ddns_domain" "$in_ddns_mx"
		    ;;
		slave)
		    if [ -z "$in_ddns_master" ];then
			write_error "`_ "You should define as minimum one master server for slave domain"`"
		    elif ! ddns_key_exist "$in_ddns_domain-transfer-key"; then
			write_error "`_  "No domain key found"`"
		    else
			ddns_domain_write_master "$in_ddns_domain" "$in_ddns_master"
		    fi
		    ;;
	    esac
	    service bind condreload >&2
	    ;;
	create)
	    [ -n "$in_new_ddns_domain" -a -n "$in_new_ddns_type" ] || return
	    if ddns_domain_exists "$in_new_ddns_domain";then
		write_error "`_ "Same domain already exists"`"
		return
	    else
		ddns_create_domain "$in_new_ddns_domain" "$in_new_ddns_type"
		service bind condreload >&2
	    fi
	    ;;
	destroy)
	    [ -n "$in_ddns_domain" ] || return
	    if [ "$in_ddns_domain" = "$(ddns_system_zone)" ];then
		write_error "`_ "Unable to destroy system domain"`"
		return
	    else
		ddns_destroy_domain "$in_ddns_domain"
		service bind condreload >&2
	    fi
	    ;;
	add)
	    [ -n "$in_ddns_domain" -a -n "$in_new_ddns_host" -a -n "$in_new_ddns_ip" ] || return

	    local zone="$in_ddns_domain"
	    local new_host="$in_new_ddns_host"
	    local new_ip="$in_new_ddns_ip"

	    if ddns_domain_has_host "$zone" "$new_ip" "$new_host";then
		write_error "`_ "Same binding of host to IP address already exists"`"
		return
	    elif ddns_domain_is_reserved_host "$new_host";then
		write_error "`_ "This hostname is registered for internal purposes"`"
		return
	    else
		ddns_domain_add_host "$zone" "$new_ip" "$new_host"
	    fi
	    ;;
	del)
	    [ -n "$in_ddns_domain" -a -n "$in_ddns_host" ] || return
	    del_ddns_host "$in_ddns_domain" "$in_ddns_host"
	    ;;
	read_key)
	    [ -n "$in_ddns_domain" ] || return
	    ddns_print_key "$in_ddns_domain-transfer-key"|write_blob_param ddns_key
	    ;;
	write_key)
	    [ -n "$in_ddns_domain" -a -n "$in_ddns_key_file" ] || return
	    if ddns_check_key "$in_ddns_domain-transfer-key" "$in_ddns_key_file"; then
		ddns_replace_key "$in_ddns_domain-transfer-key" "$in_ddns_key_file"
	    else
		write_error "`_ "Invalid domain key"`"
	    fi
    esac
}

message_loop
