chiark / gitweb /
4bba39c595a4b9972fb85fd97384373fa436585b
[chiark-utils.git] / scripts / named-conf
1 #!/bin/bash
2 set -e
3 base=/var/named
4 conf=$base/conf
5 etcfile=/etc/named/zones-rgc
6
7 check=true
8 install=false
9 hostdelg=false
10 hostzone=false
11 progress=true
12 usage=true
13
14 while [ $# -gt 0 ]
15 do
16         case "$1" in
17         -f)     usage=false; check=false; install=true ;;
18         -y)     usage=false; check=true; install=true ;;
19         -n)     usage=false; check=true; install=false ;;
20         -h)     hostdelg=true; hostzone=false ;;
21         -z)     hostdelg=true; hostzone=true ;;
22         -q)     progress=false ;;
23         *)      echo >&2 "$0: usage: $0 [-y|-f] [-h|-z] [-q]"; exit 3 ;;
24         esac
25         shift
26 done
27
28 if $usage
29 then
30         cat <<END >&2
31 usage: named-conf-regen -f|-y|-n [-h|-z]
32 operation modes:
33  -f   install without checking  } but you must then
34  -y   check and install         }  ndc reload
35  -n   check only
36 additional options:
37  -h   check output from host -C
38  -z   check output from host -C and host -val
39 END
40         exit 1
41 fi
42
43 beginfile () {
44         if $install
45         then
46                 exec >$conf/$1.new
47         else
48                 exec >/dev/null
49         fi
50         currentfile=$1
51 }
52
53 endfile () {
54         exec >/dev/null
55         files="$files $currentfile"
56 }
57
58 installfiles () {
59         if $install
60         then
61                 cd $conf
62                 for f in $files
63                 do
64                         mv -f $f.new $f
65                 done
66         fi
67 }
68
69 warnings=0
70
71 warning () {
72         echo >&2 "$zone $style: $*"
73         warnings=$[$warnings+1]
74 }
75
76 equlines () {
77         if [ "x`echo \" $2\" | wc -l`" != "x`echo \" $3\" | wc -l`" ]
78         then
79                 warning "$1 >$2|$3<"
80         fi
81 }
82
83 checkhostout () {
84         set +e
85         hostout="`host $1 \"$zone\" 2>&1 >/dev/null $2 | egrep -v \
86 '^ \!\!\! .* SOA primary .* is not advertised via NS$'`"
87         set -e
88         if [ "x$hostout" = x ]; then return; fi
89         if $hostfirstwarn
90         then
91                 warning "warnings from host:"
92                 hostfirstwarn=false
93         fi
94         echo >&2 "$hostout"
95 }
96
97 progress () {
98         if $progress
99         then
100                 echo -n "$zone $style                    " >&2
101                 echo -ne '\r' >&2
102         fi
103 }
104
105 cd $base/primary
106 zones="*_db"
107
108 beginfile primary.zones
109 for f in $zones
110 do
111         zone="`echo $f | sed -e 's/_db$//'`"
112         cat <<END
113 zone "$zone" {
114         type master;
115         file "primary/$f";
116 };
117 END
118 done
119 endfile
120
121 myname=''
122
123 beginfile secondary.zones
124 exec <$etcfile
125 while read style zone servers
126 do
127         names=''
128         case "$style" in
129         myname)
130                 myname=$zone
131                 continue
132                 ;;
133         secondary)
134                 progress
135                 file="slave/$zone"
136                 if $check
137                 then
138                         rectype=SOA
139                         set -e; soa="`host -t soa $zone.`"; set +e
140                         soaname="`echo \" $soa\" | expand | sed -e '
141                                 s/^ [^ ][^ ]*  *SOA  *//; s/ .*$//; q
142                         '`"
143                         equlines SOA "$soaname" ''
144                 fi
145                 ;;
146         backup|unoff)
147                 progress
148                 rectype=NS
149                 file="slave/$zone"
150                 ;;
151         '#'|'')
152                 continue
153                 ;;
154         *)
155                 echo >&2 "$etcfile: $style"
156                 exit 3
157         esac
158
159         if $check
160         then
161                 set -e; ns="`host -t ns $zone.`"; set +e
162                 nsnames="`echo \" $ns\" | expand | tr A-Z a-z | sed -n '
163                         1s/^ //
164                         s/^[^ ][^ ]*  *ns  *\([0-9a-z][-.0-9a-z]*\)$/\1/p
165                 '`"
166                 equlines NS "$nsnames" "$ns"
167                 nsnames="`echo $nsnames | tr '
168 ' ' '`"
169
170                 if [ "x$myname" != x ]
171                 then
172                         meadvert=false
173                         for ns in $nsnames
174                         do
175                                 if [ "x$myname" = "x$ns" ]
176                                 then
177                                         meadvert=true
178                                 fi
179                         done
180                 fi
181
182                 case "$style" in
183                 secondary)      names="$soaname"        ;;
184                 unoff|backup)   names="$nsnames"        ;;
185                 esac
186
187                 case "$style" in
188                 secondary|backup)
189                         if [ $meadvert = false ]
190                         then
191                                 warning "$myname unlisted NS $nsnames"
192                         fi
193                         ;;
194                 unoff)
195                         if $meadvert = false
196                         then
197                                 warning "$myname advertised NS $nsnames"
198                         fi
199                         ;;
200                 esac
201
202                 addrs=''
203                 for ns in $names
204                 do
205                         set -e; a="`host -t a \"$ns\".`"; set +e
206                         taddrs="`echo \" $a\" | expand | sed -n '
207                                  1s/^ //
208                                 s/^[^ ][^ ]*  *A  *\([0-9][.0-9]*\)/\1/p
209                         '`"
210                         equlines "A $ns" "$a" "$taddrs"
211                         addrs="$addrs $taddrs"
212                 done
213         fi
214
215         cat <<END
216 zone "$zone" {
217         type slave;
218         file "$file";
219         masters {
220 END
221         for server in $servers
222         do
223                 echo "          $server;"
224                 if $check
225                 then
226                         notfound=true
227                         for addr in $addrs
228                         do
229                                 if [ "x$addr" = "x$server" ]
230                                 then
231                                         notfound=false
232                                 fi
233                         done
234                         if $notfound
235                         then
236  warning "server $server? but $rectype $names" $addrs
237                         fi
238                 fi
239         done
240         cat <<END
241         };
242 };
243 END
244         hostfirstwarn=true
245         if $hostdelg
246         then
247                 checkhostout -C
248         fi
249         if $hostzone
250         then
251                 checkhostout -val localhost
252         fi
253 done
254 endfile
255
256 if [ $warnings != 0 ]
257 then
258         echo >&2 "$warnings warnings                                        "
259 fi
260
261 installfiles