1
0
Files
irix-657m-src/eoe/cmd/bsd/bind/master/mkdns
2022-09-29 17:59:04 +03:00

443 lines
12 KiB
Bash
Executable File

#!/bin/sh
# "$Revision: 1.5 $"
# Synopsis:
# -v be verbose
# -t test; generate new files but do not install them
# -d domain choose a NIS domain other than the current NIS domain
# -i file use the contents of 'file' instead of `ypcat hosts`
# /etc/hosts is the most likely file.
# -n nets blank separated, quoted list of network numbers to generate
# .rev files, even if no host of the target domain is on
# them. For example, -n "192.26.81 192.99.44"
# -N nets blank separated, quoted list of networks to exclude
# from .rev files
# -m first-last,mask first and last IP addresses of subnet with mask
# -h hosts blank separated, quoted list of hosts on which
# 'rsh host -l guest ypcat hosts' will produce interesing
# hostnames.
# -H name hostname of this machine, if not available by the
# hostname command.
# -A ouraddr IP address of this machine, if not available by looking
# up the hostname of this machine in /etc/hosts.
# -s prf MX preference for ourself
# -x 'prf xchg' a pair of MX exchanger and preference, as in
# -x '10 foo.foo.com.'
# additional pairs can be given with additional occurances
# of -x
# -O dir save previous versions of data files in this directory
# This script generates data files for the BIND DNS nameserver, named, from
# a file (e.g. /etc/hosts) or a NIS hostname database. Because it can use
# NIS to obtain the data, the DNS master need not run on the same machine
# as the NIS master.
# This script is usually run from cron if it is generating the DNS database
# files from /etc/hosts. If cooperating with NIS, it is usually run
# from /var/yp/local.make.script. A sample local.make.script can
# be found in /var/named/mkdns.
# It uses two prototype SOA files, domain.soa (where "domain" is the NIS
# domain) and hosts.soa, to generate SOA records. It modifies the words
# SERIALNUMBER, HOSTNAME, and HOSTADDR in the prototypes, so that the
# prototypes can serve for more than one domain. Sample SOA prototype
# files are also in the examples directory.
# Besides generating the hosts data file and the reverse map data file, it
# also modifies the named.boot file to point to the other files. These
# modifications of the named.boot file are delimited by a pair of lines,
# allowing this script to modify only the part of named.boot that it owns.
# "Foreign" DNS hosts that happen to be in the the NIS or /etc/hosts input
# can be excluded from the results, even if the foreigners have aliases in
# the target domain. This is the purpose of the -N arg.
# Much of the complexity of this script comes from generating CNAME
# records and the reverse maps. Both are done with awk scripts. The
# difficulty with the CNAME records is recognizing only those aliases that
# should appear in the DNS database. The difficulty with the reverse maps
# is generating separate files for each of the IN-ADDR.ARPA domains implied
# by the set of host numbers present in the input data.
# When new versions of the files have been generated, this script
# installs them only if they differ substantitively. If it does install
# new files, it signals the nameserver daemon.
USAGE="`basename $0`: [-vt] [-d domain] [-i file] [-n nets] [-N nets] [-h hosts] [-H ourname] [-A ouraddr] [-s prf] [-x 'prf xchg'] "
if [ -x /usr/bin/domainname ]
then
domain=`domainname`
fi
name=`hostname | sed -e "s/^[^.]*$/&.$domain/"`
olddir=old
while getopts "vtd:i:n:N:m:h:H:A:s:x:O:" c; do
case $c in
v) set -x;;
t) dotest="y";;
d) domain=`echo "$OPTARG" | tr '[A-Z]' [a-z]'`;;
i) ifile="$OPTARG"
if test ! -f $ifile; then
echo "`basename $0`: $OPTARG: no such file"
exit 1
fi
;;
n) nets="$nets "`echo "$OPTARG" | sed -e 's@[^ ]*@/^&./bprint@g'`;;
N) nets="$nets "`echo "$OPTARG" | sed -e 's@[^ ]*@/^&./d@g'`;;
m) if test -z "$masks"; then
masks="$OPTARG"
else
masks="$masks $OPTARG"
fi
;;
h) hosts="$hosts $OPTARG";;
H) name="$OPTARG";;
A) addr="$OPTARG";;
s) mypref="$OPTARG";;
x) mxs="$mxs\t\t\t MX `echo $OPTARG | sed 's/ */ \\\t/'`\n";;
O) olddir="$OPTARG"
if test ! -d "$olddir"; then
echo "`basename $0`: $OPTARG: no such directory"
exit 1
fi
;;
\?) echo $USAGE; exit 1;;
esac
done
if [ -z "$domain" ]
then
echo "please used -d option to specify domain name"
exit
fi
shift `expr $OPTIND - 1`
if test "$#" != 0; then
echo $USAGE
exit 1
fi
if test -n "$dotest"; then
tmpfile="/tmp/mkdns.tmp"
tmp2file="/tmp/gen2n"
tmp3file="/tmp/gen3n"
tmpsoa="/tmp/gensoa"
tmpsed="/tmp/gensed"
testdir=/tmp/
else
tmpfile="/tmp/mkdns$$"
tmp2file="/tmp/gen2n$$"
tmp3file="/tmp/gen3n$$"
tmpsoa="/tmp/gensoa$$"
tmpsed="/tmp/gensed$$"
testdir=""
rem="$tmpfile $tmp2file $tmp3file $tmpsoa $tmpsed"
trap "/bin/rm -f $rem" 0 1 2 15
fi
cd /var/named
# chose short version of domain name
subdomain=`expr "$domain" : '\([^.]*\)\..*'`
# literalized version
litdomain=`echo ".$domain" | sed 's/\./\\\./g'`
# find our network address, the addresss of the server
if test "$addr" = ""; then
addr=`egrep "^[0-9.]*[ ][ ]*$name[. ]|^[0-9.]*[ ][ ]*[ ]$name'$'" /etc/hosts \
| sed -e '2,$d' -e "s/[ ].*//"`
fi
new="new"
hostfile="$subdomain.hosts"
revfile="$subdomain.%s.rev"
nboot="named.boot"
nnboot="$testdir$nboot.$new"
soa="$subdomain.soa"
if test -f $testdir${subdomain}*.$new $nnboot $rem; then
# remove previous crop of new files
rm -f $testdir${subdomain}*.$new $nnboot $rem
fi
# generate a sed script to find network numbers and hostnames for the
# interesting networks.
echo "s/ \{2,\}/ /g" > $tmpsed
echo "/^[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\} [^ ]/!d" >> $tmpsed
echo "s/^\([^.]*\).\([^.]*\).\([^.]*\).\([^ ]*\) \([^ ]*\).*/\1 \2 \3 \4 \5/" >> $tmpsed
echo "$nets" | tr ' ' '\12' | sed -e '/^$/d' -e 's/\./ /g' >> $tmpsed
if test ! -s "$soa"; then
echo "`basename $0`: $soa is missing"
exit 1
fi
serial=`date '+%y%j%H%M'`
sed -e "s/SERIALNUMBER/$serial/g" \
-e "s/HOSTNAME/$name/g" -e "s/HOSTADDR/$addr/g" $soa > $tmpsoa
if test ! -s "$nboot"; then
echo "`basename $0`: $nboot is missing"
exit 1
fi
fline="; do not delete this 1st line--generated by mkdns"
lline="; do not delete this 2nd line--generated by mkdns"
sed -e "/^$fline/,"'$d' $nboot > $nnboot
echo "$fline" >> $nnboot
# Generate the SOA records.
cp $tmpsoa $testdir$hostfile.$new
if test -s ${subdomain}.hosts.soa; then
sed -e "s/SERIALNUMBER/$serial/g" \
-e "s/HOSTNAME/$name/g" -e "s/HOSTADDR/$addr/g" \
${subdomain}.hosts.soa >> $testdir$hostfile.$new
fi
# Get the data from NIS
if test $ifile; then
cat $ifile | tr '[A-Z] ' '[a-z] ' > $tmpfile
else
#it seems to take more than one try to get a server
ypcat -d $domain hosts.byaddr 2>/dev/null \
| tr '[A-Z] ' '[a-z] ' >$tmpfile
# it sometimes takes a while to find a server
if test ! -s "$tmpfile"; then
sleep 5
ypcat -d $domain hosts.byaddr | tr '[A-Z] ' '[a-z] ' >$tmpfile
if test ! -s "$tmpfile"; then
echo "`basename $0`: unable to obtain NIS host information"
exit 1
fi
fi
fi
cp $tmpfile $tmp3file
for nm in $hosts; do
rsh $nm -n -l guest ypcat hosts > $tmp2file
if test ! -s $tmp2file; then
echo "`basename $0`: no hosts from $nm"
exit 1
fi
cat $tmp2file | tr '[A-Z] ' '[a-z] ' >> $tmp3file
done
# Delete non-host lines, add a trailing blank, and remove extra blanks.
# Delete hosts at least one of whose names does not include the
# target domain.
# Delete aliases with the wrong domain name.
# Remove the domain from all names.
# Remove domain-names of the wrong domain.
# Then replace the periods in the address with blanks.
sed -e "/^[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\} /!d" \
-e "s/.*/& /" -e "s/ \{2,\}/ /g" \
-e "/ [^.]*$litdomain /!d" \
-e "s/$litdomain / /g" \
-e "s/ [^ ]*\.[^ ]*//g" \
-e "/^[0-9.]* *$/d" \
-e "s/^\([^.]*\).\([^.]*\).\([^.]*\)./\1 \2 \3 /" \
-e "s/ \{2,\}/ /g" \
$tmp3file \
| sort -u -n +1n -2 +2n -3 +3n -4 \
| nawk 'BEGIN {
new = "'"$new"'"
hostfile = "'"$hostfile"'"
newhostfile = "'"$testdir$hostfile.$new"'"
domain = "'"$domain"'"
newnboot = "'"$nnboot"'"
tmpsed = "'"$tmpsed"'"
mypref = "'"$mypref"'"
mxs = "'"$mxs"'"
printf "primary %-30s %s\n",
domain, hostfile >> newnboot
}
{
host = $5
printf "%-23s IN A %s\n", host,
($1 "." $2 "." $3 "." $4) >> newhostfile
if (mypref != "") {
printf "\t\t\t MX %-2d \t%s\n",
mypref, host >> newhostfile
}
printf mxs >> newhostfile
for (i = 6; i <= NF; i++) {
for (j = 5; j < i; j++) {
if ($i == $j)
break
}
if (j >= i) {
printf "%-23s IN CNAME\t%s\n", $i,
host >> newhostfile
}
}
newpat = "/^" $1 " "
if ($1 >= 128) {
newpat = newpat $2 " "
if ($1 >= 192) {
newpat = newpat $3 " "
}
}
if (newpat != pat) {
pat = newpat
print (pat "/bprint") >> tmpsed
}
}'
echo "d\n:print" >> $tmpsed
sed -f $tmpsed $tmp3file \
| sort -u -n +1n -2 +2n -3 +3n -4 \
| nawk 'BEGIN {
OFMT = "%10.0f"
new = "'"$new"'"
testdir = "'"$testdir"'"
revfile = "'"$revfile"'"
domain = "'"$domain"'"
newnboot = "'"$nnboot"'"
tmpsoa = "'"$tmpsoa"'"
net = -1
maskz = 256*256*256*256
maska = 256*256*256
maskb = 256*256
maskc = 256
split("'"$masks"'", t, " ")
for (i in t) {
split(t[i], m, ",")
if (m[1] ~ /\./) {
split(m[1], a, ".")
m[1] = ((a[1] * 256 + a[2]) * 256 + a[3]) * 256 + a[4]
}
if (m[2] ~ /\./) {
split(m[2], a, ".")
m[2] = ((a[1] * 256 + a[2]) * 256 + a[3]) * 256 + a[4]
}
if (m[3] ~ /\./) {
split(m[3], a, ".")
m[3] = ((a[1] * 256 + a[2]) * 256 + a[3]) * 256 + a[4]
}
m[3] = maskz - m[3]
masks[m[1]] = m[3]
hi[m[1]] = m[2]
}
}
func revhost(n,mask) {
n %= mask
r = n%256
n = int(n/256)
if (mask > maskc) {
r = r "." (n%256)
n = int(n/256)
if (mask > maskb) {
r = r "." (n%256)
n = int(n/256)
if (mask > maska) {
r = r "." (n%256)
}
}
}
return r
}
{
host = $5
addr = (($1 * 256 + $2) * 256 + $3) * 256 + $4
if ($1 == "127" && $2 == "0" && $3 == "0") {
netmask = maskc
} else {
if (host !~ /\./) host = host "." domain
if ($1 < 128) {
netmask = maska
} else if ($1 < 192) {
netmask = maskb
} else {
netmask = maskc
}
for (lo in masks) {
if (addr >= lo && addr <= hi[lo]) {
netmask = masks[lo]
break
}
}
}
newnet = int(addr/netmask)
if (newnet != net) {
if (curfile != "") {
close(curfile)
}
net = newnet
revnet = revhost(net,int(maskz/netmask))
curfile = sprintf(revfile,revnet)
printf "primary %-30s %s\n",
(revnet ".IN-ADDR.ARPA"), curfile >> newnboot
curfile = (testdir curfile "." new)
system("cp " tmpsoa " " curfile)
}
printf "%-10s IN PTR %s.\n",
revhost(addr,netmask), host >> curfile
}'
echo "$lline" >> $nnboot
sed -e "1,/^$lline/d" $nboot >> $nnboot
if test "$dotest"; then
exit 0
fi
# do not stop now
trap "" 1 2 15
# delete obsolete files
if test -d "$olddir" -a -n "$dotest"; then
for oldnm in ${subdomain}*.hosts ${subdomain}*.rev $nboot; do
if test -f $oldnm -a ! -f $oldnm.$new; then
oldnms="$oldnms $oldnm"
rm -f $olddir/$oldnm
mv $oldnm $olddir/$oldnm
fi
done
fi
# install new versions
for newnm in ${testdir}${subdomain}*.new $nnboot; do
oldnm=`expr $newnm : '\(.*\)\.'"$new"`
if cmp -s $newnm $oldnm; then
rm -f $newnm
elif test ! -f $oldnm; then
mv -f $newnm $oldnm
elif test 0 -ne `diff $newnm $oldnm \
| sed -e '/^[-0-9]/d' -e '/^[<>][0-9; ]*Serial$/d' \
| wc -l`; then : ;
if test -d "$olddir"; then
rm -f $olddir/$oldnm
ln $oldnm $olddir/$oldnm
fi
mv -f $newnm $oldnm
else
rm -f $newnm
fi
done
rm -f $oldnms
killall 1 named
exit 0