|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Zonemaster::Engine::Recursor;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
197
 | 
 use version; our $VERSION = version->declare("v1.0.5");  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
257
 | 
    | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
5
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
2925
 | 
 use 5.014002;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
90
 | 
    | 
| 
6
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
122
 | 
 use warnings;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
54
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
751
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
148
 | 
 use Moose;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
157
 | 
    | 
| 
9
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
166508
 | 
 use JSON::PP;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
203797
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1981
 | 
    | 
| 
10
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
1813
 | 
 use Zonemaster::Engine::Util;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1540
 | 
    | 
| 
11
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
8323
 | 
 use Zonemaster::Engine::Net::IP;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
86
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1304
 | 
    | 
| 
12
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
192
 | 
 use Zonemaster::Engine;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39262
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $seed_data;  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our %recurse_cache;  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     local $/;  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $json = <DATA>;  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $seed_data = decode_json $json;  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub recurse {  | 
| 
25
 | 
77
 | 
 
 | 
 
 | 
  
77
  
 | 
  
1
  
 | 
313
 | 
     my ( $self, $name, $type, $class ) = @_;  | 
| 
26
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
318
 | 
     $name = name( $name );  | 
| 
27
 | 
77
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
284
 | 
     $type  //= 'A';  | 
| 
28
 | 
77
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
455
 | 
     $class //= 'IN';  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
30
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
361
 | 
     Zonemaster::Engine->logger->add( RECURSE => { name => $name, type => $type, class => $class } );  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
32
 | 
77
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
320
 | 
     if ( exists $recurse_cache{$name}{$type}{$class} ) {  | 
| 
33
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
         return $recurse_cache{$name}{$type}{$class};  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
271
 | 
     my ( $p, $state ) =  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $self->_recurse( $name, $type, $class,  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         { ns => [ root_servers() ], count => 0, common => 0, seen => {}, glue => {} } );  | 
| 
39
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
608
 | 
     $recurse_cache{$name}{$type}{$class} = $p;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
41
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2215
 | 
     return $p;  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parent {  | 
| 
45
 | 
406
 | 
 
 | 
 
 | 
  
406
  
 | 
  
1
  
 | 
2091
 | 
     my ( $self, $name ) = @_;  | 
| 
46
 | 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1537
 | 
     $name = name( $name );  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
48
 | 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2043
 | 
     my ( $p, $state ) =  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $self->_recurse( $name, 'SOA', 'IN',  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         { ns => [ root_servers() ], count => 0, common => 0, seen => {}, glue => {} } );  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
52
 | 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3678
 | 
     my $pname;  | 
| 
53
 | 
406
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2269
 | 
     if ( name( $state->{trace}[0][0] ) eq name( $name ) ) {  | 
| 
54
 | 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1861
 | 
         $pname = name( $state->{trace}[1][0] );  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
57
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
         $pname = name( $state->{trace}[0][0] );  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Extra check that parent really is parent.  | 
| 
61
 | 
406
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
11690
 | 
     if ( $name->next_higher ne $pname ) {  | 
| 
62
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
         my $source_ns = $state->{trace}[0][1];  | 
| 
63
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
         my $source_ip = $state->{trace}[0][2];  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # No $source_ns means we're looking at root taken from priming  | 
| 
66
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
41
 | 
         if ( $source_ns ) {  | 
| 
67
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
334
 | 
             my $pp;  | 
| 
68
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
47
 | 
             if ( $source_ns->can( 'query' ) ) {  | 
| 
69
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
                 $pp = $source_ns->query( $name->next_higher->string, 'SOA' );  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             else {  | 
| 
72
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
                 my $n = ns( $source_ns, $source_ip );  | 
| 
73
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
                 $pp = $n->query( $name->next_higher->string, 'SOA' );  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
75
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
233
 | 
             if ( $pp ) {  | 
| 
76
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
                 my ( $rr ) = $pp->get_records( 'SOA', 'answer' );  | 
| 
77
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
70
 | 
                 if ( $rr ) {  | 
| 
78
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
                     $pname = name( $rr->owner );  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } ## end if ( $name->next_higher...)  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
406
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10900
 | 
     if ( wantarray() ) {  | 
| 
85
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
167
 | 
         return ( $pname, $p );  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
88
 | 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13855
 | 
         return $pname;  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } ## end sub parent  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _recurse {  | 
| 
93
 | 
6422
 | 
 
 | 
 
 | 
  
6422
  
 | 
 
 | 
27764
 | 
     my ( $self, $name, $type, $class, $state ) = @_;  | 
| 
94
 | 
6422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32501
 | 
     $name = q{} . name( $name );  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
6422
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
169596
 | 
     if ( $state->{in_progress}{$name}{$type} ) {  | 
| 
97
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return;  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
99
 | 
6422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22658
 | 
     $state->{in_progress}{$name}{$type} = 1;  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
101
 | 
6422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13697
 | 
     while ( my $ns = pop @{ $state->{ns} } ) {  | 
| 
 
 | 
19390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
122398
 | 
    | 
| 
102
 | 
19386
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1627303
 | 
         my $nsname    = $ns->can( 'name' )    ? q{} . $ns->name  : q{};  | 
| 
103
 | 
19386
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
514134
 | 
         my $nsaddress = $ns->can( 'address' ) ? $ns->address->ip : q{};  | 
| 
104
 | 
19386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
180757
 | 
         Zonemaster::Engine->logger->add(  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             RECURSE_QUERY => {  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 source  => "$ns",  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 ns      => $nsname,  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 address => $nsaddress,  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 name    => $name,  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 type    => $type,  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 class   => $class  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
114
 | 
19386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
132083
 | 
         my $p = $self->_do_query( $ns, $name, $type, { class => $class }, $state );  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
116
 | 
19386
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
125019
 | 
         next if not $p;    # Ask next server if no response  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
118
 | 
19337
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
127983
 | 
         if ( $p->rcode eq 'REFUSED' or $p->rcode eq 'SERVFAIL' ) {  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # Respond with these if we can't get a better response  | 
| 
120
 | 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
683
 | 
             $state->{candidate} = $p;  | 
| 
121
 | 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
540
 | 
             next;  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
124
 | 
19282
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
277348
 | 
         if ( $p->no_such_record ) {    # Node exists, but not record  | 
| 
125
 | 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8938
 | 
             return ( $p, $state );  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
128
 | 
18681
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
76112
 | 
         if ( $p->no_such_name ) {      # Node does not exist  | 
| 
129
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
219
 | 
             return ( $p, $state );  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
132
 | 
18659
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
92896
 | 
         if ( $self->_is_answer( $p ) ) {    # Return answer  | 
| 
133
 | 
5795
 | 
 
 | 
 
 | 
 
 | 
 
 | 
115386
 | 
             return ( $p, $state );  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # So it's not an error, not an empty response and not an answer  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
138
 | 
12864
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
287894
 | 
         if ( $p->is_redirect ) {  | 
| 
139
 | 
12864
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63820
 | 
             my $zname = name( lc( ( $p->get_records( 'ns' ) )[0]->name ) );  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
12864
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
131589
 | 
             next if $zname eq '.';          # Redirect to root is never right.  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
143
 | 
12863
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
51898
 | 
             next if $state->{seen}{$zname}; # We followed this redirect before  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38194
 | 
             $state->{seen}{$zname} = 1;  | 
| 
146
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45025
 | 
             my $common = name( $zname )->common( name( $state->{qname} ) );  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             next  | 
| 
149
 | 
12863
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
337570
 | 
               if $common < $state->{common};    # Redirect going up the hierarchy is not OK  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
151
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31347
 | 
             $state->{common} = $common;  | 
| 
152
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
54472
 | 
             $state->{ns} = $self->get_ns_from( $p, $state );    # Follow redirect  | 
| 
153
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42649
 | 
             $state->{count} += 1;  | 
| 
154
 | 
12863
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
54259
 | 
             return ( undef, $state ) if $state->{count} > 20;    # Loop protection  | 
| 
155
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29865
 | 
             unshift @{ $state->{trace} }, [ $zname, $ns, $p->answerfrom ];  | 
| 
 
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
105003
 | 
    | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
157
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
100126
 | 
             next;  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } ## end if ( $p->is_redirect )  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } ## end while ( my $ns = pop @{ $state...})  | 
| 
160
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     return ( $state->{candidate}, $state ) if $state->{candidate};  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
162
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     return ( undef, $state );  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } ## end sub _recurse  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _do_query {  | 
| 
166
 | 
19387
 | 
 
 | 
 
 | 
  
19387
  
 | 
 
 | 
77840
 | 
     my ( $self, $ns, $name, $type, $opts, $state ) = @_;  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
168
 | 
19387
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
180954
 | 
     if ( ref( $ns ) and $ns->can( 'query' ) ) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
169
 | 
17419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81947
 | 
         my $p = $ns->query( $name, $type, $opts );  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
171
 | 
17419
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
55493
 | 
         if ( $p ) {  | 
| 
172
 | 
17379
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
108632
 | 
             for my $rr ( grep { $_->type eq 'A' or $_->type eq 'AAAA' } $p->answer, $p->additional ) {  | 
| 
 
 | 
159471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1138050
 | 
    | 
| 
173
 | 
159186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
510180
 | 
                 $state->{glue}{ lc( name( $rr->name ) ) }{ $rr->address } = 1;  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
176
 | 
17419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
173966
 | 
         return $p;  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ( my $href = $state->{glue}{ lc( name( $ns ) ) } ) {  | 
| 
179
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         foreach my $addr ( keys %$href ) {  | 
| 
180
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             my $realns = ns( $ns, $addr );  | 
| 
181
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
             my $p = $self->_do_query( $realns, $name, $type, $opts, $state );  | 
| 
182
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
             if ( $p ) {  | 
| 
183
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
                 return $p;  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
188
 | 
1967
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9428
 | 
         $state->{glue}{ lc( name( $ns ) ) } = {};  | 
| 
189
 | 
1967
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52179
 | 
         my @addr = $self->get_addresses_for( $ns, $state );  | 
| 
190
 | 
1967
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
9778
 | 
         if ( @addr > 0 ) {  | 
| 
191
 | 
1962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6191
 | 
             foreach my $addr ( @addr ) {  | 
| 
192
 | 
1962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11181
 | 
                 $state->{glue}{ lc( name( $ns ) ) }{ $addr->short } = 1;  | 
| 
193
 | 
1962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
242356
 | 
                 my $new = ns( $ns, $addr->short );  | 
| 
194
 | 
1962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11353
 | 
                 my $p = $new->query( $name, $type, $opts );  | 
| 
195
 | 
1962
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
25126
 | 
                 return $p if $p;  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
| 
199
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
             return;  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } ## end sub _do_query  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_ns_from {  | 
| 
205
 | 
12863
 | 
 
 | 
 
 | 
  
12863
  
 | 
  
1
  
 | 
39750
 | 
     my ( $self, $p, $state ) = @_;  | 
| 
206
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26526
 | 
     my ( @new, @extra );  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
208
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46002
 | 
     my @names = sort map { name( lc( $_->nsdname ) ) } $p->get_records( 'ns' );  | 
| 
 
 | 
117589
 | 
 
 | 
 
 | 
 
 | 
 
 | 
979176
 | 
    | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $state->{glue}{ lc( name( $_->name ) ) }{ $_->address } = 1  | 
| 
211
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
178082
 | 
       for ( $p->get_records( 'a' ), $p->get_records( 'aaaa' ) );  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
213
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
125466
 | 
     foreach my $name ( @names ) {  | 
| 
214
 | 
117589
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
493476
 | 
         if ( exists $state->{glue}{ lc( name( $name ) ) } ) {  | 
| 
215
 | 
113572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
220176
 | 
             for my $addr ( keys %{ $state->{glue}{ lc( name( $name ) ) } } ) {  | 
| 
 
 | 
113572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
380007
 | 
    | 
| 
216
 | 
158144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
519734
 | 
                 push @new, ns( $name, $addr );  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
| 
220
 | 
4017
 | 
 
 | 
 
 | 
 
 | 
 
 | 
108980
 | 
             push @extra, $name;  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
224
 | 
12863
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
99584
 | 
     @new = sort { $a->name cmp $b->name or $a->address->ip cmp $b->address->ip } @new;  | 
| 
 
 | 
325241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8176392
 | 
    | 
| 
225
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52449
 | 
     @extra = sort { $a cmp $b } @extra;  | 
| 
 
 | 
2771
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7707
 | 
    | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
227
 | 
12863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
371836
 | 
     return [ @new, @extra ];  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } ## end sub get_ns_from  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_addresses_for {  | 
| 
231
 | 
2988
 | 
 
 | 
 
 | 
  
2988
  
 | 
  
1
  
 | 
9973
 | 
     my ( $self, $name, $state ) = @_;  | 
| 
232
 | 
2988
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5933
 | 
     my @res;  | 
| 
233
 | 
2988
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
12495
 | 
     $state //=  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       { ns => [ root_servers() ], count => 0, common => 0, seen => {} };  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my ( $pa ) = $self->_recurse(  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "$name", 'A', 'IN',  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ns          => [ root_servers() ],  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             count       => $state->{count},  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             common      => 0,  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             in_progress => $state->{in_progress},  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             glue        => $state->{glue}  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
245
 | 
2988
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12168
 | 
     );  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Name does not exist, just stop  | 
| 
248
 | 
2988
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
96548
 | 
     if ( $pa and $pa->no_such_name ) {  | 
| 
249
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
         return;  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my ( $paaaa ) = $self->_recurse(  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "$name", 'AAAA', 'IN',  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ns          => [ root_servers() ],  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             count       => $state->{count},  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             common      => 0,  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             in_progress => $state->{in_progress},  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             glue        => $state->{glue}  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
261
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14823
 | 
     );  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
263
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99654
 | 
     my @rrs;  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %cname;  | 
| 
265
 | 
2978
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12593
 | 
     if ( $pa ) {  | 
| 
266
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14784
 | 
         push @rrs, $pa->get_records( 'a' );  | 
| 
267
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13115
 | 
         $cname{ $_->cname } = 1 for $pa->get_records_for_name( 'CNAME', $name );  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
269
 | 
2978
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12218
 | 
     if ( $paaaa ) {  | 
| 
270
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9922
 | 
         push @rrs, $paaaa->get_records( 'aaaa' );  | 
| 
271
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10702
 | 
         $cname{ $_->cname } = 1 for $paaaa->get_records_for_name( 'CNAME', $name );  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
274
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15436
 | 
     foreach my $rr ( sort { $a->address cmp $b->address } @rrs ) {  | 
| 
 
 | 
7498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
56174
 | 
    | 
| 
275
 | 
7426
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
26064
 | 
         if ( name( $rr->name ) eq $name or $cname{ $rr->name } ) {  | 
| 
276
 | 
5365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63333
 | 
             push @res, Zonemaster::Engine::Net::IP->new( $rr->address );  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
280
 | 
2978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31504
 | 
     return @res;  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } ## end sub get_addresses_for  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _is_answer {  | 
| 
284
 | 
18659
 | 
 
 | 
 
 | 
  
18659
  
 | 
 
 | 
53905
 | 
     my ( $self, $packet ) = @_;  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
286
 | 
18659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
62083
 | 
     return ( $packet->type eq 'answer' );  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clear_cache {  | 
| 
290
 | 
53
 | 
 
 | 
 
 | 
  
53
  
 | 
  
1
  
 | 
175
 | 
     %recurse_cache = ();  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub root_servers {  | 
| 
294
 | 
166628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
645263
 | 
     return map { Zonemaster::Engine::Util::ns( $_->{name}, $_->{address} ) }  | 
| 
295
 | 
7574
 | 
 
 | 
 
 | 
  
7574
  
 | 
  
1
  
 | 
17480
 | 
       sort { $a->{name} cmp $b->{name} } @{ $seed_data->{'.'} };  | 
| 
 
 | 
507458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
695382
 | 
    | 
| 
 
 | 
7574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52071
 | 
    | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
298
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
216
 | 
 no Moose;  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
    | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
239
 | 
    | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __PACKAGE__->meta->make_immutable;  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Zonemaster::Engine::Recursor - recursive resolver for Zonemaster  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $packet = Zonemaster::Engine::Recursor->recurse($name, $type, $class);  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $pname = Zonemaster::Engine::Recursor->parent('example.org');  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 METHODS  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item recurse($name, $type, $class)  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Does a recursive resolution from the root servers down for the given triplet.  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item parent($name)  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Does a recursive resolution from the root down for the given name (using type C<SOA> and class C<IN>). If the resolution is successful, it returns  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the domain name of the second-to-last step. If the resolution is unsuccessful, it returns the domain name of the last step.  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item get_ns_from($packet, $state)  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Internal method. Takes a packet and a recursion state and returns a list of ns objects. Used to follow redirections.  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item get_addresses_for($name[, $state])  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Takes a name and returns a (possibly empty) list of IP addresses for  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 that name (in the form of L<Zonemaster::Engine::Net::IP> objects). When used  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 internally by the recursor it's passed a recursion state as its second  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 argument.  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item clear_cache()  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Class method to empty the cache of responses to recursive queries.  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item root_servers()  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns a list of ns objects representing the root servers. The list of root servers is hardcoded into this module.  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __DATA__  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    "." : [  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "m.root-servers.net",  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "202.12.27.33"  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "m.root-servers.net",  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:dc3:0:0:0:0:0:35"  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "e.root-servers.net",  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.203.230.10"  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "199.7.83.42",  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "l.root-servers.net"  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:500:3:0:0:0:0:42",  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "l.root-servers.net"  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "198.41.0.4",  | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "a.root-servers.net"  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:503:ba3e:0:0:0:2:30",  | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "a.root-servers.net"  | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.5.5.241",  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "f.root-servers.net"  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:500:2f:0:0:0:0:f",  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "f.root-servers.net"  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "199.7.91.13",  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "d.root-servers.net"  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:500:2d:0:0:0:0:d",  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "d.root-servers.net"  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.58.128.30",  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "j.root-servers.net"  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:503:c27:0:0:0:2:30",  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "j.root-servers.net"  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "128.63.2.53",  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "h.root-servers.net"  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "h.root-servers.net",  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:500:1:0:0:0:803f:235"  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "g.root-servers.net",  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.112.36.4"  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "k.root-servers.net",  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "193.0.14.129"  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:7fd:0:0:0:0:0:1",  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "k.root-servers.net"  | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "b.root-servers.net",  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.228.79.201"  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.33.4.12",  | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "c.root-servers.net"  | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "i.root-servers.net",  | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "192.36.148.17"  | 
| 
434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       },  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       {  | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "name" : "i.root-servers.net",  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          "address" : "2001:7fe:0:0:0:0:0:53"  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    ]  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  |