#!/bin/sh

network_file=/etc/sysconfig/network
system_file=/etc/sysconfig/system
resolvconf=/sbin/resolvconf
etcnet_lo_resolvconf=/etc/net/ifaces/lo/resolv.conf
max_hostname_length=64
alterator_api_version=1

. alterator-sh-functions
. avahi-sh-functions
. shell-config
. alterator-openldap-functions


test_resolver()
{
	cat /etc/resolv.conf | grep -qs "^nameserver 127.0.0.1" 
	if [ $? -eq 1 ]; then
		echo "ERROR: nameserver 127.0.0.1 not present in resolv.conf"
	else
		nameserver=`grep -s ^nameserver /etc/resolv.conf | head -n1`
		if echo $nameserver | grep -qs 127.0.0.1 ; then
			echo "OK"
		else
			echo "ERROR: 127.0.0.1 is not first in resolv.conf"
		fi
	fi
}

test_access()
{
	ping -c 1 $(read_hostname) > /dev/null 2>&1
	if [ $? -eq 1 ]; then
		echo "ERROR: fqdn is unpingable"
	else
		echo "OK"
	fi

}

test_ldap()
{
	fqdn=$(read_hostname)
	domain="${fqdn#*.}"
	dn="$(host_2_dn "$domain")"
	slapd_conf=`ldap-dn find $dn`
	if [ $? -eq 1 ]; then
		echo "ERROR: no slapd conffile for dn: '$dn'"
		exit
	fi
	slapd_rootpw=`grep ^rootpw $slapd_conf | sed -e 's,^rootpw ,,'`
	if [ -z $slapd_rootpw ] ;then 
		echo "ERROR: no rootpw specified"
		exit
	fi
	slapd_rootdn=`grep ^rootdn $slapd_conf | sed -e 's,^rootdn ,,' | sed -e 's,",,g'`
	if [ -z $slapd_rootdn ] ; then
		echo "ERROR: no rootdn specified"
		exit
	fi

	ldapsearch -x -H "ldaps://$fqdn" -b "$dn" -D "$slapd_rootdn" -w"$slapd_rootpw"  > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		echo "Error: connect to ldaps://$fqdn failed"
		exit
	fi

	ldapsearch -x -H "ldaps://$fqdn" -b "$dn" -D "$slapd_rootdn" -w"$slapd_rootpw" ou=People | grep -v "^#" | grep "ou: People" > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		echo "OK"
	else
		echo "Error: failed to ldapsearch ou=People, slapd is broken"
	fi
}

test_kdc()
{
	if ! service krb5kdc status &> /dev/null ; then
		echo "Error: krb5kdc service is stopped"
	fi
	fqdn=$(read_hostname)
	domain="${fqdn#*.}"
	dn="$(host_2_dn "$domain")"
	slapd_conf=`ldap-dn find $dn`
	if [ $? -eq 1 ]; then
		echo "ERROR: no slapd conffile for dn: '$dn'"
		exit
	fi
	slapd_rootpw=`grep ^rootpw $slapd_conf | sed -e 's,^rootpw ,,'`
	slapd_rootdn=`grep ^rootdn $slapd_conf | sed -e 's,^rootdn ,,' | sed -e 's,",,g'`
	ldapsearch -x -h localhost -b "$dn" -D "$slapd_rootdn"  "ou=kdcroot" -w"$slapd_rootpw" | grep -v "^#" | grep "ou: kdcroot" > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		echo "Error: failed to ldapsearch ou=kdcroot, no KDC base in LDAP"
		exit
	fi

	ldapsearch -x -h localhost -b "$dn" -D "$slapd_rootdn"  "objectClass=krbRealmContainer" -w"$slapd_rootpw" | grep -v "^#" | grep "objectClass: krbRealmContainer" > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		echo "OK"
	else
		echo "Error: failed to ldapsearch objectClass=krbRealmContainer, no realm container in LDAP"
	fi

}


test_smb()
{
	if service smb status &> /dev/null ; then
		echo "OK"
	else
		echo "Error: smbd service is stopped"
	fi
}

test_dhcpd()
{
	fqdn=$(read_hostname)
	domain="${fqdn#*.}"
	grep -qs "option domain-name \"$domain\";" /etc/dhcp/dhcpd.conf
	if [ $? -ne 0 ]; then
		echo "Error: domain name $domain is not provided to clients"
		exit
	fi
	grep -qs "option domain-name-servers" /etc/dhcp/dhcpd.conf
	if [ $? -ne 0 ]; then
		echo "Error: domain server is not provided to clients"
		exit
	else
		echo "OK"
	fi
}


check_hostname()
{
    local hn="$1"
    local length=

    length="$(printf "%s" "$hn" | wc -m)"
    if [ $length -gt $max_hostname_length ]; then
        write_error "`_ "Domain name is too long"`"
        return 1
    fi
    return 0
}

read_hostname()
{
    local value="$(shell_config_get "$network_file" HOSTNAME)"
    [ -n "$value" ] || value="localhost.localdomain"
    echo "$value"
}

read_domain()
{
    local value="$(read_hostname)"
    local domain="${value#*.}"
    [ "$value" != "$domain" ] || domain="localdomain"
    echo "$domain"
}

write_domain()
{
    local old_value="$(read_hostname)"
    local old_name="${old_value%%.*}"
    local new_value="$old_name.$1"

    check_hostname "$new_value" || return 1
    if [ "$old_value" != "$new_value" ];then
        shell_config_set "$network_file" HOSTNAME "$new_value"
        hostname "$new_value"
        if [ -f "$etcnet_lo_resolvconf" ]; then
            shell_config_set "$etcnet_lo_resolvconf" domain "$1" ' ' ' '
            [ -x "$resolvconf" ] && "$resolvconf" -a lo <"$etcnet_lo_resolvconf"
        fi
        run-parts /etc/hooks/hostname.d "$old_value" "$new_value"
    elif test_bool "$2";then
        hostname "$new_value"
        run-parts /etc/hooks/hostname.d "" "$new_value"
    fi

    return 0
}

read_role()
{
    shell_config_get "$system_file" SERVER_ROLE
}

write_role()
{
    local old_server_role="$(read_role)"
    local new_server_role="$1";shift
    if [ "$old_server_role" != "$new_server_role" ];then
	shell_config_set "$system_file" SERVER_ROLE "$new_server_role"
    fi
    export old_server_role
    export new_server_role
    run-parts /usr/lib/alterator/hooks/net-domain.d
}

on_message() {
  case "$in_action" in
    type)
	write_type_item domain hostname
	;;
    read)
	write_string_param domain "$(read_domain)"
	local role="$(read_role)"
	write_string_param resolver "$(test_resolver)" 
	write_string_param access "$(test_access)" 
	write_string_param ldap "$(test_ldap)" 
	write_string_param kdc "$(test_kdc)" 
	write_string_param smb "$(test_smb)" 
	write_string_param dhcpd "$(test_dhcpd)" 
	[ "$role" != "master" ]
	write_bool_param master $?
	;;
    write)
	if [ -z "$in_domain" ]; then
	    write_error "`_ "Please define domain name"`"
	    return
	elif echo "$in_domain"|egrep -iwqs "localdomain|localhost|local"; then
	    write_error "`_ "This domain name is registered for internal purposes"`"
	    return
	fi

	# Note: write_role should be before write_domain, hooks can use server role value
	role=none
	if [ "$in_master" == "#t" ]; then
		role=master
	fi
	write_role "$role"
	write_domain "$in_domain" "1" && \
	publish_service alterator-net-domain 'ALT Linux Server (%h)' '_server._tcp' '0' "role=$(read_role)" "domain=$(read_domain)"
	;;
  esac
}

message_loop
