File Coverage

blib/lib/Zonemaster/Engine/Test/Zone.pm
Criterion Covered Total %
statement 202 207 97.5
branch 82 104 78.8
condition 24 36 66.6
subroutine 31 31 100.0
pod 13 13 100.0
total 352 391 90.0


line stmt bran cond sub pod time code
1             package Zonemaster::Engine::Test::Zone;
2              
3 26     26   10545 use version; our $VERSION = version->declare("v1.0.3");
  26         61  
  26         149  
4              
5 26     26   2108 use strict;
  26         64  
  26         530  
6 26     26   133 use warnings;
  26         65  
  26         584  
7              
8 26     26   391 use 5.014002;
  26         93  
9              
10 26     26   141 use Zonemaster::Engine;
  26         59  
  26         549  
11 26     26   141 use Zonemaster::Engine::Util;
  26         55  
  26         1510  
12 26     26   189 use Zonemaster::Engine::Test::Address;
  26         72  
  26         589  
13 26     26   134 use Zonemaster::Engine::TestMethods;
  26         60  
  26         617  
14 26     26   150 use Zonemaster::Engine::Constants qw[:soa :ip];
  26         58  
  26         4015  
15 26     26   187 use List::MoreUtils qw[none];
  26         57  
  26         210  
16              
17 26     26   15152 use Carp;
  26         60  
  26         57854  
18              
19             ###
20             ### Entry Points
21             ###
22              
23             sub all {
24 7     7 1 24 my ( $class, $zone ) = @_;
25 7         13 my @results;
26              
27 7 50       24 push @results, $class->zone01( $zone ) if Zonemaster::Engine->config->should_run( 'zone01' );
28 7 50   9   42 if ( none { $_->tag eq q{NO_RESPONSE_SOA_QUERY} } @results ) {
  9         262  
29              
30 7 50       27 push @results, $class->zone02( $zone ) if Zonemaster::Engine->config->should_run( 'zone02' );
31 7 50       24 push @results, $class->zone03( $zone ) if Zonemaster::Engine->config->should_run( 'zone03' );
32 7 50       36 push @results, $class->zone04( $zone ) if Zonemaster::Engine->config->should_run( 'zone04' );
33 7 50       25 push @results, $class->zone05( $zone ) if Zonemaster::Engine->config->should_run( 'zone05' );
34 7 50       30 push @results, $class->zone06( $zone ) if Zonemaster::Engine->config->should_run( 'zone06' );
35 7 50   48   63 if ( none { $_->tag eq q{MNAME_RECORD_DOES_NOT_EXIST} } @results ) {
  48         1197  
36 7 50       23 push @results, $class->zone07( $zone ) if Zonemaster::Engine->config->should_run( 'zone07' );
37             }
38             }
39 7 50   64   111 if ( none { $_->tag eq q{MNAME_RECORD_DOES_NOT_EXIST} } @results ) {
  64         1733  
40 7 50       33 push @results, $class->zone08( $zone ) if Zonemaster::Engine->config->should_run( 'zone08' );
41 7 50   71   45 if ( none { $_->tag eq q{NO_RESPONSE_MX_QUERY} } @results ) {
  71         1749  
42 7 50       28 push @results, $class->zone09( $zone ) if Zonemaster::Engine->config->should_run( 'zone09' );
43             }
44             }
45              
46 7         71 return @results;
47             } ## end sub all
48              
49             ###
50             ### Metadata Exposure
51             ###
52              
53             sub metadata {
54 12     12 1 29 my ( $class ) = @_;
55              
56             return {
57 12         201 zone01 => [
58             qw(
59             MNAME_RECORD_DOES_NOT_EXIST
60             MNAME_NOT_AUTHORITATIVE
61             MNAME_NO_RESPONSE
62             MNAME_NOT_IN_GLUE
63             MNAME_IS_AUTHORITATIVE
64             NO_RESPONSE_SOA_QUERY
65             )
66             ],
67             zone02 => [
68             qw(
69             REFRESH_MINIMUM_VALUE_LOWER
70             REFRESH_MINIMUM_VALUE_OK
71             NO_RESPONSE_SOA_QUERY
72             )
73             ],
74             zone03 => [
75             qw(
76             REFRESH_LOWER_THAN_RETRY
77             REFRESH_HIGHER_THAN_RETRY
78             NO_RESPONSE_SOA_QUERY
79             )
80             ],
81             zone04 => [
82             qw(
83             RETRY_MINIMUM_VALUE_LOWER
84             RETRY_MINIMUM_VALUE_OK
85             NO_RESPONSE_SOA_QUERY
86             )
87             ],
88             zone05 => [
89             qw(
90             EXPIRE_MINIMUM_VALUE_LOWER
91             EXPIRE_LOWER_THAN_REFRESH
92             EXPIRE_MINIMUM_VALUE_OK
93             NO_RESPONSE_SOA_QUERY
94             )
95             ],
96             zone06 => [
97             qw(
98             SOA_DEFAULT_TTL_MAXIMUM_VALUE_HIGHER
99             SOA_DEFAULT_TTL_MAXIMUM_VALUE_LOWER
100             SOA_DEFAULT_TTL_MAXIMUM_VALUE_OK
101             NO_RESPONSE_SOA_QUERY
102             )
103             ],
104             zone07 => [
105             qw(
106             MNAME_IS_CNAME
107             MNAME_IS_NOT_CNAME
108             NO_RESPONSE_SOA_QUERY
109             MNAME_HAS_NO_ADDRESS
110             )
111             ],
112             zone08 => [
113             qw(
114             MX_RECORD_IS_CNAME
115             MX_RECORD_IS_NOT_CNAME
116             NO_RESPONSE_MX_QUERY
117             )
118             ],
119             zone09 => [
120             qw(
121             NO_MX_RECORD
122             MX_RECORD_EXISTS
123             NO_RESPONSE_MX_QUERY
124             )
125             ],
126             };
127             } ## end sub metadata
128              
129             sub translation {
130             return {
131 1     1 1 23 'RETRY_MINIMUM_VALUE_LOWER' =>
132             'SOA \'retry\' value ({retry}) is less than the recommended one ({required_retry}).',
133             'RETRY_MINIMUM_VALUE_OK' =>
134             'SOA \'retry\' value ({retry}) is more than the minimum recommended value ({required_retry}).',
135             'MNAME_NO_RESPONSE' => 'SOA \'mname\' nameserver {ns}/{address} does not respond.',
136             'MNAME_IS_CNAME' => 'SOA \'mname\' value ({mname}) refers to a NS which is an alias (CNAME).',
137             'MNAME_IS_NOT_CNAME' => 'SOA \'mname\' value ({mname}) refers to a NS which is not an alias (CNAME).',
138             'NO_MX_RECORD' => 'No target (MX, A or AAAA record) to deliver e-mail for the domain name.',
139             'MX_RECORD_EXISTS' => 'Target ({info}) found to deliver e-mail for the domain name.',
140             'REFRESH_MINIMUM_VALUE_LOWER' =>
141             'SOA \'refresh\' value ({refresh}) is less than the recommended one ({required_refresh}).',
142             'REFRESH_MINIMUM_VALUE_OK' =>
143             'SOA \'refresh\' value ({refresh}) is higher than the minimum recommended value ({required_refresh}).',
144             'EXPIRE_LOWER_THAN_REFRESH' =>
145             'SOA \'expire\' value ({expire}) is lower than the SOA \'refresh\' value ({refresh}).',
146             'SOA_DEFAULT_TTL_MAXIMUM_VALUE_HIGHER' =>
147             'SOA \'minimum\' value ({minimum}) is higher than the recommended one ({highest_minimum}).',
148             'SOA_DEFAULT_TTL_MAXIMUM_VALUE_LOWER' =>
149             'SOA \'minimum\' value ({minimum}) is less than the recommended one ({lowest_minimum}).',
150             'SOA_DEFAULT_TTL_MAXIMUM_VALUE_OK' =>
151             'SOA \'minimum\' value ({minimum}) is between the recommended ones ({lowest_minimum}/{highest_minimum}).',
152             'MNAME_NOT_AUTHORITATIVE' =>
153             'SOA \'mname\' nameserver {ns}/{address} is not authoritative for \'{zone}\' zone.',
154             'MNAME_RECORD_DOES_NOT_EXIST' => 'SOA \'mname\' field does not exist',
155             'EXPIRE_MINIMUM_VALUE_LOWER' =>
156             'SOA \'expire\' value ({expire}) is less than the recommended one ({required_expire}).',
157             'MNAME_NOT_IN_GLUE' =>
158             'SOA \'mname\' nameserver ({mname}) is not listed in "parent" NS records for tested zone ({ns}).',
159             'REFRESH_LOWER_THAN_RETRY' =>
160             'SOA \'refresh\' value ({refresh}) is lower than the SOA \'retry\' value ({retry}).',
161             'REFRESH_HIGHER_THAN_RETRY' =>
162             'SOA \'refresh\' value ({refresh}) is higher than the SOA \'retry\' value ({retry}).',
163             'MX_RECORD_IS_CNAME' => 'MX record for the domain is pointing to a CNAME.',
164             'MX_RECORD_IS_NOT_CNAME' => 'MX record for the domain is not pointing to a CNAME.',
165             'MNAME_IS_AUTHORITATIVE' => 'SOA \'mname\' nameserver ({mname}) is authoritative for \'{zone}\' zone.',
166             'NO_RESPONSE_SOA_QUERY' => 'No response from nameserver(s) on SOA queries.',
167             'NO_RESPONSE_MX_QUERY' => 'No response from nameserver(s) on MX queries.',
168             'MNAME_HAS_NO_ADDRESS' => 'No IP address found for SOA \'mname\' nameserver ({mname}).',
169             'EXPIRE_MINIMUM_VALUE_OK' =>
170             'SOA \'expire\' value ({expire}) is higher than the minimum recommended value ({required_expire}) and not lower than the \'refresh\' value ({refresh}).',
171             };
172             } ## end sub translation
173              
174             sub version {
175 17     17 1 206 return "$Zonemaster::Engine::Test::Zone::VERSION";
176             }
177              
178             sub zone01 {
179 10     10 1 29 my ( $class, $zone ) = @_;
180 10         16 my @results;
181              
182 10         261 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
183              
184 10 100 66     197 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
185 9         116 my $soa_mname = $soa->mname;
186 9         51 $soa_mname =~ s/[.]\z//smx;
187 9 100       28 if ( not $soa_mname ) {
188 1         7 push @results, info( MNAME_RECORD_DOES_NOT_EXIST => {} );
189             }
190             else {
191 8         52 foreach my $ip_address ( Zonemaster::Engine::Recursor->get_addresses_for( $soa_mname ) ) {
192              
193 8         48 my $ns = Zonemaster::Engine::Nameserver->new( { name => $soa_mname, address => $ip_address->short } );
194              
195 8 100       41 if ( _is_ip_version_disabled( $ns ) ) {
196 1         3 next;
197             }
198              
199 7         204 my $p_soa = $ns->query( $zone->name, q{SOA} );
200 7 100 66     56 if ( $p_soa and $p_soa->rcode eq q{NOERROR} ) {
201 6 100       119 if ( not $p_soa->aa ) {
202 1         24 push @results,
203             info(
204             MNAME_NOT_AUTHORITATIVE => {
205             ns => $soa_mname,
206             address => $ip_address->short,
207             zone => $zone->name,
208             }
209             );
210             }
211             }
212             else {
213 1         5 push @results,
214             info(
215             MNAME_NO_RESPONSE => {
216             ns => $soa_mname,
217             address => $ip_address->short,
218             }
219             );
220             }
221             } ## end foreach my $ip_address ( Zonemaster::Engine::Recursor...)
222 8 100   14   112 if ( none { $_ eq $soa_mname } @{ Zonemaster::Engine::TestMethods->method2( $zone ) } ) {
  14         53  
  8         54  
223             push @results,
224             info(
225             MNAME_NOT_IN_GLUE => {
226             mname => $soa_mname,
227 4         13 ns => join( q{;}, @{ Zonemaster::Engine::TestMethods->method2( $zone ) } ),
  4         13  
228             }
229             );
230             }
231             } ## end else [ if ( not $soa_mname ) ]
232 9 100       46 if ( not scalar @results ) {
233 4         103 push @results,
234             info(
235             MNAME_IS_AUTHORITATIVE => {
236             mname => $soa_mname,
237             zone => $zone->name,
238             }
239             );
240             }
241             } ## end if ( $p and my ( $soa ...))
242             else {
243 1         6 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
244             }
245              
246 10         88 return @results;
247             } ## end sub zone01
248              
249             sub zone02 {
250 8     8 1 23 my ( $class, $zone ) = @_;
251 8         17 my @results;
252              
253 8         225 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
254              
255 8 100 66     147 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
256 7         29 my $soa_refresh = $soa->refresh;
257 7 100       52 if ( $soa_refresh < $SOA_REFRESH_MINIMUM_VALUE ) {
258 2         25 push @results,
259             info(
260             REFRESH_MINIMUM_VALUE_LOWER => {
261             refresh => $soa_refresh,
262             required_refresh => $SOA_REFRESH_MINIMUM_VALUE,
263             }
264             );
265             }
266             else {
267 5         52 push @results,
268             info(
269             REFRESH_MINIMUM_VALUE_OK => {
270             refresh => $soa_refresh,
271             required_refresh => $SOA_REFRESH_MINIMUM_VALUE,
272             }
273             );
274             }
275             } ## end if ( $p and my ( $soa ...))
276             else {
277 1         5 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
278             }
279              
280 8         44 return @results;
281             } ## end sub zone02
282              
283             sub zone03 {
284 8     8 1 27 my ( $class, $zone ) = @_;
285 8         14 my @results;
286              
287 8         194 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
288              
289 8 100 66     128 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
290 7         24 my $soa_retry = $soa->retry;
291 7         58 my $soa_refresh = $soa->refresh;
292 7 100       23 if ( $soa_retry >= $soa_refresh ) {
293 3         20 push @results,
294             info(
295             REFRESH_LOWER_THAN_RETRY => {
296             retry => $soa_retry,
297             refresh => $soa_refresh,
298             }
299             );
300             }
301             else {
302 4         28 push @results,
303             info(
304             REFRESH_HIGHER_THAN_RETRY => {
305             retry => $soa_retry,
306             refresh => $soa_refresh,
307             }
308             );
309             }
310             } ## end if ( $p and my ( $soa ...))
311             else {
312 1         5 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
313             }
314              
315 8         230 return @results;
316             } ## end sub zone03
317              
318             sub zone04 {
319 8     8 1 28 my ( $class, $zone ) = @_;
320 8         16 my @results;
321              
322 8         197 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
323              
324 8 100 66     126 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
325 7         27 my $soa_retry = $soa->retry;
326 7 100       41 if ( $soa_retry < $SOA_RETRY_MINIMUM_VALUE ) {
327 1         9 push @results,
328             info(
329             RETRY_MINIMUM_VALUE_LOWER => {
330             retry => $soa_retry,
331             required_retry => $SOA_RETRY_MINIMUM_VALUE,
332             }
333             );
334             }
335             else {
336 6         53 push @results,
337             info(
338             RETRY_MINIMUM_VALUE_OK => {
339             retry => $soa_retry,
340             required_retry => $SOA_RETRY_MINIMUM_VALUE,
341             }
342             );
343             }
344             } ## end if ( $p and my ( $soa ...))
345             else {
346 1         4 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
347             }
348              
349 8         45 return @results;
350             } ## end sub zone04
351              
352             sub zone05 {
353 8     8 1 23 my ( $class, $zone ) = @_;
354 8         16 my @results;
355              
356 8         213 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
357              
358 8 100 66     127 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
359 7         32 my $soa_expire = $soa->expire;
360 7         24 my $soa_refresh = $soa->refresh;
361 7 100       39 if ( $soa_expire < $SOA_EXPIRE_MINIMUM_VALUE ) {
362 4         42 push @results,
363             info(
364             EXPIRE_MINIMUM_VALUE_LOWER => {
365             expire => $soa_expire,
366             required_expire => $SOA_EXPIRE_MINIMUM_VALUE,
367             }
368             );
369             }
370 7 100       40 if ( $soa_expire < $soa_refresh ) {
371 4         24 push @results,
372             info(
373             EXPIRE_LOWER_THAN_REFRESH => {
374             expire => $soa_expire,
375             refresh => $soa_refresh,
376             }
377             );
378             }
379 7 100       28 if ( not scalar @results ) {
380 3         15 push @results,
381             info(
382             EXPIRE_MINIMUM_VALUE_OK => {
383             expire => $soa_expire,
384             refresh => $soa_refresh,
385             required_expire => $SOA_EXPIRE_MINIMUM_VALUE,
386             }
387             );
388             }
389             } ## end if ( $p and my ( $soa ...))
390             else {
391 1         4 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
392             }
393              
394 8         57 return @results;
395             } ## end sub zone05
396              
397             sub zone06 {
398 8     8 1 27 my ( $class, $zone ) = @_;
399 8         15 my @results;
400              
401 8         211 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
402              
403 8 100 66     150 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
404 7         38 my $soa_minimum = $soa->minimum;
405 7 100       42 if ( $soa_minimum > $SOA_DEFAULT_TTL_MAXIMUM_VALUE ) {
    100          
406 1         8 push @results,
407             info(
408             SOA_DEFAULT_TTL_MAXIMUM_VALUE_HIGHER => {
409             minimum => $soa_minimum,
410             highest_minimum => $SOA_DEFAULT_TTL_MAXIMUM_VALUE,
411             }
412             );
413             }
414             elsif ( $soa_minimum < $SOA_DEFAULT_TTL_MINIMUM_VALUE ) {
415 1         13 push @results,
416             info(
417             SOA_DEFAULT_TTL_MAXIMUM_VALUE_LOWER => {
418             minimum => $soa_minimum,
419             lowest_minimum => $SOA_DEFAULT_TTL_MINIMUM_VALUE,
420             }
421             );
422             }
423             else {
424 5         80 push @results,
425             info(
426             SOA_DEFAULT_TTL_MAXIMUM_VALUE_OK => {
427             minimum => $soa_minimum,
428             highest_minimum => $SOA_DEFAULT_TTL_MAXIMUM_VALUE,
429             lowest_minimum => $SOA_DEFAULT_TTL_MINIMUM_VALUE,
430             }
431             );
432             }
433             } ## end if ( $p and my ( $soa ...))
434             else {
435 1         5 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
436             }
437              
438 8         47 return @results;
439             } ## end sub zone06
440              
441             sub zone07 {
442 8     8 1 30 my ( $class, $zone ) = @_;
443 8         18 my @results;
444              
445 8         219 my $p = _retrieve_record_from_zone( $zone, $zone->name, q{SOA} );
446              
447 8 100 66     128 if ( $p and my ( $soa ) = $p->get_records( q{SOA}, q{answer} ) ) {
448 7         72 my $soa_mname = $soa->mname;
449 7         35 $soa_mname =~ s/[.]\z//smx;
450 7         16 my $addresses_nb = 0;
451 7         21 foreach my $address_type ( q{A}, q{AAAA} ) {
452 14         84 my $p_mname = Zonemaster::Engine::Recursor->recurse( $soa_mname, $address_type );
453 14 50       61 if ( $p_mname ) {
454 14 100       70 if ( $p_mname->has_rrs_of_type_for_name( $address_type, $soa_mname ) ) {
455 6         18 $addresses_nb++;
456             }
457 14 100       66 if ( $p_mname->has_rrs_of_type_for_name( q{CNAME}, $soa_mname ) ) {
458 2         41 push @results,
459             info(
460             MNAME_IS_CNAME => {
461             mname => $soa_mname,
462             }
463             );
464             }
465             else {
466 12         65 push @results,
467             info(
468             MNAME_IS_NOT_CNAME => {
469             mname => $soa_mname,
470             }
471             );
472             }
473             } ## end if ( $p_mname )
474             } ## end foreach my $address_type ( ...)
475 7 100       33 if ( not $addresses_nb ) {
476 2         12 push @results,
477             info(
478             MNAME_HAS_NO_ADDRESS => {
479             mname => $soa_mname,
480             }
481             );
482             }
483             } ## end if ( $p and my ( $soa ...))
484             else {
485 1         4 push @results, info( NO_RESPONSE_SOA_QUERY => {} );
486             }
487              
488 8         66 return @results;
489             } ## end sub zone07
490              
491             sub zone08 {
492 7     7 1 25 my ( $class, $zone ) = @_;
493 7         16 my @results;
494              
495 7         231 my $p = $zone->query_auth( $zone->name, q{MX} );
496              
497 7 50       33 if ( $p ) {
498 7 50       174 if ( $p->has_rrs_of_type_for_name( q{CNAME}, $zone->name ) ) {
499 0         0 push @results, info( MX_RECORD_IS_CNAME => {} );
500             }
501             else {
502 7         29 push @results, info( MX_RECORD_IS_NOT_CNAME => {} );
503             }
504             }
505             else {
506 0         0 push @results, info( NO_RESPONSE_MX_QUERY => {} );
507             }
508              
509 7         24 return @results;
510             } ## end sub zone08
511              
512             sub zone09 {
513 8     8 1 25 my ( $class, $zone ) = @_;
514 8         16 my @results;
515             my $info;
516              
517 8         190 my $p = $zone->query_auth( $zone->name, q{MX} );
518              
519 8 50       35 if ( $p ) {
520 8 100       201 if ( not $p->has_rrs_of_type_for_name( q{MX}, $zone->name ) ) {
521 5         151 my $p_a = _retrieve_record_from_zone( $zone, $zone->name, q{A} );
522 5         140 my $p_aaaa = _retrieve_record_from_zone( $zone, $zone->name, q{AAAA} );
523 5 100 66     73 if (
524             ( not defined $p_a and not defined $p_aaaa )
525             or ( ( not defined $p_a or not $p_a->has_rrs_of_type_for_name( q{A}, $zone->name ) )
526             and ( not defined $p_aaaa or not $p_aaaa->has_rrs_of_type_for_name( q{AAAA}, $zone->name ) ) )
527             )
528             {
529 4         29 push @results, info( NO_MX_RECORD => {} );
530             }
531             else {
532 1 50       26 my @as = defined $p_a ? $p_a->get_records_for_name( q{A}, $zone->name ) : ();
533 1 50       37 my @aaas = defined $p_aaaa ? $p_aaaa->get_records_for_name( q{AAAA}, $zone->name ) : ();
534 1 50       4 $info = join q{/}, map { $_ =~ /:/smx ? q{AAAA=} . $_->address : q{A=} . $_->address } ( @as, @aaas );
  1         47  
535             }
536             }
537             else {
538 3         74 my @mx = $p->get_records_for_name( q{MX}, $zone->name );
539 3         11 for my $mx ( @mx ) {
540 5         9 my $tmp = q{MX=};
541 5         30 $tmp .= $mx->exchange;
542 5         22 $tmp =~ s/[.]\z//smx;
543 5         17 $info .= $tmp . q{/};
544             }
545 3         14 chop $info;
546             }
547 8 100       68 if ( not scalar @results ) {
548 4         19 push @results, info( MX_RECORD_EXISTS => { info => $info } );
549             }
550             } ## end if ( $p )
551             else {
552 0         0 push @results, info( NO_RESPONSE_MX_QUERY => {} );
553             }
554              
555 8         29 return @results;
556             } ## end sub zone09
557              
558             sub _retrieve_record_from_zone {
559 68     68   179 my ( $zone, $name, $type ) = @_;
560              
561             # Return response from the first authoritative server that gives one
562 68         105 foreach my $ns ( @{ Zonemaster::Engine::TestMethods->method5( $zone ) } ) {
  68         243  
563              
564 72 100       209 if ( _is_ip_version_disabled( $ns ) ) {
565 1         11 next;
566             }
567              
568 71         252 my $p = $ns->query( $name, $type );
569              
570 71 100 66     397 if ( defined $p and scalar $p->get_records( $type, q{answer} ) > 0 ) {
571 52 50       220 return $p if $p->aa;
572             }
573             }
574              
575 16         48 return;
576             }
577              
578             sub _is_ip_version_disabled {
579 80     80   265 my $ns = shift;
580              
581 80 50 33     310 if ( not Zonemaster::Engine->config->ipv4_ok and $ns->address->version == $IP_VERSION_4 ) {
582 0         0 Zonemaster::Engine->logger->add( SKIP_IPV4_DISABLED => { ns => "$ns" } );
583 0         0 return 1;
584             }
585              
586 80 100 100     210 if ( not Zonemaster::Engine->config->ipv6_ok and $ns->address->version == $IP_VERSION_6 ) {
587 2         45 Zonemaster::Engine->logger->add( SKIP_IPV6_DISABLED => { ns => "$ns" } );
588 2         14 return 1;
589             }
590              
591 78         275 return;
592             }
593              
594             1;
595              
596             =head1 NAME
597              
598             Zonemaster::Engine::Test::Zone - module implementing tests of the zone content in DNS, such as SOA and MX records
599              
600             =head1 SYNOPSIS
601              
602             my @results = Zonemaster::Engine::Test::Zone->all($zone);
603              
604             =head1 METHODS
605              
606             =over
607              
608             =item all($zone)
609              
610             Runs the default set of tests and returns a list of log entries made by the tests
611              
612             =item translation()
613              
614             Returns a refernce to a hash with translation data. Used by the builtin translation system.
615              
616             =item metadata()
617              
618             Returns a reference to a hash, the keys of which are the names of all test methods in the module, and the corresponding values are references to
619             lists with all the tags that the method can use in log entries.
620              
621             =item version()
622              
623             Returns a version string for the module.
624              
625             =back
626              
627             =head1 TESTS
628              
629             =over
630              
631             =item zone01($zone)
632              
633             Check that master nameserver in SOA is fully qualified.
634              
635             =item zone02($zone)
636              
637             Verify SOA 'refresh' minimum value.
638              
639             =item zone03($zone)
640              
641             Verify SOA 'retry' value is lower than SOA 'refresh' value.
642              
643             =item zone04($zone)
644              
645             Verify SOA 'retry' minimum value.
646              
647             =item zone05($zone)
648              
649             Verify SOA 'expire' minimum value.
650              
651             =item zone06($zone)
652              
653             Verify SOA 'minimum' (default TTL) value.
654              
655             =item zone07($zone)
656              
657             Verify that SOA master is not an alias (CNAME).
658              
659             =item zone08($zone)
660              
661             Verify that MX records does not resolve to a CNAME.
662              
663             =item zone09($zone)
664              
665             Verify that there is a target host (MX, A or AAAA) to deliver e-mail for the domain name.
666              
667             =back
668              
669             =cut