#!/bin/sh
#	program:	netmasktbl
#	release:	1.5.0
#	purpose:	Build an /etc/netmasks type table on stdout.
#			We also append the header and a trailer files.
#			Output is categorized by network.
#			Any line in the header or trailer with the string
#			"TIMEDATE" on it will be replaced with the output
#			from the "date" cmd.
#	input:		Domain name on command line,
#			optional nameserver to direct queries to.
#	output:		/etc/netmasks like table generated on stdout
#			or the word "ERROR", with a message on stderr.
#	exit value:	0 if succeeds, 1 if fails (and "ERROR" output).
#
# BUG in recursion code below: $mask is always derived based on the class of
#     network (i.e. class B), which is only correct when at the top-level
#     of recursion trying to figure if there are subnets.  For a subnet to
#     be subnetted, $mask would have to be the subnetmask from the PREVIOUS
#     level of recursion!  I need to pass the subnetmask from outer-calls
#     thru recursive call for the inner-calls to use as their netmask.
#
# Copyright (C) 1993-2000 Paul A. Balyoz <pab@domtools.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

TMP="/tmp/`basename $0`.$$"

AWK="/usr/local/domtools/lib/netmasktbl.awk"

networksdomopt=
test x"" != x"" && networksdomopt=" [-x]"

usage() {
	echo "usage: $0 [-d]$networksdomopt [@nameserver] dom.ain." >&2
	echo "	     $0 -n$networksdomopt [@nameserver] net.work.ip.addr" >&2
	exit 1
}

if test $# -lt 1 -o $# -gt 7; then
	usage
fi

inputtype="domain"
headerfooter=1
extracomments=
masktouse=
atnameserver=
while test $# -ge 2; do
	case "$1" in
		-d)	inputtype="domain" ;;
		-n)	inputtype="network" ;;
		-x)	extracomments="-x" ;;
		@*)	atnameserver="$1" ;;
# internal option to suppress header and footer during recursive calls:
		-s)	headerfooter=0 ;;
# internal option to pass in netmask of outer network:
		-m)	shift; masktouse="$1" ;;
# unrecognized option:
		*)	echo "$0: illegal argument $1" >&2; usage ;;
	esac
	shift
done

if test x"$extracomments" != x"" -a x"" = x""; then
	echo "$0: option -x is not currently installed; see Domtools MANUAL for details." >&2
	usage
fi

# Make a list of network(s) to be looked at in this run

if test $inputtype = "network"; then
	nets="$1"
else
	nets=`/usr/local/domtools/bin/ptr $atnameserver $1 2>/dev/null`
	if test $? -ne 0 -o x"$nets" = x"ERROR"; then
		nets=''
	fi
fi

#DEBUGGING:
#echo "headerfooter =" $headerfooter
#echo "inputtype =" $inputtype
#echo "arg = $1"
#echo "$# =" $# "(should always be 1)"
#echo "nets =" $nets
#exit 0

# Print the header file (expanding all macros)

if test $headerfooter -eq 1; then
	HOST=`hostname`
	cat /usr/local/domtools/lib/netmasktbl.header | \
		sed -e "s/TIMEDATE/`date`/g" | \
		sed -e "s/USER/$USER/g" | \
		sed -e "s/HOST/$HOST/g"
fi

# Loop through all the netmasks to be looked at

if test x"$nets" = x""; then
    echo "# (no network PTR RRs listed in domain $1  See RFC1101)"
else
    for net in $nets; do

# Sometimes network address is in in-addr.arpa. format, convert it to normal

	if test x"`/usr/local/domtools/bin/type $net`" = x"inverse"; then
		net=`/usr/local/domtools/bin/i2faddr $net`
	fi

# Remove "0"s, if any, from right hand side of network address

	net=`/usr/local/domtools/bin/netkillzeros $net`
#echo "; net =" $net
	if test $? -ne 0; then
		echo "$0: netkillzeros call failed for some reason." >&2
		echo 'ERROR'
		exit 1
	fi

# Fetch this network's name

	p=`/usr/local/domtools/bin/netname $atnameserver $net 2>/dev/null`
	if test $? -eq 0; then
		netname=`echo $p | awk -F. '{print $1}'`
#echo "; netname =" $netname

# Fetch the netmask of this network via DNS query (RFC1101).
# If none found, assume no subnetting is being done.

		mask=`/usr/local/domtools/bin/subnetmask $atnameserver $net`
		if test $? -eq 0; then

# If -x was specified, print the descriptive TXT RR for this network
# as a comment line before the netmask line itself.

			if test x"$extracomments" != x""; then
				txtrr="`/usr/local/domtools/bin/txt $atnameserver ${netname}. 2>/dev/null`"
				if test $? -eq 0; then
					echo "# $txtrr"
				fi
			fi

# Print this netmask as a tab-separated /etc/netmasks entry

			echo $net $mask | awk -f $AWK

# Figure out the netmask for this class of network, or receive the mask
# passed in from the process above us (recursion).

			if test x"$masktouse" = x""; then
				propermask=`/usr/local/domtools/bin/addr2mask $net`
			else
				propermask="$masktouse"
			fi

# If the two netmasks differ, this network is subnetted, in which case we
# generate a list of all possible subnets based on the the subnetmask,
# and call ourselves recursively to print each one.  This way we handle
# all possible levels of sub-subnets.

			if test x"$mask" != x"$propermask"; then
				/usr/local/domtools/bin/gensubnetlist `/usr/local/domtools/bin/netwithzeros $net` $propermask $mask > $TMP
				if test $? -ne 0; then
					echo "$0: gensubnetlist tool returned an error." >&2
					echo 'ERROR'
					exit 1
				fi
				i=1
				len=`wc -l < $TMP`
#echo "; i = $i, len = $len"
				while test $i -le $len; do
					subnet=`sed -e $i!d < $TMP`
#echo "; subnet = $subnet"
					/usr/local/domtools/bin/netmasktbl -n -s $extracomments \
							-m $mask $atnameserver $subnet
					if test $? -ne 0; then
						echo "$0: recursive call to ourselves returned an error." >&2
						echo 'ERROR'
						exit 1
					fi
					i=`expr $i + 1`
				done
			fi

		fi

	fi

    done
fi

# Print the footer file (expanding all macros)

if test $headerfooter -eq 1; then
	cat /usr/local/domtools/lib/netmasktbl.footer | \
		sed -e "s/TIMEDATE/`date`/g" | \
		sed -e "s/USER/$USER/g" | \
		sed -e "s/HOST/$HOST/g"
fi

rm -f $TMP
exit 0
