#!/bin/sh # # Copyright (C) 2011 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # \file # This file should be run by all IXFR tests before doing anything else. It # includes the main configuration script to set the environment variables as # well as defining useful shell subroutines. . @abs_top_builddir@/tests/system/conf.sh # Useful symbols used in the IXFR tests. # Short-hand for getting SOA - just supply address of the server DIG_SOA="$DIG +norecurse +short -p $DNS_PORT example. SOA" # All IXFR tests use a BIND 9 server serving a BIND 10 client. These have the # smae name and use the same address in all tests. SERVER_NAME=ns1 SERVER_IP=10.53.0.1 # BIND 9 CLIENT_NAME=nsx2 CLIENT_IP=10.53.0.2 # BIND 10 # \brief Check Arguments # # Most functions take the name of nameserver as the first argument and its IP # address as the second. This function is passed "$*" and just checks that # both $1 and $2 are defined. # # \arg $* Arguments passed to caller # # \return status 0 => $1 and $2 are defined, 1 => they are not. check_name_ip() { if [ "$1" = "" ]; then echo "R:FAIL name of server not supplied" return 1 fi if [ "$2" = "" ]; then echo "R:FAIL IP address of server not supplied" return 1 fi return 0 } # \brief Perform RNDC Command # # Controls the BIND 9 IXFR server. Called do_rndc (instead of rndc) to avoid # confusion if rndc itself is in the search path. # # \arg $1 - Name of the server (ns1, nsx2 etc.) # \arg $2 - IP address of the server # \arg $* - Command to execute (which may be multiple tokens) # # \return 0 on success, 1 on failure (in which case an error message will # have been output). do_rndc () { # If the following checks fail, the code is wrong. check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL do_rndc - name or ip address of server not supplied" return 1 fi name=$1 shift ip=$1 shift if [ "$1" = "" ]; then echo "R:FAIL do_rndc - rndc command not supplied" return 1 fi $RNDC -c $SYSTEM_TOP/common/rndc.conf -s $ip -p $RNDC_PORT $* 2>&1 \ | sed "s/^/I:$name /" } # \brief Wait for update # # Given a serial number and a server, poll the nameserver until the SOA serial # number is different from that given. The poll takes place every five seconds # for a minute. # # \arg $1 - Name of the server # \arg $2 - IP address of the server # \arg $3 - Serial number to check against # # \return 0 if the serial number is different (requires another poll to obtain # it), 1 if the serial number has not changed after one minute. wait_for_update() { # If the following checks fail, the code is wrong. check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL wait_for_update - name or ip address of system not supplied" return 1 fi name=$1 shift ip=$1 shift serial=$1 if [ "$serial" = "" ]; then echo "R:FAIL wait_for_update - serial number not supplied" return 1 fi # Now poll the server looking for the new serial number echo "I:$name waiting for SOA serial to change from $serial" for i in 1 2 3 4 5 6 7 8 9 10 11 12 do if [ $i -gt 1 ]; then sleep 5 fi new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'` if [ "$new_serial" != "$serial" ]; then echo "I:$name SOA serial was at $serial, now at $new_serial" return 0 fi done echo "R:$name FAIL serial number has not updated" return 1 } # \brief Update server zone # # Reloads the example. zone in the BIND 9 IXFR server and waits a maximum of # one minute for it to be served. # # \arg $1 - Name of the server (ns1, nsx2 etc.) # \arg $2 - IP address of the server # \arg $3 - Zone file to load # \arg $* - Command to execute (which may be multiple tokens) # # \return 0 on success, 1 on failure (for which an error message will have # been output). update_server_zone() { # If the following checks fail, the code is wrong. check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL update_server_zone - name or ip address of server not supplied" return 1 fi name=$1 shift ip=$1 shift file=$1 shift if [ "$file" = "" ]; then echo "R:FAIL update_server_zone - new zone file not supplied" return 1 fi if [ ! -e $file ]; then echo "R:FAIL update_server_zone - zone file does not exist: $file" return 1 fi old_serial=`$DIG_SOA @$ip | $AWK '{print $3}'` echo "I:$name IXFR server loading $file" cp $file $name/db.example do_rndc $name $ip reload if [ $? -ne 0 ]; then return 1 # Message will have already been output fi wait_for_update $name $ip $old_serial if [ $? -ne 0 ]; then echo "R:$name FAIL IXFR server did not update zone after reload" return 1 fi new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'` return 0 } # \brief Compare client and server SOAs # # Checks the SOAs of two systems and reports if they are not equal. # # \arg $1 Name of the IXFR server # \arg $2 IP of the IXFR server # \arg $3 Name of the IXFR client # \arg $4 IP of the IXFR client # # \return 0 if the systems have the same SOA, 1 if not. In the latter case, # an error will be output. compare_soa() { # If the following checks fail, the code is wrong. check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL compare_soa - name or ip address of server not supplied" return 1 fi server_name=$1 shift server_ip=$1 shift check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL compare_soa - name or ip address of client not supplied" return 1 fi client_name=$1 shift client_ip=$1 shift client_serial=`$DIG_SOA @$client_ip | $AWK '{print $3}'` server_serial=`$DIG_SOA @$server_ip | $AWK '{print $3}'` if [ "$client_serial" != "$server_serial" ]; then echo "R:FAIL client $client_name serial $client_serial not same as server $server_name serial $server_serial" return 1 fi return 0 } # \brief Compare client and server zones # # Checks the zones of two systems and reports if they are not identical. # # The check is simplistic. Each zone is listed via "dig", after which comment # lines, blank lines and spaces/tabs are removed, and the result sorted. The # output from each system is then compared. They should be identical. # # \arg $1 Name of the IXFR server # \arg $2 IP of the IXFR server # \arg $3 Name of the IXFR client # \arg $4 IP of the IXFR client # # \return 0 if the zones are the same, 1 if not. compare_zones() { # If the following checks fail, the code is wrong. check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL compare_zones - name or ip address of server not supplied" return 1 fi server_name=$1 shift server_ip=$1 shift check_name_ip $* if [ $? -ne 0 ]; then echo "R:FAIL compare_zones - name or ip address of client not supplied" return 1 fi client_name=$1 shift client_ip=$1 shift $DIG @$client_ip -p $DNS_PORT example. axfr | grep -v '^;' | grep -v '^$' \ | sed -e 's/ //g' -e 's/\t//g' | sort > client.dig $DIG @$server_ip -p $DNS_PORT example. axfr | grep -v '^;' | grep -v '^$' \ | sed -e 's/ //g' -e 's/\t//g' | sort > server.dig diff client.dig server.dig if [ $? -eq 0 ]; then echo "I:client and server zones identical" else echo "R:FAIL client $client_name zone not same as server $server_name zone" return 1 fi return 0 }