| 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__ |