#!/bin/bash

. ${TOOLKIT}-functions.sh

usedip=usedip.tmp
:> $usedip

errfile="err.tmp"
:>$errfile

print_error()
{
	echo -e "\n ERROR: $*\n"
	echo $* >>$errfile
}

compute_ranges()
{
	local net=$1	; shift
	# remaining parms are one or more couples from start {from start ...}
	local from=
	local to=
	local ip=
	local used=

	while [ $# != 0 ]
	do
		[ $# -lt 2 ] && {
			exit_err 1 "range must be couples in the 'from to' format"
			return 1
		}
		from=$1 ; shift
		to=$1 ; shift

		# check for reserved ips
		#
		ip=$from

		while [ $ip -lt $to ]
		do
			used=$(grep "$net\.$ip " $usedip) && {
				echo >&2
				putwarning "DHCP RESERVATION CLASH" \
					"$net.$ip not really reserved, is in range $from - $to," \
					"clashing entries are: $used" >&2
			}
			ip=$(expr $ip + 1)
		done

		# range entry
		echo "	range $net.$from $net.$to;"
	done
}



# (MAIN)

# first, check for ipv6 support
#
getconfirm net.use_ipv6 || {
	v4int=$(jtconf dhcp_server.interfaces_v4 2>/dev/null || :)
	[ "X$v4int" = "X" ] && {
		putwarning "DHCP IPV4 ONLY - ERROR" \
			"ipv6 disabled (net.use_ipv6 = false); you must" \
			"manually define dhcp_server.interfaces_v4"
		exit_missing_define "dhcp_server.interfaces_v4"
	}
}

#----------------------------------------------------------------
# /etc/dhcpd.conf buildup
#----------------------------------------------------------------

subnets=
for net in $(jtconf --list dhcp. | sed -e 's/dhcp\.//' -e 's/\..*//' | sort -u)
do
	getconfirm dhcp.$net.disabled || subnets="$subnets $net"
done
[ "$subnets" ] || {
	exit_err 1 "you must define at least one subnet for dhcp"
}

# per prima cosa, costruisco elenco fixed hosts, usando definizioni
# nella sezione [dhcp_hosts], ogni entry ha come chiave il nome
# host della macchina, e come valore una coppia di stringhe,
# rispettivamente mac-address e ip, se ip non e` fornito fa un
# lookup al dns con il nome
#
fixed="fixed.tmp"
fixedlist="fixedlist.tmp"

:> $fixed

echo "  computing fixed hosts"

# to speed things, we dump the entire dhchp_hosts section and parse it
#
jtconf --dump 'dhcp_hosts' | grep '^  ' | while read host mac ip
do
	msg=
	[ "X$mac" = "X" ] && {
		print_error "entry dhcp_hosts.$host must have MAC [IP] format"
		continue
	}

	[ "X$ip" = "X" ] && {
		ip=$(host $host | grep 'has address' | sed -e 's/.*has address //')
		[ "$ip" == "" ] && {
			print_error "can't resolve name '$host' (from dhcp_hosts.$host)"
			continue
		}
	}

	used=$(grep "^$ip " $usedip) && {
		msg="DUP "$(echo "$used" | cut -d' ' -f2)
	}
	case $mac in
		*:*:*:*:*:*) ;; # ok
		*)	print_error "entry dhcp_hosts.$host, '$mac' doesn't seems a mac address"
			continue
			;;
	esac
	case $ip in
		*.*.*.*) ;; # ok
		*)	print_error "entry dhcp_hosts.$host, '$ip' doesn't seems an ip address"
			continue
			;;
	esac
	printf "  %-20s  %s %-16s %s\n" "$host" "$mac" "$ip" "$msg"

	echo "
host $host {
	hardware ethernet $mac;
	fixed-address $ip;
}" >>$fixed
	echo "$ip $host" >>$usedip
done
echo
[ -s $errfile ] && exit 1

file=dhcpd.conf
outfile=$file.tmp
cp $file.base $outfile || exit $?


# for each subnet check if is part of a shared-network,
# and sort out subnets based on grouping
#
subnet_file=$RUNDIR/subnet.tmp
shared_file=$RUNDIR/shared.tmp
:> $subnet_file
:> $shared_file

for subnet in $subnets
do
	if sharenet=$(jtconf dhcp.$subnet.shared 2>/dev/null)
	then
		echo "$sharenet" >>$shared_file
		echo "$sharenet $subnet" >>$subnet_file
	else
		echo "NONE $subnet" >>$subnet_file
	fi
done


# then, for each shared-network we group subnets, and at end we
# add NONE shared-network (no grouping)
#
for sharenet in $(sort -u $shared_file) NONE
do
    [ $sharenet != NONE ] && {
    	echo -e "\n# SHARED-NET: $sharenet\n#\nshared-network $sharenet {\n" >>$outfile
    	echo -e "\n  shared-network $sharenet"
    }

    for subnet in $(grep "^$sharenet " $subnet_file | sed -e 's/.* //')
    do
	network=$(jtconf dhcp.$subnet.network)	|| exit_missing_define dhcp.$subnet.network
	netmask=$(jtconf dhcp.$subnet.netmask 2>/dev/null)	|| :
	netmask=${netmask:-"255.255.255.0"}

	printf "   subnet %-12s: %-30s  " "$subnet" "$network/$netmask"

	# null network?
	#
	gateway=$(jtconf dhcp.$subnet.gateway)		|| :
	if getconfirm dhcp.$subnet.nullnet
	then
		echo "(null network)"
		(
			echo
			echo "  # null network $subnet"
			echo "  #"
			echo "  subnet $network netmask $netmask {"
			[ "$gateway" != "" ] && echo "	option routers $gateway;"
			echo "  }"
		) >>$outfile
		continue
	fi

	gateway=$(jtconf dhcp.$subnet.gateway)		|| exit_missing_define dhcp.$subnet.gateway
	rangenet=$(jtconf dhcp.$subnet.rangenet)	|| exit_missing_define dhcp.$subnet.rangenet
	ranges=$(jtconf dhcp.$subnet.ranges)		|| exit_missing_define dhcp.$subnet.ranges

	(
		echo
		echo "  # $subnet"
		echo "  #"
		echo "  subnet $network netmask $netmask {"
		echo "	option subnet-mask $netmask;"
		echo "	option routers $gateway;"
		compute_ranges $rangenet $ranges
		echo "  }"
	) >>$outfile
	echo

    done # subnets

    [ $sharenet != NONE ] && {
    	echo -e "\n}\n# SHARED-NET: $sharenet (end)\n" >>$outfile
    }

done # shared-networks
echo


# add fixed hosts
#
[ -s $fixed ] && {
	echo -e "\n# FIXED HOSTS ENTRIES\n\n" >>$outfile
	cat $fixed >>$outfile
}

exit 0
