#!/bin/bash

. ${TOOLKIT}-functions.sh

usedip=usedip.tmp
:> $usedip

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 -e "\n" >&2
				echo "warning: $ip not really reserved, is in range $from $to" >&2
				echo "	(used by entry $used)" >&2
			}
			ip=$(expr $ip + 1)
		done

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

#----------------------------------------------------------------
# /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

:> $fixed

echo "  computing fixed hosts"

for host in $(jtconf --listvars dhcp_hosts)
do
	val=$(jtconf dhcp_hosts.$host)
	msg=

	set -- $val
	case $# in
	  2)
		mac=$1
		ip=$2
		;;
	  1)
		mac=$1
		ip=$(host $host | grep 'has address' | sed -e 's/.*has address //')
		[ "$ip" == "" ] && {
			exit_err 1 "can't resolve name '$host' (from dhcp_hosts.$host)"
		}
		;;
	  *)
		exit_err 1 "entry dhcp_hosts.$host must have MAC [IP] format"
		;;
	esac
	used=$(grep "^$ip " $usedip) && {
		msg="DUP "$(echo "$used" | cut -d' ' -f2)
	}
	case $mac in
		*:*:*:*:*:*) ;; # ok
		*) exit_err 1 "entry dhcp_hosts.$host, '$mac' doesn't seems a mac address" ;;
	esac
	case $ip in
		*.*.*.*) ;; # ok
		*) exit_err 1 "entry dhcp_hosts.$host, '$ip' doesn't seems an ip address" ;;
	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

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 shared=$(jtconf dhcp.$subnet.shared 2>/dev/null)
	then
		echo "$shared" >>$shared_file
		echo "$shared $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: $shared\n#\nshared-network $shared {\n" >>$outfile
    }

    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: $shared (end)\n" >>$outfile
    }

done # shared-networks



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

exit 0
