#!/bin/csh -f

# A minimum of effort has been made to get this to work under Linux.
# No doubt all the functionality is not here.  11/30/05

# modified to be able to get "outside" view (with "-dns dns1"); 9/28/15

switch (`uname -s``uname -r`)
case SunOS5*:
    set SOLARIS

	set HOSTPGM = /usr/local/bin/host
	set PING = /usr/sbin/ping
	set WAIT1SEC = 1
	set UCBECHO = /usr/ucb/echo
	set SNMPCsw
	set SNMPWALK = /usr/local/snmp-4.2/bin/snmpwalk
	breaksw
case Linux2*:
case Linux3*:
case Linux4*:
	set HOSTPGM = /usr/bin/host
	set PING = "/bin/ping -c1"
	set WAIT1SEC = -W1
	set UCBECHO = /bin/echo
	set SNMPCsw = -c
	set SNMPWALK = /usr/bin/snmpwalk
	breaksw
default:
	exec echo ${0}: does not run on `uname -s` `uname -r`
endsw

set BASE = `basename $0`
set DIR = `dirname $0`
set CONF = $DIR/.$BASE
if (-r $CONF) source $CONF

while($#argv)
	switch ("$1")
	case -crispin:
		set CRISPIN
		shift
		breaksw
	case -c:
		set COMMUNITY = $2
		shift; shift
		breaksw
	case -domain:
exec echo This option is now broken.
# now that rutgers.edu has lots os subdomains, we have to download them all...
		set DOMAIN = $2
		shift ; shift
		breaksw
	case -f:
		set FORCE
		shift
		breaksw
	case -k:
		set KEEP	# temp files
		shift
		breaksw
	case -g:
		set GATEWAYS
		shift
		breaksw
	case -h:
		set DQ = '"'
		echo "usage: $0 [-f] [-g] [-r] [-v] [-hi <string>] [-hv <string>] [-hinfo] [-ip] [-loc] <subnet>"
		echo ""
		echo "  where	-f means force regeneration of /tmp file"
		echo "		(perhaps host table was updated)"
		echo "  -domain <domain> (alt to rutgers.edu)"
		echo "  -g	output gateway information"
		echo "	-hi	select hosts with hinfo field containing string"
		echo "	-hv	select hosts with hinfo field not containing string"
		echo "	-hinfo	output host info"
		echo "	-ip	output IP address"
		echo "	-loc	output location"
#?		echo "		(may be repeated)"
		echo "	-v	verbose"
		echo "	-r	sort by host number"
	echo "	<subnet>	is subnet number (eg, 128.6.25)"
	echo "	(If a fourth octet is specified in the subnet number,"
	echo "	 only that portion of the subnet will be ouput)"
		exec echo ""
		breaksw
	case -hi:
		set HI = $2
		shift ; shift
		breaksw
	case -hinfo:
		set HINFO
		shift
		breaksw
	case -hv:
		set HV = "$2"
		endif
		shift ; shift
		breaksw
	case -ip:
		set IP
		shift
		breaksw
	case -loc:
		set LOC
		shift
		breaksw
	case -r:
		set REVERSE
		set REV = /tmp/reverse.$$
		shift
		breaksw
	case -d:
		set DEBUG
		shift
		breaksw
	case -dns:
		set DOMAINDNS = $2
		set CD = "-cd $BASE.`whoami`.$DOMAINDNS"
		set SERVER = "-server $2"
		shift ; shift
		breaksw
	case -v:
		set VERBOSE
		shift
		breaksw
	case -*:
		exec echo "usage: $0 [-f] [-v] <subnet>	# (-h for help)"
		breaksw
	default:
		if ($?SUBNET) exec echo "usage: $0 [-f] [-v] <subnet>	# (-h for help)"
		set SUBNET = $1
		shift
	endsw
end

if (! $?DOMAIN) set DOMAIN = rutgers.edu
if (! $?DOMAINDNS) set DOMAINDNS = dns
if (! $?CD) set CD
if (! $?SERVER) set SERVER

if (! $?COMMUNITY) set COMMUNITY = public

if (0) then

    notes for determining netmask automatically
	determine IP address for gateway on subnet:
		lcsr-gw = 128.6.25.20
	get netmask from lcsr-gw:
	    snmpget -v 1 lcsr-gw public ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.128.6.25.20
		=> ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.128.6.25.20 = IpAddress: 255.255.255.0

    bonus: get Rick's comment for subnet:
	get index for subnet interface
	    snmpget -v 1 lcsr-gw public ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.128.6.25.20
		=> ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.128.6.25.20 = 8
	get comment based on that index:
	    snmpget -v 1 lcsr-gw public 31.1.1.1.18.8
		=> 31.1.1.1.18.8 = "faculty Unix general"

endif

if (! $?SUBNET) exec echo "usage: $0 [-f] [-v] <subnet>	# (-h for help)"

# Can now specify 128.6.4.4/24
set MASKWID = `echo $SUBNET | grep / | sed 's;.*/;;'`
set SUBNET = `echo $SUBNET | sed 's;/.*;;'`
if ("$MASKWID" != "") then
    if ($?VERBOSE) echo `date +%T` Determining MASK
    set MASK = ( "128.0.0.0" "192.0.0.0" "224.0.0.0" "240.0.0.0" \
      "248.0.0.0" "252.0.0.0" "254.0.0.0" "255.0.0.0" \
      "255.128.0.0" "255.192.0.0" "255.224.0.0" "255.240.0.0" \
      "255.248.0.0" "255.252.0.0" "255.254.0.0" "255.255.0.0" \
      "255.255.128.0" "255.255.192.0" "255.255.224.0" "255.255.240.0" \
      "255.255.248.0" "255.255.252.0" "255.255.254.0" "255.255.255.0" \
      "255.255.255.128" "255.255.255.192" "255.255.255.224" "255.255.255.240" \
      "255.255.255.248" "255.255.255.252" "255.255.255.254" "255.255.255.255" )
    set PNETMASK = $MASK[$MASKWID]
    if ($?DEBUG) echo PNETMASK = $PNETMASK
    set HMask = `echo $PNETMASK | sed 's;.*\.;;'`
#echo HMask = $HMask
    set HN = `echo $SUBNET | sed 's;.*\.;;'`
#echo HN = $HN
     @ H1 = ( $HMask & $HN )
#echo H1 = $H1
    @ HMax = ( $HMask ^ 255 )
#echo HMax = $HMax
    @ NO = $HMax + 1
    @ TOP = $H1 + $HMax
    set LOWEST = $H1
    set HIGHEST = $TOP
    if ($?DEBUG) echo "(MASKWID = $MASKWID)" LOWEST = $LOWEST\; HIGHEST = $HIGHEST
endif

set DNSFILE = /tmp/whatson.$DOMAIN.$DOMAINDNS
set TMPDNSFILE = /tmp/whatson.$DOMAIN.$$
#set SNMPGET = `which snmpget`
#if ($#SNMPGET > 1 && -e /usr/local/bin/snmpget) set SNMPGET = /usr/local/bin/snmpget
if (-e /usr/local/bin/snmpget) then
	if ($?VERBOSE) echo `date +%T` snmpget exists
	set SNMPGET = /usr/local/bin/snmpget
else if (-e /usr/local/snmp-4.2/bin/snmpget) then
	set SNMPGET = /usr/local/snmp-4.2/bin/snmpget
endif
if (! $?SNMPGET) set SNMPGET = ("snmpget" "is ""not" "available" "here")

if (! -e $DNSFILE || $?FORCE) then
	umask 0
	if ($?SOLARIS) then
	if ($?VERBOSE) echo `date +%T` ~watrous/host-l -r $CD $SERVER
	    ~watrous/host-l -r $CD $SERVER | egrep -i "has address" > $DNSFILE.new
#	    mv $DNSFILE.new $DNSFILE
# mv: cannot move ‘/tmp/whatson.rutgers.edu.dns.new’ to ‘/tmp/whatson.rutgers.edu.dns’: Operation not permitted
	    cp $DNSFILE.new $DNSFILE
	    rm -f $DNSFILE.new
	else
# The following is two steps so ^C doesn't leave null /tmp file
	    if ($?DEBUG) echo `date +%T` Doing zone transfer
#	    $HOSTPGM -l -t a $DOMAIN $DOMAINDNS | egrep -i "has address" > $DNSFILE.new
#	    foreach DOMAIN ( $OURDOMAINS )
#		$HOSTPGM -l -t a $DOMAIN $DOMAINDNS | egrep -i "has address" >> $DNSFILE.new
#	    end
	if ($?VERBOSE) echo `date +%T` ~watrous/host-l -r $DOMAIN
	    ~watrous/host-l -r $DOMAIN | egrep -i "has address" > $DNSFILE.new
#	    mv $DNSFILE.new $DNSFILE
	    cp $DNSFILE.new $DNSFILE
	    rm -f $DNSFILE.new
	endif
endif

set T = `echo $SUBNET | sed 's;\.; ;g'`

switch ($#T)
case 1:
    set TARGET = $T[1]"\."
    breaksw
case 2:
    set TARGET = $T[1]"\."$T[2]"\."
    breaksw
case 3:
    set TARGET = $T[1]"\."$T[2]"\."$T[3]"\."
    breaksw
case 4:
    set TARGET = $T[1]"\."$T[2]"\."$T[3]"\."
    set T2 = $T[4]
    breaksw
default:
    exec echo huh\?
    breaksw
endsw

if (! $?T2) set T2 = -1
if ($?DEBUG) echo TARGET = "$TARGET"

set T1 = $T[1].$T[2].$T[3]
if ($#T == 4) then
	set T2 = $T[4]
else
	set T2 = -1
endif

#	echo T1 = $T1 \; T2 = $T2

set TARGET = `echo $T1"." | sed -e 's;\.;\\\.;g' -e 's;\\\.\\\.;\\\.;'`
if ($?DEBUG) echo TARGET = "$TARGET"

if ($#T != 4 && ! $?GATEWAYS) then
    goto skipsnmp
else
#    if ($#SNMPGET > 1) then
#	if ($?VERBOSE) echo "$SNMPGET"
    if (! -e $SNMPWALK) then
	if ($?VERBOSE) echo $SNMPWALK does not exist
# /etc/netmasks does not exist on Linux boxes
      if (-e /etc/netmasks) then
	set XXX = `grep ^$T[1]\.0\.0\.0 /etc/netmasks | awk '{print $NF}'`
	if ("$XXX" != "") set NETMASK = $XXX
	set XXX = `grep ^$T[1]\.$T[2]\.0\.0 /etc/netmasks | awk '{print $NF}'`
	if ("$XXX" != "") set NETMASK = $XXX
	set XXX = `grep ^$T[1]\.$T[2]\.$T[3]\.0 /etc/netmasks | awk '{print $NF}'`
	if ("$XXX" != "") set NETMASK = $XXX
      else
	set NETMASK
      endif
	if ("$NETMASK" == "") then
	    if ($?DEBUG) echo Could not find netmask in /etc/netmasks
	    set NETMASK = "255.255.255.0"
	endif
	if ($?DEBUG) echo NETMASK = "$NETMASK"
	if ("$NETMASK" == "") then
	    set T2 = -1
	    goto skipsnmp
	endif
    endif
endif

if ($?VERBOSE) echo `date +%T` Looking for $TARGET in $DNSFILE "(gw)"
set GW = `grep -i "$TARGET" $DNSFILE | grep -i "[a-z0-9]-gw\." | sed "s;has address;;"`

# beginning of subnet:
# @ FOO = ( 192 & 65 ) ; echo $FOO
# size of subnet:
# @ FOO = ( 192 ^ 255 ) ; echo $FOO

# *************
while ($#GW)
if ($?VERBOSE) echo `date +%T` $GW[1] $GW[2]
if ($?VERBOSE) echo $PING $GW[1] $WAIT1SEC
$PING $GW[1] $WAIT1SEC >& /dev/null
if ($status) then
#    set NETMASK
    if ($?DEBUG) echo $GW[1] did not reply to ping
    if ($?PNETMASK) then
	set NETMASK = $PNETMASK
	set COMM
	goto fakednetmask
    else
	goto skipit
    endif
endif

#if ($#SNMPGET == 1) then
#if ($?VERBOSE) echo $SNMPGET -v 1 $GW[1] public ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.$GW[2]
#	set GNM = `$SNMPGET -v 1 $GW[1] public ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.$GW[2]`
if (-e $SNMPWALK) then
if ($?VERBOSE) echo $SNMPWALK -v 1 $GW[1] $SNMPCsw $COMMUNITY ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.$GW[2]
	set GNM = `$SNMPWALK -v 1 $GW[1] $SNMPCsw $COMMUNITY ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.$GW[2] |& grep .`
else
    set GNM = ("x" "x" "x" $NETMASK)
endif
if ($?DEBUG) echo GNM = $GNM
	if ($#GNM == 4 && $GNM[1] != "No" && $GNM[2] != "Response") then
		set NETMASK = $GNM[4]
if ($?DEBUG) echo NETMASK = $NETMASK
	else
		if (! $?PNETMASK || $?VERBOSE) then
		    echo Could not get netmask for $GW[2]
		    echo "$GNM" ; echo ""
		endif
		if ($?PNETMASK) then
		    set NETMASK = $PNETMASK
if ($?DEBUG) echo NETMASK = $NETMASK
		else
		    set NETMASK
if ($?DEBUG) echo NETMASK = $NETMASK
		endif
		goto skipit
	endif
#	echo "	"NETMASK = $NETMASK
#if ($#SNMPGET == 1) then
#if ($?VERBOSE)	echo $SNMPGET -v 1 $GW[1] public ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.$GW[2]
#	set GIND = `$SNMPGET -v 1 $GW[1] public ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.$GW[2]`
if (-e $SNMPWALK) then
if ($?VERBOSE)	echo $SNMPWALK -v 1 $GW[1] $SNMPCsw $COMMUNITY ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.$GW[2]
	set GIND = `$SNMPWALK -v 1 $GW[1] $SNMPCsw $COMMUNITY ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.$GW[2] | sed 's;INTEGER:;;'`
else
    set GIND = ( "x" "x" "x" )
endif
	if ($#GIND == 3) then
		set IND = $GIND[3]
	else
		echo Could not get interface index for $GW[2]
		echo "$GIND"
		set IND
		goto skipit
	endif
if ($?DEBUG) echo IND = $IND
#if ($#SNMPGET == 1) then
#if ($?VERBOSE) echo $SNMPGET -v 1 $GW[1] public 31.1.1.1.18.$IND 
#	set COMM = `$SNMPGET -v 1 $GW[1] public 31.1.1.1.18.$IND | sed -e 's;[^"]*";;' -e 's;";;' -e 's;[\[\(\)\{\}\?];_;g' -e 's;\];_;g'`
if (-e $SNMPWALK) then
if ($?VERBOSE) echo $SNMPWALK -v 1 $GW[1] $SNMPCsw $COMMUNITY ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifAlias.$IND 
	set COMM = `$SNMPWALK -v 1 $GW[1] $SNMPCsw $COMMUNITY ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifAlias.$IND | sed -e 's;.* = ;;' -e 's;STRING: ;;'`
else
	set COMM
endif
#	echo COMM = "$COMM"
fakednetmask:
	set HMask = `echo $NETMASK | sed 's;.*\.;;'`
#	echo HMask = $HMask
	set HN = `echo $GW[2] | sed 's;.*\.;;'`
#	echo HN = $HN
	@ H1 = ( $HMask & $HN )
#	echo H1 = $H1
	@ HMax = ( $HMask ^ 255 )
#	echo HMax = $HMax
	@ NO = $HMax + 1
	@ TOP = $H1 + $HMax
	if ($T2 >= $H1 && $T2 <= $TOP) then
		set STAR = "* "
		set LOWEST = $H1
		if (! $?HIGHEST) set HIGHEST = $TOP
		set FNETMASK = $NETMASK
	else
		set STAR
	endif
#	echo "$STAR$GW[1] ($GW[2]) $T1.$H1/$NO"
# Oops - that notation means something else
	if ($?GATEWAYS) then
	    echo "$STAR$GW[1] ($GW[2]) $T1.$H1 ($NO hosts)"
	    echo "    Netmask=$NETMASK"
	    echo "    Comment=$COMM"
	    echo ""
	endif
skipit:
	shift GW;shift GW
end
# *************

skipsnmp:

# if we specified netmask width and it doesn't match one we found, complain
if ($?FNETMASK && $?PNETMASK) then
    if ("$FNETMASK" != "$PNETMASK") then
	if (-w /dev/stderr) then
	    echo "/$MASKWID specified, implying netmask of $PNETMASK" >> /dev/stderr
	    echo "    but actual netmask is $FNETMASK"		  >> /dev/stderr
	else
	    echo "/$MASKWID specified, implying netmask of $PNETMASK"
	    echo "    but actual netmask is $FNETMASK"
	endif
    endif
endif

# test out other routine with limits
if ($?LOWEST) then
#    echo LOWEST = $LOWEST \; HIGHEST = $HIGHEST
#    echo ""
#    if (! $?REVERSE) set IP
    goto hinfo
endif

# now test out other routine for rest
#set IP
goto hinfo

#set TARGET = `echo $SUBNET"." | sed -e 's;\.;\\\.;g' -e 's;\\\.\\\.;\\\.;'`
#if ($?DEBUG) echo TARGET = "$TARGET"

if ($?HI || $?HV || $?HINFO) goto hinfo

if ($?VERBOSE) then
	grep -i "$TARGET" $DNSFILE
else if ($?REVERSE) then
	grep -i "$TARGET" $DNSFILE \
		| sed 's;\(.*\) has address .*\.\(.*\);\2: \1;' \
		| tr '[A-Z]' '[a-z]' \
		| sort -n
else
	grep -i "$TARGET" $DNSFILE \
		| sed 's;has address \(.*\);(\1);' \
		| tr '[A-Z]' '[a-z]' \
		| sort
endif

exit

hinfo:

#get list of potential hosts

if ($?DEBUG) echo `date +%T` Creating initial list of hosts

#set PHOSTS = `grep -i "$TARGET" $DNSFILE | tee $TMPDNSFILE | sed 's; .*;;' | tr '[A-Z]' '[a-z]' | sort -u`
# avoid *.legion.oit-nbcs.rutgers.edu ; 1/18/19
set PHOSTS = `grep -i "$TARGET" $DNSFILE | tee $TMPDNSFILE | sed 's; .*;;' | tr '[A-Z]' '[a-z]' | sort -u | sed 's;\*;_AST_;g'`

if ($?DEBUG) echo PHOSTS = $PHOSTS

if ($?DEBUG) echo `date +%T` Done creating initial list of hosts

if ($?HI) then
if ($?DEBUG) echo `date +%T` Selecting hosts with hinfo containing \"$HI\"
    set NPHOSTS

    foreach HOST ( $PHOSTS )
#	/usr/local/bin/host -t hinfo $HOST | grep $HI > /dev/null
# hinfo now moved to TXT records; 7/05
	$HOSTPGM -t txt $HOST | grep -i HINFO: | grep $HI > /dev/null
	if (! $status) set NPHOSTS = ( $NPHOSTS $HOST )
    end

    set PHOSTS = ( $NPHOSTS )

#    echo PHOSTS = $PHOSTS
endif

if ($?HV) then
if ($?DEBUG) echo `date +%T` Removing hosts with hinfo containing "$HV"
    set NPHOSTS

    foreach HOST ( $PHOSTS )
#if ($?DEBUG) echo "	$HOST"
#	set THINFO = `/usr/local/bin/host -t hinfo $HOST |& egrep "$HV"`
# hinfo now moved to TXT records; 7/05
	set THINFO = `$HOSTPGM -t txt $HOST |& grep -i HINFO: | egrep "$HV"`

#if ($?DEBUG) echo $#THINFO, $THINFO
	if (! $#THINFO) then
#	    if ($?DEBUG) echo "	Adding $HOST to the list"
	    set NPHOSTS = ( $NPHOSTS $HOST )
	endif
    end

    set PHOSTS = ( $NPHOSTS )

#    echo PHOSTS = $PHOSTS
endif

if ($?DEBUG) echo `date +%T` Processing list of $#PHOSTS

foreach HOST ( $PHOSTS )
    set COMMA = ", "
    if ($?CRISPIN) then
	set HOST = `echo $HOST | sed "s;.$DOMAIN;;"`
	set COMMA = "	"
    endif
    set AHOST = "`echo $HOST | sed 's;_AST_;*;'`"
    if ($?DEBUG) echo AHOST = "$AHOST"
    set IPINF
#    if ($?IP) set IPINF = "$COMMA"`grep -iw $HOST $TMPDNSFILE | sed 's;.*address ;;'`
#    if ($?IP) set IPINF = "$COMMA"`grep "^$HOST" $TMPDNSFILE | sed 's;.*address ;;'`
    if ($?IP) set IPINF = "$COMMA"`grep -i "^$HOST " $TMPDNSFILE | sed 's;.*address ;;'`
    set HINF
#    if ($?HINFO) set HINF = "$COMMA"`/usr/local/bin/host -t hinfo $HOST | sed 's;.*host information;;'`
# hinfo now moved to TXT records; 7/05
    if ($?HINFO) set HINF = "$COMMA"`$HOSTPGM -t txt $HOST | grep -i HINFO: | sed 's;.*host information;;'`
    set LOCINF
    if ($?LOC) set LOCINF = "$COMMA"`$HOSTPGM -t txt $HOST | grep Location | sed -e 's;.*Location:;;' -e 's; Campus.*;;'`
    if ($?REVERSE || $?LOWEST) then
#	set HNS = `grep -iw $HOST $TMPDNSFILE | sed 's;.*\.;;'`
#	set HNS = `grep "^$HOST" $TMPDNSFILE | sed 's;.*\.;;'`
#	set HNS = `grep -i "^$HOST " $TMPDNSFILE | sed 's;.*\.;;'`
	set HNS = `grep -i "^$AHOST " $TMPDNSFILE | sed 's;.*\.;;'`
if ($?DEBUG) then
	echo $HOST, $HNS
	if ($?LOWEST) then
	        echo LOWEST = $LOWEST \; HIGHEST = $HIGHEST
	else
		echo LOWEST is not defined
	endif
endif
# "whatson 128.6.26 -r" produced "HN: Undefined variable"
	set HN = ( $HNS )
    endif
    unset OUTPUT
    if ($?LOWEST) then
	foreach HN ( $HNS )
	    if ($HN > $LOWEST && $HN <= $HIGHEST) then
		set OUTPUT
		break
	    endif
 	end
	
    else
if ($?DEBUG) echo LOWEST not defined
	set OUTPUT
    endif
    if ($?OUTPUT) then
	if ($?REVERSE) then
	    echo ${HN}: "$AHOST$IPINF""$HINF""$LOCINF" >> $REV
	else
#	    echo $HOST"$IPINF""$HINF""$LOCINF"
	    echo "$AHOST$IPINF""$HINF""$LOCINF"
	endif
    endif
end

if ($?REVERSE) then
    sort -n $REV
    if (! $?KEEP) /bin/rm -f $REV
endif

if (! $?KEEP) /bin/rm -f $TMPDNSFILE
