#!/usr/bin/env bash # - Sets new serial and reloads zone # - # - Return (Exit) Codes: # - success: # - 0: Serial is replaced and Zone is reloaded # - error: # - 10: Invalid Hostname/Domain given # - 15: Hostname/Domain not supported # - 11: No zonefile found # - 12: Determin new Serial failed # - 13: Increasing Serial failed # - 14: Reloading Zone failed # - 99: Fatal error # - # - usage: ./nd_set_new_serial.sh # - # - example: ./nd_set_new_serial.sh a.mx.open.de # - ## -- Variable definitions ## -- # - Bind configuration file containing zone definitions # - ZONE_CONF_FILE=/etc/bind/named.conf.local BIND_USER=bind BIND_GROUP=bind ## -- ## -- End: Variable definitions ## *** ## *** Don't make changes after this line *** ## *** ## --- some functions ## --- echononl(){ echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n "$*\\c" 1>&2 else echo -e -n "$*" 1>&2 fi rm /tmp/shprompt$$ } fatal(){ echo "" echo -e "[ \033[31m\033[1mError\033[m ]: $*" echo "" echo -e "\t\033[31m\033[1mScript is canceled\033[m\033[m" echo "" exit 1 } warn (){ echo "" echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" echo "" } info (){ echo "" echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" echo "" } ok (){ echo "" echo -e "\t[ \033[36m\033[1mOk\033[m ]: $*" echo "" } error(){ echo "" echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*" echo "" } echo_ok() { echo -e "\033[75G[ \033[32mok\033[m ]" } echo_failed(){ echo -e "\033[75G[ \033[1;31mfailed\033[m ]" } echo_skipped() { echo -e "\033[75G[ \033[33m\033[1mskipped\033[m ]" } containsElement () { local e for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done return 1 } ## --- ## --- END: functions # - Parameter "check" can be used, to test whether this script # - is accessable (e.g. from a script on a remote host) # - if [[ "$1" = "check" ]]; then echo "\$1: $1" exit 0 fi host_name=$1 echo "" # - Validate Syntax of given domain # - valid_domain_regex="^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$" echononl "\tValidate syntax of given domain.." if [[ $host_name =~ $valid_domain_regex ]]; then if [[ ! $host_name =~ \. ]]; then echo_failed error "Invalid hostname/domain \"$1\" given!" exit 10 else echo_ok fi else echo_failed error "Invalid hostname/domain ($1) given!" exit 10 fi # - Determin zone (domain) # - _failed=false _host_name=$host_name _tmp_host_name=$(echo ${_host_name//\./\\.}) while ! grep -e "$_tmp_host_name" $ZONE_CONF_FILE > /dev/null 2>&1 ; do _host_name=${_host_name#*.} _tmp_host_name=$(echo ${_host_name//\./\\.}) if [[ ! $_tmp_host_name =~ \. ]]; then _failed=true break fi done if $_failed ; then error "Given hostname/domain \"$1\" not supported by this nameserver!" else domain=$_host_name fi # - Determine zonefile (by reading bind configuration) # - _found=false declare -i _number=0 regex_zone="^[[:space:]]*zone[[:space:]]+\"$_tmp_host_name\"" regex_file="^[[:space:]]*file" while IFS='' read -r line || [[ -n "$line" ]] ; do if [[ $line =~ $regex_zone ]]; then _found=true fi if $_found ; then if [[ $line =~ $regex_file ]]; then zone_file=`echo $line | awk '{print$2}'` shopt -s extglob if [[ $zone_file =~ \; ]]; then zone_file=${zone_file%%*(\;)} fi if [[ $zone_file =~ ^\" ]]; then zone_file=${zone_file##*(\")} zone_file=${zone_file%%*(\")} fi shopt -u extglob let number++ break fi fi done < $ZONE_CONF_FILE zone_file_dir=`dirname $zone_file` if [[ $number -eq 0 ]] ; then error "No Zonefile (master) found for domain \"$domain\" ." exit 11 fi echononl "\tBackup existing directory containg zonefiles.." if [[ -d "$zone_file_dir" ]] ; then cp -a $zone_file_dir ${zone_file_dir}.BAK.`date +%Y-%m-%d-%H%M` if [[ $? -eq 0 ]]; then echo_ok else echo_failed echo "" exit 99 fi else echo_failed error "Zonefile directory not found for domain \"$domain\" ." exit 99 fi # - Determin new serial # - echononl "\tDetermin new serial.." _failed=false declare -i serial_new=`date +%Y%m%d01` serial_cur=`grep -e "^\s*[0-9]\{10\}" $zone_file | grep serial | awk '{print$1}'` if [[ $? -gt 0 ]] ; then _failed=true fi while [ ! $serial_new -gt $serial_cur ]; do let serial_new++ done if [[ $? -gt 0 ]] ; then _failed=true fi if $_failed ; then echo_failed error "Determin Serial failed!" exit 12 else echo_ok fi # - Replace serial with the new one # - echononl "\tIncrease serial for zone file \"`basename $zone_file`\".." perl -i -n -p -e "s#^(\s*)\s$serial_cur(.*)#\1 $serial_new\2#" $zone_file > /dev/null 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "Increasing Serial failed!" exit 13 fi echo "" echononl "\tCorrect Owner for $zone_file .." chown $BIND_USER:$BIND_GROUP $zone_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed exit 99 fi echononl "\tCorrect permissions on $zone_file .." chmod 644 $zone_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed exit 99 fi # - Reload Zone # - echononl "\tReloading zone \"$domain\".." rndc reload $domain > /dev/null 2>&1 if [[ $? -eq 0 ]]; then echo_ok info "Serial increased and zone reloaded ($domain)" exit 0 else echo_failed error "Increasing Serial failed!" exit 13 fi echo exit 99