#!/bin/sh

po_domain="alterator-bind"
bindconffile="/var/lib/bind/etc/options.conf"

ipregexp="([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])([.]([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9+]|25[0-5])){3}"
maskregexp="(/[0-9]|/[12][0-9]|/3[0-2])?"
netregexp="^($ipregexp$maskregexp|none|localhost|any|localnets)$"

#turn off auto expansion
set -f

. alterator-sh-functions

PATH="/usr/lib/alterator-bind/:$PATH"

### forwarders / allow-query / allow-recursion
avail_objects()
{
    sed -nr "/^[[:space:]]*$1/ {s,.*\{([^\}]*)\}.*,\1,;p}" "$bindconffile"|
	tr ';' '\n'|
        sed -r 's,[[:space:]]*([/a-z0-9\.]+).*,\1,
		/^[[:space:]]*$/ d'
}

delete_objects()
{
    sed -r "s,^([[:space:]]*$1.*)[[:space:]]*$2[[:space:]]*;(.*),\1\2," -i "$bindconffile"
}

new_objects()
{
    sed -r "s,^([[:space:]]*//[[:space:]]*$1)[[:space:]]*.*,\1 {};," -i "$bindconffile"
    sed -r "s,^([[:space:]]*)(//)?([[:space:]]*$1)[[:space:]]*\{([^}]*)\},\1\3 {\4$2;}," -i "$bindconffile"
}

### forward

read_forward()
{
    sed -nr '/^[[:space:]]*forward[[:space:]]/ {s,^[[:space:]]*forward[[:space:]]+([a-z]+).*,\1,;p}' "$bindconffile"
}

avail_forward()
{
    echo '("first") ("only")'
}

write_forward()
{
    sed -r "s,^([[:space:]]*)(//)?forward[[:space:]]+.*,\1forward $1;," -i "$bindconffile"
}

### config normalization
fix_config()
{
    #try to fix config if we need it
    normalize_config "$bindconffile" >"$bindconffile.new"
    if cmp "$bindconffile" "$bindconffile.new" >&2 ;then
        rm -f "$bindconffile.new"
    else
        chown root:named "$bindconffile.new"
        chmod 640 "$bindconffile.new"
        mv -f "$bindconffile.new" "$bindconffile"
    fi
}


net_required()
{
    if [ "$in_orig_action" = "new" ] &&  [ "$in_type" = "allow-query" -o "$in_type" = "allow-recursion" ] ;then
	echo "#t"
    else
	echo "#f"
    fi
}

### initial actions
fix_config

on_message()
{
	case "$in_action" in
		constraints)
			echo '('
			printf 'ip_name (required %s label "%s" ipv4-address #t)' \
					"$([ "$in_orig_action" = "new" -a "$in_type" = "forwarders" ] && echo "#t" || echo "#f")" \
					"`_ "IP address"`"
			printf 'net_name (required %s label "%s"  match ("%s" "%s"))' \
					"$(net_required)" \
					"`_ "Network address"`" \
					"$netregexp" \
					"`_ "Invalid network address"`"
			printf 'forwarders (label "%s")' "`_ "Forwarding servers"`"
			printf 'allow-query (label "%s")' "`_ "Networks are allowed to make simple queries"`"
			printf 'allow-recursion (label "%s")' "`_ "Networks are allowed to make recursive queries"`"
			printf 'forward    (label "%s")' "`_ "Forwarding mode"`"
			printf 'forwarders_length (exclude (0 forward))'
			echo ')'
			;;
		list)
			echo '('
			case "$in__objects" in
			    forwarders|allow-query|allow-recursion)
				    avail_objects "$in__objects"|sed 's,.*,("&"),'
				    ;;
			    forward)
				    avail_forward
				    ;;
			esac
			echo ')'
			;;
		read)
			echo '('
			printf ' forwarders_length %s' "$(avail_objects "forwarders"|wc -l)"
			printf ' forward "%s"' "$(read_forward)"
			echo ')'
			;;
		write)
			[ -n "$in_forward" ] && write_forward "$in_forward"
			service bind reload >&2
			write_nop
			;;
		new)
			local name="${in_ip_name:-$in_net_name}"
			if avail_objects "$in_type"|grep -qs "^$name$"; then
			    printf '(error "%s")' "`_ "Same IP/Network already exists"`"
			else
    			    [ -n "$name" -a -n "$in_type" ] && new_objects "$in_type" "$name"
			    service bind reload >&2
			    write_nop
			fi
			;;
		delete)
			delete_objects "${in__objects%%/*}" "${in__objects#*/}"
			service bind reload >&2
			write_nop
			;;
		*)
			echo '#f'
			;;
	esac
}

message_loop
