# HG changeset patch # User Sergey Kandaurov # Date 1386964953 -14400 # Node ID 82db241184e04b65dd8f358ce3d5f20b5e36c819 # Parent cdab739eb6ea8c49a06ace6a7f7e263396094d92 Tests: added AAAA specific resolver tests. diff --git a/http_resolver.t b/http_resolver_aaaa.t copy from http_resolver.t copy to http_resolver_aaaa.t --- a/http_resolver.t +++ b/http_resolver_aaaa.t @@ -3,7 +3,7 @@ # (C) Sergey Kandaurov # (C) Nginx, Inc. -# Tests for http resolver. +# Tests for AAAA capable http resolver. ############################################################################### @@ -22,7 +22,9 @@ use Test::Nginx; select STDERR; $| = 1; select STDOUT; $| = 1; -my $t = Test::Nginx->new()->has(qw/http proxy rewrite/); +my $t = Test::Nginx->new()->has(qw/http proxy rewrite ipv6/); + +plan(skip_all => 'no ipv6 capable resolver') unless $t->has_version('1.5.8'); $t->write_file_expand('nginx.conf', <<'EOF'); @@ -38,29 +40,22 @@ http { server { listen 127.0.0.1:8080; + listen [::1]:8080; server_name localhost; location / { resolver 127.0.0.1:8081; - resolver_timeout 1s; proxy_pass http://$host:8080/backend; proxy_next_upstream http_504 timeout error; proxy_intercept_errors on; - proxy_connect_timeout 1s; + proxy_connect_timeout 50ms; error_page 504 502 /50x; } location /two { resolver 127.0.0.1:8081 127.0.0.1:8082; proxy_pass http://$host:8080/backend; } - location /valid { - resolver 127.0.0.1:8081 valid=3s; - proxy_pass http://$host:8080/backend; - } - location /invalid { - proxy_pass http://$host:8080/backend; - } location /backend { return 200; @@ -73,50 +68,45 @@ http { EOF +eval { + open OLDERR, ">&", \*STDERR; close STDERR; + $t->run(); + open STDERR, ">&", \*OLDERR; +}; +plan(skip_all => 'no inet6 support') if $@; + $t->run_daemon(\&dns_daemon, 8081, $t); $t->run_daemon(\&dns_daemon, 8082, $t); -$t->run()->plan(27); - $t->waitforfile($t->testdir . '/8081'); $t->waitforfile($t->testdir . '/8082'); +$t->plan(72); + ############################################################################### -like(http_host_header('a.example.net', '/'), qr/200 OK/, 'A'); -like(http_host_header('short.example.net', '/'), qr/502 Bad/, - 'A short dns response'); +my (@n, $response); -like(http_host_header('nx.example.net', '/'), qr/502 Bad/, 'NXDOMAIN'); -like(http_host_header('cname.example.net', '/'), qr/200 OK/, 'CNAME'); -like(http_host_header('cname.example.net', '/'), qr/200 OK/, +like(http_host_header('aaaa.example.net', '/'), qr/\[fe80::1\]/, 'AAAA'); +like(http_host_header('cname.example.net', '/'), qr/\[fe80::1\]/, 'CNAME'); +like(http_host_header('cname.example.net', '/'), qr/\[fe80::1\]/, 'CNAME cached'); -# CNAME + A combined answer +# CNAME + AAAA combined answer # demonstrates the name in answer section different from what is asked -like(http_host_header('cname_a.example.net', '/'), qr/200 OK/, 'CNAME + A'); - -# CNAME refers to non-existing A +like(http_host_header('cname_a.example.net', '/'), qr/200 OK/, 'CNAME + AAAA'); -like(http_host_header('cname2.example.net', '/'), qr/502 Bad/, 'CNAME bad'); -like(http_host_header('long.example.net', '/'), qr/200 OK/, 'long label'); -like(http_host_header('long2.example.net', '/'), qr/200 OK/, 'long name'); - -# take into account DNAME - -like(http_host_header('alias.example.com', '/'), qr/200 OK/, 'DNAME'); - -# many A records in round robin +# many AAAA records in round robin # nonexisting IPs enumerated with proxy_next_upstream like(http_host_header('many.example.net', '/'), - qr/^127.0.0.20(1:8080, 127.0.0.202:8080|2:8080, 127.0.0.201:8080)$/m, - 'A many'); + qr/^\[fe80::(1\]:8080, \[fe80::2\]:8080|2\]:8080, \[fe80::1\]:8080)$/m, + 'AAAA many'); like(http_host_header('many.example.net', '/'), - qr/^127.0.0.20(1:8080, 127.0.0.202:8080|2:8080, 127.0.0.201:8080)$/m, - 'A many cached'); + qr/^\[fe80::(1\]:8080, \[fe80::2\]:8080|2\]:8080, \[fe80::1\]:8080)$/m, + 'AAAA many cached'); # tests for several resolvers specified in directive # query bad ns, make sure that error responses are not cached @@ -131,62 +121,122 @@ like(http_host_header('2.example.net', ' like(http_host_header('2.example.net', '/two'), qr/200 OK/, 'two ns cached'); -# ttl tested with 1st req good and 2nd req bad -# send 1st request and cache its good response +# various ipv4/ipv6 combinations -like(http_host_header('ttl.example.net', '/'), qr/200 OK/, 'ttl'); +$response = http_host_header('z_z.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'zero zero responses'); +like($response, qr/502 Bad/, 'zero zero'); -# response is cached, actual request would get error +like(http_host_header('z_n.example.net', '/'), qr/^\[fe80::1\]:8080$/ms, + 'zero AAAA'); -like(http_host_header('ttl.example.net', '/'), qr/200 OK/, 'ttl cached 1'); -like(http_host_header('ttl.example.net', '/'), qr/200 OK/, 'ttl cached 2'); +$response = http_host_header('z_c.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'zero CNAME responses'); +like($response, qr/127.0.0.201:8080/, 'zero CNAME 1'); +like($response, qr/\[fe80::1\]:8080/, 'zero CNAME 2'); -sleep 2; +$response = http_host_header('z_cn.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'zero CNAME+AAAA responses'); +like($response, qr/\[fe80::1\]:8080/, 'zero CNAME+AAAA 1'); +like($response, qr/\[fe80::2\]:8080/, 'zero CNAME+AAAA 2'); -# expired ttl causes nginx to make actual query +$response = http_host_header('z_e.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'zero error responses'); +like($response, qr/502 Bad/, 'zero error'); + +like(http_host_header('n_z.example.net', '/'), qr/^127.0.0.201:8080$/ms, + 'A zero'); -like(http_host_header('ttl.example.net', '/'), qr/502 Bad/, 'ttl expired'); +$response = http_host_header('n_n.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'A AAAA responses'); +like($response, qr/127.0.0.201:8080/, 'A AAAA 1'); +like($response, qr/\[fe80::1\]:8080/, 'A AAAA 2'); -# zero ttl prohibits response caching +like(http_host_header('n_c.example.net', '/'), qr/^127.0.0.201:8080$/ms, + 'A CNAME'); -like(http_host_header('ttl0.example.net', '/'), qr/200 OK/, 'zero ttl'); +$response = http_host_header('n_cn.example.net', '/'); +is(@n = $response =~ /8080/g, 4, 'A CNAME+AAAA responses'); +like($response, qr/127.0.0.201:8080/, 'A CNAME+AAAA 1'); +like($response, qr/127.0.0.202:8080/, 'A CNAME+AAAA 2'); +like($response, qr/\[fe80::1\]:8080/, 'A CNAME+AAAA 3'); +like($response, qr/\[fe80::2\]:8080/, 'A CNAME+AAAA 4'); -TODO: { -local $TODO = 'support for zero ttl'; +$response = http_host_header('n_e.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'A error responses'); +like($response, qr/502 Bad/, 'A error'); + +$response = http_host_header('c_z.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'CNAME zero responses'); +like($response, qr/502 Bad/, 'CNAME zero'); -like(http_host_header('ttl0.example.net', '/'), qr/502 Bad/, - 'zero ttl not cached'); +like(http_host_header('c_n.example.net', '/'), qr/^\[fe80::1\]:8080$/ms, + 'CNAME AAAA'); -} +$response = http_host_header('c_c.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'CNAME CNAME responses'); +like($response, qr/127.0.0.201:8080/, 'CNAME CNAME 1'); +like($response, qr/\[fe80::1\]:8080/, 'CNAME CNAME 2'); -# "valid" parameter tested with 1st req good and 2nd req bad -# send 1st request and cache its good response +like(http_host_header('c1_c2.example.net', '/'), qr/^\[fe80::1\]:8080$/ms, + 'CNAME1 CNAME2'); -like(http_host_header('ttl.example.net', '/valid'), qr/200 OK/, 'valid'); +$response = http_host_header('c_cn.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'CNAME CNAME+AAAA responses'); +like($response, qr/\[fe80::1\]:8080/, 'CNAME CNAME+AAAA 1'); +like($response, qr/\[fe80::2\]:8080/, 'CNAME CNAME+AAAA 1'); -# response is cached, actual request would get error +$response = http_host_header('c_e.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'CNAME error responses'); +like($response, qr/502 Bad/, 'CNAME error'); -like(http_host_header('ttl.example.net', '/valid'), qr/200 OK/, - 'valid cached 1'); -like(http_host_header('ttl.example.net', '/valid'), qr/200 OK/, - 'valid cached 2'); +$response = http_host_header('cn_z.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'CNAME+A zero responses'); +like($response, qr/127.0.0.201:8080/, 'CNAME+A zero 1'); +like($response, qr/127.0.0.202:8080/, 'CNAME+A zero 2'); -sleep 2; +$response = http_host_header('cn_n.example.net', '/'); +is(@n = $response =~ /8080/g, 4, 'CNAME+A AAAA responses'); +like($response, qr/127.0.0.201:8080/, 'CNAME+A AAAA 1'); +like($response, qr/127.0.0.202:8080/, 'CNAME+A AAAA 2'); +like($response, qr/\[fe80::1\]:8080/, 'CNAME+A AAAA 3'); +like($response, qr/\[fe80::2\]:8080/, 'CNAME+A AAAA 4'); + +$response = http_host_header('cn_c.example.net', '/'); +is(@n = $response =~ /8080/g, 2, 'CNAME+A CNAME responses'); +like($response, qr/127.0.0.201:8080/, 'CNAME+A CNAME 1'); +like($response, qr/127.0.0.202:8080/, 'CNAME+A CNAME 2'); -# expired ttl is overridden with "valid" parameter -# response is taken from cache +$response = http_host_header('cn_cn.example.net', '/'); +is(@n = $response =~ /8080/g, 4, 'CNAME+A CNAME+AAAA responses'); +like($response, qr/127.0.0.201:8080/, 'CNAME+A CNAME+AAAA 1'); +like($response, qr/127.0.0.202:8080/, 'CNAME+A CNAME+AAAA 2'); +like($response, qr/\[fe80::1\]:8080/, 'CNAME+A CNAME+AAAA 3'); +like($response, qr/\[fe80::2\]:8080/, 'CNAME+A CNAME+AAAA 4'); -like(http_host_header('ttl.example.net', '/valid'), qr/200 OK/, - 'valid overrides ttl'); +$response = http_host_header('cn_e.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'CNAME+A error responses'); +like($response, qr/502 Bad/, 'CNAME+A error'); + +$response = http_host_header('e_z.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'error zero responses'); +like($response, qr/502 Bad/, 'error zero'); -sleep 2; +$response = http_host_header('e_n.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'error AAAA responses'); +like($response, qr/502 Bad/, 'error AAAA'); -# expired "valid" value causes nginx to make actual query +$response = http_host_header('e_c.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'error CNAME responses'); +like($response, qr/502 Bad/, 'error CNAME'); -like(http_host_header('ttl.example.net', '/valid'), qr/502 Bad/, - 'valid expired'); +$response = http_host_header('e_cn.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'error CNAME+AAAA responses'); +like($response, qr/502 Bad/, 'error CNAME+AAAA'); -like(http_host_header('example.net', '/invalid'), qr/502 Bad/, 'no resolver'); +$response = http_host_header('e_e.example.net', '/'); +is(@n = $response =~ /8080/g, 0, 'error error responses'); +like($response, qr/502 Bad/, 'error error'); ############################################################################### @@ -212,6 +262,7 @@ sub reply_handler { use constant A => 1; use constant CNAME => 5; + use constant AAAA => 28; use constant DNAME => 39; use constant IN => 1; @@ -235,40 +286,37 @@ sub reply_handler { my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); my $name = join('.', @name); - if (($name eq 'a.example.net') || ($name eq 'alias.example.net')) { - if ($type == A || $type == CNAME) { - push @rdata, rd_addr($ttl, '127.0.0.1'); + if (($name eq 'aaaa.example.net') || ($name eq 'alias.example.net')) { + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, "fe80::1"); } - } elsif (($name eq 'many.example.net') && $type == A) { + } elsif ($name eq 'alias2.example.net') { + if ($type == A) { + push @rdata, rd_addr($ttl, '127.0.0.201'); + } + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, "fe80::1"); + } + + } elsif ($name eq 'alias4.example.net') { + if ($type == A) { + push @rdata, rd_addr($ttl, '127.0.0.201'); + } + + } elsif ($name eq 'alias6.example.net') { + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, "fe80::1"); + } + + } elsif (($name eq 'many.example.net') && $type == AAAA) { $state->{manycnt}++; if ($state->{manycnt} > 1) { $rcode = SERVFAIL; } - push @rdata, rd_addr($ttl, '127.0.0.201'); - push @rdata, rd_addr($ttl, '127.0.0.202'); - - - } elsif (($name eq 'short.example.net')) { - # zero length RDATA in DNS response - - if ($type == A) { - push @rdata, rd_addr($ttl, ''); - } - - } elsif (($name eq 'alias.example.com')) { - # example.com. 3600 IN DNAME example.net. - - my @dname = ('example', 'net'); - my $rdlen = length(join '', @dname) + @dname + 1; - push @rdata, pack("n3N n(w/a*)* x", 0xc012, DNAME, IN, $ttl, - $rdlen, @dname); - - # alias.example.com. 3600 IN CNAME alias.example.net. - - push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, - 8, 5, 'alias', 0xc02f); + push @rdata, rd_addr6($ttl, 'fe80::1'); + push @rdata, rd_addr6($ttl, 'fe80::2'); } elsif ($name eq 'cname.example.net') { $state->{cnamecnt}++; @@ -284,49 +332,11 @@ sub reply_handler { # points to "alias" set in previous rdata - if ($type == A) { - push @rdata, pack('n3N nC4', 0xc031, A, IN, $ttl, - 4, split(/\./, '127.0.0.1')); + if ($type == AAAA) { + push @rdata, pack('n3N nn8', 0xc031, AAAA, IN, $ttl, + 16, expand_ip6("::1")); } - } elsif ($name eq 'cname2.example.net') { - # points to non-existing A - - push @rdata, pack("n3N nCa2n", 0xc00c, CNAME, IN, $ttl, - 5, 2, 'nx', 0xc02f); - - } elsif ($name eq 'long.example.net') { - push @rdata, pack("n3N nCA63x", 0xc00c, CNAME, IN, $ttl, - 65, 63, 'a' x 63); - - } elsif (($name eq 'a' x 63) && $type == A) { - push @rdata, rd_addr($ttl, '127.0.0.1'); - - } elsif ($name eq 'long2.example.net') { - push @rdata, pack("n3N n(CA63)4x", 0xc00c, CNAME, IN, $ttl, 257, - 63, 'a' x 63, 63, 'a' x 63, 63, 'a' x 63, 63, 'a' x 63); - - } elsif (($name eq 'a' x 63 . '.' . 'a' x 63 . '.' . 'a' x 63 . '.' - . 'a' x 63) && $type == A) - { - push @rdata, rd_addr($ttl, '127.0.0.1'); - - } elsif ($name eq 'ttl.example.net' && $type == A) { - $state->{ttlcnt}++; - if ($state->{ttlcnt} == 2 || $state->{ttlcnt} == 4) { - $rcode = SERVFAIL; - } - - push @rdata, rd_addr(1, '127.0.0.1'); - - } elsif ($name eq 'ttl0.example.net' && $type == A) { - $state->{ttl0cnt}++; - if ($state->{ttl0cnt} == 2) { - $rcode = SERVFAIL; - } - - push @rdata, rd_addr(0, '127.0.0.1'); - } elsif ($name eq '2.example.net') { if ($port == 8081) { $state->{twocnt}++; @@ -335,8 +345,231 @@ sub reply_handler { $rcode = SERVFAIL; } + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, '::1'); + } + + } elsif ($name eq 'z_z.example.net') { + # assume no answers given + + } elsif ($name eq 'z_n.example.net') { + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, 'fe80::1'); + } + + } elsif ($name eq 'z_c.example.net') { + if ($type == AAAA) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc010); + } + + } elsif ($name eq 'z_cn.example.net') { + if ($type == AAAA) { + push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, + 8, 5, 'alias', 0xc011); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::1")); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::2")); + } + + } elsif ($name eq 'z_e.example.net') { + if ($type == AAAA) { + $rcode = SERVFAIL; + } + + } elsif ($name eq 'n_z.example.net') { if ($type == A) { - push @rdata, rd_addr($ttl, '127.0.0.1'); + push @rdata, rd_addr($ttl, '127.0.0.201'); + } + + } elsif ($name eq 'n_n.example.net') { + if ($type == A) { + push @rdata, rd_addr($ttl, '127.0.0.201'); + } + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, 'fe80::1'); + } + + } elsif ($name eq 'n_c.example.net') { + if ($type == A) { + push @rdata, rd_addr($ttl, '127.0.0.201'); + } + if ($type == AAAA) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc010); + } + + } elsif ($name eq 'n_cn.example.net') { + if ($type == A) { + push @rdata, rd_addr($ttl, '127.0.0.201'); + push @rdata, rd_addr($ttl, '127.0.0.202'); + } + if ($type == AAAA) { + push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, + 8, 5, 'alias', 0xc011); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::1")); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::2")); + } + + } elsif ($name eq 'n_e.example.net') { + if ($type == A) { + push @rdata, rd_addr($ttl, '127.0.0.201'); + } + if ($type == AAAA) { + $rcode = SERVFAIL; + } + + } elsif ($name eq 'c_z.example.net') { + if ($type == A) { + push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, + 8, 5, 'alias', 0xc010); + } + + } elsif ($name eq 'c_n.example.net') { + if ($type == A) { + push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, + 8, 5, 'alias', 0xc010); + } + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, "fe80::1"); + } + + } elsif ($name eq 'c_c.example.net') { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc010); + + } elsif ($name eq 'c1_c2.example.net') { + if ($type == A) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias4', 0xc012); + } + if ($type == AAAA) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias6', 0xc012); + } + + } elsif ($name eq 'c_cn.example.net') { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc011); + + if ($type == AAAA) { + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::1")); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::2")); + } + + } elsif ($name eq 'cn_z.example.net') { + if ($type == A) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc011); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.201')); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.202')); + } + + } elsif ($name eq 'cn_n.example.net') { + if ($type == A) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc011); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.201')); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.202')); + } + if ($type == AAAA) { + push @rdata, pack('n3N nn8', 0xc00c, AAAA, IN, $ttl, + 16, expand_ip6("fe80::1")); + push @rdata, pack('n3N nn8', 0xc00c, AAAA, IN, $ttl, + 16, expand_ip6("fe80::2")); + } + + } elsif ($name eq 'cn_c.example.net') { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc011); + if ($type == A) { + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.201')); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.202')); + } + + } elsif ($name eq 'cn_cn.example.net') { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc012); + + if ($type == A) { + push @rdata, pack("n3N nC4", 0xc02f, A, IN, $ttl, + 4, split('\.', '127.0.0.201')); + push @rdata, pack("n3N nC4", 0xc02f, A, IN, $ttl, + 4, split('\.', '127.0.0.202')); + } + if ($type == AAAA) { + push @rdata, pack('n3N nn8', 0xc02f, AAAA, IN, $ttl, + 16, expand_ip6("fe80::1")); + push @rdata, pack('n3N nn8', 0xc02f, AAAA, IN, $ttl, + 16, expand_ip6("fe80::2")); + } + + } elsif ($name eq 'cn_e.example.net') { + if ($type == A) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc011); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.201')); + push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl, + 4, split('\.', '127.0.0.202')); + } + if ($type == AAAA) { + $rcode = SERVFAIL; + } + + + } elsif ($name eq 'e_z.example.net') { + if ($type == A) { + $rcode = SERVFAIL; + } + + } elsif ($name eq 'e_n.example.net') { + if ($type == A) { + $rcode = SERVFAIL; + } + if ($type == AAAA) { + push @rdata, rd_addr6($ttl, 'fe80::1'); + } + + } elsif ($name eq 'e_c.example.net') { + if ($type == A) { + $rcode = SERVFAIL; + } + if ($type == AAAA) { + push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl, + 9, 6, 'alias2', 0xc010); + } + + } elsif ($name eq 'e_cn.example.net') { + if ($type == A) { + $rcode = SERVFAIL; + } + if ($type == AAAA) { + push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, + 8, 5, 'alias', 0xc011); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::1")); + push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl, + 16, expand_ip6("fe80::2")); + } + + } elsif ($name eq 'e_e.example.net') { + if ($type == A) { + $rcode = SERVFAIL; + } + if ($type == AAAA) { + $rcode = NXDOMAIN; } } @@ -350,9 +583,21 @@ sub rd_addr { my $code = 'split(/\./, $addr)'; - return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; + pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); +} + +sub expand_ip6 { + my ($addr) = @_; - pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); + substr ($addr, index($addr, "::"), 2) = + join "0", map { ":" } (0 .. 8 - (split /:/, $addr) + 1); + map { hex "0" x (4 - length $_) . "$_" } split /:/, $addr; +} + +sub rd_addr6 { + my ($ttl, $addr) = @_; + + pack 'n3N nn8', 0xc00c, AAAA, IN, $ttl, 16, expand_ip6($addr); } sub dns_daemon { @@ -371,8 +616,6 @@ sub dns_daemon { my %state = ( cnamecnt => 0, twocnt => 0, - ttlcnt => 0, - ttl0cnt => 0, manycnt => 0, );