File Coverage

blib/lib/Net/Patricia.pm
Criterion Covered Total %
statement 143 188 76.0
branch 45 130 34.6
condition 11 53 20.7
subroutine 34 42 80.9
pod 6 8 75.0
total 239 421 56.7


line stmt bran cond sub pod time code
1             # Net::Patricia - Patricia Trie perl module for fast IP address lookups
2             # Copyright (C) 2000-2005 Dave Plonka
3             # Copyright (C) 2009 Dave Plonka & Philip Prindeville
4             #
5             # This program is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by
7             # the Free Software Foundation; either version 2 of the License, or
8             # (at your option) any later version.
9             #
10             # This program is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13             # GNU General Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License
16             # along with this program; if not, write to the Free Software
17             # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18              
19             # Dave Plonka
20             # Philip Prindeville
21              
22             package Net::Patricia;
23              
24 1     1   246938 use strict;
  1         3  
  1         57  
25 1     1   7 use warnings;
  1         2  
  1         53  
26              
27             require 5.008;
28              
29 1     1   652 use version;
  1         2173  
  1         7  
30 1     1   84 use Carp;
  1         2  
  1         87  
31 1     1   4 use vars qw($VERSION @ISA @EXPORT);
  1         2  
  1         63  
32 1     1   741 use Socket qw(AF_INET AF_INET6);
  1         3114  
  1         211  
33              
34             BEGIN {
35 1     1   9 require Exporter;
36 1         4 require DynaLoader;
37 1         9 @ISA = qw(Exporter DynaLoader);
38 1         488 @EXPORT = qw(AF_INET AF_INET6);
39             }
40              
41             '$Revision: 1.18_81 $' =~ m/(\d+)\.(\d+)((_\d+)|)/ && ( $VERSION = "$1.$2$3");
42              
43             bootstrap Net::Patricia $VERSION;
44              
45             sub new {
46 2     2 1 645 my ($class, $type) = @_;
47              
48 2   100     10 $type ||= AF_INET;
49              
50 2 100       7 if ($type == AF_INET) {
51 1         14 return bless _new(32), 'Net::Patricia::AF_INET';
52             }
53              
54 1 50       3 if ($type == AF_INET6) {
55 1         8 return bless _new(128), 'Net::Patricia::AF_INET6';
56             }
57              
58 0         0 croak "new: unimplemented type";
59             }
60              
61             ##
62             ## Compat functions
63             ##
64              
65             sub _ip_bits {
66 25     25   31 my ($self, $str) = @_;
67 25         27 my $bits;
68              
69 25 100       89 if (ref ($self) eq 'Net::Patricia::AF_INET6') {
70 2 50       16 $bits = ($str =~ s|/(\d+)$||) ? $1 : 128;
71             } else {
72 23 100       115 $bits = ($str =~ s|/(\d+)$||) ? $1 : 32;
73             }
74 25         95 ($str,$bits);
75             }
76              
77             sub add_string {
78 12 50 33 12 1 5173 croak "add_string: wrong number of args" if (@_ < 2 || @_ > 3);
79 12         20 my ($self,$str,$data) = @_;
80 12 100       24 $data = $str unless @_ > 2;
81 12         34 $self->add($self->_ip_bits($str),$data);
82             }
83              
84             sub match_string {
85 8 50   8 1 645 croak "match_string: wrong number of args" if (@_ != 2);
86 8         14 my ($self,$str) = @_;
87 8         17 $self->match($self->_ip_bits($str))
88             }
89              
90             sub match_exact_string {
91 1 50   1 1 8 croak "match_exact_string: wrong number of args" if (@_ != 2);
92 1         2 my ($self,$str) = @_;
93 1         3 $self->exact($self->_ip_bits($str))
94             }
95              
96             sub match_exact_integer {
97 3     3 1 33 shift->exact_integer(@_)
98             }
99              
100             sub remove_string {
101 4 50   4 1 13 croak "remove_string: wrong number of args" if (@_ != 2);
102 4         8 my ($self,$str) = @_;
103 4         10 $self->remove($self->_ip_bits($str))
104             }
105              
106             BEGIN {
107 1     1   1 eval {
108 1         2 my $class = 'Net::CIDR::Lite';
109 1         52 eval "require $class";
110             };
111 1 50       3016 last if (@_);
112              
113             sub add_cidr {
114 1 50   1 0 7 croak "add_cidr: wrong number of args" if (@_ != 3);
115 1         4 my ($self, $range, $data) = @_;
116 1         12 my $cidr = Net::CIDR::Lite->new();
117 1         91 $cidr->add_range($range);
118              
119 1         241 my @list = ();
120 1         5 for ($cidr->list()) {
121 2 50       104 push(@list, $_) if ($self->add_string($_, $data));
122             }
123 1         14 @list;
124             }
125              
126             sub remove_cidr {
127 1 50   1 0 6 croak "remove_cidr: wrong number of args" if (@_ != 2);
128 1         2 my ($self, $range) = @_;
129 1         4 my $cidr = Net::CIDR::Lite->new();
130 1         10 $cidr->add_range($range);
131              
132 1         142 my @list = ();
133 1         4 for ($cidr->list()) {
134 2 50       123 push(@list, $_) if ($self->remove_string($_));
135             }
136 1         8 @list;
137             }
138             }
139              
140             ##
141             ## AF_INET
142             ##
143              
144             package Net::Patricia::AF_INET;
145              
146 1     1   5 use Carp;
  1         1  
  1         45  
147 1     1   4 use Socket qw(AF_INET inet_aton inet_ntoa);
  1         1  
  1         40  
148 1     1   3 use vars qw(@ISA @EXPORT);
  1         1  
  1         63  
149              
150             BEGIN {
151 1     1   3 require Exporter;
152 1         3 require DynaLoader;
153 1         10 @ISA = qw(Exporter DynaLoader Net::Patricia);
154 1         499 @EXPORT = qw(AF_INET);
155             }
156              
157             sub add {
158 11 50 33 11   51 croak "add: wrong number of args" if (@_ < 2 || @_ > 4);
159 11         18 my ($self, $ip, $bits, $data) = @_;
160 11 0       23 $data = (defined $bits ? "$ip/$bits" : $ip) if (@_ < 4);
    50          
161 11         9739 my $packed = inet_aton($ip);
162 11 100       542 croak("invalid key") unless (defined $packed);
163 10 50       18 $bits = 32 if (@_ < 3);
164 10         104 $self->SUPER::_add(AF_INET, $packed, $bits, $data);
165             }
166              
167             sub add_integer {
168 0 0 0 0   0 croak "add_integer: wrong number of args" if (@_ < 2 || @_ > 4);
169 0         0 my ($self, $num, $bits, $data) = @_;
170 0         0 my $packed = pack("N", $num);
171 0         0 my $ip = inet_ntoa($packed);
172 0 0       0 croak("invalid address") unless (defined $ip);
173 0 0       0 $data = (defined $bits ? "$ip/$bits" : $ip) if (@_ < 4);
    0          
174 0 0       0 $bits = 32 if (@_ < 3);
175 0         0 $self->SUPER::_add(AF_INET, $packed, $bits, $data);
176             }
177              
178             sub match_integer {
179 3 50 33 3   298 croak "match_integer: wrong number of args" if (@_ < 2 || @_ > 3);
180 3         5 my ($self, $num, $bits) = @_;
181 3 50       9 $bits = 32 if (@_ < 3);
182 3         33 $self->SUPER::_match(AF_INET, pack("N",$num), $bits);
183             }
184              
185             sub exact_integer {
186 3 50 33 3   19 croak "exact_integer: wrong number of args" if (@_ < 2 || @_ > 3);
187 3         5 my ($self, $num, $bits) = @_;
188 3 100       6 $bits = 32 if (@_ < 3);
189 3         39 $self->SUPER::_exact(AF_INET, pack("N",$num), $bits);
190             }
191              
192             sub match {
193 7 50 33 7   39 croak "match: wrong number of args" if (@_ < 2 || @_ > 3);
194 7         15 my ($self, $ip, $bits) = @_;
195 7         22 my $packed = inet_aton($ip);
196 7 50       19 croak("invalid key") unless (defined $packed);
197 7 50       15 $bits = 32 if (@_ < 3);
198 7         82 $self->SUPER::_match(AF_INET, $packed, $bits);
199             }
200              
201             sub exact {
202 1 50 33 1   8 croak "exact: wrong number of args" if (@_ < 2 || @_ > 3);
203 1         3 my ($self, $ip, $bits) = @_;
204 1         4 my $packed = inet_aton($ip);
205 1 50       3 croak("invalid key") unless (defined $packed);
206 1 50       4 $bits = 32 if (@_ < 3);
207 1         14 $self->SUPER::_exact(AF_INET, $packed, $bits);
208             }
209              
210             sub remove {
211 4 50 33 4   22 croak "remove: wrong number of args" if (@_ < 2 || @_ > 3);
212 4         6 my ($self, $ip, $bits) = @_;
213 4         13 my $packed = inet_aton($ip);
214 4 50       7 croak("invalid key") unless (defined $packed);
215 4 50       11 $bits = 32 if (@_ < 3);
216 4         51 $self->SUPER::_remove(AF_INET, $packed, $bits);
217             }
218              
219             sub remove_integer {
220 0 0 0 0   0 croak "remote_integer: wrong number of args" if (@_ < 2 || @_ > 3);
221 0         0 my ($self, $num, $bits) = @_;
222 0 0       0 $bits = 32 if (@_ < 3);
223 0         0 $self->SUPER::_remove(AF_INET, pack("N",$num), $bits);
224             }
225              
226             ##
227             ## AF_INET6
228             ##
229              
230             package Net::Patricia::AF_INET6;
231              
232 1     1   5 use Carp;
  1         0  
  1         53  
233 1     1   3 use Socket qw(AF_INET6);
  1         1  
  1         29  
234 1     1   425 use Socket6 qw(inet_pton inet_ntop);
  1         901  
  1         85  
235 1     1   5 use vars qw(@ISA @EXPORT);
  1         1  
  1         95  
236              
237             BEGIN {
238 1     1   5 require Exporter;
239 1         3 require DynaLoader;
240 1         10 @ISA = qw(Exporter DynaLoader Net::Patricia);
241 1         623 @EXPORT = qw(AF_INET6);
242             }
243              
244             sub add {
245 1 50 33 1   14 croak "add: wrong number of args" if (@_ < 2 || @_ > 4);
246 1         3 my ($self, $ip, $bits, $data) = @_;
247 1 0       4 $data = (defined $bits ? "$ip/$bits" : $ip) if (@_ < 3);
    50          
248 1         13 my $packed = inet_pton(AF_INET6, $ip);
249 1 50       4 croak("invalid key") unless (defined $packed);
250 1 50       4 $bits = 128 if (@_ < 4);
251 1         17 $self->SUPER::_add(AF_INET6, $packed, $bits, $data);
252             }
253              
254             sub add_integer {
255 0 0 0 0   0 croak "add_integer: wrong number of args" if (@_ < 2 || @_ > 4);
256 0         0 my ($self, $num, $bits, $data) = @_;
257 0         0 my $packed = pack("N", $num);
258 0         0 my $ip = inet_ntop(AF_INET6, $packed);
259 0 0       0 croak("invalid address") unless (defined $ip);
260 0 0       0 $data = (defined $bits ? "$ip/$bits" : $ip) if (@_ < 3);
    0          
261 0 0       0 $bits = 128 if (@_ < 4);
262 0         0 $self->SUPER::_add(AF_INET6, $packed, $bits, $data);
263             }
264              
265             sub match_integer {
266 0 0 0 0   0 croak "match_integer: wrong number of args" if (@_ < 2 || @_ > 3);
267 0         0 my ($self, $num, $bits) = @_;
268 0 0       0 $bits = 128 if (@_ < 3);
269 0         0 $self->SUPER::_match(AF_INET6, pack("N",$num), $bits);
270             }
271              
272             sub exact_integer {
273 0 0 0 0   0 croak "exact_integer: wrong number of args" if (@_ < 2 || @_ > 3);
274 0         0 my ($self, $num, $bits) = @_;
275 0 0       0 $bits = 128 if (@_ < 3);
276 0         0 $self->SUPER::_exact(AF_INET6, pack("N",$num), $bits);
277             }
278              
279             sub match {
280 1 50 33 1   10 croak "match: wrong number of args" if (@_ < 2 || @_ > 3);
281 1         2 my ($self, $ip, $bits) = @_;
282 1         5 my $packed = inet_pton(AF_INET6, $ip);
283 1 50       2 croak("invalid key") unless (defined $packed);
284 1 50       4 $bits = 128 if (@_ < 3);
285 1         13 $self->SUPER::_match(AF_INET6, $packed, $bits);
286             }
287              
288             sub exact {
289 0 0 0 0     croak "exact: wrong number of args" if (@_ < 2 || @_ > 3);
290 0           my ($self, $ip, $bits) = @_;
291 0           my $packed = inet_pton(AF_INET6, $ip);
292 0 0         croak("invalid key") unless (defined $packed);
293 0 0         $bits = 128 if (@_ < 3);
294 0           $self->SUPER::_exact(AF_INET6, $packed, $bits);
295             }
296              
297             sub remove {
298 0 0 0 0     croak "remove: wrong number of args" if (@_ < 2 || @_ > 3);
299 0           my ($self, $ip, $bits) = @_;
300 0           my $packed = inet_pton(AF_INET6, $ip);
301 0 0         croak("invalid key") unless (defined $packed);
302 0 0         $bits = 128 if (@_ < 3);
303 0           $self->SUPER::_remove(AF_INET6, $packed, $bits);
304             }
305              
306             sub remove_integer {
307 0 0 0 0     croak "remote_integer: wrong number of args" if (@_ < 2 || @_ > 3);
308 0           my ($self, $num, $bits) = @_;
309 0 0         $bits = 128 if (@_ < 3);
310 0           $self->SUPER::_remove(AF_INET6, pack("N",$num), $bits);
311             }
312              
313             1;
314             __END__