comparison http_resolver_aaaa.t @ 360:82db241184e0

Tests: added AAAA specific resolver tests.
author Sergey Kandaurov <pluknet@nginx.com>
date Sat, 14 Dec 2013 00:02:33 +0400
parents http_resolver.t@cdab739eb6ea
children c28ecaef065f
comparison
equal deleted inserted replaced
359:cdab739eb6ea 360:82db241184e0
1 #!/usr/bin/perl
2
3 # (C) Sergey Kandaurov
4 # (C) Nginx, Inc.
5
6 # Tests for AAAA capable http resolver.
7
8 ###############################################################################
9
10 use warnings;
11 use strict;
12
13 use Test::More;
14
15 BEGIN { use FindBin; chdir($FindBin::Bin); }
16
17 use lib 'lib';
18 use Test::Nginx;
19
20 ###############################################################################
21
22 select STDERR; $| = 1;
23 select STDOUT; $| = 1;
24
25 my $t = Test::Nginx->new()->has(qw/http proxy rewrite ipv6/);
26
27 plan(skip_all => 'no ipv6 capable resolver') unless $t->has_version('1.5.8');
28
29 $t->write_file_expand('nginx.conf', <<'EOF');
30
31 %%TEST_GLOBALS%%
32
33 daemon off;
34
35 events {
36 }
37
38 http {
39 %%TEST_GLOBALS_HTTP%%
40
41 server {
42 listen 127.0.0.1:8080;
43 listen [::1]:8080;
44 server_name localhost;
45
46 location / {
47 resolver 127.0.0.1:8081;
48 proxy_pass http://$host:8080/backend;
49
50 proxy_next_upstream http_504 timeout error;
51 proxy_intercept_errors on;
52 proxy_connect_timeout 50ms;
53 error_page 504 502 /50x;
54 }
55 location /two {
56 resolver 127.0.0.1:8081 127.0.0.1:8082;
57 proxy_pass http://$host:8080/backend;
58 }
59
60 location /backend {
61 return 200;
62 }
63 location /50x {
64 return 200 $upstream_addr;
65 }
66 }
67 }
68
69 EOF
70
71 eval {
72 open OLDERR, ">&", \*STDERR; close STDERR;
73 $t->run();
74 open STDERR, ">&", \*OLDERR;
75 };
76 plan(skip_all => 'no inet6 support') if $@;
77
78 $t->run_daemon(\&dns_daemon, 8081, $t);
79 $t->run_daemon(\&dns_daemon, 8082, $t);
80
81 $t->waitforfile($t->testdir . '/8081');
82 $t->waitforfile($t->testdir . '/8082');
83
84 $t->plan(72);
85
86 ###############################################################################
87
88 my (@n, $response);
89
90 like(http_host_header('aaaa.example.net', '/'), qr/\[fe80::1\]/, 'AAAA');
91 like(http_host_header('cname.example.net', '/'), qr/\[fe80::1\]/, 'CNAME');
92 like(http_host_header('cname.example.net', '/'), qr/\[fe80::1\]/,
93 'CNAME cached');
94
95 # CNAME + AAAA combined answer
96 # demonstrates the name in answer section different from what is asked
97
98 like(http_host_header('cname_a.example.net', '/'), qr/200 OK/, 'CNAME + AAAA');
99
100 # many AAAA records in round robin
101 # nonexisting IPs enumerated with proxy_next_upstream
102
103 like(http_host_header('many.example.net', '/'),
104 qr/^\[fe80::(1\]:8080, \[fe80::2\]:8080|2\]:8080, \[fe80::1\]:8080)$/m,
105 'AAAA many');
106
107 like(http_host_header('many.example.net', '/'),
108 qr/^\[fe80::(1\]:8080, \[fe80::2\]:8080|2\]:8080, \[fe80::1\]:8080)$/m,
109 'AAAA many cached');
110
111 # tests for several resolvers specified in directive
112 # query bad ns, make sure that error responses are not cached
113
114 like(http_host_header('2.example.net', '/two'), qr/502 Bad/, 'two ns bad');
115
116 # now get correct response
117
118 like(http_host_header('2.example.net', '/two'), qr/200 OK/, 'two ns good');
119
120 # response is cached, actual request would get error
121
122 like(http_host_header('2.example.net', '/two'), qr/200 OK/, 'two ns cached');
123
124 # various ipv4/ipv6 combinations
125
126 $response = http_host_header('z_z.example.net', '/');
127 is(@n = $response =~ /8080/g, 0, 'zero zero responses');
128 like($response, qr/502 Bad/, 'zero zero');
129
130 like(http_host_header('z_n.example.net', '/'), qr/^\[fe80::1\]:8080$/ms,
131 'zero AAAA');
132
133 $response = http_host_header('z_c.example.net', '/');
134 is(@n = $response =~ /8080/g, 2, 'zero CNAME responses');
135 like($response, qr/127.0.0.201:8080/, 'zero CNAME 1');
136 like($response, qr/\[fe80::1\]:8080/, 'zero CNAME 2');
137
138 $response = http_host_header('z_cn.example.net', '/');
139 is(@n = $response =~ /8080/g, 2, 'zero CNAME+AAAA responses');
140 like($response, qr/\[fe80::1\]:8080/, 'zero CNAME+AAAA 1');
141 like($response, qr/\[fe80::2\]:8080/, 'zero CNAME+AAAA 2');
142
143 $response = http_host_header('z_e.example.net', '/');
144 is(@n = $response =~ /8080/g, 0, 'zero error responses');
145 like($response, qr/502 Bad/, 'zero error');
146
147 like(http_host_header('n_z.example.net', '/'), qr/^127.0.0.201:8080$/ms,
148 'A zero');
149
150 $response = http_host_header('n_n.example.net', '/');
151 is(@n = $response =~ /8080/g, 2, 'A AAAA responses');
152 like($response, qr/127.0.0.201:8080/, 'A AAAA 1');
153 like($response, qr/\[fe80::1\]:8080/, 'A AAAA 2');
154
155 like(http_host_header('n_c.example.net', '/'), qr/^127.0.0.201:8080$/ms,
156 'A CNAME');
157
158 $response = http_host_header('n_cn.example.net', '/');
159 is(@n = $response =~ /8080/g, 4, 'A CNAME+AAAA responses');
160 like($response, qr/127.0.0.201:8080/, 'A CNAME+AAAA 1');
161 like($response, qr/127.0.0.202:8080/, 'A CNAME+AAAA 2');
162 like($response, qr/\[fe80::1\]:8080/, 'A CNAME+AAAA 3');
163 like($response, qr/\[fe80::2\]:8080/, 'A CNAME+AAAA 4');
164
165 $response = http_host_header('n_e.example.net', '/');
166 is(@n = $response =~ /8080/g, 0, 'A error responses');
167 like($response, qr/502 Bad/, 'A error');
168
169 $response = http_host_header('c_z.example.net', '/');
170 is(@n = $response =~ /8080/g, 0, 'CNAME zero responses');
171 like($response, qr/502 Bad/, 'CNAME zero');
172
173 like(http_host_header('c_n.example.net', '/'), qr/^\[fe80::1\]:8080$/ms,
174 'CNAME AAAA');
175
176 $response = http_host_header('c_c.example.net', '/');
177 is(@n = $response =~ /8080/g, 2, 'CNAME CNAME responses');
178 like($response, qr/127.0.0.201:8080/, 'CNAME CNAME 1');
179 like($response, qr/\[fe80::1\]:8080/, 'CNAME CNAME 2');
180
181 like(http_host_header('c1_c2.example.net', '/'), qr/^\[fe80::1\]:8080$/ms,
182 'CNAME1 CNAME2');
183
184 $response = http_host_header('c_cn.example.net', '/');
185 is(@n = $response =~ /8080/g, 2, 'CNAME CNAME+AAAA responses');
186 like($response, qr/\[fe80::1\]:8080/, 'CNAME CNAME+AAAA 1');
187 like($response, qr/\[fe80::2\]:8080/, 'CNAME CNAME+AAAA 1');
188
189 $response = http_host_header('c_e.example.net', '/');
190 is(@n = $response =~ /8080/g, 0, 'CNAME error responses');
191 like($response, qr/502 Bad/, 'CNAME error');
192
193 $response = http_host_header('cn_z.example.net', '/');
194 is(@n = $response =~ /8080/g, 2, 'CNAME+A zero responses');
195 like($response, qr/127.0.0.201:8080/, 'CNAME+A zero 1');
196 like($response, qr/127.0.0.202:8080/, 'CNAME+A zero 2');
197
198 $response = http_host_header('cn_n.example.net', '/');
199 is(@n = $response =~ /8080/g, 4, 'CNAME+A AAAA responses');
200 like($response, qr/127.0.0.201:8080/, 'CNAME+A AAAA 1');
201 like($response, qr/127.0.0.202:8080/, 'CNAME+A AAAA 2');
202 like($response, qr/\[fe80::1\]:8080/, 'CNAME+A AAAA 3');
203 like($response, qr/\[fe80::2\]:8080/, 'CNAME+A AAAA 4');
204
205 $response = http_host_header('cn_c.example.net', '/');
206 is(@n = $response =~ /8080/g, 2, 'CNAME+A CNAME responses');
207 like($response, qr/127.0.0.201:8080/, 'CNAME+A CNAME 1');
208 like($response, qr/127.0.0.202:8080/, 'CNAME+A CNAME 2');
209
210 $response = http_host_header('cn_cn.example.net', '/');
211 is(@n = $response =~ /8080/g, 4, 'CNAME+A CNAME+AAAA responses');
212 like($response, qr/127.0.0.201:8080/, 'CNAME+A CNAME+AAAA 1');
213 like($response, qr/127.0.0.202:8080/, 'CNAME+A CNAME+AAAA 2');
214 like($response, qr/\[fe80::1\]:8080/, 'CNAME+A CNAME+AAAA 3');
215 like($response, qr/\[fe80::2\]:8080/, 'CNAME+A CNAME+AAAA 4');
216
217 $response = http_host_header('cn_e.example.net', '/');
218 is(@n = $response =~ /8080/g, 0, 'CNAME+A error responses');
219 like($response, qr/502 Bad/, 'CNAME+A error');
220
221 $response = http_host_header('e_z.example.net', '/');
222 is(@n = $response =~ /8080/g, 0, 'error zero responses');
223 like($response, qr/502 Bad/, 'error zero');
224
225 $response = http_host_header('e_n.example.net', '/');
226 is(@n = $response =~ /8080/g, 0, 'error AAAA responses');
227 like($response, qr/502 Bad/, 'error AAAA');
228
229 $response = http_host_header('e_c.example.net', '/');
230 is(@n = $response =~ /8080/g, 0, 'error CNAME responses');
231 like($response, qr/502 Bad/, 'error CNAME');
232
233 $response = http_host_header('e_cn.example.net', '/');
234 is(@n = $response =~ /8080/g, 0, 'error CNAME+AAAA responses');
235 like($response, qr/502 Bad/, 'error CNAME+AAAA');
236
237 $response = http_host_header('e_e.example.net', '/');
238 is(@n = $response =~ /8080/g, 0, 'error error responses');
239 like($response, qr/502 Bad/, 'error error');
240
241 ###############################################################################
242
243 sub http_host_header {
244 my ($host, $uri) = @_;
245 return http(<<EOF);
246 GET $uri HTTP/1.0
247 Host: $host
248
249 EOF
250 }
251
252 ###############################################################################
253
254 sub reply_handler {
255 my ($recv_data, $port, $state) = @_;
256
257 my (@name, @rdata);
258
259 use constant NOERROR => 0;
260 use constant SERVFAIL => 2;
261 use constant NXDOMAIN => 3;
262
263 use constant A => 1;
264 use constant CNAME => 5;
265 use constant AAAA => 28;
266 use constant DNAME => 39;
267
268 use constant IN => 1;
269
270 # default values
271
272 my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600);
273
274 # decode name
275
276 my ($len, $offset) = (undef, 12);
277 while (1) {
278 $len = unpack("\@$offset C", $recv_data);
279 last if $len == 0;
280 $offset++;
281 push @name, unpack("\@$offset A$len", $recv_data);
282 $offset += $len;
283 }
284
285 $offset -= 1;
286 my ($id, $type, $class) = unpack("n x$offset n2", $recv_data);
287
288 my $name = join('.', @name);
289 if (($name eq 'aaaa.example.net') || ($name eq 'alias.example.net')) {
290 if ($type == AAAA) {
291 push @rdata, rd_addr6($ttl, "fe80::1");
292 }
293
294 } elsif ($name eq 'alias2.example.net') {
295 if ($type == A) {
296 push @rdata, rd_addr($ttl, '127.0.0.201');
297 }
298 if ($type == AAAA) {
299 push @rdata, rd_addr6($ttl, "fe80::1");
300 }
301
302 } elsif ($name eq 'alias4.example.net') {
303 if ($type == A) {
304 push @rdata, rd_addr($ttl, '127.0.0.201');
305 }
306
307 } elsif ($name eq 'alias6.example.net') {
308 if ($type == AAAA) {
309 push @rdata, rd_addr6($ttl, "fe80::1");
310 }
311
312 } elsif (($name eq 'many.example.net') && $type == AAAA) {
313 $state->{manycnt}++;
314 if ($state->{manycnt} > 1) {
315 $rcode = SERVFAIL;
316 }
317
318 push @rdata, rd_addr6($ttl, 'fe80::1');
319 push @rdata, rd_addr6($ttl, 'fe80::2');
320
321 } elsif ($name eq 'cname.example.net') {
322 $state->{cnamecnt}++;
323 if ($state->{cnamecnt} > 2) {
324 $rcode = SERVFAIL;
325 }
326 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
327 8, 5, 'alias', 0xc012);
328
329 } elsif ($name eq 'cname_a.example.net') {
330 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
331 8, 5, 'alias', 0xc014);
332
333 # points to "alias" set in previous rdata
334
335 if ($type == AAAA) {
336 push @rdata, pack('n3N nn8', 0xc031, AAAA, IN, $ttl,
337 16, expand_ip6("::1"));
338 }
339
340 } elsif ($name eq '2.example.net') {
341 if ($port == 8081) {
342 $state->{twocnt}++;
343 }
344 if ($state->{twocnt} & 1) {
345 $rcode = SERVFAIL;
346 }
347
348 if ($type == AAAA) {
349 push @rdata, rd_addr6($ttl, '::1');
350 }
351
352 } elsif ($name eq 'z_z.example.net') {
353 # assume no answers given
354
355 } elsif ($name eq 'z_n.example.net') {
356 if ($type == AAAA) {
357 push @rdata, rd_addr6($ttl, 'fe80::1');
358 }
359
360 } elsif ($name eq 'z_c.example.net') {
361 if ($type == AAAA) {
362 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
363 9, 6, 'alias2', 0xc010);
364 }
365
366 } elsif ($name eq 'z_cn.example.net') {
367 if ($type == AAAA) {
368 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
369 8, 5, 'alias', 0xc011);
370 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
371 16, expand_ip6("fe80::1"));
372 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
373 16, expand_ip6("fe80::2"));
374 }
375
376 } elsif ($name eq 'z_e.example.net') {
377 if ($type == AAAA) {
378 $rcode = SERVFAIL;
379 }
380
381 } elsif ($name eq 'n_z.example.net') {
382 if ($type == A) {
383 push @rdata, rd_addr($ttl, '127.0.0.201');
384 }
385
386 } elsif ($name eq 'n_n.example.net') {
387 if ($type == A) {
388 push @rdata, rd_addr($ttl, '127.0.0.201');
389 }
390 if ($type == AAAA) {
391 push @rdata, rd_addr6($ttl, 'fe80::1');
392 }
393
394 } elsif ($name eq 'n_c.example.net') {
395 if ($type == A) {
396 push @rdata, rd_addr($ttl, '127.0.0.201');
397 }
398 if ($type == AAAA) {
399 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
400 9, 6, 'alias2', 0xc010);
401 }
402
403 } elsif ($name eq 'n_cn.example.net') {
404 if ($type == A) {
405 push @rdata, rd_addr($ttl, '127.0.0.201');
406 push @rdata, rd_addr($ttl, '127.0.0.202');
407 }
408 if ($type == AAAA) {
409 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
410 8, 5, 'alias', 0xc011);
411 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
412 16, expand_ip6("fe80::1"));
413 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
414 16, expand_ip6("fe80::2"));
415 }
416
417 } elsif ($name eq 'n_e.example.net') {
418 if ($type == A) {
419 push @rdata, rd_addr($ttl, '127.0.0.201');
420 }
421 if ($type == AAAA) {
422 $rcode = SERVFAIL;
423 }
424
425 } elsif ($name eq 'c_z.example.net') {
426 if ($type == A) {
427 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
428 8, 5, 'alias', 0xc010);
429 }
430
431 } elsif ($name eq 'c_n.example.net') {
432 if ($type == A) {
433 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
434 8, 5, 'alias', 0xc010);
435 }
436 if ($type == AAAA) {
437 push @rdata, rd_addr6($ttl, "fe80::1");
438 }
439
440 } elsif ($name eq 'c_c.example.net') {
441 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
442 9, 6, 'alias2', 0xc010);
443
444 } elsif ($name eq 'c1_c2.example.net') {
445 if ($type == A) {
446 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
447 9, 6, 'alias4', 0xc012);
448 }
449 if ($type == AAAA) {
450 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
451 9, 6, 'alias6', 0xc012);
452 }
453
454 } elsif ($name eq 'c_cn.example.net') {
455 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
456 9, 6, 'alias2', 0xc011);
457
458 if ($type == AAAA) {
459 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
460 16, expand_ip6("fe80::1"));
461 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
462 16, expand_ip6("fe80::2"));
463 }
464
465 } elsif ($name eq 'cn_z.example.net') {
466 if ($type == A) {
467 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
468 9, 6, 'alias2', 0xc011);
469 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
470 4, split('\.', '127.0.0.201'));
471 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
472 4, split('\.', '127.0.0.202'));
473 }
474
475 } elsif ($name eq 'cn_n.example.net') {
476 if ($type == A) {
477 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
478 9, 6, 'alias2', 0xc011);
479 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
480 4, split('\.', '127.0.0.201'));
481 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
482 4, split('\.', '127.0.0.202'));
483 }
484 if ($type == AAAA) {
485 push @rdata, pack('n3N nn8', 0xc00c, AAAA, IN, $ttl,
486 16, expand_ip6("fe80::1"));
487 push @rdata, pack('n3N nn8', 0xc00c, AAAA, IN, $ttl,
488 16, expand_ip6("fe80::2"));
489 }
490
491 } elsif ($name eq 'cn_c.example.net') {
492 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
493 9, 6, 'alias2', 0xc011);
494 if ($type == A) {
495 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
496 4, split('\.', '127.0.0.201'));
497 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
498 4, split('\.', '127.0.0.202'));
499 }
500
501 } elsif ($name eq 'cn_cn.example.net') {
502 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
503 9, 6, 'alias2', 0xc012);
504
505 if ($type == A) {
506 push @rdata, pack("n3N nC4", 0xc02f, A, IN, $ttl,
507 4, split('\.', '127.0.0.201'));
508 push @rdata, pack("n3N nC4", 0xc02f, A, IN, $ttl,
509 4, split('\.', '127.0.0.202'));
510 }
511 if ($type == AAAA) {
512 push @rdata, pack('n3N nn8', 0xc02f, AAAA, IN, $ttl,
513 16, expand_ip6("fe80::1"));
514 push @rdata, pack('n3N nn8', 0xc02f, AAAA, IN, $ttl,
515 16, expand_ip6("fe80::2"));
516 }
517
518 } elsif ($name eq 'cn_e.example.net') {
519 if ($type == A) {
520 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
521 9, 6, 'alias2', 0xc011);
522 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
523 4, split('\.', '127.0.0.201'));
524 push @rdata, pack("n3N nC4", 0xc02e, A, IN, $ttl,
525 4, split('\.', '127.0.0.202'));
526 }
527 if ($type == AAAA) {
528 $rcode = SERVFAIL;
529 }
530
531
532 } elsif ($name eq 'e_z.example.net') {
533 if ($type == A) {
534 $rcode = SERVFAIL;
535 }
536
537 } elsif ($name eq 'e_n.example.net') {
538 if ($type == A) {
539 $rcode = SERVFAIL;
540 }
541 if ($type == AAAA) {
542 push @rdata, rd_addr6($ttl, 'fe80::1');
543 }
544
545 } elsif ($name eq 'e_c.example.net') {
546 if ($type == A) {
547 $rcode = SERVFAIL;
548 }
549 if ($type == AAAA) {
550 push @rdata, pack("n3N nCa6n", 0xc00c, CNAME, IN, $ttl,
551 9, 6, 'alias2', 0xc010);
552 }
553
554 } elsif ($name eq 'e_cn.example.net') {
555 if ($type == A) {
556 $rcode = SERVFAIL;
557 }
558 if ($type == AAAA) {
559 push @rdata, pack("n3N nCa5n", 0xc00c, CNAME, IN, $ttl,
560 8, 5, 'alias', 0xc011);
561 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
562 16, expand_ip6("fe80::1"));
563 push @rdata, pack('n3N nn8', 0xc02e, AAAA, IN, $ttl,
564 16, expand_ip6("fe80::2"));
565 }
566
567 } elsif ($name eq 'e_e.example.net') {
568 if ($type == A) {
569 $rcode = SERVFAIL;
570 }
571 if ($type == AAAA) {
572 $rcode = NXDOMAIN;
573 }
574 }
575
576 $len = @name;
577 pack("n6 (w/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata,
578 0, 0, @name, $type, $class) . join('', @rdata);
579 }
580
581 sub rd_addr {
582 my ($ttl, $addr) = @_;
583
584 my $code = 'split(/\./, $addr)';
585
586 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code);
587 }
588
589 sub expand_ip6 {
590 my ($addr) = @_;
591
592 substr ($addr, index($addr, "::"), 2) =
593 join "0", map { ":" } (0 .. 8 - (split /:/, $addr) + 1);
594 map { hex "0" x (4 - length $_) . "$_" } split /:/, $addr;
595 }
596
597 sub rd_addr6 {
598 my ($ttl, $addr) = @_;
599
600 pack 'n3N nn8', 0xc00c, AAAA, IN, $ttl, 16, expand_ip6($addr);
601 }
602
603 sub dns_daemon {
604 my ($port, $t) = @_;
605
606 my ($data, $recv_data);
607 my $socket = IO::Socket::INET->new(
608 LocalAddr => '127.0.0.1',
609 LocalPort => $port,
610 Proto => 'udp',
611 )
612 or die "Can't create listening socket: $!\n";
613
614 # track number of relevant queries
615
616 my %state = (
617 cnamecnt => 0,
618 twocnt => 0,
619 manycnt => 0,
620 );
621
622 # signal we are ready
623
624 open my $fh, '>', $t->testdir() . '/' . $port;
625 close $fh;
626
627 while (1) {
628 $socket->recv($recv_data, 65536);
629 $data = reply_handler($recv_data, $port, \%state);
630 $socket->send($data);
631 }
632 }
633
634 ###############################################################################