From f91c31b250ebc57af96ba9ac1e3c33372e1258f1 Mon Sep 17 00:00:00 2001 From: Christoph Date: Mon, 25 Dec 2023 00:30:04 +0100 Subject: [PATCH] Add scripts bind_change_ip.sh'' and 'bind_change_ip.sh'. --- bind_change_ip.sh | 76 +++- bind_change_ttl.sh | 91 +++- conf/tmp_bind.conf,sample | 85 ++++ tmp_bind_change_ip.sh | 855 ++++++++++++++++++++++++++++++++++++++ tmp_bind_change_ttl.sh | 852 +++++++++++++++++++++++++++++++++++++ 5 files changed, 1945 insertions(+), 14 deletions(-) create mode 100644 conf/tmp_bind.conf,sample create mode 100755 tmp_bind_change_ip.sh create mode 100755 tmp_bind_change_ttl.sh diff --git a/bind_change_ip.sh b/bind_change_ip.sh index 029132d..b145b32 100755 --- a/bind_change_ip.sh +++ b/bind_change_ip.sh @@ -393,6 +393,36 @@ done [[ $OK = "yes" ]] && IGNORE_ALT_HOSTNAMES=true +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Ignore Hostnames \"autoconfig\" (as autoconfig.oopen.de)" +echo "" +echo " Type 'return' for the yellow highlighted one.." +echo "" +OK= +IGNORE_AUTOCONFIG_HOSTNAMES=false +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Ignore Hostnames \"autoconfig.\"? [\033[33m\033[1myes\033[m/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + OK='yes' + #echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + #OK="" + #continue + fi + if [ "$OK" = "yes" -o "$OK" = "no" ] ; then + break + else + OK="" + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] && IGNORE_AUTOCONFIG_HOSTNAMES=true + + echo "" echo "" echo -e "\033[32m--\033[m" @@ -494,6 +524,7 @@ else fi echo "" echo "Ignore hostnames containing \"-alt\"/\"-neu\"..: $IGNORE_ALT_HOSTNAMES" +echo "Ignore hostnames \"autoconfig.\".....: $IGNORE_AUTOCONFIG_HOSTNAMES" echo "" echo "Bind Configuration Directory...............: $CONF_FILE_DIR" echo "Zones Declaration File.....................: $ZONES_DECLARATION_FILE" @@ -538,6 +569,7 @@ echo -e "\033[37m\033[1mDetermine zone files conatining ip-adressse requested fo _found=false _is_master=false zonefiles_arr=() +zonefiles_not_present_arr=() zone_file="" regex_master="type[[:space:]]+master" regex_file="^[[:space:]]*file" @@ -569,6 +601,16 @@ while IFS='' read -r _line || [[ -n $_line ]] ; do fi shopt -u extglob fi + + if [[ -n "${zone_file}" ]] ; then + if [[ ! -f "${zone_file}" ]] ; then + if ! containsElement "${zone_file}" "${zonefiles_not_present_arr[@]}" ; then + zonefiles_not_present_arr+=("${zone_file}") + fi + continue + fi + fi + if [[ $_line =~ $regex_master ]]; then _is_master=true fi @@ -611,8 +653,6 @@ done < "$ZONES_DECLARATION_FILE" echo "" - - for _val in ${zonefiles_arr[@]} ; do IFS=':' read -a _val_arr <<< "${_val}" @@ -620,6 +660,11 @@ for _val in ${zonefiles_arr[@]} ; do zone_file="${_val_arr[0]}" zone="${_val_arr[1]}" + if [[ ! -f "${zone_file}" ]]; then + warn "Zonefile \033[1m$zone_file\033[m no fount!" + continue + fi + echo -e "\tEditing \033[1m$zone_file\033[m .." _replaced=false @@ -644,12 +689,20 @@ for _val in ${zonefiles_arr[@]} ; do fi fi + if $IGNORE_AUTOCONFIG_HOSTNAMES ; then + + perl -i -n -p -e "s#^\s*(autoconfig.*)\s+IN\s+A\s+$IPv4_ADDRESS_OLD#\1 IN A 888.888.888.888#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + fi + perl -i -n -p -e "s#IN\s+A\s+$IPv4_ADDRESS_OLD#IN A $IPv4_ADDRESS_NEW#" $zone_file > /dev/null 2>&1 if [[ $? -gt 0 ]]; then _failed=true fi - if $IGNORE_ALT_HOSTNAMES ; then + if $IGNORE_ALT_HOSTNAMES || $IGNORE_AUTOCONFIG_HOSTNAMES ; then perl -i -n -p -e "s#IN\s+A\s+888.888.888.888#IN A $IPv4_ADDRESS_OLD#" $zone_file > /dev/null 2>&1 if [[ $? -gt 0 ]]; then @@ -690,12 +743,19 @@ for _val in ${zonefiles_arr[@]} ; do fi fi + if $IGNORE_AUTOCONFIG_HOSTNAMES ; then + perl -i -n -p -e "s#^\s*(autoconfig.*)\s+IN\s+AAAA\s+$IPv6_ADDRESS_OLD#\1 IN AAAA 88:88:88::88#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + fi + perl -i -n -p -e "s#IN\s+AAAA\s+$IPv6_ADDRESS_OLD#IN AAAA $IPv6_ADDRESS_NEW#" $zone_file if [[ $? -gt 0 ]]; then _failed=true fi - if $IGNORE_ALT_HOSTNAMES ; then + if $IGNORE_ALT_HOSTNAMES || $IGNORE_AUTOCONFIG_HOSTNAMES ; then perl -i -n -p -e "s#IN\s+AAAA\s+88:88:88::88#IN AAAA $IPv6_ADDRESS_OLD#" $zone_file > /dev/null 2>&1 if [[ $? -gt 0 ]]; then @@ -777,6 +837,14 @@ if [[ -d "${ZONE_FILE_MASTER_DIR}.${backup_date}" ]] ; then fi fi +if [[ ${#zonefiles_not_present_arr[@]} -gt 0 ]] ; then + echo "" + warn "The following zonefiles were not found!" + for _val in ${zonefiles_not_present_arr[@]} ; do + echo -e "\t $_val" + done +fi + echo "" clean_up 0 diff --git a/bind_change_ttl.sh b/bind_change_ttl.sh index df21dae..608c870 100755 --- a/bind_change_ttl.sh +++ b/bind_change_ttl.sh @@ -324,6 +324,36 @@ done [[ $OK = "yes" ]] && IGNORE_ALT_HOSTNAMES=true +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Ignore Hostnames \"autoconfig\" (as autoconfig.oopen.de)" +echo "" +echo " Type 'return' for the yellow highlighted one.." +echo "" +OK= +IGNORE_AUTOCONFIG_HOSTNAMES=false +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Ignore Hostnames \"autoconfig.\"? [yes/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + OK='yes' + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + OK="" + continue + fi + if [ "$OK" = "yes" -o "$OK" = "no" ] ; then + break + else + OK="" + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] && IGNORE_AUTOCONFIG_HOSTNAMES=true + + echo "" echo "" echo -e "\033[32m--\033[m" @@ -425,24 +455,25 @@ echo "" echo "" if $_set_ipv4 ; then - echo "IPv4 Address(es)..................: $IPv4_ADDRESS" + echo "IPv4 Address(es)........................: $IPv4_ADDRESS" else - echo -e "IPv4 Address(es)..................: \033[33mNone\033[m" + echo -e "IPv4 Address(es)........................: \033[33mNone\033[m" fi if $_set_ipv6 ; then - echo "IPv6 Address(es)..................: $IPv6_ADDRESS" + echo "IPv6 Address(es)........................: $IPv6_ADDRESS" else - echo -e "IPv6 Address(es)..................: \033[33mNone\033[m" + echo -e "IPv6 Address(es)........................: \033[33mNone\033[m" fi echo "" -echo "New TTL...........................: $TTL" +echo "New TTL.................................: $TTL" echo "" -echo "Ignore hostnames containing \"-alt\": $IGNORE_ALT_HOSTNAMES" +echo "Ignore hostnames containing \"-alt\"......: $IGNORE_ALT_HOSTNAMES" +echo "Ignore hostnames \"autoconfig.\"..: $IGNORE_AUTOCONFIG_HOSTNAMES" echo "" -echo "Bind Configuration Directory......: $CONF_FILE_DIR" -echo "Zones Declaration File............: $ZONES_DECLARATION_FILE" -echo "Zone File Directory...............: $ZONE_FILE_MASTER_DIR" -#echo "Zone File Suffix..................: $ZONE_FILE_SUFFIX" +echo "Bind Configuration Directory............: $CONF_FILE_DIR" +echo "Zones Declaration File..................: $ZONES_DECLARATION_FILE" +echo "Zone File Directory.....................: $ZONE_FILE_MASTER_DIR" +#echo "Zone File Suffix........................: $ZONE_FILE_SUFFIX" echo "" OK= @@ -535,6 +566,7 @@ echo -e "\033[37m\033[1mDetermine zone files conatining ip-adressse for which TT _found=false _is_master=false zonefiles_arr=() +zonefiles_not_present_arr=() zone_file="" regex_master="type[[:space:]]+master" regex_file="^[[:space:]]*file" @@ -566,6 +598,16 @@ while IFS='' read -r _line || [[ -n $_line ]] ; do fi shopt -u extglob fi + + if [[ -n "${zone_file}" ]] ; then + if [[ ! -f "${zone_file}" ]] ; then + if ! containsElement "${zone_file}" "${zonefiles_not_present_arr[@]}" ; then + zonefiles_not_present_arr+=("${zone_file}") + fi + continue + fi + fi + if [[ $_line =~ $regex_master ]]; then _is_master=true fi @@ -669,6 +711,16 @@ for _val in ${zonefiles_arr[@]} ; do error "Setting back hostnames containing \"-alt\" for $_ipv4_address in zone file \"$zone_file\" failed!" fi fi + if $_replaced && $IGNORE_AUTOCONFIG_HOSTNAMES ; then + echononl "\t Setting back hostnames \"autoconfig.\".." + perl -i -n -p -e "s#^(\s*autoconfig\s+)$TTL\s+IN\s+A\s+$_ipv4_address#\1IN A $_ipv4_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Setting back hostnames containing \"-alt\" for $_ipv4_address in zone file \"$zone_file\" failed!" + fi + fi fi done fi @@ -707,6 +759,16 @@ for _val in ${zonefiles_arr[@]} ; do error "Setting back hostnames containing \"-alt\" for $_ipv6_address in zone file \"$zone_file\" failed!" fi fi + if $_replaced && $IGNORE_AUTOCONFIG_HOSTNAMES ; then + echononl "\t Setting back hostnames \"autoconfig.\".." + perl -i -n -p -e "s#^(\s*autoconfig\s+)$TTL\s+IN\s+AAAA\s+$_ipv6_address#\1IN AAAA $_ipv6_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Setting back hostnames containing \"-alt\" for $_ipv6_address in zone file \"$zone_file\" failed!" + fi + fi fi done fi @@ -771,5 +833,14 @@ if [[ -d "${ZONE_FILE_MASTER_DIR}.${backup_date}" ]] ; then fi fi +if [[ ${#zonefiles_not_present_arr[@]} -gt 0 ]] ; then + echo "" + warn "The following zonefiles were not found!" + for _val in ${zonefiles_not_present_arr[@]} ; do + echo -e "\t $_val" + done +fi + + echo "" clean_up 0 diff --git a/conf/tmp_bind.conf,sample b/conf/tmp_bind.conf,sample new file mode 100644 index 0000000..fb995f3 --- /dev/null +++ b/conf/tmp_bind.conf,sample @@ -0,0 +1,85 @@ +# ---------------------------------------------------- +# --- +# - Parameter Settings for bind administration scripts. +# --- +# ---------------------------------------------------- + + +# - BIND_USER +# - +# - The user under which the nameservice is running +# - +# - Defaults to 'bind' +# - +#BIND_USER="bind" + + +# - BIND_GROUP +# - +# - The group under which the nameservice is running +# - +# - Defaults to 'bind' +# - +#BIND_GROUP="bind" + + +# - CONF_FILE_DIR +# - +# - Directory containing bind configuration files +# - +# - Defaults to "/root/tmp/bind" +# - +#CONF_FILE_DIR="/root/tmp/bind" + + +# - ZONE_FILE_MASTER_DIR +# - +# - Directory containing the zone files (master) +# - +# - Defaults to "${CONF_FILE_DIR}/master" +# - +#ZONE_FILE_MASTER_DIR="${CONF_FILE_DIR}/master" + + +# - ZONE_FILE_SLAVE_DIR +# - +# - Directory containing the zone files (slave) +# - +# - Defaults to "${CONF_FILE_DIR}/slave" +# - +#ZONE_FILE_SLAVE_DIR="${CONF_FILE_DIR}/slave" + + +# - ZONE_FILE_SUFFIX +# - +# - Defaults to 'zone' +# - +#ZONE_FILE_SUFFIX="zone" + + +# - ZONES_DECLARATION_FILE +# - +# - File containing zone declarations +# - +# - Defaults to ${CONF_FILE_DIR}/named.conf.local +# - +#ZONES_DECLARATION_FILE="${CONF_FILE_DIR}/named.conf.local" + + + +# ----- +# - bind_change_SOA.sh +# ----- + +# - SOA_PRIMARY_MASTER +# - +# - Primary master for all zones +# - +SOA_PRIMARY_MASTER="a.ns.oopen.de" + +# - SOA_ADMIN_EMAIL +# - +# - mail address of the responsible of all zones +# - +SOA_ADMIN_EMAIL="domreg@oopen.de" + diff --git a/tmp_bind_change_ip.sh b/tmp_bind_change_ip.sh new file mode 100755 index 0000000..a696b60 --- /dev/null +++ b/tmp_bind_change_ip.sh @@ -0,0 +1,855 @@ +#!/usr/bin/env bash + + +working_dir="$(dirname $(realpath $0))" +conf_file="${working_dir}/conf/tmp_bind.conf" + +log_file="$(mktemp)" + +backup_date="$(date +%Y-%m-%d-%H%M)" + +_serial_new=`date +%Y%m%d01` + + +#--------------------------------------- +#----------------------------- +# Base Function(s) +#----------------------------- +#--------------------------------------- + +clean_up() { + + # Perform program exit housekeeping + rm $log_file + exit $1 +} + +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 "" + clean_up 1 +} + +warn (){ + echo "" + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + echo "" +} + +info (){ + echo "" + echo -e "\t[ \033[33m\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_done() { + 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 +} + + +## - Test of valid IPv4 Address +## - +## - Returns 0 if valid, > 0 otherwise +## - +is_valid_ipv4() { + local -a octets=( ${1//\./ } ) + local RETURNVALUE=0 + + # return an error if the IP doesn't have exactly 4 octets + [[ ${#octets[@]} -ne 4 ]] && return 1 + + for octet in ${octets[@]} + do + if [[ ${octet} =~ ^[0-9]{1,3}$ ]] + then # shift number by 8 bits, anything larger than 255 will be > 0 + ((RETURNVALUE += octet>>8 )) + else # octet wasn't numeric, return error + return 1 + fi + done + return ${RETURNVALUE} +} + +is_valid_ipv6() { + local _ipv6=$1 + + if [ "$1" != "${1#[0-9a-f]*:}" ] \ + && [ "$1" = "${1#*[^0-9a-f:]}" ] \ + && [ "${1#*[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]}" = "${1#*:*:*:*:*:*:*:*:*:}" ]; then + return 0 + else + return 1 + fi +} + +trap clean_up SIGHUP SIGINT SIGTERM + + + +#--------------------------------------- +#----------------------------- +# Setting Defaults +#----------------------------- +#--------------------------------------- + +DEFAULT_CONF_FILE_DIR="/root/tmp/bind" +DEFAULT_BIND_CACHE_DIR="/var/cache/bind" + + + +#--------------------------------------- +#----------------------------- +# Load default values from bind.conf +# +# Overwrites the settings above +# +#----------------------------- +#--------------------------------------- + +#clear +echo "" +echo "" +echononl " Loading default Configuration values from $(basename ${conf_file}).." +if [[ ! -f "$conf_file" ]]; then + echo_skipped +else + source "${conf_file}" > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + fatal "$(cat $log_file)" + fi +fi + +[[ -n "$CONF_FILE_DIR" ]] && DEFAULT_CONF_FILE_DIR="$CONF_FILE_DIR" + +[[ -n "$BIND_CACHE_DIR" ]] && DEFAULT_BIND_CACHE_DIR="$BIND_CACHE_DIR" + + +if [[ -n "$ZONE_FILE_MASTER_DIR" ]] ; then + DEFAULT_ZONE_FILE_MASTER_DIR="$ZONE_FILE_MASTER_DIR" +else + DEFAULT_ZONE_FILE_MASTER_DIR="${DEFAULT_CONF_FILE_DIR}/master" +fi + +if [[ -n "$ZONE_FILE_SLAVE_DIR" ]] ; then + DEFAULT_ZONE_FILE_SLAVE_DIR="$ZONE_FILE_SLAVE_DIR" +else + DEFAULT_ZONE_FILE_SLAVE_DIR="${DEFAULT_BIND_CACHE_DIR}" +fi + +if [[ -n "$ZONES_DECLARATION_FILE" ]] ; then + DEFAULT_ZONES_DECLARATION_FILE="$ZONES_DECLARATION_FILE" +else + DEFAULT_ZONES_DECLARATION_FILE="${CONF_FILE_DIR}/named.conf.local" +fi + + +echo "" + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Insert IPv4-Address which do you want to change (old address)." +echo "" +echo -e "Type \"\033[33mNone\033[m\" if no IPv4 address should be changed." +echo "" +IPv4_ADDRESS_OLD= +_set_ipv4=true +while [ "X$IPv4_ADDRESS_OLD" = "X" ]; do + echononl "Old IPv4-Address: " + read IPv4_ADDRESS_OLD + ## - To lower case + IPv4_ADDRESS_OLD=${IPv4_ADDRESS_OLD,,} + if [ "X$IPv4_ADDRESS_OLD" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + IPv4_ADDRESS_OLD="" + continue + fi + if [ "${IPv4_ADDRESS_OLD,,}" = "none" ];then + _set_ipv4=false + break + fi + + ipv4_addresses_old_arr=() + for _ipv4_address in $IPv4_ADDRESS_OLD ; do + containsElement "$_ipv4_address" "${ipv4_addresses_old_arr[@]}" && continue + ipv4_addresses_old_arr+=("$_ipv4_address") + done + if [ ${#ipv4_addresses_old_arr[@]} -gt 1 ] ; then + echo -e "\n\t\033[33m\033[1mOnly one address is possible!\033[m\n" + IPv4_ADDRESS_OLD="" + continue + fi + unset ipv4_addresses_old_arr + + if ! is_valid_ipv4 $IPv4_ADDRESS_OLD ; then + echo -e "\n\t\033[33m\033[1m$IPv4_ADDRESS_OLD\033[m is NOT a valid IPv4 Address\n" + IPv4_ADDRESS_OLD="" + continue + fi +done + +if $_set_ipv4 ; then + + echo "" + echo -e "\033[32m--\033[m" + echo "" + echo "Insert IPv4-Address which do you want to replace (new address)." + echo "" + + IPv4_ADDRESS_NEW= + _set_ipv4=true + while [ "X$IPv4_ADDRESS_NEW" = "X" ]; do + echononl "New IPv4-Address: " + read IPv4_ADDRESS_NEW + ## - To lower case + IPv4_ADDRESS_NEW=${IPv4_ADDRESS_NEW,,} + if [ "X$IPv4_ADDRESS_NEW" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + IPv4_ADDRESS_NEW="" + continue + fi + + ipv4_addresses_new_arr=() + for _ipv4_address in $IPv4_ADDRESS_NEW ; do + containsElement "$_ipv4_address" "${ipv4_addresses_new_arr[@]}" && continue + ipv4_addresses_new_arr+=("$_ipv4_address") + done + if [ ${#ipv4_addresses_new_arr[@]} -gt 1 ] ; then + echo -e "\n\t\033[33m\033[1mOnly one address is possible!\033[m\n" + IPv4_ADDRESS_NEW="" + continue + fi + unset ipv4_addresses_new_arr + + if ! is_valid_ipv4 $IPv4_ADDRESS_NEW ; then + echo -e "\n\t\033[33m\033[1m$IPv4_ADDRESS_NEW\033[m is NOT a valid IPv4 Address\n" + IPv4_ADDRESS_NEW="" + continue + fi + done +fi + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Insert IPv6-Address which do you want to change (old address)." +echo "" +echo -e "Type \"\033[33mnone\033[m\" if no IPv6 address should be changed." +echo "" +IPv6_ADDRESS_OLD= +_set_ipv6=true +while [ "X$IPv6_ADDRESS_OLD" = "X" ]; do + echononl "Old IPv6-Address: " + read IPv6_ADDRESS_OLD + ## - To lower case + IPv6_ADDRESS_OLD=${IPv6_ADDRESS_OLD,,} + if [ "X$IPv6_ADDRESS_OLD" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + IPv6_ADDRESS_OLD="" + continue + fi + if [ "${IPv6_ADDRESS_OLD,,}" = "none" ];then + _set_ipv6=false + break + fi + + ipv6_addresses_old_arr=() + for _ipv6_address in $IPv6_ADDRESS_OLD ; do + containsElement "$_ipv6_address" "${ipv6_addresses_old_arr[@]}" && continue + ipv6_addresses_old_arr+=("$_ipv6_address") + done + if [ ${#ipv6_addresses_old_arr[@]} -gt 1 ] ; then + echo -e "\n\t\033[33m\033[1mOnly one address is possible!\033[m\n" + IPv6_ADDRESS_OLD="" + continue + fi + unset ipv6_addresses_old_arr + + if ! is_valid_ipv6 $IPv6_ADDRESS_OLD ; then + echo -e "\n\t\033[33m\033[1m$IPv6_ADDRESS_OLD\033[m is NOT a valid IPv6 Address\n" + IPv6_ADDRESS_OLD="" + continue + fi +done + +if $_set_ipv6 ; then + + echo "" + echo -e "\033[32m--\033[m" + echo "" + echo "Insert IPv6-Address which do you want to replace (new address)." + echo "" + + IPv6_ADDRESS_NEW= + _set_ipv6=true + while [ "X$IPv6_ADDRESS_NEW" = "X" ]; do + echononl "New IPv6-Address: " + read IPv6_ADDRESS_NEW + ## - To lower case + IPv6_ADDRESS_NEW=${IPv6_ADDRESS_NEW,,} + if [ "X$IPv6_ADDRESS_NEW" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + IPv6_ADDRESS_NEW="" + continue + fi + + ipv6_addresses_new_arr=() + for _ipv6_address in $IPv6_ADDRESS_NEW ; do + containsElement "$_ipv6_address" "${ipv6_addresses_new_arr[@]}" && continue + ipv6_addresses_new_arr+=("$_ipv6_address") + done + if [ ${#ipv6_addresses_new_arr[@]} -gt 1 ] ; then + echo -e "\n\t\033[33m\033[1mOnly one address is possible!\033[m\n" + IPv6_ADDRESS_NEW="" + continue + fi + unset ipv6_addresses_new_arr + + if ! is_valid_ipv6 $IPv6_ADDRESS_NEW ; then + echo -e "\n\t\033[33m\033[1m$IPv6_ADDRESS_NEW\033[m is NOT a valid IPv6 Address\n" + IPv6_ADDRESS_NEW="" + continue + fi + done +fi + + +if ! $_set_ipv6 && ! $_set_ipv4 ; then + fatal "Neither IPv4-Adress nor IPv6-Adress given .." +fi + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Ignore Hostnames containing \"-alt\" (as ww-alt.oopen.de or d-alt.mx.oopen.de)" +echo "" +echo " Type 'return' for the yellow highlighted one.." +echo "" +OK= +IGNORE_ALT_HOSTNAMES=false +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Ignore Hostnames containing \"-alt\"? [\033[33m\033[1myes\033[m/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + OK='yes' + #echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + #OK="" + #continue + fi + if [ "$OK" = "yes" -o "$OK" = "no" ] ; then + break + else + OK="" + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] && IGNORE_ALT_HOSTNAMES=true + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Ignore Hostnames \"autoconfig\" (as autoconfig.oopen.de)" +echo "" +echo " Type 'return' for the yellow highlighted one.." +echo "" +OK= +IGNORE_AUTOCONFIG_HOSTNAMES=false +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Ignore Hostnames \"autoconfig.\"? [\033[33m\033[1myes\033[m/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + OK='yes' + #echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + #OK="" + #continue + fi + if [ "$OK" = "yes" -o "$OK" = "no" ] ; then + break + else + OK="" + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] && IGNORE_AUTOCONFIG_HOSTNAMES=true + + +echo "" +echo "" +echo -e "\033[32m--\033[m" +echo "Common parameters" +echo -e "\033[32m--\033[m" + + +echo "" +echo "Insert directory containing the bind configuration files." +echo "" +CONF_FILE_DIR="" +if [[ -n "$DEFAULT_CONF_FILE_DIR" ]] ; then + echononl "Bind Configuration Directory [${DEFAULT_CONF_FILE_DIR}]: " + read CONF_FILE_DIR + if [[ "X$CONF_FILE_DIR" = "X" ]]; then + CONF_FILE_DIR="$DEFAULT_CONF_FILE_DIR" + fi +else + echononl "Bind Configuration Directory: " + read CONF_FILE_DIR + while [ "X$CONF_FILE_DIR" = "X" ] ; do + echo -e "\n\t\033[33m\033[1mSetting 'Bind Configuration Directory' is required!\033[m\n" + echononl "Bind Configuration Directory: " + read CONF_FILE_DIR + done +fi + +[[ -n "$ZONES_DECLARATION_FILE" ]] || DEFAULT_ZONES_DECLARATION_FILE="${CONF_FILE_DIR}/named.conf.local" + + +echo "" +echo -e "\033[32m--\033[m" + +echo "" +echo "Insert zones declaration file." +echo "" +ZONES_DECLARATION_FILE="" +if [[ -n "$DEFAULT_ZONES_DECLARATION_FILE" ]] ; then + echononl "Zones Declaration File [${DEFAULT_ZONES_DECLARATION_FILE}]: " + read ZONES_DECLARATION_FILE + if [[ "X$ZONES_DECLARATION_FILE" = "X" ]]; then + ZONES_DECLARATION_FILE="$DEFAULT_ZONES_DECLARATION_FILE" + fi +else + echononl "Zones Declaration File: " + read ZONES_DECLARATION_FILE + while [ "X$ZONES_DECLARATION_FILE" = "X" ] ; do + echo -e "\n\t\033[33m\033[1mSetting 'Zones Declaration File' is required!\033[m\n" + echononl "Zones Declaration File: " + read ZONES_DECLARATION_FILE + done +fi + + +echo "" +echo -e "\033[32m--\033[m" + +echo "" +echo "Insert the directory, where your zone-files resides." +echo "" +echo "" +ZONE_FILE_MASTER_DIR="" +if [[ -n "$DEFAULT_ZONE_FILE_MASTER_DIR" ]] ; then + echononl "Zone File Directory (master) [${DEFAULT_ZONE_FILE_MASTER_DIR}]: " + read ZONE_FILE_MASTER_DIR + if [[ "X$ZONE_FILE_MASTER_DIR" = "X" ]]; then + ZONE_FILE_MASTER_DIR="$DEFAULT_ZONE_FILE_MASTER_DIR" + fi +else + echononl "Zone File Directory (master): " + read ZONE_FILE_MASTER_DIR + while [ "X$ZONE_FILE_MASTER_DIR" = "X" ] ; do + echo -e "\n\t\033[33m\033[1mSetting 'Zone File Directory (master)' is required!\033[m\n" + echononl "Zone File Directory (master): " + read ZONE_FILE_MASTER_DIR + done +fi + + +clear +echo "" +echo "" +echo -e "\033[21G\033[32mReplace IP-Address(es)\033[m" +echo "" + +echo "" +if $_set_ipv4 ; then + echo "Old IPv4 Address...........................: $IPv4_ADDRESS_OLD" + echo "New IPv4 Address...........................: $IPv4_ADDRESS_NEW" +else + echo -e "IPv4 Address(es)...........................: \033[33mNone\033[m" +fi +echo "" +if $_set_ipv6 ; then + echo "Old IPv6 Address...........................: $IPv6_ADDRESS_OLD" + echo "New IPv6 Address...........................: $IPv6_ADDRESS_NEW" +else + echo -e "IPv6 Address(es)........................: \033[33mNone\033[m" +fi +echo "" +echo "Ignore hostnames containing \"-alt\"/\"-neu\"..: $IGNORE_ALT_HOSTNAMES" +echo "Ignore hostnames \"autoconfig.\".....: $IGNORE_AUTOCONFIG_HOSTNAMES" +echo "" +echo "Bind Configuration Directory...............: $CONF_FILE_DIR" +echo "Zones Declaration File.....................: $ZONES_DECLARATION_FILE" +echo "Zone File Directory (master)...............: $ZONE_FILE_MASTER_DIR" +#echo "Zone File Suffix...........................: $ZONE_FILE_SUFFIX" + +echo "" +OK= +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Parameters ok? [yes/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + OK="" + continue + fi + if [ "$OK" != "yes" -o "$OK" != "no" ] ; then + break + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] || fatal Repeat execution with different parameters + +echo "" + + +echononl "\tBackup directory '${ZONE_FILE_MASTER_DIR}'.." +cp -a "${ZONE_FILE_MASTER_DIR}" "${ZONE_FILE_MASTER_DIR}.${backup_date}" > $log_file 2>&1 +if [[ $? -eq 0 ]]; then + echo_ok +else + echo_failed + fatal "$(cat $log_file)" +fi + +echo "" +echo "" +echo -e "\033[37m\033[1mDetermine zone files conatining ip-adressse requested for change..\033[m" + +_found=false +_is_master=false +zonefiles_arr=() +zonefiles_not_present_arr=() +zone_file="" +regex_master="type[[:space:]]+master" +regex_file="^[[:space:]]*file" +while IFS='' read -r _line || [[ -n $_line ]] ; do + + if [[ $_line =~ ^[[:space:]]*zone[[:space:]]+ ]]; then + _found=true + zone="$(echo $_line | awk '{print$2}')" + shopt -s extglob + if [[ $zone =~ \; ]]; then + zone=${zone%%*(\;)} + fi + if [[ $zone =~ ^\" ]]; then + zone=${zone##*(\")} + zone=${zone%%*(\")} + fi + shopt -u extglob + 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 + fi + + if [[ -n "${zone_file}" ]] ; then + if [[ ! -f "${zone_file}" ]] ; then + if ! containsElement "${zone_file}" "${zonefiles_not_present_arr[@]}" ; then + zonefiles_not_present_arr+=("${zone_file}") + fi + continue + fi + if ! $(echo ${zone_file} | grep -q -e "$ZONE_FILE_MASTER_DIR" 2> /dev/null) ; then + fatal "Zonefile to change does not live in directory '$ZONE_FILE_MASTER_DIR'! + + Zonefile to change: \033[33m${zone_file}\033[m" + fi + fi + + if [[ $_line =~ $regex_master ]]; then + _is_master=true + fi + if [[ "$_line" =~ ^[[:space:]]*\}[[:space:]]*\; ]]; then + if $_is_master && [[ -n "$zone_file" ]]; then + + + if $_set_ipv4 ; then + + if $(grep -q -e "$IPv4_ADDRESS_OLD" "$zone_file") ; then + if [ ${#zonefiles_arr[@]} -eq 0 ] ; then + zonefiles_arr+=("${zone_file}:$zone") + else + if ! containsElement "${zone_file}:$zone" "${zonefiles_arr[@]}" ; then + zonefiles_arr+=("${zone_file}:$zone") + fi + fi + fi + fi + + if $_set_ipv6 ; then + if $(grep -q -e "$IPv6_ADDRESS_OLD" "$zone_file") ; then + if [ ${#zonefiles_arr[@]} -eq 0 ] ; then + zonefiles_arr+=("${zone_file}:$zone") + else + if ! containsElement "${zone_file}:$zone" "${zonefiles_arr[@]}" ; then + zonefiles_arr+=("${zone_file}:$zone") + fi + fi + fi + fi + + fi + _is_master=false + _found=false + zone_file="" + fi + fi +done < "$ZONES_DECLARATION_FILE" + +echo "" + +for _val in ${zonefiles_arr[@]} ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + zone_file="${_val_arr[0]}" + zone="${_val_arr[1]}" + + if [[ ! -f "${zone_file}" ]]; then + warn "Zonefile \033[1m$zone_file\033[m no fount!" + continue + fi + + echo -e "\tEditing \033[1m$zone_file\033[m .." + + _replaced=false + + ## - setze neue ipv4 adresse + ## - + echononl "\t Set new IPv4 address ($IPv4_ADDRESS_NEW).." + + _replaced=false + _failed=false + if grep -e "IN\s*A\s*$IPv4_ADDRESS_OLD" $zone_file > /dev/null 2>&1 ; then + + if $IGNORE_ALT_HOSTNAMES ; then + + perl -i -n -p -e "s#^(.+(-alt).*)\s+IN\s+A\s+$IPv4_ADDRESS_OLD#\1 IN A 888.888.888.888#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + perl -i -n -p -e "s#^(.+(-neu).*)\s+IN\s+A\s+$IPv4_ADDRESS_OLD#\1 IN A 888.888.888.888#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + fi + + if $IGNORE_AUTOCONFIG_HOSTNAMES ; then + + perl -i -n -p -e "s#^\s*(autoconfig.*)\s+IN\s+A\s+$IPv4_ADDRESS_OLD#\1 IN A 888.888.888.888#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + fi + + perl -i -n -p -e "s#IN\s+A\s+$IPv4_ADDRESS_OLD#IN A $IPv4_ADDRESS_NEW#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + + if $IGNORE_ALT_HOSTNAMES || $IGNORE_AUTOCONFIG_HOSTNAMES ; then + + perl -i -n -p -e "s#IN\s+A\s+888.888.888.888#IN A $IPv4_ADDRESS_OLD#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + + fi + + if $_failed ; then + echo_failed + error "Replacing $IPv4_ADDRESS_OLD with $IPv4_ADDRESS_NEW in zone file \"$zone_file\" failed!" + else + echo_ok + _replaced=true + fi + else + echo_skipped + fi + + + ## - setze neue ipv6 adresse + ## - + echononl "\t Set new IPv6 address ($IPv6_ADDRESS_NEW).." + + _replaced_ipv6=false + _failed=false + if grep -e "IN\s*AAAA\s*$IPv6_ADDRESS_OLD" $zone_file > /dev/null 2>&1 ; then + + if $IGNORE_ALT_HOSTNAMES ; then + + perl -i -n -p -e "s#^(.+(-alt).*)\s+IN\s+AAAA\s+$IPv6_ADDRESS_OLD#\1 IN AAAA 88:88:88::88#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + perl -i -n -p -e "s#^(.+(-neu).*)\s+IN\s+AAAA\s+$IPv6_ADDRESS_OLD#\1 IN AAAA 88:88:88::88#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + fi + + if $IGNORE_AUTOCONFIG_HOSTNAMES ; then + perl -i -n -p -e "s#^\s*(autoconfig.*)\s+IN\s+AAAA\s+$IPv6_ADDRESS_OLD#\1 IN AAAA 88:88:88::88#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + fi + + perl -i -n -p -e "s#IN\s+AAAA\s+$IPv6_ADDRESS_OLD#IN AAAA $IPv6_ADDRESS_NEW#" $zone_file + if [[ $? -gt 0 ]]; then + _failed=true + fi + + if $IGNORE_ALT_HOSTNAMES || $IGNORE_AUTOCONFIG_HOSTNAMES ; then + + perl -i -n -p -e "s#IN\s+AAAA\s+88:88:88::88#IN AAAA $IPv6_ADDRESS_OLD#" $zone_file > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + _failed=true + fi + + fi + + if $_failed ; then + echo_failed + error "Replacing $IPv6_ADDRESS_OLD with $IPv6_ADDRESS_NEW in zone file \"$zone_file\" failed!" + else + echo_ok + _replaced=true + _replaced_ipv6=true + fi + else + echo_skipped + fi + + # - Calculate new serial + # - + echo "" + echononl "\t Calculate new serial" + if $_replaced ; then + declare -i __serial=`grep -e "[0-9]\{10\}" $zone_file | grep serial | awk '{print$1}'` + while [ ! $_serial_new -gt $__serial ]; do + let _serial_new++ + done + echo_done + else + echo_skipped + fi + + # - Set new serial + # - + echononl "\t Increase Serial for zone file \"`basename $zone_file`\"" + if $_replaced ; then + perl -i -n -p -e "s#^(\s*)\s$__serial(.*)#\1 $_serial_new\2#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Increasing Serial for zone file \"`basename $zone_file`\" failed!" + fi + else + echo_skipped + fi + + # - Reload Zone + # - + echononl "\t Reload zone '${zone}'" + if $_replaced ; then + /usr/sbin/rndc reload $zone > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + echo_failed + else + echo_ok + fi + else + echo_skipped + fi + + echo + +done + +if [[ -d "${ZONE_FILE_MASTER_DIR}.${backup_date}" ]] ; then + diff -Nur "${ZONE_FILE_MASTER_DIR}" "${ZONE_FILE_MASTER_DIR}.${backup_date}" > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + info "No zone file has changed.\n\t Removing previously created backup" + echononl "\tDelete '${ZONE_FILE_MASTER_DIR}.${backup_date}'.." + rm -rf "${ZONE_FILE_MASTER_DIR}.${backup_date}" > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + fi + fi +fi + +if [[ ${#zonefiles_not_present_arr[@]} -gt 0 ]] ; then + echo "" + warn "The following zonefiles were not found!" + for _val in ${zonefiles_not_present_arr[@]} ; do + echo -e "\t $_val" + done +fi + + +echo "" +clean_up 0 diff --git a/tmp_bind_change_ttl.sh b/tmp_bind_change_ttl.sh new file mode 100755 index 0000000..405ffc6 --- /dev/null +++ b/tmp_bind_change_ttl.sh @@ -0,0 +1,852 @@ +#!/usr/bin/env bash + + +working_dir="$(dirname $(realpath $0))" +conf_file="${working_dir}/conf/tmp_bind.conf" + +log_file="$(mktemp)" + +backup_date="$(date +%Y-%m-%d-%H%M)" + +_serial_new=`date +%Y%m%d01` + + +#--------------------------------------- +#----------------------------- +# Base Function(s) +#----------------------------- +#--------------------------------------- + +clean_up() { + + # Perform program exit housekeeping + rm $log_file + exit $1 +} + +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 "" + clean_up 1 +} + +warn (){ + echo "" + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + echo "" +} + +info (){ + echo "" + echo -e "\t[ \033[33m\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_done() { + echo -e "\033[75G[ \033[32mdone\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 +} + + +## - Test of valid IPv4 Address +## - +## - Returns 0 if valid, > 0 otherwise +## - +is_valid_ipv4() { + local -a octets=( ${1//\./ } ) + local RETURNVALUE=0 + + # return an error if the IP doesn't have exactly 4 octets + [[ ${#octets[@]} -ne 4 ]] && return 1 + + for octet in ${octets[@]} + do + if [[ ${octet} =~ ^[0-9]{1,3}$ ]] + then # shift number by 8 bits, anything larger than 255 will be > 0 + ((RETURNVALUE += octet>>8 )) + else # octet wasn't numeric, return error + return 1 + fi + done + return ${RETURNVALUE} +} + +is_valid_ipv6() { + local _ipv6=$1 + + if [ "$1" != "${1#[0-9a-f]*:}" ] \ + && [ "$1" = "${1#*[^0-9a-f:]}" ] \ + && [ "${1#*[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]}" = "${1#*:*:*:*:*:*:*:*:*:}" ]; then + return 0 + else + return 1 + fi +} + +trap clean_up SIGHUP SIGINT SIGTERM + + + +#--------------------------------------- +#----------------------------- +# Setting Defaults +#----------------------------- +#--------------------------------------- + +DEFAULT_CONF_FILE_DIR="/root/tmp/bind" +DEFAULT_BIND_CACHE_DIR="/var/cache/bind" + + + +#--------------------------------------- +#----------------------------- +# Load default values from bind.conf +# +# Overwrites the settings above +# +#----------------------------- +#--------------------------------------- + +#clear +echo "" +echo "" +echononl " Loading default Configuration values from $(basename ${conf_file}).." +if [[ ! -f "$conf_file" ]]; then + echo_skipped +else + source "${conf_file}" > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + fatal "$(cat $log_file)" + fi +fi + +[[ -n "$CONF_FILE_DIR" ]] && DEFAULT_CONF_FILE_DIR="$CONF_FILE_DIR" + +[[ -n "$BIND_CACHE_DIR" ]] && DEFAULT_BIND_CACHE_DIR="$BIND_CACHE_DIR" + +if [[ -n "$ZONE_FILE_MASTER_DIR" ]] ; then + DEFAULT_ZONE_FILE_MASTER_DIR="$ZONE_FILE_MASTER_DIR" +else + DEFAULT_ZONE_FILE_MASTER_DIR="${DEFAULT_CONF_FILE_DIR}/master" +fi + +if [[ -n "$ZONE_FILE_SLAVE_DIR" ]] ; then + DEFAULT_ZONE_FILE_SLAVE_DIR="$ZONE_FILE_SLAVE_DIR" +else + DEFAULT_ZONE_FILE_SLAVE_DIR="$DEFAULT_BIND_CACHE_DIR" +fi + +if [[ -n "$ZONE_FILE_SUFFIX" ]] ; then + DEFAULT_ZONE_FILE_SUFFIX="$ZONE_FILE_SUFFIX" +else + DEFAULT_ZONE_FILE_SUFFIX='zone' +fi + +if [[ -n "$ZONES_DECLARATION_FILE" ]] ; then + DEFAULT_ZONES_DECLARATION_FILE="$ZONES_DECLARATION_FILE" +else + DEFAULT_ZONES_DECLARATION_FILE="${CONF_FILE_DIR}/named.conf.local" +fi + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Insert IPv4-Address(es) to change TTL for." +echo "" +echo "For multiple IPv4 Addresses, insert a blank separated list" +echo "" +echo -e "Type \"\033[33mNone\033[m\" if no IPv4 address should be changed." +echo "" +IPv4_ADDRESS= +_set_ipv4=true +while [ "X$IPv4_ADDRESS" = "X" ]; do + echononl "IPv4-Address: " + read IPv4_ADDRESS + ## - To lower case + IPv4_ADDRESS=${IPv4_ADDRESS,,} + if [ "X$IPv4_ADDRESS" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + IPv4_ADDRESS="" + continue + fi + if [ "$IPv4_ADDRESS" = "none" ];then + _set_ipv4=false + break + fi + for _addr in $IPv4_ADDRESS ; do + if ! is_valid_ipv4 $_addr ; then + echo -e "\n\t\033[33m\033[1m$_addr\033[m is NOT a valid IPv4 Address\n" + IPv4_ADDRESS="" + break + fi + done +done + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Insert IPv6-Address to change TTL for." +echo "" +echo "For multiple IPv6 Addresses, insert a blank separated list" +echo "" +echo -e "Type \"\033[33mNone\033[m\" if no IPv6 address should be changed." +echo "" +IPv6_ADDRESS= +_set_ipv6=true +while [ "X$IPv6_ADDRESS" = "X" ]; do + echononl "IPv6-Address: " + read IPv6_ADDRESS + ## - To lower case + IPv6_ADDRESS=${IPv6_ADDRESS,,} + if [ "X$IPv6_ADDRESS" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + IPv6_ADDRESS="" + continue + fi + if [ "$IPv6_ADDRESS" = "none" ];then + _set_ipv6=false + break + fi + for _addr in $IPv6_ADDRESS ; do + if ! is_valid_ipv6 $_addr ; then + echo -e "\n\t\033[33m\033[1m$_addr\033[m is NOT a valid IPv6 Address\n" + IPv6_ADDRESS="" + break + fi + done +done + + +if ! $_set_ipv6 && ! $_set_ipv4 ; then + fatal "No IP-Adresses given to change TTL for.." +fi + +echo "" +echo -e "\033[32m--\033[m" +echo "" + +echo "Insert New TTL for the given IP-Address(es)" +echo "" +echo -e "[ \033[33mTIP\033[m ]: Choose a extraordinary Number (like 363 or 181), so you can" +echo " identify it later very simple for setting back." +echo "" +TTL= +regular_expression_number='^[0-9]+$' +while [ "X$TTL" = "X" ]; do + echononl "TTL: " + read TTL + if [ "X$TTL" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + TTL="" + continue + fi + if ! [[ $TTL =~ $regular_expression_number ]] ; then + echo -e "\n\t\033[33m\033[1m$TTL\033[m is NOT a number\n" + TTL="" + continue + elif [[ $TTL -lt "61" ]]; then + echo -e "\n\t\033[33m\033[1m$TTL\033[m Choose a number greater than "60"\n" + TTL="" + continue + fi +done + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Ignore Hostnames containing \"-alt\" (as ww-alt.oopen.de or d-alt.mx.oopen.de)" +echo "" +echo "" +OK= +IGNORE_ALT_HOSTNAMES=false +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Ignore Hostnames containing \"-alt\"? [yes/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + OK="" + continue + fi + if [ "$OK" = "yes" -o "$OK" = "no" ] ; then + break + else + OK="" + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] && IGNORE_ALT_HOSTNAMES=true + + +echo "" +echo -e "\033[32m--\033[m" +echo "" +echo "Ignore Hostnames \"autoconfig\" (as autoconfig.oopen.de)" +echo "" +echo " Type 'return' for the yellow highlighted one.." +echo "" +OK= +IGNORE_AUTOCONFIG_HOSTNAMES=false +while [ "$OK" != "yes" -o "$OK" != "no" ] ; do + echononl "Ignore Hostnames \"autoconfig.\"? [yes/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + OK='yes' + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + OK="" + continue + fi + if [ "$OK" = "yes" -o "$OK" = "no" ] ; then + break + else + OK="" + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] && IGNORE_AUTOCONFIG_HOSTNAMES=true + + +echo "" +echo "" +echo -e "\033[32m--\033[m" +echo "Common parameters" +echo -e "\033[32m--\033[m" + + +echo "" +echo "Insert directory containing the bind configuration files." +echo "" +CONF_FILE_DIR="" +if [[ -n "$DEFAULT_CONF_FILE_DIR" ]] ; then + echononl "Bind Configuration Directory [${DEFAULT_CONF_FILE_DIR}]: " + read CONF_FILE_DIR + if [[ "X$CONF_FILE_DIR" = "X" ]]; then + CONF_FILE_DIR="$DEFAULT_CONF_FILE_DIR" + fi +else + echononl "Bind Configuration Directory: " + read CONF_FILE_DIR + while [ "X$CONF_FILE_DIR" = "X" ] ; do + echo -e "\n\t\033[33m\033[1mSetting 'Bind Configuration Directory' is required!\033[m\n" + echononl "Bind Configuration Directory: " + read CONF_FILE_DIR + done +fi + +[[ -n "$ZONES_DECLARATION_FILE" ]] || DEFAULT_ZONES_DECLARATION_FILE="${CONF_FILE_DIR}/named.conf.local" + + +echo "" +echo -e "\033[32m--\033[m" + +echo "" +echo "Insert zones declaration file." +echo "" +ZONES_DECLARATION_FILE="" +if [[ -n "$DEFAULT_ZONES_DECLARATION_FILE" ]] ; then + echononl "Zones Declaration File [${DEFAULT_ZONES_DECLARATION_FILE}]: " + read ZONES_DECLARATION_FILE + if [[ "X$ZONES_DECLARATION_FILE" = "X" ]]; then + ZONES_DECLARATION_FILE="$DEFAULT_ZONES_DECLARATION_FILE" + fi +else + echononl "Zones Declaration File: " + read ZONES_DECLARATION_FILE + while [ "X$ZONES_DECLARATION_FILE" = "X" ] ; do + echo -e "\n\t\033[33m\033[1mSetting 'Zones Declaration File' is required!\033[m\n" + echononl "Zones Declaration File: " + read ZONES_DECLARATION_FILE + done +fi + + +echo "" +echo -e "\033[32m--\033[m" + +echo "" +echo "Insert the directory, where your zone-files resides." +echo "" +echo "" +ZONE_FILE_MASTER_DIR="" +if [[ -n "$DEFAULT_ZONE_FILE_MASTER_DIR" ]] ; then + echononl "Zone File Directory (master) [${DEFAULT_ZONE_FILE_MASTER_DIR}]: " + read ZONE_FILE_MASTER_DIR + if [[ "X$ZONE_FILE_MASTER_DIR" = "X" ]]; then + ZONE_FILE_MASTER_DIR="$DEFAULT_ZONE_FILE_MASTER_DIR" + fi +else + echononl "Zone File Directory (master): " + read ZONE_FILE_MASTER_DIR + while [ "X$ZONE_FILE_MASTER_DIR" = "X" ] ; do + echo -e "\n\t\033[33m\033[1mSetting 'Zone File Directory (master)' is required!\033[m\n" + echononl "Zone File Directory (master): " + read ZONE_FILE_MASTER_DIR + done +fi + +#echo "" +#echo -e "\033[32m--\033[m" +# +#echo "" +#echo "Insert the file-suffix of thr zone-files" +#echo "" +#echo "" +#ZONE_FILE_SUFFIX= +#echononl "Suffix of Zone Files [$_zone_file_suffix]: " +#read ZONE_FILE_SUFFIX +#if [ "X$ZONE_FILE_SUFFIX" = "X" ]; then +# ZONE_FILE_SUFFIX=$_zone_file_suffix +#fi + + +clear +echo "" +echo "" +echo -e "\033[21G\033[32mChange TTL Settings\033[m" +echo "" + +echo "" +if $_set_ipv4 ; then + echo "IPv4 Address(es)........................: $IPv4_ADDRESS" +else + echo -e "IPv4 Address(es)........................: \033[33mNone\033[m" +fi +if $_set_ipv6 ; then + echo "IPv6 Address(es)........................: $IPv6_ADDRESS" +else + echo -e "IPv6 Address(es)........................: \033[33mNone\033[m" +fi +echo "" +echo "New TTL.................................: $TTL" +echo "" +echo "Ignore hostnames containing \"-alt\"......: $IGNORE_ALT_HOSTNAMES" +echo "Ignore hostnames \"autoconfig.\"..: $IGNORE_AUTOCONFIG_HOSTNAMES" +echo "" +echo "Bind Configuration Directory............: $CONF_FILE_DIR" +echo "Zones Declaration File..................: $ZONES_DECLARATION_FILE" +echo "Zone File Directory.....................: $ZONE_FILE_MASTER_DIR" +#echo "Zone File Suffix........................: $ZONE_FILE_SUFFIX" + +echo "" +OK= +while [ "$OK" != "yes" -a "$OK" != "no" ] ; do + echononl "Parameters ok? [yes/no]: " + read OK + ## - To lower case + OK=${OK,,} + if [ "X$OK" = "X" ]; then + echo -e "\n\t\033[33m\033[1mAn entry is required!\033[m\n" + OK="" + continue + fi + if [ "$OK" != "yes" -a "$OK" != "no" ] ; then + OK="" + else + break + fi + echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n" +done +[[ $OK = "yes" ]] || fatal Repeat execution with different parameters + + +echo "" +echo "" +echononl "\tBackup directory '${ZONE_FILE_MASTER_DIR}'.." +cp -a "${ZONE_FILE_MASTER_DIR}" "${ZONE_FILE_MASTER_DIR}.${backup_date}" > $log_file 2>&1 +if [[ $? -eq 0 ]]; then + echo_ok +else + echo_failed + fatal "$(cat $log_file)" +fi + +echo "" +echononl "\tCreate array of given IPv4 addresses" +ipv4_addresses_arr=() +for _ipv4_address in $IPv4_ADDRESS ; do + containsElement "$_ipv4_address" "${ipv4_addresses_arr[@]}" && continue + ipv4_addresses_arr+=("$_ipv4_address") +done +echo_done + +echononl "\tCreate array of given IPv6 addresses" +ipv6_addresses_arr=() +for _ipv6_address in $IPv6_ADDRESS ; do + containsElement "$_ipv6_address" "${ipv6_addresses_arr[@]}" && continue + ipv6_addresses_arr+=("$_ipv6_address") +done +echo_done + +#zonefiles_arr=() +#if $_set_ipv4 ; then +# for _ipv4_address in ${ipv4_addresses_arr[@]} ; do +# _zone_files_ipv4=`grep -l -e "$_ipv4_address" ${ZONE_FILE_DIR}/*.$ZONE_FILE_SUFFIX` +# if [ ${#zonefiles_arr[@]} -eq 0 ] ; then +# for _zone_file in $_zone_files_ipv4 ; do +# zonefiles_arr+=("$_zone_file") +# done +# else +# for _zone_file in $_zone_files_ipv4 ; do +# containsElement "$_zone_file" "${zonefiles_arr[@]}" && continue +# zonefiles_arr+=("$_zone_file") +# done +# fi +# done +#fi +# +#if $_set_ipv6 ; then +# for _ipv6_address in "${ipv6_addresses_arr[@]}" ; do +# _zone_files_ipv6=`grep -l -e "$_ipv6_address" ${ZONE_FILE_DIR}/*.$ZONE_FILE_SUFFIX` +# if [ ${#zonefiles_arr[@]} -eq 0 ] ; then +# for _zone_file in $_zone_files_ipv6 ; do +# zonefiles_arr+=("$_zone_file") +# done +# else +# for _zone_file in $_zone_files_ipv6 ; do +# containsElement "$_zone_file" ${zonefiles_arr[@]} && continue +# zonefiles_arr+=("$_zone_file") +# done +# fi +# done +#fi + + +echo "" +echo "" +echo -e "\033[37m\033[1mDetermine zone files conatining ip-adressse for which TTL time is requested to change..\033[m" + +_found=false +_is_master=false +zonefiles_arr=() +zonefiles_not_present_arr=() +zone_file="" +regex_master="type[[:space:]]+master" +regex_file="^[[:space:]]*file" +while IFS='' read -r _line || [[ -n $_line ]] ; do + + if [[ $_line =~ ^[[:space:]]*zone[[:space:]]+ ]]; then + _found=true + zone="$(echo $_line | awk '{print$2}')" + shopt -s extglob + if [[ $zone =~ \; ]]; then + zone=${zone%%*(\;)} + fi + if [[ $zone =~ ^\" ]]; then + zone=${zone##*(\")} + zone=${zone%%*(\")} + fi + shopt -u extglob + 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 + fi + + if [[ -n "${zone_file}" ]] ; then + if [[ ! -f "${zone_file}" ]] ; then + if ! containsElement "${zone_file}" "${zonefiles_not_present_arr[@]}" ; then + zonefiles_not_present_arr+=("${zone_file}") + fi + continue + fi + if ! $(echo ${zone_file} | grep -q -e "$ZONE_FILE_MASTER_DIR" 2> /dev/null) ; then + fatal "Zonefile to change does not live in directory '$ZONE_FILE_MASTER_DIR'! + + Zonefile to change: \033[33m${zone_file}\033[m" + fi + fi + + if [[ $_line =~ $regex_master ]]; then + _is_master=true + fi + if [[ "$_line" =~ ^[[:space:]]*\}[[:space:]]*\; ]]; then + if $_is_master && [[ -n "$zone_file" ]]; then + + + if $_set_ipv4 ; then + + for _ipv4_address in "${ipv4_addresses_arr[@]}" ; do + if $(grep -q -E "IN\s+A\s+$_ipv4_address" "$zone_file") ; then + if [ ${#zonefiles_arr[@]} -eq 0 ] ; then + zonefiles_arr+=("${zone_file}:$zone") + else + if ! containsElement "${zone_file}:$zone" "${zonefiles_arr[@]}" ; then + zonefiles_arr+=("${zone_file}:$zone") + fi + fi + fi + done + + fi + + if $_set_ipv6 ; then + + for _ipv6_address in "${ipv6_addresses_arr[@]}" ; do + if $(grep -q -E "IN\s+AAAA\s+$_ipv6_address" "$zone_file") > /dev/null 2>&1 ; then + if [ ${#zonefiles_arr[@]} -eq 0 ] ; then + zonefiles_arr+=("${zone_file}:$zone") + else + if ! containsElement "${zone_file}:$zone" "${zonefiles_arr[@]}" ; then + zonefiles_arr+=("${zone_file}:$zone") + fi + fi + fi + done + fi + + fi + _is_master=false + _found=false + zone_file="" + fi + fi +done < "$ZONES_DECLARATION_FILE" + +echo "" + + +#for _val in "${zonefiles_arr[@]}" ; do +# echo +# echo -e "$_val" +#done +# +#clean_up 0 + + + +for _val in ${zonefiles_arr[@]} ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + zone_file="${_val_arr[0]}" + zone="${_val_arr[1]}" + + echo -e "\n\tEditing \033[37m\033[1m$zone_file\033[m .." + + _replaced=false + + if $_set_ipv4 ; then + + for _ipv4_address in "${ipv4_addresses_arr[@]}" ; do + if $(grep -q -E "IN\s+A\s+$_ipv4_address" "$zone_file") ; then + + ## - setze neue ttl für ipv4 address + ## - + echononl "\t Set new TTL ($TTL) for IPv4 address $_ipv4_address .." + + if $(grep -q -E "\s+$TTL\s+IN\s+As+$_ipv4_address" $zone_file 2> /dev/null) ; then + echo_skipped + else + # Note: + # '\1${TTL}' in replace string DOES NOT work in perl regex. + # + sed -i -r -e"s#(\s+)([0-9]{2,5}\s+)?IN\s+A\s+$_ipv4_address#\1${TTL} IN A $_ipv4_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + _replaced=true + else + echo_failed + error "Setting new TTL for $_ipv4_address in zone file \"$zone_file\" failed!" + fi + fi + + if $_replaced && $IGNORE_ALT_HOSTNAMES ; then + echononl "\t Setting back hostnames containing \"-alt\".." + perl -i -n -p -e "s#^(.+(-alt)\s+)$TTL\s+IN\s+A\s+$_ipv4_address#\1IN A $_ipv4_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Setting back hostnames containing \"-alt\" for $_ipv4_address in zone file \"$zone_file\" failed!" + fi + fi + if $_replaced && $IGNORE_AUTOCONFIG_HOSTNAMES ; then + echononl "\t Setting back hostnames \"autoconfig.\".." + perl -i -n -p -e "s#^(\s*autoconfig\s+)$TTL\s+IN\s+A\s+$_ipv4_address#\1IN A $_ipv4_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Setting back hostnames containing \"-alt\" for $_ipv4_address in zone file \"$zone_file\" failed!" + fi + fi + fi + done + fi + + if $_set_ipv6 ; then + + for _ipv6_address in "${ipv6_addresses_arr[@]}" ; do + if $(grep -q -E "IN\s+AAAA\s+$_ipv6_address" "$zone_file") > /dev/null 2>&1 ; then + + ## - setze neue ttl für ipv6 address + ## - + echononl "\t Set new TTL ($TTL) for IPv6 address $_ipv6_address .." + + if $(grep -q -E "\s+$TTL\s+IN\s+AAAA\s+$_ipv6_address" $zone_file 2> /dev/null) ; then + echo_skipped + else + # Note: + # '\1${TTL}' in replace string DOES NOT work in perl regex. + # + sed -i -r -e"s#(\s+)([0-9]{2,5}\s+)?IN\s+AAAA\s+$_ipv6_address#\1${TTL} IN AAAA $_ipv6_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + _replaced=true + else + echo_failed + error "Setting new TTL for $_ipv6_address in zone file \"$zone_file\" failed!" + fi + fi + if $_replaced && $IGNORE_ALT_HOSTNAMES ; then + echononl "\t Setting back hostnames containing \"-alt\".." + perl -i -n -p -e "s#^(.+(-alt)\s+)$TTL\s+IN\s+AAAA\s+$_ipv6_address#\1IN AAAA $_ipv6_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Setting back hostnames containing \"-alt\" for $_ipv6_address in zone file \"$zone_file\" failed!" + fi + fi + if $_replaced && $IGNORE_AUTOCONFIG_HOSTNAMES ; then + echononl "\t Setting back hostnames \"autoconfig.\".." + perl -i -n -p -e "s#^(\s*autoconfig\s+)$TTL\s+IN\s+AAAA\s+$_ipv6_address#\1IN AAAA $_ipv6_address#" $zone_file > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_ok + else + echo_failed + error "Setting back hostnames containing \"-alt\" for $_ipv6_address in zone file \"$zone_file\" failed!" + fi + fi + fi + done + fi + + # - Calculate new serial + # - + echo "" + echononl "\t Calculate new serial" + if $_replaced ; then + declare -i __serial=`grep -e "[0-9]\{10\}" $zone_file | grep serial | awk '{print$1}'` + while [ ! $_serial_new -gt $__serial ]; do + let _serial_new++ + done + echo_done + else + echo_skipped + fi + + # - Set new serial + # - + echononl "\t Increase Serial for zone file \"`basename $zone_file`\"" + if $_replaced ; then + perl -i -n -p -e "s#^(\s*)\s$__serial(.*)#\1 $_serial_new\2#" $zone_file > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + error "Increasing Serial for zone file \"`basename $zone_file`\" failed!" + fi + else + echo_skipped + fi + + # - Reload Zone + # - + echononl "\t Reload zone '${zone}'" + if $_replaced ; then + /usr/sbin/rndc reload $zone > /dev/null 2>&1 + if [[ $? -gt 0 ]]; then + echo_failed + else + echo_ok + fi + else + echo_skipped + fi + +done + + +if [[ -d "${ZONE_FILE_MASTER_DIR}.${backup_date}" ]] ; then + diff -Nur "${ZONE_FILE_MASTER_DIR}" "${ZONE_FILE_MASTER_DIR}.${backup_date}" > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + info "No zone file has changed.\n\t Removing previously created backup" + echononl "\tDelete '${ZONE_FILE_MASTER_DIR}.${backup_date}'.." + rm -rf "${ZONE_FILE_MASTER_DIR}.${backup_date}" > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + fi + fi +fi + +if [[ ${#zonefiles_not_present_arr[@]} -gt 0 ]] ; then + echo "" + warn "The following zonefiles were not found!" + for _val in ${zonefiles_not_present_arr[@]} ; do + echo -e "\t $_val" + done +fi + + +echo "" +clean_up 0