3 # Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
4 # Copyright (C) 2000, 2001 Internet Software Consortium.
6 # Permission to use, copy, modify, and/or distribute this software for any
7 # purpose with or without fee is hereby granted, provided that the above
8 # copyright notice and this permission notice appear in all copies.
10 # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 # AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 # PERFORMANCE OF THIS SOFTWARE.
19 # Dynamic update test suite.
23 # perl update_test.pl [-s server] [-p port] zone
25 # The server defaults to 127.0.0.1.
26 # The port defaults to 53.
28 # The "Special NS rules" tests will only work correctly if the
29 # zone has no NS records to begin with, or alternatively has a
30 # single NS record pointing at the name "ns1" (relative to
35 # This program uses the Net::DNS::Resolver module.
36 # You can install it by saying
38 # perl -MCPAN -e "install Net::DNS"
40 # Id: update_test.pl,v 1.10 2007/06/19 23:47:04 tbox Exp
46 use Net
::DNS
::Resolver
;
53 $res = new Net
::DNS
::Resolver
;
54 $res->nameservers($opt_s);
56 $res->defnames(0); # Do not append default domain.
59 "usage: perl update_test.pl [-s server] [-p port] zone\n";
66 my ($cond, $explanation) = @_;
68 print "I:Test Failed: $explanation ***\n";
74 my ($expected, @records) = @_;
76 my $update = new Net
::DNS
::Update
("$zone");
78 foreach $rec (@records) {
82 $reply = $res->send($update);
86 my $rcode = $reply->header->rcode;
87 assert
($rcode eq $expected, "expected $expected, got $rcode");
89 print "I:Update failed: ", $res->errorstring, "\n";
98 section
("Delete any leftovers from previous tests");
99 test
("NOERROR", ["update", rr_del
("a.$zone")]);
100 test
("NOERROR", ["update", rr_del
("b.$zone")]);
101 test
("NOERROR", ["update", rr_del
("c.$zone")]);
102 test
("NOERROR", ["update", rr_del
("d.$zone")]);
103 test
("NOERROR", ["update", rr_del
("e.$zone")]);
104 test
("NOERROR", ["update", rr_del
("f.$zone")]);
105 test
("NOERROR", ["update", rr_del
("ns.s.$zone")]);
106 test
("NOERROR", ["update", rr_del
("s.$zone")]);
107 test
("NOERROR", ["update", rr_del
("t.$zone")]);
108 test
("NOERROR", ["update", rr_del
("*.$zone")]);
109 test
("NOERROR", ["update", rr_del
("u.$zone")]);
110 test
("NOERROR", ["update", rr_del
("a.u.$zone")]);
111 test
("NOERROR", ["update", rr_del
("b.u.$zone")]);
113 section
("Simple prerequisites in the absence of data");
115 test
("NXDOMAIN", ["pre", yxdomain
("a.$zone")]);
116 # RRset exists (value independent)
117 test
("NXRRSET", ["pre", yxrrset
("a.$zone A")]);
119 test
("NOERROR", ["pre", nxdomain
("a.$zone")]);
120 # RRset does not exist
121 test
("NOERROR", ["pre", nxrrset
("a.$zone A")]);
122 # RRset exists (value dependent)
123 test
("NXRRSET", ["pre", yxrrset
("a.$zone 300 A 73.80.65.49")]);
126 section
("Simple creation of data");
127 test
("NOERROR", ["update", rr_add
("a.$zone 300 A 73.80.65.49")]);
129 section
("Simple prerequisites in the presence of data");
131 test
("NOERROR", ["pre", yxdomain
("a.$zone")]);
132 # RRset exists (value independent)
133 test
("NOERROR", ["pre", yxrrset
("a.$zone A")]);
135 test
("YXDOMAIN", ["pre", nxdomain
("a.$zone")]);
136 # RRset does not exist
137 test
("YXRRSET", ["pre", nxrrset
("a.$zone A")]);
138 # RRset exists (value dependent)
139 test
("NOERROR", ["pre", yxrrset
("a.$zone 300 A 73.80.65.49")]);
144 test
("NOERROR", ["update", rr_add
("a.$zone 300 A 73.80.65.50")]);
146 section
("Detailed tests of \"RRset exists (value dependent)\" prerequisites");
147 test
("NOERROR", ["pre",
148 yxrrset
("a.$zone 300 A 73.80.65.49"),
149 yxrrset
("a.$zone 300 A 73.80.65.50")]);
150 test
("NOERROR", ["pre",
151 yxrrset
("a.$zone 300 A 73.80.65.50"),
152 yxrrset
("a.$zone 300 A 73.80.65.49")]);
153 test
("NXRRSET", ["pre", yxrrset
("a.$zone 300 A 73.80.65.49")]);
154 test
("NXRRSET", ["pre", yxrrset
("a.$zone 300 A 73.80.65.50")]);
155 test
("NXRRSET", ["pre",
156 yxrrset
("a.$zone 300 A 73.80.65.49"),
157 yxrrset
("a.$zone 300 A 73.80.65.50"),
158 yxrrset
("a.$zone 300 A 73.80.65.51")]);
161 section
("Torture test of \"RRset exists (value dependent)\" prerequisites.");
163 test
("NOERROR", ["update",
164 rr_add
("e.$zone 300 A 73.80.65.49"),
165 rr_add
("e.$zone 300 TXT 'one'"),
166 rr_add
("e.$zone 300 A 73.80.65.50")]);
167 test
("NOERROR", ["update",
168 rr_add
("e.$zone 300 A 73.80.65.52"),
169 rr_add
("f.$zone 300 A 73.80.65.52"),
170 rr_add
("e.$zone 300 A 73.80.65.51")]);
171 test
("NOERROR", ["update",
172 rr_add
("e.$zone 300 TXT 'three'"),
173 rr_add
("e.$zone 300 TXT 'two'")]);
174 test
("NOERROR", ["update",
175 rr_add
("e.$zone 300 MX 10 mail.$zone")]);
177 test
("NOERROR", ["pre",
178 yxrrset
("e.$zone 300 A 73.80.65.52"),
179 yxrrset
("e.$zone 300 TXT 'two'"),
180 yxrrset
("e.$zone 300 A 73.80.65.51"),
181 yxrrset
("e.$zone 300 TXT 'three'"),
182 yxrrset
("e.$zone 300 A 73.80.65.50"),
183 yxrrset
("f.$zone 300 A 73.80.65.52"),
184 yxrrset
("e.$zone 300 A 73.80.65.49"),
185 yxrrset
("e.$zone 300 TXT 'one'")]);
188 section
("Subtraction of RRsets");
189 test
("NOERROR", ["update", rr_del
("a.$zone 300 A 73.80.65.49")]);
190 test
("NOERROR", ["pre",
191 yxrrset
("a.$zone 300 A 73.80.65.50")]);
193 test
("NOERROR", ["update", rr_del
("a.$zone 300 A 73.80.65.50")]);
194 test
("NOERROR", ["pre", nxrrset
("a.$zone 300 A")]);
195 test
("NOERROR", ["pre", nxdomain
("a.$zone")]);
197 section
("Other forms of deletion");
198 test
("NOERROR", ["update", rr_add
("a.$zone 300 A 73.80.65.49")]);
199 test
("NOERROR", ["update", rr_add
("a.$zone 300 A 73.80.65.50")]);
200 test
("NOERROR", ["update", rr_add
("a.$zone 300 MX 10 mail.$zone")]);
201 test
("NOERROR", ["update", rr_del
("a.$zone 300 A")]);
202 test
("NOERROR", ["pre", nxrrset
("a.$zone 300 A")]);
203 test
("NOERROR", ["update", rr_add
("a.$zone 300 A 73.80.65.49")]);
204 test
("NOERROR", ["update", rr_add
("a.$zone 300 A 73.80.65.50")]);
205 test
("NOERROR", ["update", rr_del
("a.$zone")]);
206 test
("NOERROR", ["pre", nxdomain
("a.$zone")]);
208 section
("Case insensitivity");
209 test
("NOERROR", ["update", rr_add
("a.$zone 300 PTR foo.net.")]);
210 test
("NOERROR", ["pre", yxrrset
("A.$zone 300 PTR fOo.NeT.")]);
212 section
("Special CNAME rules");
213 test
("NOERROR", ["update", rr_add
("b.$zone 300 CNAME foo.net.")]);
214 test
("NOERROR", ["update", rr_add
("b.$zone 300 A 73.80.65.49")]);
215 test
("NOERROR", ["pre", yxrrset
("b.$zone 300 CNAME foo.net.")]);
216 test
("NOERROR", ["pre", nxrrset
("b.$zone A")]);
218 test
("NOERROR", ["update", rr_add
("c.$zone 300 A 73.80.65.49")]);
219 test
("NOERROR", ["update", rr_add
("c.$zone 300 CNAME foo.net.")]);
220 test
("NOERROR", ["pre", yxrrset
("c.$zone A")]);
221 test
("NOERROR", ["pre", nxrrset
("c.$zone CNAME")]);
223 # XXX should test with SIG, KEY, NXT, too.
226 # Currently commented out because Net::DNS does not properly
227 # support WKS records.
229 #section("Special WKS rules");
230 #test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP telnet ftp")]);
231 #test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp")]);
232 #test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]);
233 #test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP smtp")]);
234 #test("NOERROR", ["pre",
235 # yxrrset("c.$zone 300 WKS 73.80.65.49 TCP smtp"),
236 # yxrrset("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp"),
237 # yxrrset("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]);
240 section
("Special NS rules");
242 # Deleting the last NS record using "Delete an RR from an RRset"
243 # should fail at the zone apex and work elsewhere. The pseudocode
244 # in RFC2136 says it should fail everywhere, but this is in conflict
245 # with the actual text.
248 test
("NOERROR", ["update",
249 rr_add
("$zone 300 NS ns1.$zone"),
250 rr_add
("$zone 300 NS ns2.$zone")]);
251 test
("NOERROR", ["update", rr_del
("$zone 300 NS ns1.$zone")]);
252 test
("NOERROR", ["update", rr_del
("$zone 300 NS ns2.$zone")]);
253 test
("NOERROR", ["pre",
254 yxrrset
("$zone 300 NS ns2.$zone")]);
257 test
("NOERROR", ["update", rr_add
("n.$zone 300 NS ns1.$zone")]);
258 test
("NOERROR", ["update", rr_del
("n.$zone 300 NS ns1.$zone")]);
259 test
("NOERROR", ["pre", nxrrset
("n.$zone 300 NS")]);
261 # Other ways of deleting NS records should also fail at the apex
262 # and work elsewhere.
265 test
("NOERROR", ["update", rr_add
("n.$zone 300 NS ns1.$zone")]);
266 test
("NOERROR", ["update", rr_del
("n.$zone 300 NS")]);
267 test
("NOERROR", ["pre", nxrrset
("n.$zone 300 NS")]);
269 test
("NOERROR", ["update", rr_add
("n.$zone 300 NS ns1.$zone")]);
270 test
("NOERROR", ["pre", yxrrset
("n.$zone 300 NS")]);
271 test
("NOERROR", ["update", rr_del
("n.$zone")]);
272 test
("NOERROR", ["pre", nxrrset
("n.$zone 300 NS")]);
275 test
("NOERROR", ["update", rr_del
("$zone NS")]);
276 test
("NOERROR", ["pre",
277 yxrrset
("$zone 300 NS ns2.$zone")]);
279 test
("NOERROR", ["update", rr_del
("$zone")]);
280 test
("NOERROR", ["pre",
281 yxrrset
("$zone 300 NS ns2.$zone")]);
283 # They should not touch the SOA, either.
285 test
("NOERROR", ["update", rr_del
("$zone SOA")]);
286 test
("NOERROR", ["pre", yxrrset
("$zone SOA")]);
289 section
("Idempotency");
291 test
("NOERROR", ["update", rr_add
("d.$zone 300 A 73.80.65.49")]);
292 test
("NOERROR", ["pre", yxrrset
("d.$zone 300 A 73.80.65.49")]);
293 test
("NOERROR", ["update",
294 rr_add
("d.$zone 300 A 73.80.65.49"),
295 rr_del
("d.$zone A")]);
296 test
("NOERROR", ["pre", nxrrset
("d.$zone 300 A 73.80.65.49")]);
298 test
("NOERROR", ["update", rr_del
("d.$zone 300 A 73.80.65.49")]);
299 test
("NOERROR", ["pre", nxrrset
("d.$zone 300 A")]);
300 test
("NOERROR", ["update",
301 rr_del
("d.$zone 300 A"),
302 rr_add
("d.$zone 300 A 73.80.65.49")]);
304 test
("NOERROR", ["pre", yxrrset
("d.$zone 300 A")]);
306 section
("Out-of-zone prerequisites and updates");
307 test
("NOTZONE", ["pre", yxrrset
("a.somewhere.else. 300 A 73.80.65.49")]);
308 test
("NOTZONE", ["update", rr_add
("a.somewhere.else. 300 A 73.80.65.49")]);
312 test
("NOERROR", ["update", rr_add
("s.$zone 300 NS ns.s.$zone")]);
313 test
("NOERROR", ["update", rr_add
("ns.s.$zone 300 A 73.80.65.49")]);
314 test
("NOERROR", ["pre", yxrrset
("ns.s.$zone 300 A 73.80.65.49")]);
316 section
("Wildcards");
317 test
("NOERROR", ["update", rr_add
("*.$zone 300 MX 10 mail.$zone")]);
318 test
("NOERROR", ["pre", yxrrset
("*.$zone 300 MX 10 mail.$zone")]);
319 test
("NXRRSET", ["pre", yxrrset
("w.$zone 300 MX 10 mail.$zone")]);
320 test
("NOERROR", ["pre", nxrrset
("w.$zone MX")]);
321 test
("NOERROR", ["pre", nxdomain
("w.$zone")]);
324 section
("SOA serial handling");
326 my $soatimers = "20 20 1814400 3600";
328 # Get the current SOA serial number.
329 my $query = $res->query($zone, "SOA");
330 my ($old_soa) = $query->answer;
332 my $old_serial = $old_soa->serial;
334 # Increment it by 10.
335 my $new_serial = $old_serial + 10;
336 if ($new_serial > 0xFFFFFFFF) {
337 $new_serial -= 0x80000000;
338 $new_serial -= 0x80000000;
341 # Replace the SOA with a new one.
342 test
("NOERROR", ["update", rr_add
("$zone 300 SOA mname1. . $new_serial $soatimers")]);
344 # Check that the SOA really got replaced.
345 ($db_soa) = $res->query($zone, "SOA")->answer;
346 assert
($db_soa->mname eq "mname1");
348 # Check that attempts to decrement the serial number are ignored.
349 $new_serial = $old_serial - 10;
350 if ($new_serial < 0) {
351 $new_serial += 0x80000000;
352 $new_serial += 0x80000000;
354 test
("NOERROR", ["update", rr_add
("$zone 300 SOA mname2. . $new_serial $soatimers")]);
355 assert
($db_soa->mname eq "mname1");
357 # Check that attempts to leave the serial number unchanged are ignored.
358 ($old_soa) = $res->query($zone, "SOA")->answer;
359 $old_serial = $old_soa->serial;
360 test
("NOERROR", ["update", rr_add
("$zone 300 SOA mname3. . $old_serial " .
362 ($db_soa) = $res->query($zone, "SOA")->answer;
363 assert
($db_soa->mname eq "mname1");
366 # Currently commented out because Net::DNS does not properly
367 # support multiple strings in TXT records.
369 #section("Big data");
370 #test("NOERROR", ["update", rr_add("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]);
371 #test("NOERROR", ["update", rr_del("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]);
372 test
("NOERROR", ["update", rr_add
("a.$zone 300 TXT " . ("foo " x
3))]);
374 section
("Updating TTLs only");
376 test
("NOERROR", ["update", rr_add
("t.$zone 300 A 73.80.65.49")]);
377 ($a) = $res->query("t.$zone", "A")->answer;
379 assert
($ttl == 300, "incorrect TTL value $ttl != 300");
380 test
("NOERROR", ["update",
381 rr_del
("t.$zone 300 A 73.80.65.49"),
382 rr_add
("t.$zone 301 A 73.80.65.49")]);
383 ($a) = $res->query("t.$zone", "A")->answer;
385 assert
($ttl == 301, "incorrect TTL value $ttl != 301");
387 # Add an RR that is identical to an existing one except for the TTL.
388 # RFC2136 is not clear about what this should do; it says "duplicate RRs
389 # will be silently ignored" but is an RR differing only in TTL
390 # to be considered a duplicate or not? The test assumes that it
391 # should not be considered a duplicate.
392 test
("NOERROR", ["update", rr_add
("t.$zone 302 A 73.80.65.50")]);
393 ($a) = $res->query("t.$zone", "A")->answer;
395 assert
($ttl == 302, "incorrect TTL value $ttl != 302");
397 section
("TTL normalization");
399 # The desired behaviour is that the old RRs get their TTL
400 # changed to match the new one. RFC2136 does not explicitly
401 # specify this, but I think it makes more sense than the
404 test
("NOERROR", ["update", rr_add
("t.$zone 303 A 73.80.65.51")]);
405 (@answers) = $res->query("t.$zone", "A")->answer;
406 $nanswers = scalar @answers;
407 assert
($nanswers == 3, "wrong number of answers $nanswers != 3");
408 foreach $a (@answers) {
410 assert
($ttl == 303, "incorrect TTL value $ttl != 303");
413 section
("Obscuring existing data by zone cut");
414 test
("NOERROR", ["update", rr_add
("a.u.$zone 300 A 73.80.65.49")]);
415 test
("NOERROR", ["update", rr_add
("b.u.$zone 300 A 73.80.65.49")]);
416 test
("NOERROR", ["update", rr_add
("u.$zone 300 TXT txt-not-in-nxt")]);
417 test
("NOERROR", ["update", rr_add
("u.$zone 300 NS ns.u.$zone")]);
419 test
("NOERROR", ["update", rr_del
("u.$zone 300 NS ns.u.$zone")]);
422 print "I:$failures tests failed.\n";
424 print "I:All tests successful.\n";