File Coverage

lib/NetAddr/IP/FastNew.pm
Criterion Covered Total %
statement 22 27 81.4
branch n/a
condition n/a
subroutine 9 11 81.8
pod 5 5 100.0
total 36 43 83.7


line stmt bran cond sub pod time code
1             package NetAddr::IP::FastNew;
2              
3 1     1   24985 use strict;
  1         3  
  1         31  
4 1     1   5 use warnings;
  1         2  
  1         26  
5 1     1   1049 use NetAddr::IP;
  1         40756  
  1         5  
6             # 1.95 required for inet_pton
7 1     1   177 use Socket 1.95 qw(inet_pton AF_INET AF_INET6);
  1         25  
  1         273  
8 1     1   6 use NetAddr::IP::Util;
  1         2  
  1         7  
9             # the minimum version I test with. 5.10 doesn't support inet_pton.
10             # MSWin32 also doesn't support Socket::inet_pton
11 1     1   91 use v5.12.5;
  1         3  
  1         1615  
12              
13             # The following code is from spamassassin. I may use this to workaround Socket issues, but it only
14             # helps if Socket6 is available. Currently this only affects two platforms on
15             # cpantesters. OpenBSD (5.5) and GNUkfreebsd (8.1), so they could just upgrade to a
16             # version of Socket.pm that supports inet_pton (they're both running 1.94 so
17             # they only have to go up to 1.95)
18              
19             # # try to load inet_pton from Socket or Socket6
20             # my $ip6 = eval {
21             # require Socket;
22             # Socket->VERSION(1.95);
23             # Socket->import( 'inet_pton' );
24             # 1;
25             # } || eval {
26             # require Socket6;
27             # Socket6->import( 'inet_pton' );
28             # 1;
29             # };
30              
31             our $VERSION = eval '0.3';
32              
33             =head1 NAME
34              
35             NetAddr::IP::FastNew - NetAddr::IP new() methods with no validation
36              
37             =head1 VERSION
38              
39             0.3
40              
41             =head1 SYNOPSIS
42              
43             use NetAddr::IP::FastNew;
44              
45             my $ip = new NetAddr::IP::FastNew( '10.10.10.5' );
46              
47             =head1 DESCRIPTION
48              
49             This module is designed to quickly create NetAddr::IP objects.
50              
51             If you have a situation where you need 200_000 NetAddr::IP objects then the
52             initialization speed can really become a problem.
53              
54             =head1 CREDITS
55              
56             Robert Drake, Erdrake@cpan.orgE
57              
58             =head1 COPYRIGHT AND LICENSE
59              
60             Copyright (C) 2014 by Robert Drake
61              
62             This library is free software; you can redistribute it and/or modify
63             it under the same terms as Perl itself, either Perl version 5.8.7 or,
64             at your option, any later version of Perl 5 you may have available.
65              
66             =cut
67              
68             my $ones = "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377";
69             # this is to zero the ipv6 portion of the address. This is used when we're
70             # building IPv4 objects.
71             my $zerov6 = "\0\0\0\0\0\0\0\0\0\0\0\0";
72              
73             my $masks = {
74             0 => "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
75             1 => "\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
76             10 => "\377\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
77             100 => "\377\377\377\377\377\377\377\377\377\377\377\377\360\0\0\0",
78             101 => "\377\377\377\377\377\377\377\377\377\377\377\377\370\0\0\0",
79             102 => "\377\377\377\377\377\377\377\377\377\377\377\377\374\0\0\0",
80             103 => "\377\377\377\377\377\377\377\377\377\377\377\377\376\0\0\0",
81             104 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0",
82             105 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\200\0\0",
83             106 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\300\0\0",
84             107 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\340\0\0",
85             108 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\360\0\0",
86             109 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\370\0\0",
87             11 => "\377\340\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
88             110 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\374\0\0",
89             111 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\376\0\0",
90             112 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0",
91             113 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\200\0",
92             114 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300\0",
93             115 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\340\0",
94             116 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\360\0",
95             117 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\370\0",
96             118 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\374\0",
97             119 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376\0",
98             12 => "\377\360\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
99             120 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0",
100             121 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\200",
101             122 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300",
102             123 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\340",
103             124 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\360",
104             125 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\370",
105             126 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\374",
106             127 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376",
107             128 => "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377",
108             13 => "\377\370\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
109             14 => "\377\374\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
110             15 => "\377\376\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
111             16 => "\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
112             17 => "\377\377\200\0\0\0\0\0\0\0\0\0\0\0\0\0",
113             18 => "\377\377\300\0\0\0\0\0\0\0\0\0\0\0\0\0",
114             19 => "\377\377\340\0\0\0\0\0\0\0\0\0\0\0\0\0",
115             2 => "\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
116             20 => "\377\377\360\0\0\0\0\0\0\0\0\0\0\0\0\0",
117             21 => "\377\377\370\0\0\0\0\0\0\0\0\0\0\0\0\0",
118             22 => "\377\377\374\0\0\0\0\0\0\0\0\0\0\0\0\0",
119             23 => "\377\377\376\0\0\0\0\0\0\0\0\0\0\0\0\0",
120             24 => "\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0",
121             25 => "\377\377\377\200\0\0\0\0\0\0\0\0\0\0\0\0",
122             26 => "\377\377\377\300\0\0\0\0\0\0\0\0\0\0\0\0",
123             27 => "\377\377\377\340\0\0\0\0\0\0\0\0\0\0\0\0",
124             28 => "\377\377\377\360\0\0\0\0\0\0\0\0\0\0\0\0",
125             29 => "\377\377\377\370\0\0\0\0\0\0\0\0\0\0\0\0",
126             3 => "\340\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
127             30 => "\377\377\377\374\0\0\0\0\0\0\0\0\0\0\0\0",
128             31 => "\377\377\377\376\0\0\0\0\0\0\0\0\0\0\0\0",
129             32 => "\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0",
130             33 => "\377\377\377\377\200\0\0\0\0\0\0\0\0\0\0\0",
131             34 => "\377\377\377\377\300\0\0\0\0\0\0\0\0\0\0\0",
132             35 => "\377\377\377\377\340\0\0\0\0\0\0\0\0\0\0\0",
133             36 => "\377\377\377\377\360\0\0\0\0\0\0\0\0\0\0\0",
134             37 => "\377\377\377\377\370\0\0\0\0\0\0\0\0\0\0\0",
135             38 => "\377\377\377\377\374\0\0\0\0\0\0\0\0\0\0\0",
136             39 => "\377\377\377\377\376\0\0\0\0\0\0\0\0\0\0\0",
137             4 => "\360\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
138             40 => "\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0",
139             41 => "\377\377\377\377\377\200\0\0\0\0\0\0\0\0\0\0",
140             42 => "\377\377\377\377\377\300\0\0\0\0\0\0\0\0\0\0",
141             43 => "\377\377\377\377\377\340\0\0\0\0\0\0\0\0\0\0",
142             44 => "\377\377\377\377\377\360\0\0\0\0\0\0\0\0\0\0",
143             45 => "\377\377\377\377\377\370\0\0\0\0\0\0\0\0\0\0",
144             46 => "\377\377\377\377\377\374\0\0\0\0\0\0\0\0\0\0",
145             47 => "\377\377\377\377\377\376\0\0\0\0\0\0\0\0\0\0",
146             48 => "\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0",
147             49 => "\377\377\377\377\377\377\200\0\0\0\0\0\0\0\0\0",
148             5 => "\370\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
149             50 => "\377\377\377\377\377\377\300\0\0\0\0\0\0\0\0\0",
150             51 => "\377\377\377\377\377\377\340\0\0\0\0\0\0\0\0\0",
151             52 => "\377\377\377\377\377\377\360\0\0\0\0\0\0\0\0\0",
152             53 => "\377\377\377\377\377\377\370\0\0\0\0\0\0\0\0\0",
153             54 => "\377\377\377\377\377\377\374\0\0\0\0\0\0\0\0\0",
154             55 => "\377\377\377\377\377\377\376\0\0\0\0\0\0\0\0\0",
155             56 => "\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0",
156             57 => "\377\377\377\377\377\377\377\200\0\0\0\0\0\0\0\0",
157             58 => "\377\377\377\377\377\377\377\300\0\0\0\0\0\0\0\0",
158             59 => "\377\377\377\377\377\377\377\340\0\0\0\0\0\0\0\0",
159             6 => "\374\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
160             60 => "\377\377\377\377\377\377\377\360\0\0\0\0\0\0\0\0",
161             61 => "\377\377\377\377\377\377\377\370\0\0\0\0\0\0\0\0",
162             62 => "\377\377\377\377\377\377\377\374\0\0\0\0\0\0\0\0",
163             63 => "\377\377\377\377\377\377\377\376\0\0\0\0\0\0\0\0",
164             64 => "\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0",
165             65 => "\377\377\377\377\377\377\377\377\200\0\0\0\0\0\0\0",
166             66 => "\377\377\377\377\377\377\377\377\300\0\0\0\0\0\0\0",
167             67 => "\377\377\377\377\377\377\377\377\340\0\0\0\0\0\0\0",
168             68 => "\377\377\377\377\377\377\377\377\360\0\0\0\0\0\0\0",
169             69 => "\377\377\377\377\377\377\377\377\370\0\0\0\0\0\0\0",
170             7 => "\376\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
171             70 => "\377\377\377\377\377\377\377\377\374\0\0\0\0\0\0\0",
172             71 => "\377\377\377\377\377\377\377\377\376\0\0\0\0\0\0\0",
173             72 => "\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0",
174             73 => "\377\377\377\377\377\377\377\377\377\200\0\0\0\0\0\0",
175             74 => "\377\377\377\377\377\377\377\377\377\300\0\0\0\0\0\0",
176             75 => "\377\377\377\377\377\377\377\377\377\340\0\0\0\0\0\0",
177             76 => "\377\377\377\377\377\377\377\377\377\360\0\0\0\0\0\0",
178             77 => "\377\377\377\377\377\377\377\377\377\370\0\0\0\0\0\0",
179             78 => "\377\377\377\377\377\377\377\377\377\374\0\0\0\0\0\0",
180             79 => "\377\377\377\377\377\377\377\377\377\376\0\0\0\0\0\0",
181             8 => "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
182             80 => "\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0",
183             81 => "\377\377\377\377\377\377\377\377\377\377\200\0\0\0\0\0",
184             82 => "\377\377\377\377\377\377\377\377\377\377\300\0\0\0\0\0",
185             83 => "\377\377\377\377\377\377\377\377\377\377\340\0\0\0\0\0",
186             84 => "\377\377\377\377\377\377\377\377\377\377\360\0\0\0\0\0",
187             85 => "\377\377\377\377\377\377\377\377\377\377\370\0\0\0\0\0",
188             86 => "\377\377\377\377\377\377\377\377\377\377\374\0\0\0\0\0",
189             87 => "\377\377\377\377\377\377\377\377\377\377\376\0\0\0\0\0",
190             88 => "\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0",
191             89 => "\377\377\377\377\377\377\377\377\377\377\377\200\0\0\0\0",
192             9 => "\377\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
193             90 => "\377\377\377\377\377\377\377\377\377\377\377\300\0\0\0\0",
194             91 => "\377\377\377\377\377\377\377\377\377\377\377\340\0\0\0\0",
195             92 => "\377\377\377\377\377\377\377\377\377\377\377\360\0\0\0\0",
196             93 => "\377\377\377\377\377\377\377\377\377\377\377\370\0\0\0\0",
197             94 => "\377\377\377\377\377\377\377\377\377\377\377\374\0\0\0\0",
198             95 => "\377\377\377\377\377\377\377\377\377\377\377\376\0\0\0\0",
199             96 => "\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0",
200             97 => "\377\377\377\377\377\377\377\377\377\377\377\377\200\0\0\0",
201             98 => "\377\377\377\377\377\377\377\377\377\377\377\377\300\0\0\0",
202             99 => "\377\377\377\377\377\377\377\377\377\377\377\377\340\0\0\0"
203             };
204              
205              
206             my $masks4 = {
207             0 => "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
208             1 => "\0\0\0\0\0\0\0\0\0\0\0\0\200\0\0\0",
209             3 => "\0\0\0\0\0\0\0\0\0\0\0\0\340\0\0\0",
210             2 => "\0\0\0\0\0\0\0\0\0\0\0\0\300\0\0\0",
211             4 => "\0\0\0\0\0\0\0\0\0\0\0\0\360\0\0\0",
212             5 => "\0\0\0\0\0\0\0\0\0\0\0\0\370\0\0\0",
213             6 => "\0\0\0\0\0\0\0\0\0\0\0\0\374\0\0\0",
214             7 => "\0\0\0\0\0\0\0\0\0\0\0\0\376\0\0\0",
215             8 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0",
216             9 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\200\0\0",
217             10 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\300\0\0",
218             11 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\340\0\0",
219             12 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\360\0\0",
220             13 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\370\0\0",
221             14 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\374\0\0",
222             15 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\376\0\0",
223             16 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\0\0",
224             17 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\200\0",
225             18 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\300\0",
226             19 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\340\0",
227             20 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\360\0",
228             21 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\370\0",
229             22 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\374\0",
230             23 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\376\0",
231             24 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\0",
232             25 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\200",
233             26 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\300",
234             27 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\340",
235             28 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\360",
236             29 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\370",
237             30 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\374",
238             31 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\376",
239             32 => "\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377",
240             };
241              
242              
243              
244             =head1 METHODS
245              
246             =head2 new
247              
248             Right now this just calls NetAddr::IP->new().
249              
250             my $ip = NetAddr::IP::FastNew->new("127.0.0.1");
251              
252             =cut
253              
254             sub new {
255             # attempt to beat NetAddr::IP speeds by guessing the type of address and
256             # initializing it. This will probably not support nearly as many formats
257             # as the original, but will be useful to some users who want something
258             # fast and easy.
259 0     0 1 0 my $class = shift;
260 0         0 return NetAddr::IP->new(@_);
261             }
262              
263              
264             =head2 new_ipv4
265              
266             Create a real NetAddr::IP from a single IPv4 address with almost no
267             validation. This has more overhead than the FastNew new() but it's much
268             faster if you make use of the IP object.
269              
270             This only takes one argument, the single IP address. Anything else will fail
271             in (probably) bad ways. Validation is completely up to you and is not done
272             here.
273              
274             my $ip = NetAddr::IP::FastNew->new_ipv4("127.0.0.1");
275              
276             =cut
277              
278              
279             sub new_ipv4 {
280 1     1 1 30 return bless {
281             addr => $zerov6 . inet_pton(AF_INET, $_[1]),
282             mask => $ones,
283             isv6 => 0,
284             }, 'NetAddr::IP';
285             }
286              
287             =head2 new_ipv4_mask
288              
289             Create a real NetAddr::IP from a IPv4 subnet with almost no
290             validation.
291              
292             This requires the IP address and the subnet mask as it's two arguments.
293             Anything else will fail in (probably) bad ways. Validation is completely
294             up to the caller is not done here.
295              
296             my $ip = NetAddr::IP::FastNew->new_ipv4_mask("127.0.0.0", "255.255.255.0");
297              
298             =cut
299              
300             sub new_ipv4_mask {
301 1     1 1 17 return bless {
302             addr => $zerov6 . inet_pton(AF_INET, $_[1]),
303             mask => $zerov6 . inet_pton(AF_INET, $_[2]),
304             isv6 => 0,
305             }, 'NetAddr::IP';
306             }
307              
308             =head2 new_ipv4_cidr
309              
310             Create a real NetAddr::IP object from a IPv4 cidr with almost no
311             validation.
312              
313             This requires the IP address and the cidr in a single argument.
314             Anything else will fail in (probably) bad ways. Validation is completely
315             up to the caller is not done here.
316              
317             my $ip = NetAddr::IP::FastNew->new_ipv4_cidr("127.0.0.0/24");
318              
319             =cut
320              
321             # you can use the ipv6 mask table by saying $masks->{128-32+$cidr}. Since
322             # it's an IPv4 address NetAddr::IP ignores the first 2 hextets.
323             # Unfortunately, it seems to be about 50,000 calls/sec slower than having an
324             # ipv4 mask table (I guess the overhead of doing the simple 96+$cidr math..)
325              
326             # for whatever reason, split is faster for this too, but this is the slowest
327             # function. Try to use the other two when possible.
328              
329             sub new_ipv4_cidr {
330 1     1 1 11 my ($ip, $cidr) = split('/', $_[1]);
331             #my $pos = index($_[1],'/');
332             #my $ip = substr($_[1], 0, $pos);
333              
334 1         11 return bless { 'addr' => $zerov6 . inet_pton(AF_INET, $ip),
335             'mask' => $masks4->{$cidr},
336             'isv6' => 0
337             }, 'NetAddr::IP';
338             }
339              
340             =head2 new_ipv6
341              
342             Create a real NetAddr::IP object from an IPv6 subnet with no validation. This
343             is almost as fast as the lazy object. The only caveat being it requires a
344             cidr mask.
345              
346             my $ip = NetAddr::IP::FastNew->new_ipv6("fe80::/64");
347              
348             =cut
349              
350             sub new_ipv6 {
351 0     0 1   my $pos = index($_[1],'/');
352 0           my $ip = substr($_[1], 0, $pos);
353 0           return bless { 'addr' => inet_pton(AF_INET6, $ip), 'mask' => $masks->{substr($_[1], $pos+1)}, 'isv6' => 1 }, 'NetAddr::IP';
354             }
355              
356              
357             1;