File Coverage

lib/NetAddr/IP/FastNew.pm
Criterion Covered Total %
statement 25 27 92.5
branch n/a
condition n/a
subroutine 10 11 90.9
pod 5 5 100.0
total 40 43 93.0


line stmt bran cond sub pod time code
1             package NetAddr::IP::FastNew;
2              
3 2     2   32225 use strict;
  2         4  
  2         59  
4 2     2   8 use warnings;
  2         3  
  2         50  
5 2     2   1114 use NetAddr::IP;
  2         47604  
  2         8  
6             # 1.95 required for inet_pton
7 2     2   212 use Socket 1.95 qw(inet_pton AF_INET AF_INET6);
  2         34  
  2         412  
8 2     2   8 use NetAddr::IP::Util;
  2         3  
  2         8  
9             # the minimum version I test with. 5.10 doesn't support inet_pton.
10             # MSWin32 also doesn't support Socket::inet_pton
11 2     2   129 use v5.12.5;
  2         5  
  2         2106  
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.4';
32              
33             =head1 NAME
34              
35             NetAddr::IP::FastNew - NetAddr::IP new() methods with no validation
36              
37             =head1 VERSION
38              
39             0.4
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.
268              
269             This only takes one argument, the single IP address. Anything else will fail
270             in (probably) bad ways. Validation is completely up to you and is not done
271             here.
272              
273             my $ip = NetAddr::IP::FastNew->new_ipv4("127.0.0.1");
274              
275             =cut
276              
277              
278             sub new_ipv4 {
279 1     1 1 21 return bless {
280             addr => $zerov6 . inet_pton(AF_INET, $_[1]),
281             mask => $ones,
282             isv6 => 0,
283             }, 'NetAddr::IP';
284             }
285              
286             =head2 new_ipv4_mask
287              
288             Create a real NetAddr::IP from a IPv4 subnet with almost no
289             validation.
290              
291             This requires the IP address and the subnet mask as it's two arguments.
292             Anything else will fail in (probably) bad ways. Validation is completely
293             up to the caller is not done here.
294              
295             my $ip = NetAddr::IP::FastNew->new_ipv4_mask("127.0.0.0", "255.255.255.0");
296              
297             =cut
298              
299             sub new_ipv4_mask {
300 1     1 1 12 return bless {
301             addr => $zerov6 . inet_pton(AF_INET, $_[1]),
302             mask => $zerov6 . inet_pton(AF_INET, $_[2]),
303             isv6 => 0,
304             }, 'NetAddr::IP';
305             }
306              
307             =head2 new_ipv4_cidr
308              
309             Create a real NetAddr::IP object from a IPv4 cidr with almost no
310             validation.
311              
312             This requires the IP address and the cidr in a single argument.
313             Anything else will fail in (probably) bad ways. Validation is completely
314             up to the caller is not done here.
315              
316             my $ip = NetAddr::IP::FastNew->new_ipv4_cidr("127.0.0.0/24");
317              
318             =cut
319              
320             # you can use the ipv6 mask table by saying $masks->{128-32+$cidr}. Since
321             # it's an IPv4 address NetAddr::IP ignores the first 2 hextets.
322             # Unfortunately, it seems to be about 50,000 calls/sec slower than having an
323             # ipv4 mask table (I guess the overhead of doing the simple 96+$cidr math..)
324              
325             # for whatever reason, split is faster for this too, but this is the slowest
326             # function. Try to use the other two when possible.
327              
328             sub new_ipv4_cidr {
329 1     1 1 8 my ($ip, $cidr) = split('/', $_[1]);
330             #my $pos = index($_[1],'/');
331             #my $ip = substr($_[1], 0, $pos);
332              
333 1         8 return bless { 'addr' => $zerov6 . inet_pton(AF_INET, $ip),
334             'mask' => $masks4->{$cidr},
335             'isv6' => 0
336             }, 'NetAddr::IP';
337             }
338              
339             =head2 new_ipv6
340              
341             Create a real NetAddr::IP object from an IPv6 subnet with no validation. This
342             is almost as fast as the lazy object. The only caveat being it requires a
343             cidr mask.
344              
345             my $ip = NetAddr::IP::FastNew->new_ipv6("fe80::/64");
346              
347             =cut
348              
349             sub new_ipv6 {
350 1     1 1 12 my $pos = index($_[1],'/');
351 1         2 my $ip = substr($_[1], 0, $pos);
352 1         12 return bless { 'addr' => inet_pton(AF_INET6, $ip), 'mask' => $masks->{substr($_[1], $pos+1)}, 'isv6' => 1 }, 'NetAddr::IP';
353             }
354              
355              
356             1;