File Coverage

blib/lib/Net/Patricia.pm
Criterion Covered Total %
statement 146 192 76.0
branch 44 130 33.8
condition 11 53 20.7
subroutine 35 43 81.4
pod 6 8 75.0
total 242 426 56.8


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