1*00b67f09SDavid van Moolenbroek#!/usr/bin/perl 2*00b67f09SDavid van Moolenbroek# 3*00b67f09SDavid van Moolenbroek# Copyright (C) 2004, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") 4*00b67f09SDavid van Moolenbroek# Copyright (C) 2000, 2001 Internet Software Consortium. 5*00b67f09SDavid van Moolenbroek# 6*00b67f09SDavid van Moolenbroek# Permission to use, copy, modify, and/or distribute this software for any 7*00b67f09SDavid van Moolenbroek# purpose with or without fee is hereby granted, provided that the above 8*00b67f09SDavid van Moolenbroek# copyright notice and this permission notice appear in all copies. 9*00b67f09SDavid van Moolenbroek# 10*00b67f09SDavid van Moolenbroek# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11*00b67f09SDavid van Moolenbroek# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12*00b67f09SDavid van Moolenbroek# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13*00b67f09SDavid van Moolenbroek# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14*00b67f09SDavid van Moolenbroek# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15*00b67f09SDavid van Moolenbroek# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16*00b67f09SDavid van Moolenbroek# PERFORMANCE OF THIS SOFTWARE. 17*00b67f09SDavid van Moolenbroek 18*00b67f09SDavid van Moolenbroek# 19*00b67f09SDavid van Moolenbroek# Dynamic update test suite. 20*00b67f09SDavid van Moolenbroek# 21*00b67f09SDavid van Moolenbroek# Usage: 22*00b67f09SDavid van Moolenbroek# 23*00b67f09SDavid van Moolenbroek# perl update_test.pl [-s server] [-p port] zone 24*00b67f09SDavid van Moolenbroek# 25*00b67f09SDavid van Moolenbroek# The server defaults to 127.0.0.1. 26*00b67f09SDavid van Moolenbroek# The port defaults to 53. 27*00b67f09SDavid van Moolenbroek# 28*00b67f09SDavid van Moolenbroek# The "Special NS rules" tests will only work correctly if the 29*00b67f09SDavid van Moolenbroek# zone has no NS records to begin with, or alternatively has a 30*00b67f09SDavid van Moolenbroek# single NS record pointing at the name "ns1" (relative to 31*00b67f09SDavid van Moolenbroek# the zone name). 32*00b67f09SDavid van Moolenbroek# 33*00b67f09SDavid van Moolenbroek# Installation notes: 34*00b67f09SDavid van Moolenbroek# 35*00b67f09SDavid van Moolenbroek# This program uses the Net::DNS::Resolver module. 36*00b67f09SDavid van Moolenbroek# You can install it by saying 37*00b67f09SDavid van Moolenbroek# 38*00b67f09SDavid van Moolenbroek# perl -MCPAN -e "install Net::DNS" 39*00b67f09SDavid van Moolenbroek# 40*00b67f09SDavid van Moolenbroek# Id: update_test.pl,v 1.10 2007/06/19 23:47:04 tbox Exp 41*00b67f09SDavid van Moolenbroek# 42*00b67f09SDavid van Moolenbroek 43*00b67f09SDavid van Moolenbroekuse Getopt::Std; 44*00b67f09SDavid van Moolenbroekuse Net::DNS; 45*00b67f09SDavid van Moolenbroekuse Net::DNS::Update; 46*00b67f09SDavid van Moolenbroekuse Net::DNS::Resolver; 47*00b67f09SDavid van Moolenbroek 48*00b67f09SDavid van Moolenbroek$opt_s = "127.0.0.1"; 49*00b67f09SDavid van Moolenbroek$opt_p = 53; 50*00b67f09SDavid van Moolenbroek 51*00b67f09SDavid van Moolenbroekgetopt('s:p:'); 52*00b67f09SDavid van Moolenbroek 53*00b67f09SDavid van Moolenbroek$res = new Net::DNS::Resolver; 54*00b67f09SDavid van Moolenbroek$res->nameservers($opt_s); 55*00b67f09SDavid van Moolenbroek$res->port($opt_p); 56*00b67f09SDavid van Moolenbroek$res->defnames(0); # Do not append default domain. 57*00b67f09SDavid van Moolenbroek 58*00b67f09SDavid van Moolenbroek@ARGV == 1 or die 59*00b67f09SDavid van Moolenbroek "usage: perl update_test.pl [-s server] [-p port] zone\n"; 60*00b67f09SDavid van Moolenbroek 61*00b67f09SDavid van Moolenbroek$zone = shift @ARGV; 62*00b67f09SDavid van Moolenbroek 63*00b67f09SDavid van Moolenbroekmy $failures = 0; 64*00b67f09SDavid van Moolenbroek 65*00b67f09SDavid van Moolenbroeksub assert { 66*00b67f09SDavid van Moolenbroek my ($cond, $explanation) = @_; 67*00b67f09SDavid van Moolenbroek if (!$cond) { 68*00b67f09SDavid van Moolenbroek print "I:Test Failed: $explanation ***\n"; 69*00b67f09SDavid van Moolenbroek $failures++ 70*00b67f09SDavid van Moolenbroek } 71*00b67f09SDavid van Moolenbroek} 72*00b67f09SDavid van Moolenbroek 73*00b67f09SDavid van Moolenbroeksub test { 74*00b67f09SDavid van Moolenbroek my ($expected, @records) = @_; 75*00b67f09SDavid van Moolenbroek 76*00b67f09SDavid van Moolenbroek my $update = new Net::DNS::Update("$zone"); 77*00b67f09SDavid van Moolenbroek 78*00b67f09SDavid van Moolenbroek foreach $rec (@records) { 79*00b67f09SDavid van Moolenbroek $update->push(@$rec); 80*00b67f09SDavid van Moolenbroek } 81*00b67f09SDavid van Moolenbroek 82*00b67f09SDavid van Moolenbroek $reply = $res->send($update); 83*00b67f09SDavid van Moolenbroek 84*00b67f09SDavid van Moolenbroek # Did it work? 85*00b67f09SDavid van Moolenbroek if (defined $reply) { 86*00b67f09SDavid van Moolenbroek my $rcode = $reply->header->rcode; 87*00b67f09SDavid van Moolenbroek assert($rcode eq $expected, "expected $expected, got $rcode"); 88*00b67f09SDavid van Moolenbroek } else { 89*00b67f09SDavid van Moolenbroek print "I:Update failed: ", $res->errorstring, "\n"; 90*00b67f09SDavid van Moolenbroek } 91*00b67f09SDavid van Moolenbroek} 92*00b67f09SDavid van Moolenbroek 93*00b67f09SDavid van Moolenbroeksub section { 94*00b67f09SDavid van Moolenbroek my ($msg) = @_; 95*00b67f09SDavid van Moolenbroek print "I:$msg\n"; 96*00b67f09SDavid van Moolenbroek} 97*00b67f09SDavid van Moolenbroek 98*00b67f09SDavid van Moolenbroeksection("Delete any leftovers from previous tests"); 99*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("a.$zone")]); 100*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("b.$zone")]); 101*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("c.$zone")]); 102*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("d.$zone")]); 103*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("e.$zone")]); 104*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("f.$zone")]); 105*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("ns.s.$zone")]); 106*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("s.$zone")]); 107*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("t.$zone")]); 108*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("*.$zone")]); 109*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("u.$zone")]); 110*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("a.u.$zone")]); 111*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("b.u.$zone")]); 112*00b67f09SDavid van Moolenbroek 113*00b67f09SDavid van Moolenbroeksection("Simple prerequisites in the absence of data"); 114*00b67f09SDavid van Moolenbroek# Name is in Use 115*00b67f09SDavid van Moolenbroektest("NXDOMAIN", ["pre", yxdomain("a.$zone")]); 116*00b67f09SDavid van Moolenbroek# RRset exists (value independent) 117*00b67f09SDavid van Moolenbroektest("NXRRSET", ["pre", yxrrset("a.$zone A")]); 118*00b67f09SDavid van Moolenbroek# Name is not in use 119*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxdomain("a.$zone")]); 120*00b67f09SDavid van Moolenbroek# RRset does not exist 121*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("a.$zone A")]); 122*00b67f09SDavid van Moolenbroek# RRset exists (value dependent) 123*00b67f09SDavid van Moolenbroektest("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.49")]); 124*00b67f09SDavid van Moolenbroek 125*00b67f09SDavid van Moolenbroek 126*00b67f09SDavid van Moolenbroeksection ("Simple creation of data"); 127*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); 128*00b67f09SDavid van Moolenbroek 129*00b67f09SDavid van Moolenbroeksection ("Simple prerequisites in the presence of data"); 130*00b67f09SDavid van Moolenbroek# Name is in use 131*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxdomain("a.$zone")]); 132*00b67f09SDavid van Moolenbroek# RRset exists (value independent) 133*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("a.$zone A")]); 134*00b67f09SDavid van Moolenbroek# Name is not in use 135*00b67f09SDavid van Moolenbroektest("YXDOMAIN", ["pre", nxdomain("a.$zone")]); 136*00b67f09SDavid van Moolenbroek# RRset does not exist 137*00b67f09SDavid van Moolenbroektest("YXRRSET", ["pre", nxrrset("a.$zone A")]); 138*00b67f09SDavid van Moolenbroek# RRset exists (value dependent) 139*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("a.$zone A 73.80.65.49")]); 140*00b67f09SDavid van Moolenbroek 141*00b67f09SDavid van Moolenbroek# 142*00b67f09SDavid van Moolenbroek# Merging of RRsets 143*00b67f09SDavid van Moolenbroek# 144*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]); 145*00b67f09SDavid van Moolenbroek 146*00b67f09SDavid van Moolenbroeksection("Detailed tests of \"RRset exists (value dependent)\" prerequisites"); 147*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 148*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.49"), 149*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.50")]); 150*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 151*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.50"), 152*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.49")]); 153*00b67f09SDavid van Moolenbroektest("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.49")]); 154*00b67f09SDavid van Moolenbroektest("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.50")]); 155*00b67f09SDavid van Moolenbroektest("NXRRSET", ["pre", 156*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.49"), 157*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.50"), 158*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.51")]); 159*00b67f09SDavid van Moolenbroek 160*00b67f09SDavid van Moolenbroek 161*00b67f09SDavid van Moolenbroeksection("Torture test of \"RRset exists (value dependent)\" prerequisites."); 162*00b67f09SDavid van Moolenbroek 163*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 164*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 A 73.80.65.49"), 165*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 TXT 'one'"), 166*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 A 73.80.65.50")]); 167*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 168*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 A 73.80.65.52"), 169*00b67f09SDavid van Moolenbroek rr_add("f.$zone 300 A 73.80.65.52"), 170*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 A 73.80.65.51")]); 171*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 172*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 TXT 'three'"), 173*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 TXT 'two'")]); 174*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 175*00b67f09SDavid van Moolenbroek rr_add("e.$zone 300 MX 10 mail.$zone")]); 176*00b67f09SDavid van Moolenbroek 177*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 178*00b67f09SDavid van Moolenbroek yxrrset("e.$zone A 73.80.65.52"), 179*00b67f09SDavid van Moolenbroek yxrrset("e.$zone TXT 'two'"), 180*00b67f09SDavid van Moolenbroek yxrrset("e.$zone A 73.80.65.51"), 181*00b67f09SDavid van Moolenbroek yxrrset("e.$zone TXT 'three'"), 182*00b67f09SDavid van Moolenbroek yxrrset("e.$zone A 73.80.65.50"), 183*00b67f09SDavid van Moolenbroek yxrrset("f.$zone A 73.80.65.52"), 184*00b67f09SDavid van Moolenbroek yxrrset("e.$zone A 73.80.65.49"), 185*00b67f09SDavid van Moolenbroek yxrrset("e.$zone TXT 'one'")]); 186*00b67f09SDavid van Moolenbroek 187*00b67f09SDavid van Moolenbroek 188*00b67f09SDavid van Moolenbroeksection("Subtraction of RRsets"); 189*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("a.$zone A 73.80.65.49")]); 190*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 191*00b67f09SDavid van Moolenbroek yxrrset("a.$zone A 73.80.65.50")]); 192*00b67f09SDavid van Moolenbroek 193*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("a.$zone A 73.80.65.50")]); 194*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("a.$zone A")]); 195*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxdomain("a.$zone")]); 196*00b67f09SDavid van Moolenbroek 197*00b67f09SDavid van Moolenbroeksection("Other forms of deletion"); 198*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); 199*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]); 200*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 MX 10 mail.$zone")]); 201*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("a.$zone A")]); 202*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("a.$zone A")]); 203*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); 204*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]); 205*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("a.$zone")]); 206*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxdomain("a.$zone")]); 207*00b67f09SDavid van Moolenbroek 208*00b67f09SDavid van Moolenbroeksection("Case insensitivity"); 209*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 PTR foo.net.")]); 210*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("A.$zone PTR fOo.NeT.")]); 211*00b67f09SDavid van Moolenbroek 212*00b67f09SDavid van Moolenbroeksection("Special CNAME rules"); 213*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("b.$zone 300 CNAME foo.net.")]); 214*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("b.$zone 300 A 73.80.65.49")]); 215*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("b.$zone CNAME foo.net.")]); 216*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("b.$zone A")]); 217*00b67f09SDavid van Moolenbroek 218*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("c.$zone 300 A 73.80.65.49")]); 219*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("c.$zone 300 CNAME foo.net.")]); 220*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("c.$zone A")]); 221*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("c.$zone CNAME")]); 222*00b67f09SDavid van Moolenbroek 223*00b67f09SDavid van Moolenbroek# XXX should test with SIG, KEY, NXT, too. 224*00b67f09SDavid van Moolenbroek 225*00b67f09SDavid van Moolenbroek# 226*00b67f09SDavid van Moolenbroek# Currently commented out because Net::DNS does not properly 227*00b67f09SDavid van Moolenbroek# support WKS records. 228*00b67f09SDavid van Moolenbroek# 229*00b67f09SDavid van Moolenbroek#section("Special WKS rules"); 230*00b67f09SDavid van Moolenbroek#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP telnet ftp")]); 231*00b67f09SDavid van Moolenbroek#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp")]); 232*00b67f09SDavid van Moolenbroek#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]); 233*00b67f09SDavid van Moolenbroek#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP smtp")]); 234*00b67f09SDavid van Moolenbroek#test("NOERROR", ["pre", 235*00b67f09SDavid van Moolenbroek# yxrrset("c.$zone WKS 73.80.65.49 TCP smtp"), 236*00b67f09SDavid van Moolenbroek# yxrrset("c.$zone WKS 73.80.65.49 UDP telnet ftp"), 237*00b67f09SDavid van Moolenbroek# yxrrset("c.$zone WKS 73.80.65.50 TCP telnet ftp")]); 238*00b67f09SDavid van Moolenbroek 239*00b67f09SDavid van Moolenbroek 240*00b67f09SDavid van Moolenbroeksection("Special NS rules"); 241*00b67f09SDavid van Moolenbroek 242*00b67f09SDavid van Moolenbroek# Deleting the last NS record using "Delete an RR from an RRset" 243*00b67f09SDavid van Moolenbroek# should fail at the zone apex and work elsewhere. The pseudocode 244*00b67f09SDavid van Moolenbroek# in RFC2136 says it should fail everywhere, but this is in conflict 245*00b67f09SDavid van Moolenbroek# with the actual text. 246*00b67f09SDavid van Moolenbroek 247*00b67f09SDavid van Moolenbroek# Apex 248*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 249*00b67f09SDavid van Moolenbroek rr_add("$zone 300 NS ns1.$zone"), 250*00b67f09SDavid van Moolenbroek rr_add("$zone 300 NS ns2.$zone")]); 251*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("$zone NS ns1.$zone")]); 252*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("$zone NS ns2.$zone")]); 253*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 254*00b67f09SDavid van Moolenbroek yxrrset("$zone NS ns2.$zone")]); 255*00b67f09SDavid van Moolenbroek 256*00b67f09SDavid van Moolenbroek# Non-apex 257*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]); 258*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("n.$zone NS ns1.$zone")]); 259*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("n.$zone NS")]); 260*00b67f09SDavid van Moolenbroek 261*00b67f09SDavid van Moolenbroek# Other ways of deleting NS records should also fail at the apex 262*00b67f09SDavid van Moolenbroek# and work elsewhere. 263*00b67f09SDavid van Moolenbroek 264*00b67f09SDavid van Moolenbroek# Non-apex 265*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]); 266*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("n.$zone NS")]); 267*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("n.$zone NS")]); 268*00b67f09SDavid van Moolenbroek 269*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]); 270*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("n.$zone NS")]); 271*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("n.$zone")]); 272*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("n.$zone NS")]); 273*00b67f09SDavid van Moolenbroek 274*00b67f09SDavid van Moolenbroek# Apex 275*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("$zone NS")]); 276*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 277*00b67f09SDavid van Moolenbroek yxrrset("$zone NS ns2.$zone")]); 278*00b67f09SDavid van Moolenbroek 279*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("$zone")]); 280*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", 281*00b67f09SDavid van Moolenbroek yxrrset("$zone NS ns2.$zone")]); 282*00b67f09SDavid van Moolenbroek 283*00b67f09SDavid van Moolenbroek# They should not touch the SOA, either. 284*00b67f09SDavid van Moolenbroek 285*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("$zone SOA")]); 286*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("$zone SOA")]); 287*00b67f09SDavid van Moolenbroek 288*00b67f09SDavid van Moolenbroek 289*00b67f09SDavid van Moolenbroeksection("Idempotency"); 290*00b67f09SDavid van Moolenbroek 291*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("d.$zone 300 A 73.80.65.49")]); 292*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("d.$zone A 73.80.65.49")]); 293*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 294*00b67f09SDavid van Moolenbroek rr_add("d.$zone 300 A 73.80.65.49"), 295*00b67f09SDavid van Moolenbroek rr_del("d.$zone A")]); 296*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("d.$zone A")]); 297*00b67f09SDavid van Moolenbroek 298*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("d.$zone A 73.80.65.49")]); 299*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("d.$zone A")]); 300*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 301*00b67f09SDavid van Moolenbroek rr_del("d.$zone A"), 302*00b67f09SDavid van Moolenbroek rr_add("d.$zone 300 A 73.80.65.49")]); 303*00b67f09SDavid van Moolenbroek 304*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("d.$zone A")]); 305*00b67f09SDavid van Moolenbroek 306*00b67f09SDavid van Moolenbroeksection("Out-of-zone prerequisites and updates"); 307*00b67f09SDavid van Moolenbroektest("NOTZONE", ["pre", yxrrset("a.somewhere.else. A 73.80.65.49")]); 308*00b67f09SDavid van Moolenbroektest("NOTZONE", ["update", rr_add("a.somewhere.else. 300 A 73.80.65.49")]); 309*00b67f09SDavid van Moolenbroek 310*00b67f09SDavid van Moolenbroek 311*00b67f09SDavid van Moolenbroeksection("Glue"); 312*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("s.$zone 300 NS ns.s.$zone")]); 313*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("ns.s.$zone 300 A 73.80.65.49")]); 314*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("ns.s.$zone A 73.80.65.49")]); 315*00b67f09SDavid van Moolenbroek 316*00b67f09SDavid van Moolenbroeksection("Wildcards"); 317*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("*.$zone 300 MX 10 mail.$zone")]); 318*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", yxrrset("*.$zone MX 10 mail.$zone")]); 319*00b67f09SDavid van Moolenbroektest("NXRRSET", ["pre", yxrrset("w.$zone MX 10 mail.$zone")]); 320*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxrrset("w.$zone MX")]); 321*00b67f09SDavid van Moolenbroektest("NOERROR", ["pre", nxdomain("w.$zone")]); 322*00b67f09SDavid van Moolenbroek 323*00b67f09SDavid van Moolenbroek 324*00b67f09SDavid van Moolenbroeksection("SOA serial handling"); 325*00b67f09SDavid van Moolenbroek 326*00b67f09SDavid van Moolenbroekmy $soatimers = "20 20 1814400 3600"; 327*00b67f09SDavid van Moolenbroek 328*00b67f09SDavid van Moolenbroek# Get the current SOA serial number. 329*00b67f09SDavid van Moolenbroekmy $query = $res->query($zone, "SOA"); 330*00b67f09SDavid van Moolenbroekmy ($old_soa) = $query->answer; 331*00b67f09SDavid van Moolenbroek 332*00b67f09SDavid van Moolenbroekmy $old_serial = $old_soa->serial; 333*00b67f09SDavid van Moolenbroek 334*00b67f09SDavid van Moolenbroek# Increment it by 10. 335*00b67f09SDavid van Moolenbroekmy $new_serial = $old_serial + 10; 336*00b67f09SDavid van Moolenbroekif ($new_serial > 0xFFFFFFFF) { 337*00b67f09SDavid van Moolenbroek $new_serial -= 0x80000000; 338*00b67f09SDavid van Moolenbroek $new_serial -= 0x80000000; 339*00b67f09SDavid van Moolenbroek} 340*00b67f09SDavid van Moolenbroek 341*00b67f09SDavid van Moolenbroek# Replace the SOA with a new one. 342*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("$zone 300 SOA mname1. . $new_serial $soatimers")]); 343*00b67f09SDavid van Moolenbroek 344*00b67f09SDavid van Moolenbroek# Check that the SOA really got replaced. 345*00b67f09SDavid van Moolenbroek($db_soa) = $res->query($zone, "SOA")->answer; 346*00b67f09SDavid van Moolenbroekassert($db_soa->mname eq "mname1"); 347*00b67f09SDavid van Moolenbroek 348*00b67f09SDavid van Moolenbroek# Check that attempts to decrement the serial number are ignored. 349*00b67f09SDavid van Moolenbroek$new_serial = $old_serial - 10; 350*00b67f09SDavid van Moolenbroekif ($new_serial < 0) { 351*00b67f09SDavid van Moolenbroek $new_serial += 0x80000000; 352*00b67f09SDavid van Moolenbroek $new_serial += 0x80000000; 353*00b67f09SDavid van Moolenbroek} 354*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("$zone 300 SOA mname2. . $new_serial $soatimers")]); 355*00b67f09SDavid van Moolenbroekassert($db_soa->mname eq "mname1"); 356*00b67f09SDavid van Moolenbroek 357*00b67f09SDavid van Moolenbroek# Check that attempts to leave the serial number unchanged are ignored. 358*00b67f09SDavid van Moolenbroek($old_soa) = $res->query($zone, "SOA")->answer; 359*00b67f09SDavid van Moolenbroek$old_serial = $old_soa->serial; 360*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("$zone 300 SOA mname3. . $old_serial " . 361*00b67f09SDavid van Moolenbroek $soatimers)]); 362*00b67f09SDavid van Moolenbroek($db_soa) = $res->query($zone, "SOA")->answer; 363*00b67f09SDavid van Moolenbroekassert($db_soa->mname eq "mname1"); 364*00b67f09SDavid van Moolenbroek 365*00b67f09SDavid van Moolenbroek# 366*00b67f09SDavid van Moolenbroek# Currently commented out because Net::DNS does not properly 367*00b67f09SDavid van Moolenbroek# support multiple strings in TXT records. 368*00b67f09SDavid van Moolenbroek# 369*00b67f09SDavid van Moolenbroek#section("Big data"); 370*00b67f09SDavid van Moolenbroek#test("NOERROR", ["update", rr_add("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]); 371*00b67f09SDavid van Moolenbroek#test("NOERROR", ["update", rr_del("a.$zone TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]); 372*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.$zone 300 TXT " . ("foo " x 3))]); 373*00b67f09SDavid van Moolenbroek 374*00b67f09SDavid van Moolenbroeksection("Updating TTLs only"); 375*00b67f09SDavid van Moolenbroek 376*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("t.$zone 300 A 73.80.65.49")]); 377*00b67f09SDavid van Moolenbroek($a) = $res->query("t.$zone", "A")->answer; 378*00b67f09SDavid van Moolenbroek$ttl = $a->ttl; 379*00b67f09SDavid van Moolenbroekassert($ttl == 300, "incorrect TTL value $ttl != 300"); 380*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", 381*00b67f09SDavid van Moolenbroek rr_del("t.$zone A 73.80.65.49"), 382*00b67f09SDavid van Moolenbroek rr_add("t.$zone 301 A 73.80.65.49")]); 383*00b67f09SDavid van Moolenbroek($a) = $res->query("t.$zone", "A")->answer; 384*00b67f09SDavid van Moolenbroek$ttl = $a->ttl; 385*00b67f09SDavid van Moolenbroekassert($ttl == 301, "incorrect TTL value $ttl != 301"); 386*00b67f09SDavid van Moolenbroek 387*00b67f09SDavid van Moolenbroek# Add an RR that is identical to an existing one except for the TTL. 388*00b67f09SDavid van Moolenbroek# RFC2136 is not clear about what this should do; it says "duplicate RRs 389*00b67f09SDavid van Moolenbroek# will be silently ignored" but is an RR differing only in TTL 390*00b67f09SDavid van Moolenbroek# to be considered a duplicate or not? The test assumes that it 391*00b67f09SDavid van Moolenbroek# should not be considered a duplicate. 392*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("t.$zone 302 A 73.80.65.50")]); 393*00b67f09SDavid van Moolenbroek($a) = $res->query("t.$zone", "A")->answer; 394*00b67f09SDavid van Moolenbroek$ttl = $a->ttl; 395*00b67f09SDavid van Moolenbroekassert($ttl == 302, "incorrect TTL value $ttl != 302"); 396*00b67f09SDavid van Moolenbroek 397*00b67f09SDavid van Moolenbroeksection("TTL normalization"); 398*00b67f09SDavid van Moolenbroek 399*00b67f09SDavid van Moolenbroek# The desired behaviour is that the old RRs get their TTL 400*00b67f09SDavid van Moolenbroek# changed to match the new one. RFC2136 does not explicitly 401*00b67f09SDavid van Moolenbroek# specify this, but I think it makes more sense than the 402*00b67f09SDavid van Moolenbroek# alternatives. 403*00b67f09SDavid van Moolenbroek 404*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("t.$zone 303 A 73.80.65.51")]); 405*00b67f09SDavid van Moolenbroek(@answers) = $res->query("t.$zone", "A")->answer; 406*00b67f09SDavid van Moolenbroek$nanswers = scalar @answers; 407*00b67f09SDavid van Moolenbroekassert($nanswers == 3, "wrong number of answers $nanswers != 3"); 408*00b67f09SDavid van Moolenbroekforeach $a (@answers) { 409*00b67f09SDavid van Moolenbroek $ttl = $a->ttl; 410*00b67f09SDavid van Moolenbroek assert($ttl == 303, "incorrect TTL value $ttl != 303"); 411*00b67f09SDavid van Moolenbroek} 412*00b67f09SDavid van Moolenbroek 413*00b67f09SDavid van Moolenbroeksection("Obscuring existing data by zone cut"); 414*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("a.u.$zone 300 A 73.80.65.49")]); 415*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("b.u.$zone 300 A 73.80.65.49")]); 416*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("u.$zone 300 TXT txt-not-in-nxt")]); 417*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_add("u.$zone 300 NS ns.u.$zone")]); 418*00b67f09SDavid van Moolenbroek 419*00b67f09SDavid van Moolenbroektest("NOERROR", ["update", rr_del("u.$zone NS ns.u.$zone")]); 420*00b67f09SDavid van Moolenbroek 421*00b67f09SDavid van Moolenbroekif ($failures) { 422*00b67f09SDavid van Moolenbroek print "I:$failures tests failed.\n"; 423*00b67f09SDavid van Moolenbroek} else { 424*00b67f09SDavid van Moolenbroek print "I:All tests successful.\n"; 425*00b67f09SDavid van Moolenbroek} 426*00b67f09SDavid van Moolenbroekexit $failures; 427