Mercurial > hg > nginx-tests
comparison http_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 | 7a472e46772c |
children | cdab739eb6ea |
comparison
equal
deleted
inserted
replaced
356:7a472e46772c | 357:e0c00e695cb5 |
---|---|
19 | 19 |
20 ############################################################################### | 20 ############################################################################### |
21 | 21 |
22 select STDERR; $| = 1; | 22 select STDERR; $| = 1; |
23 select STDOUT; $| = 1; | 23 select STDOUT; $| = 1; |
24 | |
25 eval { require Net::DNS::Nameserver; }; | |
26 plan(skip_all => "Net::DNS::Nameserver not installed") if $@; | |
27 | 24 |
28 my $t = Test::Nginx->new()->has(qw/http proxy rewrite ipv6/); | 25 my $t = Test::Nginx->new()->has(qw/http proxy rewrite ipv6/); |
29 | 26 |
30 $t->write_file_expand('nginx.conf', <<'EOF'); | 27 $t->write_file_expand('nginx.conf', <<'EOF'); |
31 | 28 |
85 } | 82 } |
86 } | 83 } |
87 } | 84 } |
88 | 85 |
89 EOF | 86 EOF |
90 | |
91 $t->run_daemon(\&dns_daemon, 8081); | |
92 $t->run_daemon(\&dns_daemon, 8082); | |
93 | 87 |
94 eval { | 88 eval { |
95 open OLDERR, ">&", \*STDERR; close STDERR; | 89 open OLDERR, ">&", \*STDERR; close STDERR; |
96 $t->run(); | 90 $t->run(); |
97 open STDERR, ">&", \*OLDERR; | 91 open STDERR, ">&", \*OLDERR; |
98 }; | 92 }; |
99 plan(skip_all => 'no inet6 support') if $@; | 93 plan(skip_all => 'no inet6 support') if $@; |
100 | 94 |
101 $t->waitforsocket('127.0.0.1:8081'); | 95 $t->run_daemon(\&dns_daemon, 8081, $t); |
102 $t->waitforsocket('127.0.0.1:8082'); | 96 $t->run_daemon(\&dns_daemon, 8082, $t); |
97 | |
98 $t->waitforfile($t->testdir . '/8081'); | |
99 $t->waitforfile($t->testdir . '/8082'); | |
103 | 100 |
104 $t->plan(28); | 101 $t->plan(28); |
105 | 102 |
106 ############################################################################### | 103 ############################################################################### |
107 | 104 |
229 } | 226 } |
230 | 227 |
231 ############################################################################### | 228 ############################################################################### |
232 | 229 |
233 sub reply_handler { | 230 sub reply_handler { |
234 my ($name, $class, $type, $peerhost, $query, $conn) = @_; | 231 my ($recv_data, $port) = @_; |
235 my ($rcode, @ans, $ttl, $rdata); | 232 |
236 | 233 my (@name, @rdata); |
237 $rcode = 'NOERROR'; | 234 |
238 $ttl = 3600; | 235 use constant NOERROR => 0; |
239 | 236 use constant SERVFAIL => 2; |
237 use constant NXDOMAIN => 3; | |
238 | |
239 use constant A => 1; | |
240 use constant CNAME => 5; | |
241 use constant AAAA => 28; | |
242 use constant DNAME => 39; | |
243 | |
244 use constant IN => 1; | |
245 | |
246 # default values | |
247 | |
248 my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600); | |
249 | |
250 # decode name | |
251 | |
252 my ($len, $offset) = (undef, 12); | |
253 while (1) { | |
254 $len = unpack("\@$offset C", $recv_data); | |
255 last if $len == 0; | |
256 $offset++; | |
257 push @name, unpack("\@$offset A$len", $recv_data); | |
258 $offset += $len; | |
259 } | |
260 | |
261 $offset -= 1; | |
262 my ($id, $type, $class) = unpack("n x$offset n2", $recv_data); | |
263 | |
264 my $name = join('.', @name); | |
240 if (($name eq 'a.example.net') || ($name eq 'alias.example.net')) { | 265 if (($name eq 'a.example.net') || ($name eq 'alias.example.net')) { |
241 ($rdata) = ('127.0.0.1'); | 266 push @rdata, rd_addr($ttl, '127.0.0.1'); |
242 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | |
243 | 267 |
244 } elsif (($name eq 'many.example.net')) { | 268 } elsif (($name eq 'many.example.net')) { |
245 if ($conn->{sockport} == 8082) { | 269 if ($port == 8082) { |
246 return 'SERVFAIL'; | 270 $rcode = SERVFAIL; |
247 } | 271 } |
248 ($rdata) = ('127.0.0.201'); | 272 |
249 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 273 push @rdata, rd_addr($ttl, '127.0.0.201'); |
250 ($rdata) = ('127.0.0.202'); | 274 push @rdata, rd_addr($ttl, '127.0.0.202'); |
251 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | |
252 | 275 |
253 } elsif (($name eq 'aaaa.example.net')) { | 276 } elsif (($name eq 'aaaa.example.net')) { |
254 ($type, $rdata) = ('AAAA', '::1'); | 277 # AAAA [::1] |
255 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 278 |
279 push @rdata, pack('n3N nx15C', 0xc00c, AAAA, IN, $ttl, | |
280 16, 1); | |
256 | 281 |
257 } elsif (($name eq 'short.example.net')) { | 282 } elsif (($name eq 'short.example.net')) { |
258 # zero length RDATA in DNS response | 283 # zero length RDATA in DNS response |
259 ($name, $rdata) = ($name, ''); | 284 |
260 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 285 push @rdata, rd_addr($ttl, ''); |
261 | 286 |
262 } elsif (($name eq 'alias.example.com')) { | 287 } elsif (($name eq 'alias.example.com')) { |
263 my $dname = 'example.com'; | 288 # example.com. 3600 IN DNAME example.net. |
264 ($type, $rdata) = ('DNAME', 'example.net'); | 289 |
265 push @ans, Net::DNS::RR->new("$dname $ttl $class $type $rdata"); | 290 my @dname = ('example', 'net'); |
266 ($type, $rdata) = ('CNAME', 'alias.example.net'); | 291 my $rdlen = length(join '', @dname) + @dname + 1; |
267 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 292 push @rdata, pack("n3N n(w/a*)* x", 0xc012, DNAME, IN, $ttl, |
293 $rdlen, @dname); | |
294 | |
295 # alias.example.com. 3600 IN CNAME alias.example.net. | |
296 | |
297 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, | |
298 8, 5, 'alias', 0xc02f); | |
268 | 299 |
269 } elsif ($name eq 'cname.example.net') { | 300 } elsif ($name eq 'cname.example.net') { |
270 if ($conn->{sockport} == 8082) { | 301 if ($port == 8082) { |
271 return 'SERVFAIL'; | 302 $rcode = SERVFAIL; |
272 } | 303 } |
273 ($type, $rdata) = ('CNAME', 'alias.example.net'); | 304 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, |
274 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 305 8, 5, 'alias', 0xc012); |
275 | 306 |
276 } elsif ($name eq 'cname_a.example.net') { | 307 } elsif ($name eq 'cname_a.example.net') { |
277 ($type, $rdata) = ('CNAME', 'alias.example.net'); | 308 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl, |
278 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 309 8, 5, 'alias', 0xc014); |
279 | 310 |
280 ($name, $type, $rdata) = ('alias.example.net', 'A', '127.0.0.1'); | 311 # points to "alias" set in previous rdata |
281 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 312 |
313 push @rdata, pack('n3N nC4', 0xc031, A, IN, $ttl, | |
314 4, split(/\./, '127.0.0.1')); | |
282 | 315 |
283 } elsif ($name eq 'cname2.example.net') { | 316 } elsif ($name eq 'cname2.example.net') { |
284 # points to non-existing A | 317 # points to non-existing A |
285 ($type, $rdata) = ('CNAME', 'nx.example.net'); | 318 |
286 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 319 push @rdata, pack("n3N nCa2n", 0xc00c, CNAME, IN, $ttl, |
320 5, 2, 'nx', 0xc02f); | |
287 | 321 |
288 } elsif ($name eq 'long.example.net') { | 322 } elsif ($name eq 'long.example.net') { |
289 ($type, $rdata) = ('CNAME', 'a' x 63); | 323 push @rdata, pack("n3N nCA63x", 0xc00c, CNAME, IN, $ttl, |
290 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 324 65, 63, 'a' x 63); |
291 | 325 |
292 } elsif (($name eq 'a' x 63)) { | 326 } elsif (($name eq 'a' x 63)) { |
293 ($rdata) = ('127.0.0.1'); | 327 push @rdata, rd_addr($ttl, '127.0.0.1'); |
294 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | |
295 | 328 |
296 } elsif ($name eq 'long2.example.net') { | 329 } elsif ($name eq 'long2.example.net') { |
297 ($type, $rdata) = ('CNAME', 'a' x 63 . '.' . 'a' x 63 . '.' | 330 push @rdata, pack("n3N n(CA63)4x", 0xc00c, CNAME, IN, $ttl, 257, |
298 . 'a' x 63 . '.' . 'a' x 63); | 331 63, 'a' x 63, 63, 'a' x 63, 63, 'a' x 63, 63, 'a' x 63); |
299 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | |
300 | 332 |
301 } elsif (($name eq 'a' x 63 . '.' . 'a' x 63 . '.' . 'a' x 63 . '.' | 333 } elsif (($name eq 'a' x 63 . '.' . 'a' x 63 . '.' . 'a' x 63 . '.' |
302 . 'a' x 63)) | 334 . 'a' x 63)) |
303 { | 335 { |
304 ($rdata) = ('127.0.0.1'); | 336 push @rdata, rd_addr($ttl, '127.0.0.1'); |
305 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | |
306 | 337 |
307 } elsif ($name eq 'ttl.example.net') { | 338 } elsif ($name eq 'ttl.example.net') { |
308 if ($conn->{sockport} == 8082) { | 339 if ($port == 8082) { |
309 return 'SERVFAIL'; | 340 $rcode = SERVFAIL; |
310 } | 341 } |
311 ($ttl, $rdata) = (1, '127.0.0.1'); | 342 |
312 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 343 push @rdata, rd_addr(1, '127.0.0.1'); |
313 | 344 |
314 } elsif ($name eq 'ttl0.example.net') { | 345 } elsif ($name eq 'ttl0.example.net') { |
315 if ($conn->{sockport} == 8082) { | 346 if ($port == 8082) { |
316 return 'SERVFAIL'; | 347 $rcode = SERVFAIL; |
317 } | 348 } |
318 ($ttl, $rdata) = (0, '127.0.0.1'); | 349 |
319 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 350 push @rdata, rd_addr(0, '127.0.0.1'); |
320 | 351 |
321 } elsif ($name eq '2.example.net') { | 352 } elsif ($name eq '2.example.net') { |
322 if ($conn->{sockport} == 8081) { | 353 if ($port == 8081) { |
323 return 'SERVFAIL'; | 354 $rcode = SERVFAIL; |
324 } | 355 } |
325 ($rdata) = ('127.0.0.1'); | 356 |
326 push @ans, Net::DNS::RR->new("$name $ttl $class $type $rdata"); | 357 push @rdata, rd_addr(0, '127.0.0.1'); |
327 | 358 |
328 } else { | 359 } else { |
329 $rcode = 'NXDOMAIN'; | 360 $rcode = NXDOMAIN; |
330 } | 361 } |
331 | 362 |
332 return ($rcode, \@ans); | 363 $len = @name; |
364 pack("n6 (w/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, | |
365 0, 0, @name, $type, $class) . join('', @rdata); | |
366 } | |
367 | |
368 sub rd_addr { | |
369 my ($ttl, $addr) = @_; | |
370 | |
371 my $code = 'split(/\./, $addr)'; | |
372 | |
373 return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq ''; | |
374 | |
375 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); | |
333 } | 376 } |
334 | 377 |
335 sub dns_daemon { | 378 sub dns_daemon { |
336 my ($port) = @_; | 379 my ($port, $t) = @_; |
337 | 380 |
338 my $ns = Net::DNS::Nameserver->new( | 381 my ($data, $recv_data); |
382 my $socket = IO::Socket::INET->new( | |
339 LocalAddr => '127.0.0.1', | 383 LocalAddr => '127.0.0.1', |
340 LocalPort => $port, | 384 LocalPort => $port, |
341 Proto => 'udp', | 385 Proto => 'udp', |
342 ReplyHandler => \&reply_handler, | |
343 ) | 386 ) |
344 or die "Can't create nameserver object: $!\n"; | 387 or die "Can't create listening socket: $!\n"; |
345 | 388 |
346 $ns->main_loop; | 389 # signal we are ready |
347 } | 390 |
348 | 391 open my $fh, '>', $t->testdir() . '/' . $port; |
349 ############################################################################### | 392 close $fh; |
393 | |
394 while (1) { | |
395 $socket->recv($recv_data, 65536); | |
396 $data = reply_handler($recv_data, $port); | |
397 $socket->send($data); | |
398 } | |
399 } | |
400 | |
401 ############################################################################### |