2 Domtool (http
://hcoop
.sf
.net
/)
3 Copyright (C
) 2004 Adam Chlipala
5 This program is free software
; you can redistribute it
and/or
6 modify it under the terms
of the GNU General Public License
7 as published by the Free Software Foundation
; either version
2
8 of the License
, or (at your option
) any later version
.
10 This program is distributed
in the hope that it will be useful
,
11 but WITHOUT ANY WARRANTY
; without even the implied warranty
of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
. See the
13 GNU General Public License for more details
.
15 You should have received a copy
of the GNU General Public License
16 along
with this program
; if not
, write to the Free Software
17 Foundation
, Inc
., 59 Temple Place
- Suite
330, Boston
, MA
02111-1307, USA
.
20 (* Djbdns DNS mapping config
*)
22 structure Djbdns
:> DJBDNS
=
24 open Config DjbdnsConfig Util
26 val ldHandler
= ref (fn _
: string => ())
27 fun setLocalDomainHandler f
= ldHandler
:= f
29 val relayingHandler
= ref (fn _
: string => ())
30 fun setRelayingDomainHandler f
= relayingHandler
:= f
32 val dns
= ref (NONE
: TextIO.outstream option
)
35 (dns
:= SOME (TextIO.openOut (scratchDir ^
"/data.shared"));
36 ignore (OS
.Process
.system ("cd /tmp; " ^ rm ^
" -rf " ^ scratchDir ^
"/slaves/*"));
37 ignore (OS
.Process
.system ("cd /tmp; " ^ rm ^
" -rf " ^ afxrSlavesTemp
));
38 ignore (OS
.Process
.system (mkdir ^
" " ^ afxrSlavesTemp
)))
39 fun finish () = (TextIO.closeOut (valOf (!dns
));
42 fun handler (data
: Domtool
.handlerData
) =
45 val domain
= String.extract (#domain data
, 5, NONE
)
46 val parent
= #parent data
49 val slaves
= #slaves data
52 val _
= Domtool
.dprint ("Reading dns " ^ path ^
" for " ^ parent ^
"....")
54 val dns
= valOf (!dns
)
56 val al
= TextIO.openIn path
59 val hasEmail
= ref
false
60 val hasRelaying
= ref
false
61 val isSlave
= ref
false
63 fun loop (line
, (slaveDirs
, mxnum
, chans
, ttl
)) =
69 app (fn ch
=> TextIO.output (ch
, s
)) chans
71 fun err () = (Domtool
.error (path
, "Invalid entry: " ^ trimLast line
);
72 (slaveDirs
, mxnum
, chans
, ttl
))
74 case String.tokens
Char.isSpace line
of
75 [] => (slaveDirs
, mxnum
, chans
, ttl
)
77 (case resolveAddr (vars
, addr
) of
82 ignore (OS
.Process
.system (echo ^
" " ^ addr ^
" >> " ^ slaveDir ^
"/slaves/" ^ parent
)))
84 TextIO.output (dns
, "# Master for " ^ parent ^
": " ^ addr ^
"\n");
85 ignore (OS
.Process
.system (echo ^
" " ^ addr ^
" >> " ^ afxrSlavesTemp ^
"/" ^ parent
));
86 (slaveDirs
, mxnum
, chans
, ttl
)))
87 |
["TTL", "default"] => (slaveDirs
, mxnum
, chans
, "")
89 (case Int.fromString n
of
93 (slaveDirs
, mxnum
, chans
, ":" ^ n
)
96 |
["Default", addr
] =>
97 (case resolveAddr (vars
, addr
) of
99 | addr
=> (writeDns ("=" ^ parent ^
":" ^ addr ^ ttl ^
"\n");
100 (slaveDirs
, mxnum
, chans
, ttl
)))
102 (if validDomainUC host
then
103 (writeDns ("@" ^ parent ^
"::" ^ host ^
":" ^
Int.toString mxnum ^ ttl ^
"\n");
104 (slaveDirs
, mxnum
+1, chans
, ttl
))
107 |
["BackupMail", host
, addr
] =>
108 (case resolveAddr (vars
, addr
) of
111 (if not (!hasRelaying
) andalso member (addr
, localMailIps
) then
112 (hasRelaying
:= true;
113 !relayingHandler parent
)
116 if validHost host
then
117 (writeDns ("@" ^ parent ^
":" ^ addr ^
":" ^ host ^
"." ^ parent ^
":" ^
Int.toString mxnum ^ ttl ^
"\n");
118 (slaveDirs
, mxnum
+1, chans
, ttl
))
121 |
["Slave", slave
] =>
122 (case StringMap
.find (slaves
, slave
) of
123 NONE
=> (Domtool
.error ("Unknown slave " ^ slave ^
" in", path
);
124 (slaveDirs
, mxnum
, chans
, ttl
))
126 case String.fields (fn ch
=> ch
= #
";") addrs
of
129 val slaveDir
= scratchDir ^
"/slaves/" ^ slave
131 val _
= if Posix
.FileSys
.access (slaveDir
, []) then
134 (Posix
.FileSys
.mkdir (slaveDir
, Posix
.FileSys
.S
.irwxu
);
135 Posix
.FileSys
.mkdir (slaveDir ^
"/slaves", Posix
.FileSys
.S
.irwxu
))
137 val domFile
= slaveDir ^
"/" ^ domain ^
".dns"
139 val dest
= TextIO.openOut (slaveDir ^
"/destination")
140 val _
= TextIO.output (dest
, addr
)
141 val _
= TextIO.closeOut dest
143 val dest
= TextIO.openOut (slaveDir ^
"/slaves_destination")
144 val _
= TextIO.output (dest
, saddr
)
145 val _
= TextIO.closeOut dest
147 val chan
= TextIO.openOut domFile
149 writeDns ("# " ^ domain ^
" Slave " ^ slave ^
"\n");
150 (slaveDir
:: slaveDirs
, mxnum
, chan
:: chans
, ttl
)
152 | _
=> (Domtool
.error ("Bad slave format", path
);
153 (slaveDirs
, mxnum
, chans
, ttl
)))
154 |
["Primary", host
] =>
155 (case StringMap
.find (nses
, host
) of
156 NONE
=> (Domtool
.error ("Unknown outside name server: " ^ host
, path
);
157 (slaveDirs
, mxnum
, chans
, ttl
))
158 | SOME addr
=> (hasNs
:= true;
159 writeDns ("." ^ parent ^
":" ^ addr ^
":" ^ host ^ ttl ^
"\n");
160 (slaveDirs
, mxnum
, chans
, ttl
)))
161 |
["Secondary", host
] =>
162 (case StringMap
.find (nses
, host
) of
163 NONE
=> (Domtool
.error ("Unknown outside name server: " ^ host
, path
);
164 (slaveDirs
, mxnum
, chans
, ttl
))
165 | SOME addr
=> (hasNs
:= true;
166 writeDns ("&" ^ parent ^
":" ^ addr ^
":" ^ host ^ ttl ^
"\n");
167 (slaveDirs
, mxnum
, chans
, ttl
)))
168 |
[ty
, host
, addr
] =>
172 "Primary" => (hasNs
:= true; ".")
173 |
"Secondary" => (hasNs
:= true; "&")
181 (case resolveDomain (vars
, addr
) of
184 if validHost host
then
185 (writeDns (pre ^ host ^
"." ^ parent ^
":" ^ host
' ^ ttl ^
"\n");
186 (slaveDirs
, mxnum
, chans
, ttl
))
189 else case (resolveAddr (vars
, addr
), pre
) of
192 if validHost host
then
193 (writeDns (pre ^ parent ^
":" ^ addr ^
":" ^ host ^
"." ^ parent ^ ttl ^
"\n");
194 (slaveDirs
, mxnum
, chans
, ttl
))
198 if validHost host
then
199 (writeDns (pre ^ parent ^
":" ^ addr ^
":" ^ host ^
"." ^ parent ^ ttl ^
"\n");
200 (slaveDirs
, mxnum
, chans
, ttl
))
204 (if not (!hasEmail
) andalso member (addr
, localMailIps
) then
209 if validHost host
then
210 (writeDns (pre ^ parent ^
":" ^ addr ^
":" ^ host ^
"." ^ parent ^
":" ^
Int.toString mxnum ^ ttl ^
"\n");
211 (slaveDirs
, mxnum
+1, chans
, ttl
))
215 if validHost host
then
216 (writeDns (pre ^ host ^
"." ^ parent ^
":" ^ addr ^ ttl ^
"\n");
217 (slaveDirs
, mxnum
, chans
, ttl
))
221 if validHost host
then
222 (writeDns (pre ^ host ^
"." ^ parent ^
":" ^ addr ^ ttl ^
"\n");
223 (slaveDirs
, mxnum
, chans
, ttl
))
231 fun closeChans chans
=
233 [] => raise Fail
"closeChans should never reach an empty list!"
236 (TextIO.closeOut chan
;
239 val (slaveDirs
, _
, chans
, ttl
) = ioOptLoopFold (fn () => Domtool
.inputLine al
) loop ([], 0, [dns
], "")
245 app (fn ch
=> TextIO.output (ch
, s
)) chans
250 (writeDns ("." ^ parent ^
"::ns.hcoop.net" ^ ttl ^
"\n");
251 writeDns ("&" ^ parent ^
"::ns2.hcoop.net" ^ ttl ^
"\n"));
254 end handle ex
=> Domtool
.handleException (#path data
, ex
)
257 if OS
.Process
.isSuccess (OS
.Process
.system
258 (diff ^
" " ^ scratchDir ^
"/data.shared " ^ dataFile
)) then
260 else if not (OS
.Process
.isSuccess (OS
.Process
.system
261 (rm ^
" -rf " ^ afxrSlaves ^
"; " ^ mv ^
" -f " ^ afxrSlavesTemp ^
" " ^ afxrSlaves
))) then
262 (print
"Error copying AFXR slaves\n";
264 else if not (OS
.Process
.isSuccess (OS
.Process
.system
265 (chown ^
" -R root.root " ^ afxrSlaves
))) then
266 (print
"Error chown'ing AFXR slaves\n";
268 else if not (OS
.Process
.isSuccess (OS
.Process
.system
269 (cp ^
" " ^ scratchDir ^
"/data.shared " ^ dataFile
))) then
270 (print
"Error copying data.shared\n";
272 else if not (OS
.Process
.isSuccess (OS
.Process
.system pubCommand
)) then
273 (print
"Error publishing data.shared\n";
277 val slaveDir
= scratchDir ^
"/slaves"
278 val dir
= Posix
.FileSys
.opendir slaveDir
280 fun doEntry (name
, ()) =
282 val fullName
= slaveDir ^
"/" ^ name
283 val st
= Posix
.FileSys
.stat fullName
285 if Posix
.FileSys
.ST
.isDir st
then
287 (*if OS
.Process
.isSuccess (OS
.Process
.system (rsync ^
" -az --delete " ^ fullName ^
"/*.dns `" ^ cat ^
" " ^ fullName ^
"/destination`")) then
288 if OS
.Process
.isSuccess (OS
.Process
.system (rsync ^
" -az --delete " ^ fullName ^
"/slaves/* `" ^ cat ^
" " ^ fullName ^
"/slaves_destination`")) then
291 print ("Error sending sub-slaves to slave " ^ name ^
"\n")
293 print ("Error sending to slave " ^ name ^
"\n")*)
298 ioOptLoop (fn () => Posix
.FileSys
.readdir dir
) doEntry ();
299 Posix
.FileSys
.closedir dir
;
303 fun mkdom
{path
, ...} = OS
.Process
.system (cp ^
" " ^ defaultFile ^
" " ^ path ^
"/.dns")
305 val _
= Domtool
.setHandler (".dns", {init
= init
,