dns-scripts/dns-functions.sh

178 lines
5.8 KiB
Bash
Executable File

#!/bin/sh
GetZoneFileSerial() {
if [ -f "$1" ]; then
INSOASpec="^\s*\S\+\s\+\([0-9]*\s\)\?\s*IN\s\+SOA\s\+"
FirstSOALineAndFollowing="/""$INSOASpec""/,\$!d;"
RemoveComments=":a;s/;.*$//g;"
RemoveLineBreaks=":a;N;\$!ba;s/\n//g;"
SearchPrintSerial="s/""$INSOASpec""\S\+\s\+\S\+\s\+\((\s\)\?\s*\([0-9]*\).*/\3/i"
ZoneSerial=$(sed -e "$FirstSOALineAndFollowing""$RemoveComments""$RemoveLineBreaks""$SearchPrintSerial" "$1")
fi
echo "${ZoneSerial:-0}"
}
InsertZoneToIncludeFile() {
if [ ! -f "$3" ]; then
{
echo "zone \"""$1""\" {"
echo " type master;"
echo " file \"""$2""\";"
echo "};"
} > "$3"
else
sed -i "1i\
zone \"""$1""\" {\n\
type master;\n\
file \"""$2""\";\n\
};" "$3"
fi
}
GetReverseZoneFileFromZone() {
echo "db.""$(echo "$1" | awk -F. '{ printf $(NF-2);for(i=NF-3;i>0;--i) printf "."$i}')"
}
FillIPv4MissingBlocks() {
echo "$1" | sed -ne 's/^\([^.]\+\)\.\(\([^.]\+\)\.\)\?\(\([^.]\+\)\.\)\?\([^.]\+\)$/\1.\3.\5.\6/p' | sed -r 's/\.\./\.0\./g;s/\.\./\.0\./g'
}
GetReverseIPv4Domains() {
IPFilled="$(FillIPv4MissingBlocks "${1%/*}")"
Mask="${1##*/}"
Statics=$((Mask / 8))
Filler=$((Mask % 8))
RevDomain="$(echo "$IPFilled" | awk -F. '{for(i='"$Statics"';i>0;--i)printf "."$i}')"".in-addr.arpa."
if [ $Filler -eq 0 ]; then
echo "${RevDomain#.}"
else
Filler=$((8 - Filler))
Filler=$((1 << Filler))
Start=$(echo "$IPFilled" | awk -F. '{printf $'"$((Statics+1))"'}')
Start=$((Start - Start % Filler))
for Sub in $(seq $Start $((Start + Filler - 1))); do
echo "$Sub""$RevDomain"
done
fi
}
FillIPv6Zeroes() {
echo "$1" | awk -F: 'BEGIN{OFS=""}{FillCount=9-NF; for(i=1;i<=NF;i++){if(length($i)!=0||i==1||i==NF) {$i=substr(("0000" $i), length($i)+1);} else {for(j=1;j<=FillCount;j++){$i=($i "0000");}}}; print}'
}
GetReverseIPv6Domains() {
IPFilled="$(FillIPv6Zeroes "$(echo "${1%/*}" | awk '{print tolower($0)}')")"
Mask="${1##*/}"
Statics=$((Mask / 4))
Filler=$((Mask % 4))
RevDomain="$(echo "$IPFilled" | awk 'BEGIN{FS=""}{for(i='"$Statics"';i>0;i--) printf "." $i;}')"".ip6.arpa."
if [ $Filler -eq 0 ]; then
echo "${RevDomain#.}"
else
Filler=$((4 - Filler))
Filler=$((1 << Filler))
Start="$(printf %d 0x"$(echo "$IPFilled" | awk 'BEGIN{FS=""}{printf $'"$((Statics+1))"'}')")"
Start=$((Start - Start % Filler))
for Sub in $(seq $Start $((Start + Filler - 1))); do
echo "$(printf %x "$Sub")""$RevDomain"
done
fi
}
GetReverseDomains() {
Subnet="$1"
if IsValidIPv4Subnet "$Subnet"; then
GetReverseIPv4Domains "$Subnet"
elif IsValidIPv6Subnet "$Subnet"; then
GetReverseIPv6Domains "$Subnet"
else
TraceErrAndExit "$1"" is no valid Subnet"
fi
}
ExpandHostname() {
Hostname="$1"
[ -n "${Hostname##*.}" ] && Hostname="$Hostname"".""$2"
echo "$Hostname"
}
GetServernameSEDEntry() {
CommunityName="$1"
ServerName="$DNSSCRIPT_SERVER_NAME"
if [ -z "${ServerName##*$CommunityName}" ]; then
ServerName="\(""$ServerName"".\|""${ServerName%*.$CommunityName}""\)"
else
ServerName="\(""$ServerName"".\)"
fi
echo "$ServerName" | sed -r 's/\./\\\./g'
}
NormalizeZoneFileFormatting() {
awk 'BEGIN{FS="\t"}{l=length($1);f=substr(" ", 1+length($1));
s=substr(" ", 1+length($2));
x=substr($0,length($1)+length($2)+3);
print $1 f " " $2 s " " x}'
}
GetOwnGlueRecords() {
ServerName="$DNSSCRIPT_SERVER_NAME"
if [ -n "${ServerName##*$1}" ]; then
ServerName="$ServerName""$1"
fi
ServerName="$ServerName""."
sed -ne 's/^\s*'"$(GetServernameSEDEntry "$1")"'\s\+[Ii][Nn]\s\+\([Aa]\|[Aa]\{4\}\)\s\+\(.*\)$/'"$ServerName"'\tIN \2\t\3/p' "$2" | \
NormalizeZoneFileFormatting
}
GetOwnHoods() {
Entries="$(sed -ne "s/^\s*\(\S*\).*\s\+[Ii][Nn]\s\+[Nn][Ss]\s\+""$(GetServernameSEDEntry "$1")""\s*;\s*Subnets:\s*\([^;]*\)/\1 \3/p" "$2")"
Entries="$(echo "$Entries" | sed -r 's/\s+/#/g')"
echo "$Entries"
}
IsValidIPv4Subnet() {
[ -n "$(echo "$1" | sed -e '/[^/]*\/\([12]\?[0-9]\|3[0-2]\)$/!d')" ] && IsValidIPv4 "${1%/*}"
return $?
}
IsValidIPv4() {
[ -n "$(echo "$1" | sed -e '/^\(\(25[0-5]\|\(2[0-4]\|1[0-9]\|[1-9]\)\?[0-9]\)\.\)\{0,3\}\(25[0-5]\|\(2[0-4]\|1[0-9]\|[1-9]\)\?[0-9]\)$/!d')" ]
return $?
}
IsValidIPv6Subnet() {
[ -n "$(echo "$1" | sed -e '/[^/]*\/\([1-9]\?[0-9]\|1\([01][0-9]\|2[0-8]\)\)$/!d')" ] && IsValidIPv6 "${1%/*}"
return $?
}
IsValidIPv6() {
Max8BlocksMax4Hex="/^\([0-9a-fA-F]\{0,4\}[:]\{1,2\}\)\{1,7\}[0-9a-fA-F]\{0,4\}$/!d;"
MaxOneDoubleColon="/^.*::.*::.*$/d;"
SingleColon8BlocksOrNoSingleColonBeginEnd="/^\(\([^:]\+:\)\{7\}[^:]\+\|\(\|[^:].*\)::\(\|.*[^:]\)\)$/!d"
[ -n "$(echo "$1" | sed -e "$Max8BlocksMax4Hex""$MaxOneDoubleColon""$SingleColon8BlocksOrNoSingleColonBeginEnd")" ]
return $?
}
IPv4IsInSubnet() {
IPFilled="$(FillIPv4MissingBlocks "$1")"
SubnetIPFilled="$(FillIPv4MissingBlocks "${2%/*}")"
Mask="${2##*/}"
Statics=$((Mask / 8))
BlockMask=$((Mask % 8))
IPStaticPart="$(echo "$IPFilled" | awk -F. '{for(i='"$Statics"';i>0;--i)printf "."$i}')"
SubnetStaticPart="$(echo "$SubnetIPFilled" | awk -F. '{for(i='"$Statics"';i>0;--i) printf "."$i}')"
AreEqual="$([ "$IPStaticPart" = "$SubnetStaticPart" ]; echo "$?")"
if [ $AreEqual -eq 0 ] && [ $BlockMask -ne 0 ]; then
BlockMask=$((8 - BlockMask))
BlockMask=$((-1 << BlockMask))
IPBlock=$(echo "$IPFilled" | awk -F. '{printf $'"$((Statics+1))"'}')
SubnetBlock=$(echo "$SubnetIPFilled" | awk -F. '{printf $'"$((Statics+1))"'}')
IPBlock=$((IPBlock & BlockMask))
SubnetBlock=$((SubnetBlock & BlockMask))
AreEqual="$([ $IPBlock -eq $SubnetBlock ]; echo "$?")"
fi
return $AreEqual
}
ReloadZone() {
if [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 0 ]; then
systemctl reload bind9
elif [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 1 ]; then
for Zone in $2; do
rndc reload "$1" IN "$Zone" || touch "/tmp/dnsscript-forcereconf"
done
elif [ $((DNSSCRIPT_BIND_RELOAD_VER)) -eq 2 ]; then
/etc/init.d/named reload
fi
}
TraceErrAndExit() {
echo "$1" 1>&2
exit 1
}