File Coverage

blib/lib/Net/IP/Lite.pm
Criterion Covered Total %
statement 344 349 98.5
branch 235 242 97.1
condition 82 88 93.1
subroutine 50 52 96.1
pod 20 21 95.2
total 731 752 97.2


line stmt bran cond sub pod time code
1             package Net::IP::Lite;
2              
3 23     23   763440 use strict;
  23         55  
  23         820  
4 23     23   138 use warnings;
  23         42  
  23         823  
5              
6 23     23   134 use Carp qw(croak);
  23         45  
  23         1877  
7 23     23   128 use Scalar::Util qw(blessed);
  23         39  
  23         2729  
8              
9 23     23   142 use base 'Exporter';
  23         66  
  23         3713  
10              
11             our @EXPORT = qw(
12             ip2bin ip_validate ip_is_ipv4 ip_is_ipv6 ip_is_ipv6ipv4
13             ip_transform ip_equal ip_equal_v4 ip_equal_v6 ip_in_range
14             );
15              
16 23     23   239 use constant IPV6IPV4HEAD => '0' x 80 . '1' x 16;
  23         48  
  23         129977  
17              
18             our $VERSION = '0.03';
19              
20             sub _wrong_ip {
21 693     693   1677 my $addr = shift;
22 693 100       1396 $addr = 'UNDEFINED' unless defined $addr;
23 693         10114 return "Wrong IP address: '$addr'";
24             }
25              
26             sub _wrong_ipv6ipv4 {
27 42     42   49 my $addr = shift;
28 42 50       90 $addr = 'UNDEFINED' unless defined $addr;
29 42         626 return "Failed to convert IPv6 address '$addr' to IPv4 address";
30             }
31              
32             sub _wrong_net {
33 212     212   388 my $net = shift;
34 212 100       425 $net = 'UNDEFINED' unless defined $net;
35 212         2446 return "Wrong network definition: '$net'";
36             }
37              
38             sub ip2bin {
39 10668     10668 1 43964 my $addr = shift;
40 10668 100       25764 return '' unless defined $addr;
41              
42 10651         27670 my $bin = '';
43              
44 10651 100       44880 if ($addr =~ /:/) {
    100          
    100          
    100          
    100          
45             # IPv6 address
46              
47 3087 100       7749 return '0' x 128 if $addr eq '::';
48              
49 2600 100 100     12323 return '' if $addr =~ s/^:// && $addr !~ /^:/;
50 2370 100 100     15334 return '' if $addr =~ s/:$// && $addr !~ /:$/;
51              
52 2229         9340 my @words = split(/:/, $addr, -1);
53 2229         4106 my $words_amount = scalar @words;
54              
55             # IPv4 representation
56 2229 100       5980 $words_amount++ if $addr =~ /\./;
57              
58 2229         2877 my $reduct = 0;
59 2229         9481 my $i = 0;
60 2229         4398 for my $word (@words) {
61 11841         12695 $i++;
62 11841 100       72914 if ($word =~ /\./) {
    100          
    100          
63             # IPv4 representation
64 318 100 100     2001 return '' if $i != scalar @words || $bin ne IPV6IPV4HEAD;
65 218         1099 my @octets = split(/\./, $word);
66 218 100       637 return '' if scalar @octets != 4;
67 198         350 for my $octet (@octets) {
68 792 100 100     5546 return '' if $octet !~ /^\d+$/ || $octet > 255;
69 752         3766 $bin .= unpack('B8', pack('C', $octet));
70             }
71 158         676 return $bin;
72             } elsif (!length $word) {
73 1336 100       2877 return '' if $reduct;
74 1198         1302 $reduct = 1;
75 1198         1668 my $len = (9 - $words_amount) << 4;
76 1198 100       2544 return '' unless $len;
77 1173         3178 $bin .= '0' x ((9 - $words_amount) << 4);
78             } elsif ($word =~ /^[0-9a-f]+$/i) {
79 10110         19146 $word =~ s/^0+//i;
80 10110 100       20846 return '' if length($word) > 4;
81 9927         12959 my $int = hex($word);
82 9927         30903 $bin .= unpack('B16', pack('n', $int));
83             } else {
84 77         289 return '';
85             }
86 11100 50       29041 return '' if length($bin) > 128;
87             }
88 1488 100       5037 return '' if length($bin) < 128;
89             } elsif ($addr =~ /\./) {
90             # IPv4
91 5205         19272 my @octets = split(/\./, $addr, -1);
92 5205 100       13580 return '' if scalar @octets > 4;
93 5182         13283 my $i = 0;
94 5182         10347 for my $octet (@octets) {
95 19805         28865 $i++;
96 19805         20899 my $dec;
97 19805 100       81042 if ($octet =~ /^0[0-7]+$/) {
    100          
    100          
98             # Octal octet
99 2297         6836 $octet =~ s/^0+//;
100 2297 50       6252 return '' if length($octet) > 3;
101 2297         3272 $dec = oct($octet);
102             } elsif ($octet =~ /^\d+$/) {
103             # Decimal octet
104 15736 100       31009 return '' if length($octet) > 3;
105 15713         20678 $dec = $octet;
106             } elsif ($octet =~ /^0x[0-9a-f]+$/i) {
107             # Hexadecimal octet
108 1617         5193 $octet =~ s/^0x0*//i;
109 1617 100       4367 return '' if length($octet) > 2;
110 1594         2300 $dec = hex($octet);
111             } else {
112 155         530 return '';
113             }
114 19604 100       44303 return '' if $dec > 255;
115 19581 100 100     80934 if ($i == scalar @octets && $i < 4) {
116             # add missed octets
117 336         1224 $bin .= '0' x ((4 - $i) << 3);
118             }
119 19581         90784 $bin .= unpack('B8', pack('C', $dec));
120             }
121             } elsif ($addr =~ /^0[0-7]+$/) {
122             # Octal IPv4 address
123 604         2267 $addr =~ s/^0+//i;
124 604 100       1858 return '' if $addr > 37777777777;
125 581         1067 my $int = oct($addr);
126 581         2316 $bin = unpack('B32', pack('N', $int));
127             } elsif ($addr =~ /^\d+$/) {
128             # Decimal IPv4 address
129 1151 100       2951 return '' if $addr > 4294967295;
130 1128         4322 $bin = unpack('B32', pack('N', $addr));
131             } elsif ($addr =~ /^0x[0-9a-f]+$/i) {
132             # Hexadecimal IPv4 addres
133 544         1833 $addr =~ s/^0x0*//i;
134 544 100       1720 return '' if length($addr) > 8;
135 521         911 my $int = hex($addr);
136 521         2071 $bin = unpack('B32', pack('N', $int));
137             }
138 8711         24607 return $bin;
139             }
140              
141             sub _ip_validate {
142 12612     12612   41870 return length(shift) > 0;
143             }
144              
145             sub ip_validate {
146 87     87 1 55386 return _ip_validate(ip2bin(shift)) > 0;
147             }
148              
149             sub _ip_is_ipv4 {
150 5087     5087   19338 return length(shift) eq 32;
151             }
152              
153             sub ip_is_ipv4 {
154 87     87 1 43221 return _ip_is_ipv4(ip2bin(shift));
155             }
156              
157             sub _ip_type_equal {
158 4610     4610   15519 return length(shift) == length(shift);
159             }
160              
161             sub _ip_is_ipv6 {
162 647     647   3969 return length(shift) eq 128;
163             }
164              
165             sub ip_is_ipv6 {
166 87     87 1 37836 return _ip_is_ipv6(ip2bin(shift));
167             }
168              
169             sub _ip_is_ipv6ipv4 {
170 536     536   2265 return substr(shift, 0, 96) eq IPV6IPV4HEAD;
171             }
172              
173             sub ip_is_ipv6ipv4 {
174 87     87 1 40061 return _ip_is_ipv6ipv4(ip2bin(shift));
175             }
176              
177             sub _bin2ipv6 {
178 640     640   1137 my ($bin, $lead_zeros, $short) = @_;
179 640         747 my $result = '';
180 640         6346 my @chunks = $bin =~ m/[0..1]{16}/g;
181              
182 640         1161 my $short_len = 0;
183 640 100       1195 if ($short) {
184 200         210 my @zero_chunks;
185 200         221 my $i = 0;
186 200         296 for my $chunk (@chunks) {
187 1528 100       2739 if ($chunk !~ /1/) {
188 1120         1742 $zero_chunks[$i]++;
189             } else {
190 408 100       935 $i++ if defined $zero_chunks[$i];
191             }
192             }
193 200         553 @zero_chunks = sort @zero_chunks;
194 200 100       522 $short_len = pop @zero_chunks if scalar @zero_chunks;
195             }
196 640         984 for my $chunk (@chunks) {
197 4960         12300 my $word = unpack('H4', pack('B16', $chunk)) . ':';
198 4960 100       16636 $word =~ s/^0{1,3}// unless $lead_zeros;
199 4960         8290 $result .= $word;
200             }
201              
202 640 100       5360 $result =~ s/(^|:)(0{1,4}:){$short_len}/::/ if $short_len > 1;
203 640 100       3814 $result =~ s/:$// if $result !~ /::$/;
204 640         2389 return $result;
205             }
206              
207             sub _bin2ipv4 {
208 730     730   1415 my ($bin, $format, $lead_zeros, $short) = @_;
209              
210 730   100     2356 $format ||= '';
211 730         5086 my @chunks = $bin =~ m/[0..1]{8}/g;
212              
213 730 100       1934 if ($format =~ /^(D|O|X)$/) {
214 72         82 my $result = 0;
215 72         82 my $i = 0;
216 72         112 for my $chunk (reverse @chunks) {
217 288         615 $result += unpack('C', pack('B8', $chunk)) << $i;
218 288         421 $i +=8;
219             }
220              
221 72 100       268 return sprintf("%#1o", $result) if $format eq 'O';
222 48 100 100     201 return sprintf("0x%.8x", $result) if $format eq 'X' && $lead_zeros;
223 40 100       150 return sprintf("0x%x", $result) if $format eq 'X';
224 20         63 return $result;
225             } else {
226 658         743 my $result = '';
227 658         807 my $f = '';
228 658 100       1587 if ($format eq 'o') {
    100          
229 40         59 $f = '%#.1o';
230             } elsif ($format eq 'x') {
231 48 100       108 $f = $lead_zeros ? '0x%.2x' : '0x%x' ;
232             }
233              
234 658         723 my $i = 4;
235 658         1113 for my $chunk (reverse @chunks) {
236 2632         3549 $i--;
237 2632         5698 my $octet = unpack('C', pack('B8', $chunk));
238 2632 100       4996 if ($short) {
239 452 100 100     2416 next if (!$octet && $i && $i < 3 );
      100        
240 242 100       433 $short = 0 if $i == 2;
241             }
242 2422 100       5354 if ($format eq 'o') {
    100          
243 128         299 $octet = sprintf($f, $octet);
244             } elsif ($format eq 'x') {
245 158         8662 $octet = sprintf($f, $octet);
246             }
247 2422         5275 $result = "$octet.$result";
248             }
249 658         3087 $result =~ s/\.$//;
250 658         2653 return $result;
251             }
252             }
253              
254             sub _reverse {
255 352     352   419 my $bin = shift;
256 352 100       551 my $len = _ip_is_ipv4($bin) ? 8 : 16;
257 352         9627 my @chunks = $bin =~ m/[0..1]{$len}/g;
258 352         1652 return join('', reverse @chunks);
259             }
260              
261             sub _ip_transform {
262 704     704   941 my ($bin, $opts) = @_;
263              
264 704   100     2474 my $format = $opts->{format_ipv4} || '';
265 704   100     2051 my $convert_to = $opts->{convert_to} || '';
266              
267 704         1756 my $ipv6;
268             my $ipv4;
269              
270 704 100 100     2535 if ($convert_to eq 'ipv4' && _ip_is_ipv6ipv4($bin)) {
271             # convert ipv6ipv4 to ipv4
272 36         67 $bin = substr($bin, 96, 32);
273             }
274              
275 704 100 100     2846 if (($convert_to eq 'ipv6' || $convert_to eq 'ipv6ipv4') && _ip_is_ipv4($bin)) {
      100        
276             # convert ipv4 to ipv6
277 136         374 $bin = IPV6IPV4HEAD . $bin;
278             }
279              
280 704 100 100     2000 if ($convert_to eq 'ipv6ipv4' && _ip_is_ipv6ipv4($bin)) {
281             # convert ipv4 to ipv6ipv4
282 80         127 $ipv4 = substr($bin, 96, 32);
283 80 100       196 $ipv4 = _reverse($ipv4) if $opts->{reverse};
284 80         110 $bin = IPV6IPV4HEAD;
285             } else {
286 624 100       2100 $bin = _reverse($bin) if $opts->{reverse};
287             }
288              
289 704         1046 my $result = '';
290 704 100       1838 if (length($bin) > 32) {
291             # IPv6
292 366         1267 $result = _bin2ipv6($bin, $opts->{lead_zeros}, $opts->{short_ipv6});
293 366 100       951 if ($ipv4) {
294 80         87 $bin = $ipv4;
295 80         103 $ipv6 = $result;
296             }
297             }
298              
299 704 100       1315 if (length($bin) == 32) {
300             # IPv4
301 418 100       602 if ($ipv6) {
302 80         155 $result = "$ipv6:" . _bin2ipv4($bin);
303             } else {
304 338         1212 $result = _bin2ipv4($bin, $format, $opts->{lead_zeros}, $opts->{short_ipv4});
305             }
306             }
307              
308 704         5158 return $result;
309             }
310              
311             sub ip_transform {
312 416     416 1 167199 my ($addr, $opts) = @_;
313              
314 416   100     1181 $opts ||= {};
315 416 100       1173 croak 'Options must be a hash' unless ref($opts) eq 'HASH';
316              
317 415         757 my $bin = ip2bin($addr);
318 415 100       850 croak _wrong_ip($addr) unless _ip_validate($bin);
319 352         770 return _ip_transform($bin, $opts);
320             }
321              
322             sub _ip_equal {
323 2951     2951   4578 my ($bin1, $bin2) = @_;
324 2951         46735 return $bin1 eq $bin2;
325             }
326              
327             sub ip_equal {
328 157     157 1 189353 my ($addr1, $addr2) = @_;
329 157         375 my $bin1 = ip2bin($addr1);
330 157         686 my $bin2 = ip2bin($addr2);
331              
332 157 100       324 croak _wrong_ip($addr1) unless _ip_validate($bin1);
333 94 100       182 croak _wrong_ip($addr2) unless _ip_validate($bin2);
334              
335 31         182 return $bin1 eq $bin2;
336             }
337              
338             sub _ip_equal_v4 {
339 93     93   192 my ($bin1, $bin2) = @_;
340 93 100       134 $bin1 = substr($bin1, 96, 32) if _ip_is_ipv6ipv4($bin1);
341 93 100       154 $bin2 = substr($bin2, 96, 32) if _ip_is_ipv6ipv4($bin2);
342 93         174 return _ip_equal($bin1, $bin2);
343             }
344              
345             sub ip_equal_v4 {
346 177     177 1 189457 my ($addr1, $addr2) = @_;
347 177         348 my $bin1 = ip2bin($addr1);
348 177         429 my $bin2 = ip2bin($addr2);
349              
350 177 50       905 croak _wrong_ip($addr1) unless _ip_validate($bin1);
351 177 100       424 croak _wrong_ip($addr2) unless _ip_validate($bin2);
352              
353 51 100 100     101 if ((_ip_is_ipv6($bin1) && ! _ip_is_ipv6ipv4($bin1))) {
354 11         24 croak _wrong_ipv6ipv4($addr1);
355             }
356              
357 40 100 100     75 if ((_ip_is_ipv6($bin2) && ! _ip_is_ipv6ipv4($bin2))) {
358 9         15 croak _wrong_ipv6ipv4($addr2);
359             }
360              
361 31         58 return _ip_equal_v4($bin1, $bin2);
362             }
363              
364             sub _ip_equal_v6 {
365 114     114   180 my ($bin1, $bin2) = @_;
366 114 100       200 $bin1 = IPV6IPV4HEAD . $bin1 if _ip_is_ipv4($bin1);
367 114 100       214 $bin2 = IPV6IPV4HEAD . $bin2 if _ip_is_ipv4($bin2);
368 114         223 return _ip_equal($bin1, $bin2);
369             }
370              
371             sub ip_equal_v6 {
372 164     164 1 141507 my ($addr1, $addr2) = @_;
373 164         301 my $bin1 = ip2bin($addr1);
374 164         270 my $bin2 = ip2bin($addr2);
375              
376 164 50       292 croak _wrong_ip($addr1) unless _ip_validate($bin1);
377 164 100       262 croak _wrong_ip($addr2) unless _ip_validate($bin2);
378              
379 38         67 return _ip_equal_v6($bin1, $bin2);
380             }
381              
382             sub __ip_in_range {
383 2682     2682   4931 my ($bin_addr, $bin_net, $bin_mask) = @_;
384              
385 2682         36607 my @addr_bits = split(//, $bin_addr);
386 2682         43937 my @mask_bits = split(//, $bin_mask);
387 2682         8411 my $result = '';
388              
389 2682         3773 my $i = 0;
390 2682         4205 for my $bit (@addr_bits) {
391 130560         174476 $result .= $bit & $mask_bits[$i];
392 130560         143907 $i++;
393             }
394              
395 2682         6905 return _ip_equal($bin_net, $result);
396             }
397              
398             sub _ip_in_range {
399 2098     2098   3276 my ($bin_addr, $net, $addr) = @_;
400              
401 2098         2313 my $bin_net;
402             my $bin_mask;
403              
404 2098 100       16866 if ($net =~ /^(.+)\/(\d+)$/) {
    100          
405 796         1577 my $mask = $2;
406 796         1435 $bin_net = ip2bin($1);
407 796 50       1734 croak _wrong_net($net) unless _ip_validate($bin_net);
408              
409 796 100       1621 my $mask_len = _ip_is_ipv4($bin_net) ? 32 : 128;
410 796 100       1877 croak _wrong_net($net) if $mask > $mask_len;
411              
412 792         1902 $bin_mask = '1' x $mask . '0' x ($mask_len - $mask);
413             } elsif ($net =~ /^(\S+)\s+(\S+)$/) {
414 474         854 $bin_net = ip2bin($1);
415 474         972 $bin_mask = ip2bin($2);
416             } else {
417 828         1568 $bin_net = ip2bin($net);
418 828 100       1999 $bin_mask = '1' x (_ip_is_ipv4($bin_net) ? 32 : 128);
419             }
420              
421 2094 100 100     4448 unless (_ip_validate($bin_net) && _ip_validate($bin_mask) && _ip_type_equal($bin_net, $bin_mask)) {
      100        
422 206         347 croak _wrong_net($net);
423             }
424              
425 1888 100       4340 return 0 unless _ip_type_equal($bin_addr, $bin_net);
426              
427 1870         4221 return __ip_in_range($bin_addr, $bin_net, $bin_mask);
428             }
429              
430             sub ip_in_range {
431 1403     1403 1 327780 my ($addr, $range) = @_;
432              
433 1403 100       3538 croak _wrong_net($range) unless defined $range;
434              
435 1402 100       3363 if (ref($range) eq 'ARRAY') {
436 410         687 for my $net (@$range) {
437 617 100       1205 return 1 if ip_in_range($addr, $net);
438             }
439 107         809 return 0;
440             }
441              
442 992         1744 my $bin_addr = ip2bin($addr);
443 992 100       2709 croak _wrong_ip($addr) unless _ip_validate($bin_addr);
444              
445 929         2207 return _ip_in_range($bin_addr, $range, $addr);
446             }
447              
448             sub new {
449 4533     4533 0 756862 my ($class, $addr) = @_;
450              
451 4533         9005 my $bin = ip2bin($addr);
452 4533 100       8656 return 0 unless _ip_validate($bin);
453              
454 4371         15565 my $self = {
455             bin => $bin,
456             addr => $addr
457             };
458              
459 4371         11051 bless $self, $class;
460 4371         11285 return $self;
461             }
462              
463             sub _set_binary {
464 0     0   0 my ($self, $bin) = @_;
465 0         0 $self->{bin} = $bin;
466 0         0 $self->{addr} = $self->transform();
467             }
468              
469             sub address {
470 1182     1182 1 1419 my $self = shift;
471 1182         3533 return $self->{addr};
472             }
473              
474             sub binary {
475 8377     8377 1 17302 my $self = shift;
476 8377         28294 return $self->{bin};
477             }
478              
479             sub is_ipv4 {
480 2616     2616 1 3595 my $self = shift;
481 2616         4787 return _ip_is_ipv4($self->binary);
482             }
483              
484             sub is_ipv6 {
485 398     398 1 593 my $self = shift;
486 398         733 return _ip_is_ipv6($self->binary);
487             }
488              
489             sub is_ipv6ipv4 {
490 51     51 1 137 my $self = shift;
491 51         87 return _ip_is_ipv6ipv4($self->binary);
492             }
493              
494             sub transform {
495 353     353 1 7784 my ($self, $opts) = @_;
496 353   100     672 $opts ||= {};
497 353 100       773 croak 'Options must be a hash' unless ref($opts) eq 'HASH';
498 352         593 return _ip_transform($self->binary, $opts);
499             }
500              
501             sub equal {
502 125     125 1 416 my ($self, $addr) = @_;
503              
504 125 100 66     517 if (blessed($addr) && $addr->isa('Net::IP::Lite')) {
505 31         63 return _ip_equal($self->binary, $addr->binary);
506             }
507              
508 94         147 my $bin2 = ip2bin($addr);
509 94 100       175 croak _wrong_ip($addr) unless _ip_validate($bin2);
510              
511 31         89 return _ip_equal($self->binary, $bin2);
512             }
513              
514             sub equal_v4 {
515 147     147 1 699 my ($self, $addr) = @_;
516              
517 147 100 66     670 my $bin2 = (blessed($addr) && $addr->isa('Net::IP::Lite')) ? $addr->binary : ip2bin($addr);
518 147 100       273 croak _wrong_ip($addr) unless _ip_validate($bin2);
519              
520 84 100 100     173 if (($self->is_ipv6() && ! $self->is_ipv6ipv4())) {
521 13         27 croak _wrong_ipv6ipv4($self->address);
522             }
523              
524 71 100 100     116 if ((_ip_is_ipv6($bin2) && ! _ip_is_ipv6ipv4($bin2))) {
525 9         16 croak _wrong_ipv6ipv4($addr);
526             }
527              
528 62         129 return _ip_equal_v4($self->binary, $bin2);
529             }
530              
531             sub equal_v6 {
532 139     139 1 547 my ($self, $addr) = @_;
533              
534 139 100 66     715 my $bin2 = (blessed($addr) && $addr->isa('Net::IP::Lite')) ? $addr->binary : ip2bin($addr);
535              
536 139 100       288 croak _wrong_ip($addr) unless _ip_validate($bin2);
537              
538 76         186 return _ip_equal_v6($self->binary, $bin2);
539             }
540              
541             sub in_range {
542 2234     2234 1 4732 my ($self, $range) = @_;
543              
544 2234 100       5428 croak _wrong_net($range) unless defined $range;
545              
546 2233 100       5170 if (ref($range) eq 'ARRAY') {
547 650         1150 for my $net (@$range) {
548 1097 100       2401 return 1 if $self->in_range($net);
549             }
550 227         1915 return 0;
551             }
552              
553 1583 100 66     7943 if (blessed($range) && $range->isa('Net::IP::Lite::Net')) {
554 414         1183 return $range->contains($self);
555             }
556              
557 1169         2423 return _ip_in_range($self->binary, $range, $self->address);
558             }
559              
560             package Net::IP::Lite::Net;
561 23     23   251 use Carp qw(croak);
  23         46  
  23         1459  
562 23     23   149 use Scalar::Util qw(blessed);
  23         55  
  23         1418  
563              
564 23     23   126 use base qw(Net::IP::Lite);
  23         54  
  23         17791  
565              
566             sub new {
567 1104     1104   262347 my ($class, $net) = @_;
568              
569 1104 100       3006 return 0 unless defined $net;
570              
571 1103         1707 my $self = {};
572 1103         1317 my $bin_mask;
573              
574 1103 100       6194 if ($net =~ /^(.+)\/(\d+)$/) {
    100          
575 511         1132 my $mask = $2;
576 511         1618 $self = $class->SUPER::new($1);
577              
578 511 100       1390 my $mask_len = $self->is_ipv4() ? 32 : 128;
579 511 100       1661 return 0 if $mask > $mask_len;
580              
581 509         1724 $bin_mask = '1' x $mask . '0' x ($mask_len - $mask);
582             } elsif ($net =~ /^(\S+)\s+(\S+)$/) {
583 454         1402 $self = $class->SUPER::new($1);
584 454 100       1162 return 0 unless $self;
585 453         1085 $self->{mask} = Net::IP::Lite->new($2);
586             } else {
587 138         431 $self = $class->SUPER::new($net);
588 138 100       405 return 0 unless $self;
589 77 100       173 $bin_mask = '1' x ($self->is_ipv4 ? 32 : 128);
590             }
591              
592 1039 100       2767 if ($bin_mask) {
593 586 100       1270 if (length($bin_mask) == 32) {
594 312         719 $self->{mask} = Net::IP::Lite->new(Net::IP::Lite::_bin2ipv4($bin_mask));
595             } else {
596 274         809 $self->{mask} = Net::IP::Lite->new(Net::IP::Lite::_bin2ipv6($bin_mask));
597             }
598             }
599              
600 1039 100       2910 return 0 unless $self->{mask};
601              
602 1002         2443 my $ipv4_mask = $self->{mask}->is_ipv4;
603 1002 100 100     2492 return 0 unless (($self->is_ipv4 && $ipv4_mask) || ($self->is_ipv6 && ! $ipv4_mask));
      100        
      66        
604              
605 999         3859 $self->{net} = $net;
606 999         2765 return $self;
607             }
608              
609             sub mask {
610 962     962   2204 my ($self) = @_;
611 962         2215 return $self->{mask};
612             }
613              
614             sub network {
615 0     0   0 my ($self) = @_;
616 0         0 return $self->{net};
617             }
618              
619             sub contains {
620 828     828   2042 my ($self, $addr) = @_;
621              
622 828 100 66     5100 if (blessed($addr) && $addr->isa('Net::IP::Lite')) {
623 414 100       896 return 0 unless Net::IP::Lite::_ip_type_equal($self->binary, $addr->binary);
624 406         1037 return Net::IP::Lite::__ip_in_range($addr->binary, $self->binary, $self->mask->binary);
625             } else {
626 414         791 my $bin_addr = Net::IP::Lite::ip2bin($addr);
627 414 50       958 croak Net::IP::Lite::_wrong_ip($addr) unless Net::IP::Lite::_ip_validate($bin_addr);
628 414 100       9086 return 0 unless Net::IP::Lite::_ip_type_equal($self->binary, $bin_addr);
629 406         977 return Net::IP::Lite::__ip_in_range($bin_addr, $self->binary, $self->mask->binary);
630             }
631             }
632              
633              
634             1;
635              
636             __END__