File Coverage

blib/lib/Net/DNS/Method/Pool.pm
Criterion Covered Total %
statement 77 79 97.4
branch 17 26 65.3
condition 17 38 44.7
subroutine 13 13 100.0
pod 1 4 25.0
total 125 160 78.1


line stmt bran cond sub pod time code
1             package Net::DNS::Method::Pool;
2              
3             require 5.005_62;
4              
5 2     2   1961 use Carp;
  2         6  
  2         117  
6 2     2   851 use Net::DNS;
  2         63519  
  2         182  
7 2     2   869 use NetAddr::IP 3.00;
  2         34375  
  2         17  
8 2     2   228 use Net::DNS::Method;
  2         4  
  2         128  
9 2     2   14 use vars qw($VERSION @ISA);
  2         4  
  2         107  
10              
11             @ISA = qw(Net::DNS::Method);
12              
13 2     2   12 use strict;
  2         4  
  2         65  
14 2     2   10 use warnings;
  2         2  
  2         2093  
15              
16             $VERSION = '2.00';
17              
18             # Default responses
19             our $DEF_ZONE = 'some.com';
20             our $DEF_PREFIX = 'dyn-';
21             our $DEF_TTL = '36000'; # 10 hours
22              
23             sub new {
24 1     1 0 23 my $type = shift;
25 1   50     9 my $class = ref($type) || $type || "Net::DNS::Method::Pool";
26              
27 1         2 my $ref = shift;
28              
29 1 50 33     33 my $self =
    50 33        
    50 33        
30             {
31             start => time,
32             counter => {},
33             zone => (defined($ref) && defined($ref->{BaseDomain}) ?
34             $ref->{BaseDomain} : $DEF_ZONE),
35             prefix => (defined($ref) && defined($ref->{Prefix}) ?
36             $ref->{Prefix} : $DEF_PREFIX),
37             ttl => (defined($ref) && defined($ref->{ttl}) ?
38             $ref->{ttl} : $DEF_TTL),
39             pool => []
40             };
41              
42 1 50       8 if (exists $ref->{Pool}) {
43 1         1 for my $ip (@{$ref->{Pool}}) {
  1         3  
44 2         21 my $a = new NetAddr::IP $ip;
45              
46 2 50       388 croak "Address $ip cannot be parsed"
47             unless $a;
48            
49 2         1031 push @{$self->{pool}}, $a;
  2         7  
50             }
51             }
52             else {
53 0         0 croak
54             "Net::DNS::Method::Pool requires a pool of IP addresses to serve";
55             }
56            
57 1         6 bless $self, $class;
58             }
59              
60             sub _parse_ptr ($$) {
61 3     3   7 my $self = shift;
62 3         4 my $q = shift;
63              
64 3 100       8 if ($q->qname =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)\.in-addr\.arpa\.?$/i) {
65             # warn "_parse_ptr found $4.$3.$2.$1\n";
66 1         28 return new NetAddr::IP "$4.$3.$2.$1";
67             }
68              
69 2         33 return undef;
70             }
71              
72             sub _parse_a ($$) {
73 4     4   4 my $self = shift;
74 4         4 my $q = shift;
75              
76 4         15 my $name = $q->qname;
77              
78             # warn "check on $name\n";
79              
80 4 100       161 if (index($name, $self->{prefix}) == 0) {
81 2         11 substr($name, 0, length($self->{prefix})) = '';
82             }
83 2         7 else { return undef; }
84              
85             # warn "match 1 on $name\n";
86              
87 2 50       10 if (my $i = index($name, '.' . $self->{zone})) {
88 2         7 substr($name, $i, length($self->{zone}) + 1) = '';
89             }
90 0         0 else { return undef; }
91              
92             # warn "match 2 on $name\n";
93              
94 2 50 66     56 if ($name =~ m/^([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)$/i
      66        
      33        
      33        
      33        
      33        
      33        
      33        
95             and $1 >= 0 and $1 <= 255
96             and $2 >= 0 and $2 <= 255
97             and $3 >= 0 and $3 <= 255
98             and $4 >= 0 and $4 <= 255)
99             {
100             # warn "_parse_a found $1.$2.$3.$4\n";
101 1         9 return new NetAddr::IP "$1.$2.$3.$4";
102             }
103              
104 1         5 return undef;
105             }
106              
107             sub PTR {
108 3     3 0 4 my $self = shift;
109 3         5 my $q = shift;
110 3         5 my $ans = shift;
111              
112 3 100       10 if (my $a = $self->_parse_ptr($q)) {
113 1         426 for my $s (@{$self->{pool}}) {
  1         4  
114 1 50       5 if ($s->contains($a)) {
115 1         25 my $name = $a->addr;
116 1         136 $name =~ s/\./-/g;
117 1         5 substr($name, 0, 0) = $self->{prefix};
118 1         3 $name .= '.';
119 1         4 $name .= $self->{zone};
120              
121 1         5 $ans->push('answer', new Net::DNS::RR $q->qname .
122             ' ' . $self->{ttl} . " IN PTR " .
123             $name);
124 1         1940 $ans->header->rcode('NOERROR');
125 1         101 return NS_OK | NS_STOP;
126             }
127             }
128             }
129              
130 2         9 return NS_FAIL; # No match or error
131             }
132              
133             sub A {
134 4     4 1 7 my $self = shift;
135 4         6 my $q = shift;
136 4         5 my $ans = shift;
137              
138 4 100       12 if (my $a = $self->_parse_a($q)) {
139 1         413 for my $s (@{$self->{pool}}) {
  1         4  
140 1 50       11 if ($s->contains($a)) {
141 1         28 $ans->push('answer', new Net::DNS::RR $q->qname .
142             ' ' . $self->{ttl} . " IN A " .
143             $a->addr);
144 1         2073 $ans->header->rcode('NOERROR');
145 1         3326 return NS_OK | NS_STOP;
146             }
147             }
148             }
149              
150 3         18 return NS_FAIL; # No match or error
151             }
152              
153 4   100 4 0 4577 sub ANY { return A(@_ )|| PTR(@_); }
154              
155             1;
156             __END__