Mercurial > hg > nginx-tests
comparison mail_resolver.t @ 357:e0c00e695cb5
Tests: removed Net::DNS dependency.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Fri, 22 Nov 2013 15:20:16 +0400 |
parents | 14eba1ad0880 |
children | cdab739eb6ea |
comparison
equal
deleted
inserted
replaced
356:7a472e46772c | 357:e0c00e695cb5 |
---|---|
22 | 22 |
23 select STDERR; $| = 1; | 23 select STDERR; $| = 1; |
24 select STDOUT; $| = 1; | 24 select STDOUT; $| = 1; |
25 | 25 |
26 local $SIG{PIPE} = 'IGNORE'; | 26 local $SIG{PIPE} = 'IGNORE'; |
27 | |
28 eval { require Net::DNS::Nameserver; }; | |
29 plan(skip_all => "Net::DNS::Nameserver not installed") if $@; | |
30 | 27 |
31 my $t = Test::Nginx->new()->has(qw/mail smtp http rewrite/) | 28 my $t = Test::Nginx->new()->has(qw/mail smtp http rewrite/) |
32 ->run_daemon(\&Test::Nginx::SMTP::smtp_test_daemon); | 29 ->run_daemon(\&Test::Nginx::SMTP::smtp_test_daemon); |
33 | 30 |
34 $t->write_file_expand('nginx.conf', <<'EOF'); | 31 $t->write_file_expand('nginx.conf', <<'EOF'); |
95 } | 92 } |
96 } | 93 } |
97 | 94 |
98 EOF | 95 EOF |
99 | 96 |
100 $t->run_daemon(\&dns_daemon, 8081); | 97 $t->run_daemon(\&dns_daemon, 8081, $t); |
101 $t->run_daemon(\&dns_daemon, 8082); | 98 $t->run_daemon(\&dns_daemon, 8082, $t); |
102 $t->run_daemon(\&dns_daemon, 8083); | 99 $t->run_daemon(\&dns_daemon, 8083, $t); |
103 $t->run_daemon(\&dns_daemon, 8084); | 100 $t->run_daemon(\&dns_daemon, 8084, $t); |
104 $t->run(); | 101 $t->run(); |
105 | 102 |
106 $t->waitforsocket('127.0.0.1:8081'); | 103 $t->waitforfile($t->testdir . '/8081'); |
107 $t->waitforsocket('127.0.0.1:8082'); | 104 $t->waitforfile($t->testdir . '/8082'); |
108 $t->waitforsocket('127.0.0.1:8083'); | 105 $t->waitforfile($t->testdir . '/8083'); |
109 $t->waitforsocket('127.0.0.1:8084'); | 106 $t->waitforfile($t->testdir . '/8084'); |
110 | 107 |
111 $t->plan(5); | 108 $t->plan(5); |
112 | 109 |
113 ############################################################################### | 110 ############################################################################### |
114 | 111 |
203 } | 200 } |
204 | 201 |
205 ############################################################################### | 202 ############################################################################### |
206 | 203 |
207 sub reply_handler { | 204 sub reply_handler { |
208 my ($name, $class, $type, $peerhost, $query, $conn) = @_; | 205 my ($recv_data, $port) = @_; |
209 my ($rcode, @ans, $ttl, $rdata); | 206 |
210 | 207 my (@name, @rdata); |
211 $rcode = 'NOERROR'; | 208 |
212 $ttl = 3600; | 209 use constant NOERROR => 0; |
213 | 210 use constant SERVFAIL => 2; |
214 if ($name eq 'a.example.net' && $type eq 'A') { | 211 use constant NXDOMAIN => 3; |
215 ($rdata) = ('127.0.0.1'); | 212 |
216 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 213 use constant A => 1; |
217 | 214 use constant CNAME => 5; |
218 } elsif ($name eq '1.0.0.127.in-addr.arpa' && $type eq 'PTR') { | 215 use constant PTR => 12; |
219 if ($conn->{sockport} == 8081) { | 216 |
220 $rdata = 'a.example.net'; | 217 use constant IN => 1; |
221 push @ans, Net::DNS::RR->new( | 218 |
222 "$name $ttl $class $type $rdata" | 219 # default values |
223 ); | 220 |
224 | 221 my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); |
225 } elsif ($conn->{sockport} == 8082) { | 222 |
226 return 'SERVFAIL'; | 223 # decode name |
227 | 224 |
228 } elsif ($conn->{sockport} == 8083) { | 225 my ($len, $offset) = (undef, 12); |
226 while (1) { | |
227 $len = unpack("\@$offset C", $recv_data); | |
228 last if $len == 0; | |
229 $offset++; | |
230 push @name, unpack("\@$offset A$len", $recv_data); | |
231 $offset += $len; | |
232 } | |
233 | |
234 $offset -= 1; | |
235 my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); | |
236 | |
237 my $name = join('.', @name); | |
238 if ($name eq 'a.example.net' && $type == A) { | |
239 push @rdata, rd_addr($ttl, '127.0.0.1'); | |
240 | |
241 } elsif ($name eq '1.0.0.127.in-addr.arpa' && $type == PTR) { | |
242 if ($port == 8081) { | |
243 push @rdata, rd_name(PTR, $ttl, 'a.example.net'); | |
244 | |
245 } elsif ($port == 8082) { | |
246 $rcode = SERVFAIL; | |
247 | |
248 } elsif ($port == 8083) { | |
229 # zero length RDATA | 249 # zero length RDATA |
230 $rdata = ''; | 250 |
231 push @ans, Net::DNS::RR->new( | 251 push @rdata, pack("n3N n", 0xc00c, PTR, IN, $ttl, 0); |
232 "$name $ttl $class $type $rdata" | 252 |
233 ); | 253 } elsif ($port == 8084) { |
234 | |
235 } elsif ($conn->{sockport} == 8084) { | |
236 # PTR answered with CNAME | 254 # PTR answered with CNAME |
237 ($type, $rdata) = ('CNAME', | 255 |
256 push @rdata, rd_name(CNAME, $ttl, | |
238 '1.1.0.0.127.in-addr.arpa'); | 257 '1.1.0.0.127.in-addr.arpa'); |
239 push @ans, Net::DNS::RR->new( | |
240 "$name $ttl $class $type $rdata" | |
241 ); | |
242 } | 258 } |
243 | 259 |
244 } elsif ($name eq '1.1.0.0.127.in-addr.arpa' && $type eq 'PTR') { | 260 } elsif ($name eq '1.1.0.0.127.in-addr.arpa' && $type == PTR) { |
245 $rdata = 'a.example.net'; | 261 push @rdata, rd_name(PTR, $ttl, 'a.example.net'); |
246 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | |
247 | 262 |
248 } else { | 263 } else { |
249 $rcode = 'NXDOMAIN'; | 264 $rcode = NXDOMAIN; |
250 } | 265 } |
251 | 266 |
252 return ($rcode, \@ans); | 267 $len = @name; |
268 pack("n6 (w/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, | |
269 0, 0, @name, $type, $class) . join('', @rdata); | |
270 } | |
271 | |
272 sub rd_name { | |
273 my ($type, $ttl, $name) = @_; | |
274 my ($rdlen, @rdname); | |
275 | |
276 @rdname = split /\./, $name; | |
277 $rdlen = length(join '', @rdname) + @rdname + 1; | |
278 pack("n3N n(w/a*)* x", 0xc00c, PTR, IN, $ttl, $rdlen, @rdname); | |
279 } | |
280 | |
281 sub rd_addr { | |
282 my ($ttl, $addr) = @_; | |
283 | |
284 my $code = 'split(/\./, $addr)'; | |
285 | |
286 # use a special pack string to not zero pad | |
287 | |
288 return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; | |
289 | |
290 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); | |
253 } | 291 } |
254 | 292 |
255 sub dns_daemon { | 293 sub dns_daemon { |
256 my ($port) = @_; | 294 my ($port, $t) = @_; |
257 | 295 |
258 my $ns = Net::DNS::Nameserver->new( | 296 my ($data, $recv_data); |
297 my $socket = IO::Socket::INET->new( | |
259 LocalAddr => '127.0.0.1', | 298 LocalAddr => '127.0.0.1', |
260 LocalPort => $port, | 299 LocalPort => $port, |
261 Proto => 'udp', | 300 Proto => 'udp', |
262 ReplyHandler => \&reply_handler, | |
263 ) | 301 ) |
264 or die "Can't create nameserver object: $!\n"; | 302 or die "Can't create listening socket: $!\n"; |
265 | 303 |
266 $ns->main_loop; | 304 # signal we are ready |
267 } | 305 |
268 | 306 open my $fh, '>', $t->testdir() . '/' . $port; |
269 ############################################################################### | 307 close $fh; |
308 | |
309 while (1) { | |
310 $socket->recv($recv_data, 65536); | |
311 $data = reply_handler($recv_data, $port); | |
312 $socket->send($data); | |
313 } | |
314 } | |
315 | |
316 ############################################################################### |