From 8f21a75f671b652fe6d66ea92dbb10837680f851 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Fri, 31 Aug 2012 11:06:07 -0600 Subject: [PATCH] Add DNS entries to the hosts "ctrladdr" knows about. (By fetching a zone transfer for $OURDOMAIN, and hunting through it for addresses on the control network.) --- configure | 45 ++++++++++++++++++++++++++++++++++++-- configure.in | 1 + utils/ctrladdr.in | 55 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/configure b/configure index a4c5d4cb5..ef426e1d9 100755 --- a/configure +++ b/configure @@ -698,6 +698,7 @@ CXX AR RANLIB STRIP +DIG ELVIN_CONFIG JAVAC JAR @@ -4442,6 +4443,46 @@ fi +# Extract the first word of "dig", so it can be a program name with args. +set dummy dig; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_DIG+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $DIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_DIG="$DIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +DIG=$ac_cv_path_DIG +if test -n "$DIG"; then + { $as_echo "$as_me:$LINENO: result: $DIG" >&5 +$as_echo "$DIG" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + # Extract the first word of "elvin-config", so it can be a program name with args. set dummy elvin-config; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 @@ -7429,7 +7470,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ utils/spewconlog utils/xlogin \ utils/opsdb_control utils/opsdb_control.proxy \ utils/remove_old_www utils/epmodeset \ - utils/mkblob utils/rmblob \ + utils/mkblob utils/rmblob utils/ctrladdr \ www/GNUmakefile www/defs.php3 www/dbdefs.php3 www/xmlrpc.php3 \ www/xmlrpcpipe.php3 \ www/swish.conf www/websearch \ @@ -7568,7 +7609,7 @@ outfiles="$outfiles clientside/GNUmakefile \ clientside/tmcc/freebsd10/GNUmakefile clientside/tmcc/freebsd10/netif-emulab \ clientside/tmcc/cygwinxp/GNUmakefile clientside/tmcc/dp/GNUmakefile \ clientside/tmcc/openbsd/GNUmakefile clientside/tmcc/ron/GNUmakefile \ - clientside/tmcc/plab/GNUmakefile \ + clientside/tmcc/plab/GNUmakefile clientside/tmcc/cygwinseven/GNUmakefile \ clientside/os/dijkstra/GNUmakefile clientside/os/genhostsfile/GNUmakefile \ clientside/os/growdisk/GNUmakefile \ clientside/os/zapdisk/GNUmakefile \ diff --git a/configure.in b/configure.in index 106ba15f8..1cf38041e 100755 --- a/configure.in +++ b/configure.in @@ -86,6 +86,7 @@ AC_CHECK_TOOL(STRIP,strip) AC_EXEEXT +AC_PATH_PROG(DIG,dig) AC_PATH_PROG(ELVIN_CONFIG,elvin-config) AC_PATH_PROG(JAVAC,javac) AC_PATH_PROG(JAR,jar) diff --git a/utils/ctrladdr.in b/utils/ctrladdr.in index 84ac8aa8d..c38e3a615 100755 --- a/utils/ctrladdr.in +++ b/utils/ctrladdr.in @@ -6,6 +6,26 @@ # All rights reserved. # +# +# Show (un)allocated addresses on the control net. +# +# By default, the output is supposed to be easy to parse and simply +# displays the first available address. More than one available address +# can be requested with the "-n" option (e.g. "-n 10" will show the +# first ten unallocated addresses). "-n 0" will show every free +# address on the subnet. +# +# The "-a" option (meant more for human consumption) also describes +# allocated addresses. For instance, "ctrladdr -a -n 0" will show +# every address on the control net, and what it's used for (if +# anything). "-r" will compress ranges of consecutive free addresses +# onto a single line. +# +# To test whether a particular address is in use, invoke it as (e.g.) +# "ctrladdr -t 155.98.36.1". This will give an exit code of 0 if the +# address is available, and 1 if used. Any other options are ignored +# if "-t" is specified. + use English; use Getopt::Std; use strict; @@ -17,6 +37,8 @@ use Socket; my $TB = "@prefix@"; my $control_network = "@CONTROL_NETWORK@"; my $control_netmask = "@CONTROL_NETMASK@"; +my $DIG = "@DIG@"; +my $ourdomain = "@OURDOMAIN@"; # # Turn off line buffering on output @@ -72,6 +94,10 @@ if( $options{ 'r' } ) { usage() unless @ARGV == 0; + +my $net = unpack( "N", inet_aton( $control_network ) ); +my $mask = unpack( "N", inet_aton( $control_netmask ) ); + my %used = (); sub show($) { @@ -97,13 +123,34 @@ sub range_done($) { } else { print inet_ntoa( pack( "N", $range_start ) ) . "-" . inet_ntoa( pack( "N", $i - 1 ) ) . " (" . - ( $i - 1 - $range_start ) . " addresses)\n"; + ( $i - $range_start ) . " addresses)\n"; } $range_start = undef; } } +# +# Populate the set of known addresses. +# +if( open( DNS, "$DIG -t axfr $ourdomain |" ) ) { + while( ) { + if( /^([-a-zA-Z0-9.]+)\.\s+[0-9]+\s+IN\s+A\s+([0-9.]+)/ ) { + my $dns_name = $1; + my $dns_addr = $2; + my $dns_addr_num = unpack( "N", inet_aton( $2 ) ); + + if( ( $dns_addr_num & $mask ) == $net ) { + $used{ $dns_addr } = $dns_name; + } + } + } + close( DNS ); +} else { + print STDERR "Could not read zone transfer\n"; + exit( 1 ); +} + my $result = DBQueryWarn( "SELECT IP, node_id FROM interfaces WHERE " . "role='ctrl';" ); if( !$result ) { @@ -129,12 +176,12 @@ while( my( $IP ) = $result->fetchrow_array() ) { # XXX Find any other addresses which are allocated, and add them to %used -my $net = unpack( "N", inet_aton( $control_network ) ); -my $mask = unpack( "N", inet_aton( $control_netmask ) ); - $used{ inet_ntoa( pack( "N", $net ) ) } = "the network"; $used{ inet_ntoa( pack( "N", $net | ~$mask ) ) } = "broadcast"; +# +# The list is complete... ready to compute the output. +# if( $test ) { my $t = unpack( "N", inet_aton( $test ) ); -- GitLab