File Coverage

blib/lib/Geo/IP2Proxy.pm
Criterion Covered Total %
statement 330 712 46.3
branch 69 322 21.4
condition 44 132 33.3
subroutine 47 67 70.1
pod 20 37 54.0
total 510 1270 40.1


line stmt bran cond sub pod time code
1             #MIT License
2             #
3             #Copyright (c) 2021 IP2Location.com
4             #
5             #Permission is hereby granted, free of charge, to any person obtaining a copy
6             #of this software and associated documentation files (the "Software"), to deal
7             #in the Software without restriction, including without limitation the rights
8             #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9             #copies of the Software, and to permit persons to whom the Software is
10             #furnished to do so, subject to the following conditions:
11             #
12             #The above copyright notice and this permission notice shall be included in all
13             #copies or substantial portions of the Software.
14             #
15             #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16             #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17             #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18             #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19             #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20             #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21             #SOFTWARE.
22              
23             package Geo::IP2Proxy;
24              
25 3     3   16548 use strict;
  3         19  
  3         108  
26 3     3   17 use vars qw(@ISA $VERSION @EXPORT);
  3         5  
  3         203  
27 3     3   11821 use Math::BigInt;
  3         74239  
  3         15  
28              
29             $VERSION = '3.20';
30              
31             require Exporter;
32             @ISA = qw(Exporter);
33              
34 3     3   73915 use constant UNKNOWN => "UNKNOWN IP ADDRESS";
  3         7  
  3         171  
35 3     3   17 use constant IPV6_ADDRESS_IN_IPV4_BIN => "IPV6 ADDRESS MISSING IN IPV4 BIN";
  3         6  
  3         122  
36 3     3   15 use constant NO_IP => "MISSING IP ADDRESS";
  3         4  
  3         6495  
37 3     3   25 use constant INVALID_IPV6_ADDRESS => "INVALID IPV6 ADDRESS";
  3         7  
  3         165  
38 3     3   16 use constant INVALID_IPV4_ADDRESS => "INVALID IPV4 ADDRESS";
  3         6  
  3         108  
39 3     3   21 use constant INVALID_IP_ADDRESS => "INVALID IP ADDRESS";
  3         5  
  3         106  
40 3     3   16 use constant INVALID_BIN_DATABASE => "Incorrect IP2Proxy BIN file format. Please make sure that you are using the latest IP2Proxy BIN file.";
  3         6  
  3         146  
41 3     3   15 use constant NOT_SUPPORTED => "NOT SUPPORTED";
  3         7  
  3         143  
42 3     3   17 use constant MAX_IPV4_RANGE => 4294967295;
  3         4  
  3         127  
43 3     3   16 use constant MAX_IPV6_RANGE => 340282366920938463463374607431768211455;
  3         6  
  3         156  
44              
45 3     3   17 use constant COUNTRYSHORT => 1;
  3         5  
  3         122  
46 3     3   14 use constant COUNTRYLONG => 2;
  3         5  
  3         152  
47 3     3   16 use constant REGION => 3;
  3         4  
  3         192  
48 3     3   17 use constant CITY => 4;
  3         5  
  3         108  
49 3     3   14 use constant ISP => 5;
  3         5  
  3         130  
50 3     3   15 use constant PROXYTYPE => 6;
  3         5  
  3         118  
51 3     3   25 use constant ISPROXY => 7;
  3         4  
  3         104  
52 3     3   14 use constant DOMAIN => 8;
  3         5  
  3         149  
53 3     3   16 use constant USAGETYPE => 9;
  3         4  
  3         199  
54 3     3   17 use constant ASN => 10;
  3         4  
  3         136  
55 3     3   17 use constant AS => 11;
  3         4  
  3         113  
56 3     3   13 use constant LASTSEEN => 12;
  3         6  
  3         113  
57 3     3   14 use constant THREAT => 13;
  3         12  
  3         133  
58 3     3   15 use constant PROVIDER => 14;
  3         4  
  3         138  
59              
60 3     3   16 use constant ALL => 100;
  3         5  
  3         156  
61 3     3   15 use constant IPV4 => 0;
  3         5  
  3         1927  
62 3     3   15 use constant IPV6 => 1;
  3         10  
  3         20909  
63              
64             my @IPV4_COUNTRY_POSITION = (0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
65             my @IPV4_REGION_POSITION = (0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4);
66             my @IPV4_CITY_POSITION = (0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5);
67             my @IPV4_ISP_POSITION = (0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6);
68             my @IPV4_PROXYTYPE_POSITION = (0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2);
69             my @IPV4_DOMAIN_POSITION = (0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7);
70             my @IPV4_USAGETYPE_POSITION = (0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8);
71             my @IPV4_ASN_POSITION = (0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9);
72             my @IPV4_AS_POSITION = (0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10);
73             my @IPV4_LASTSEEN_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11);
74             my @IPV4_THREAT_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12);
75             my @IPV4_PROVIDER_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13);
76              
77             my @IPV6_COUNTRY_POSITION = (0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
78             my @IPV6_REGION_POSITION = (0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4);
79             my @IPV6_CITY_POSITION = (0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5);
80             my @IPV6_ISP_POSITION = (0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6);
81             my @IPV6_PROXYTYPE_POSITION = (0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2);
82             my @IPV6_DOMAIN_POSITION = (0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7);
83             my @IPV6_USAGETYPE_POSITION = (0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8);
84             my @IPV6_ASN_POSITION = (0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9);
85             my @IPV6_AS_POSITION = (0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10);
86             my @IPV6_LASTSEEN_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11);
87             my @IPV6_THREAT_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12);
88             my @IPV6_PROVIDER_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13);
89              
90             my $IPv6_re = qr/:(?::[0-9a-fA-F]{1,4}){0,5}(?:(?::[0-9a-fA-F]{1,4}){1,2}|:(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})))|[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}|:)|(?::(?:[0-9a-fA-F]{1,4})?|(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))))|:(?:(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4})?|))|(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|:[0-9a-fA-F]{1,4}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){0,2})|:))|(?:(?::[0-9a-fA-F]{1,4}){0,2}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){1,2})|:))|(?:(?::[0-9a-fA-F]{1,4}){0,3}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){1,2})|:))|(?:(?::[0-9a-fA-F]{1,4}){0,4}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){1,2})|:))/;
91             my $IPv4_re = qr/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
92              
93             my $getLastErrorMessage = "";
94              
95             sub open {
96 2 50 33 2 1 39 unless( (@_ > 1) && ($_[1]) ) {
97 0         0 $getLastErrorMessage = "Geo::IP2Proxy::open() requires a database path name.";
98 0         0 die "Geo::IP2Proxy::open() requires a database path name";
99             }
100 2         7 my ($class, $db_file) = @_;
101 2         3 my $handle;
102             my $obj;
103 2 50       82 unless (CORE::open $handle, "$db_file") {
104 0         0 $getLastErrorMessage = "Geo::IP2Proxy::open() error in opening $db_file" . ".";
105 0         0 die "Geo::IP2Proxy::open() error in opening $db_file";
106             }
107 2         10 binmode($handle);
108 2         11 $obj = bless {filehandle => $handle}, $class;
109 2         9 $obj->initialize();
110 2 50       8 if ($obj->{"productcode"} == 2) {
111             } else {
112 2 50 33     15 if (($obj->{"databaseyear"} <= 20) && ($obj->{"productcode"} == 0)) {
113             } else {
114 0         0 $obj->close();
115 0         0 undef $obj;
116 0         0 $getLastErrorMessage = INVALID_BIN_DATABASE;
117 0         0 die INVALID_BIN_DATABASE;
118             }
119             }
120 2         7 return $obj;
121             }
122              
123             sub close {
124 0     0 0 0 my ($class) = @_;
125 0 0       0 if (CORE::close($class->{filehandle})) {
126 0         0 return 0;
127             } else {
128 0         0 return 1;
129             }
130             }
131              
132             sub initialize {
133 2     2 0 7 my ($obj) = @_;
134 2         20 $obj->{"databasetype"} = $obj->read8($obj->{filehandle}, 1);
135 2         9 $obj->{"databasecolumn"} = $obj->read8($obj->{filehandle}, 2);
136 2         8 $obj->{"databaseyear"} = $obj->read8($obj->{filehandle}, 3);
137 2         8 $obj->{"databasemonth"} = $obj->read8($obj->{filehandle}, 4);
138 2         8 $obj->{"databaseday"} = $obj->read8($obj->{filehandle}, 5);
139 2         42 $obj->{"ipv4databasecount"} = $obj->read32($obj->{filehandle}, 6);
140 2         9 $obj->{"ipv4databaseaddr"} = $obj->read32($obj->{filehandle}, 10);
141 2         8 $obj->{"ipv6databasecount"} = $obj->read32($obj->{filehandle}, 14);
142 2         16 $obj->{"ipv6databaseaddr"} = $obj->read32($obj->{filehandle}, 18);
143 2         6 $obj->{"ipv4indexbaseaddr"} = $obj->read32($obj->{filehandle}, 22);
144 2         7 $obj->{"ipv6indexbaseaddr"} = $obj->read32($obj->{filehandle}, 26);
145 2         7 $obj->{"productcode"} = $obj->read8($obj->{filehandle}, 30);
146 2         7 $obj->{"licensecode"} = $obj->read8($obj->{filehandle}, 31);
147 2         6 $obj->{"databasesize"} = $obj->read32($obj->{filehandle}, 32);
148 2         6 return $obj;
149             }
150              
151             sub get_last_error_message {
152 0     0 1 0 my $class = shift(@_);
153 0         0 return ($getLastErrorMessage);
154             }
155              
156             sub getModuleVersion {
157 0     0 1 0 my $obj = shift(@_);
158 0         0 return $VERSION;
159             }
160              
161             sub getPackageVersion {
162 0     0 1 0 my $obj = shift(@_);
163 0         0 return $obj->{"databasetype"};
164             }
165              
166             sub getDatabaseVersion {
167 0     0 1 0 my $obj = shift(@_);
168 0         0 my $databaseyear = 2000 + $obj->{"databaseyear"};
169 0         0 return $databaseyear . "." . $obj->{"databasemonth"} . "." . $obj->{"databaseday"};
170             }
171              
172             sub getCountryShort {
173 6     6 1 10146 my $obj = shift(@_);
174 6         14 my $ipaddr = shift(@_);
175 6         24 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
176 6 100       19 if ($ipv == 4) {
177 3         12 return $obj->getIPv4Record($ipnum, COUNTRYSHORT);
178             } else {
179 3 50       8 if ($ipv == 6) {
180 3         18 return $obj->getIPv6Record($ipnum, COUNTRYSHORT);
181             } else {
182 0         0 return INVALID_IP_ADDRESS;
183             }
184             }
185             }
186              
187             sub getCountryLong {
188 0     0 1 0 my $obj = shift(@_);
189 0         0 my $ipaddr = shift(@_);
190 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
191 0 0       0 if ($ipv == 4) {
192 0         0 return $obj->getIPv4Record($ipnum, COUNTRYLONG);
193             } else {
194 0 0       0 if ($ipv == 6) {
195 0         0 return $obj->getIPv6Record($ipnum, COUNTRYLONG);
196             } else {
197 0         0 return INVALID_IP_ADDRESS;
198             }
199             }
200             }
201              
202             sub getRegion {
203 0     0 1 0 my $obj = shift(@_);
204 0         0 my $ipaddr = shift(@_);
205 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
206 0 0       0 if ($ipv == 4) {
207 0         0 return $obj->getIPv4Record($ipnum, REGION);
208             } else {
209 0 0       0 if ($ipv == 6) {
210 0         0 return $obj->getIPv6Record($ipnum, REGION);
211             } else {
212 0         0 return INVALID_IP_ADDRESS;
213             }
214             }
215             }
216              
217             sub getCity {
218 0     0 1 0 my $obj = shift(@_);
219 0         0 my $ipaddr = shift(@_);
220 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
221 0 0       0 if ($ipv == 4) {
222 0         0 return $obj->getIPv4Record($ipnum, CITY);
223             } else {
224 0 0       0 if ($ipv == 6) {
225 0         0 return $obj->getIPv6Record($ipnum, CITY);
226             } else {
227 0         0 return INVALID_IP_ADDRESS;
228             }
229             }
230             }
231              
232             sub getISP {
233 0     0 1 0 my $obj = shift(@_);
234 0         0 my $ipaddr = shift(@_);
235 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
236 0 0       0 if ($ipv == 4) {
237 0         0 return $obj->getIPv4Record($ipnum, ISP);
238             } else {
239 0 0       0 if ($ipv == 6) {
240 0         0 return $obj->getIPv6Record($ipnum, ISP);
241             } else {
242 0         0 return INVALID_IP_ADDRESS;
243             }
244             }
245             }
246              
247             sub getProxyType {
248 0     0 1 0 my $obj = shift(@_);
249 0         0 my $ipaddr = shift(@_);
250 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
251 0 0       0 if ($ipv == 4) {
252 0         0 return $obj->getIPv4Record($ipnum, PROXYTYPE);
253             } else {
254 0 0       0 if ($ipv == 6) {
255 0         0 return $obj->getIPv6Record($ipnum, PROXYTYPE);
256             } else {
257 0         0 return INVALID_IP_ADDRESS;
258             }
259             }
260             }
261              
262             sub isProxy {
263 0     0 1 0 my $obj = shift(@_);
264 0         0 my $ipaddr = shift(@_);
265 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
266 0 0       0 if ($ipv == 4) {
267 0         0 return $obj->getIPv4Record($ipnum, ISPROXY);
268             } else {
269 0 0       0 if ($ipv == 6) {
270 0         0 return $obj->getIPv6Record($ipnum, ISPROXY);
271             } else {
272 0         0 return -1;
273             }
274             }
275             }
276              
277             sub getDomain {
278 0     0 1 0 my $obj = shift(@_);
279 0         0 my $ipaddr = shift(@_);
280 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
281 0 0       0 if ($ipv == 4) {
282 0         0 return $obj->getIPv4Record($ipnum, DOMAIN);
283             } else {
284 0 0       0 if ($ipv == 6) {
285 0         0 return $obj->getIPv6Record($ipnum, DOMAIN);
286             } else {
287 0         0 return INVALID_IP_ADDRESS;
288             }
289             }
290             }
291              
292             sub getUsageType {
293 0     0 1 0 my $obj = shift(@_);
294 0         0 my $ipaddr = shift(@_);
295 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
296 0 0       0 if ($ipv == 4) {
297 0         0 return $obj->getIPv4Record($ipnum, USAGETYPE);
298             } else {
299 0 0       0 if ($ipv == 6) {
300 0         0 return $obj->getIPv6Record($ipnum, USAGETYPE);
301             } else {
302 0         0 return INVALID_IP_ADDRESS;
303             }
304             }
305             }
306              
307             sub getASN {
308 0     0 1 0 my $obj = shift(@_);
309 0         0 my $ipaddr = shift(@_);
310 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
311 0 0       0 if ($ipv == 4) {
312 0         0 return $obj->getIPv4Record($ipnum, ASN);
313             } else {
314 0 0       0 if ($ipv == 6) {
315 0         0 return $obj->getIPv6Record($ipnum, ASN);
316             } else {
317 0         0 return INVALID_IP_ADDRESS;
318             }
319             }
320             }
321              
322             sub getAS {
323 0     0 1 0 my $obj = shift(@_);
324 0         0 my $ipaddr = shift(@_);
325 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
326 0 0       0 if ($ipv == 4) {
327 0         0 return $obj->getIPv4Record($ipnum, AS);
328             } else {
329 0 0       0 if ($ipv == 6) {
330 0         0 return $obj->getIPv6Record($ipnum, AS);
331             } else {
332 0         0 return INVALID_IP_ADDRESS;
333             }
334             }
335             }
336              
337             sub getLastSeen {
338 0     0 1 0 my $obj = shift(@_);
339 0         0 my $ipaddr = shift(@_);
340 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
341 0 0       0 if ($ipv == 4) {
342 0         0 return $obj->getIPv4Record($ipnum, LASTSEEN);
343             } else {
344 0 0       0 if ($ipv == 6) {
345 0         0 return $obj->getIPv6Record($ipnum, LASTSEEN);
346             } else {
347 0         0 return INVALID_IP_ADDRESS;
348             }
349             }
350             }
351              
352             sub getThreat {
353 0     0 1 0 my $obj = shift(@_);
354 0         0 my $ipaddr = shift(@_);
355 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
356 0 0       0 if ($ipv == 4) {
357 0         0 return $obj->getIPv4Record($ipnum, THREAT);
358             } else {
359 0 0       0 if ($ipv == 6) {
360 0         0 return $obj->getIPv6Record($ipnum, THREAT);
361             } else {
362 0         0 return INVALID_IP_ADDRESS;
363             }
364             }
365             }
366              
367             sub getProvider {
368 0     0 1 0 my $obj = shift(@_);
369 0         0 my $ipaddr = shift(@_);
370 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
371 0 0       0 if ($ipv == 4) {
372 0         0 return $obj->getIPv4Record($ipnum, PROVIDER);
373             } else {
374 0 0       0 if ($ipv == 6) {
375 0         0 return $obj->getIPv6Record($ipnum, PROVIDER);
376             } else {
377 0         0 return INVALID_IP_ADDRESS;
378             }
379             }
380             }
381              
382             sub getAll {
383 0     0 1 0 my $obj = shift(@_);
384 0         0 my $ipaddr = shift(@_);
385 0         0 my ($ipv, $ipnum) = $obj->validateIP($ipaddr);
386 0 0       0 if ($ipv == 4) {
387 0         0 return $obj->getIPv4Record($ipnum, ALL);
388             } else {
389 0 0       0 if ($ipv == 6) {
390 0         0 return $obj->getIPv6Record($ipnum, ALL);
391             } else {
392 0         0 return (-1, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS);
393             }
394             }
395             }
396              
397             sub getIPv6Record {
398 3     3 0 7 my $obj = shift(@_);
399 3         6 my $ipnum = shift(@_);
400 3         6 my $mode = shift(@_);
401 3         10 my $dbtype = $obj->{"databasetype"};
402              
403 3 50       13 if ($ipnum eq "") {
404 0 0       0 if ($mode == ALL) {
405 0         0 return (-1, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP);
406             } else {
407 0 0       0 if ($mode == ISPROXY) {
408 0         0 return -1;
409             } else {
410 0         0 return NO_IP;
411             }
412             }
413             }
414              
415 3 50 33     92 if (($mode == COUNTRYSHORT) && ($IPV6_COUNTRY_POSITION[$dbtype] == 0)) {
416 0         0 return NOT_SUPPORTED;
417             }
418 3 50 33     15 if (($mode == COUNTRYLONG) && ($IPV6_COUNTRY_POSITION[$dbtype] == 0)) {
419 0         0 return NOT_SUPPORTED;
420             }
421 3 50 33     14 if (($mode == REGION) && ($IPV6_REGION_POSITION[$dbtype] == 0)) {
422 0         0 return NOT_SUPPORTED;
423             }
424 3 50 33     19 if (($mode == CITY) && ($IPV6_CITY_POSITION[$dbtype] == 0)) {
425 0         0 return NOT_SUPPORTED;
426             }
427 3 50 33     13 if (($mode == ISP) && ($IPV6_ISP_POSITION[$dbtype] == 0)) {
428 0         0 return NOT_SUPPORTED;
429             }
430 3 50 33     10 if (($mode == PROXYTYPE) && ($IPV6_PROXYTYPE_POSITION[$dbtype] == 0)) {
431 0         0 return NOT_SUPPORTED;
432             }
433 3 50 33     11 if (($mode == DOMAIN) && ($IPV6_DOMAIN_POSITION[$dbtype] == 0)) {
434 0         0 return NOT_SUPPORTED;
435             }
436 3 50 33     8 if (($mode == USAGETYPE) && ($IPV6_USAGETYPE_POSITION[$dbtype] == 0)) {
437 0         0 return NOT_SUPPORTED;
438             }
439 3 50 33     11 if (($mode == ASN) && ($IPV6_ASN_POSITION[$dbtype] == 0)) {
440 0         0 return NOT_SUPPORTED;
441             }
442 3 50 33     18 if (($mode == AS) && ($IPV6_AS_POSITION[$dbtype] == 0)) {
443 0         0 return NOT_SUPPORTED;
444             }
445 3 50 33     11 if (($mode == LASTSEEN) && ($IPV6_LASTSEEN_POSITION[$dbtype] == 0)) {
446 0         0 return NOT_SUPPORTED;
447             }
448 3 50 33     9 if (($mode == THREAT) && ($IPV6_THREAT_POSITION[$dbtype] == 0)) {
449 0         0 return NOT_SUPPORTED;
450             }
451 3 50 33     8 if (($mode == PROVIDER) && ($IPV6_PROVIDER_POSITION[$dbtype] == 0)) {
452 0         0 return NOT_SUPPORTED;
453             }
454              
455 3         10 my $realipno = Math::BigInt->new($ipnum);
456 3         133 my $handle = $obj->{"filehandle"};
457 3         9 my $baseaddr = $obj->{"ipv6databaseaddr"};
458 3         5 my $dbcount = $obj->{"ipv6databasecount"};
459 3         6 my $dbcolumn = $obj->{"databasecolumn"};
460 3         8 my $indexbaseaddr = $obj->{"ipv6indexbaseaddr"};
461              
462 3 50       7 if ($dbcount == 0) {
463 0 0       0 if ($mode == ALL) {
464 0         0 return (IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN);
465             } else {
466 0         0 return IPV6_ADDRESS_IN_IPV4_BIN;
467             }
468             }
469              
470 3         7 my $ipnum1_2 = new Math::BigInt($ipnum);
471 3         84 my $remainder = 0;
472 3         14 ($ipnum1_2, $remainder) = $ipnum1_2->bdiv(2**112);
473 3         1342 my $indexaddr = $indexbaseaddr + ($ipnum1_2 << 3);
474              
475 3         988 my $low = 0;
476 3         6 my $high = $dbcount;
477 3 50       9 if ($indexbaseaddr > 0) {
478 3         13 $low = $obj->read32($handle, $indexaddr);
479 3         20 $high = $obj->read32($handle, $indexaddr + 4);
480             }
481              
482 3         11 my $mid = 0;
483 3         5 my $ipfrom = 0;
484 3         4 my $ipto = 0;
485 3         65 my $ipno = 0;
486              
487 3         8 $ipno = $realipno;
488 3 50       11 if ($realipno == "340282366920938463463374607431768211455") {
489 0         0 $ipno = $ipno->bsub(1);
490             }
491              
492 3         359 while ($low <= $high) {
493 4         9 $mid = int(($low + $high)/2);
494 4         16 $ipfrom = $obj->read128($handle, $baseaddr + $mid * (($dbcolumn * 4) + 12));
495 4         101 $ipto = $obj->read128($handle, $baseaddr + ($mid + 1) * (($dbcolumn * 4) + 12));
496 4 100 66     92 if (($ipno >= $ipfrom) && ($ipno < $ipto)) {
497 3         599 my $row_pointer = $baseaddr + $mid * (($dbcolumn * 4) + 12);
498             # read whole results string into temp string and parse results from memory
499 3         6 my $raw_positions_row;
500 3         45 seek($handle, $row_pointer - 1, 0);
501 3         32 read($handle, $raw_positions_row, $dbcolumn * 4 + 12);
502              
503 3 50       13 if ($mode == ALL) {
504 0         0 my $countryshort = NOT_SUPPORTED;
505 0         0 my $countrylong = NOT_SUPPORTED;
506 0         0 my $region = NOT_SUPPORTED;
507 0         0 my $city = NOT_SUPPORTED;
508 0         0 my $isp = NOT_SUPPORTED;
509 0         0 my $proxytype = NOT_SUPPORTED;
510 0         0 my $domain = NOT_SUPPORTED;
511 0         0 my $usagetype = NOT_SUPPORTED;
512 0         0 my $asn = NOT_SUPPORTED;
513 0         0 my $as = NOT_SUPPORTED;
514 0         0 my $lastseen = NOT_SUPPORTED;
515 0         0 my $threat = NOT_SUPPORTED;
516 0         0 my $provider = NOT_SUPPORTED;
517 0         0 my $isproxy = -1;
518            
519 0 0       0 if ($IPV6_COUNTRY_POSITION[$dbtype] != 0) {
520 0         0 $countryshort = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_COUNTRY_POSITION[$dbtype]), 4)));
521 0         0 $countrylong = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_COUNTRY_POSITION[$dbtype]), 4)) + 3);
522             }
523 0 0       0 if ($IPV6_REGION_POSITION[$dbtype] != 0) {
524 0         0 $region = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_REGION_POSITION[$dbtype]), 4)));
525             }
526 0 0       0 if ($IPV6_CITY_POSITION[$dbtype] != 0) {
527 0         0 $city = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_CITY_POSITION[$dbtype]), 4)));
528             }
529 0 0       0 if ($IPV6_ISP_POSITION[$dbtype] != 0) {
530 0         0 $isp = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_ISP_POSITION[$dbtype]), 4)));
531             }
532 0 0       0 if ($IPV6_PROXYTYPE_POSITION[$dbtype] != 0) {
533 0         0 $proxytype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_PROXYTYPE_POSITION[$dbtype]), 4)));
534             }
535 0 0       0 if ($IPV6_DOMAIN_POSITION[$dbtype] != 0) {
536 0         0 $domain = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_DOMAIN_POSITION[$dbtype]), 4)));
537             }
538 0 0       0 if ($IPV6_USAGETYPE_POSITION[$dbtype] != 0) {
539 0         0 $usagetype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_USAGETYPE_POSITION[$dbtype]), 4)));
540             }
541 0 0       0 if ($IPV6_ASN_POSITION[$dbtype] != 0) {
542 0         0 $asn = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_ASN_POSITION[$dbtype]), 4)));
543             }
544 0 0       0 if ($IPV6_AS_POSITION[$dbtype] != 0) {
545 0         0 $as = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_AS_POSITION[$dbtype]), 4)));
546             }
547 0 0       0 if ($IPV6_LASTSEEN_POSITION[$dbtype] != 0) {
548 0         0 $lastseen = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_LASTSEEN_POSITION[$dbtype]), 4)));
549             }
550 0 0       0 if ($IPV6_THREAT_POSITION[$dbtype] != 0) {
551 0         0 $threat = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_THREAT_POSITION[$dbtype]), 4)));
552             }
553 0 0       0 if ($IPV6_PROVIDER_POSITION[$dbtype] != 0) {
554 0         0 $threat = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_PROVIDER_POSITION[$dbtype]), 4)));
555             }
556              
557 0 0 0     0 if (($countryshort eq "-") || ($proxytype eq "-")) {
558 0         0 $isproxy = 0;
559             } else {
560 0 0 0     0 if (($proxytype eq "DCH") || ($proxytype eq "SES")) {
561 0         0 $isproxy = 2;
562             } else {
563 0         0 $isproxy = 1;
564             }
565             }
566 0         0 return ($isproxy, $proxytype, $countryshort, $countrylong, $region, $city, $isp, $domain, $usagetype, $asn, $as, $lastseen, $threat, $provider);
567             }
568 3 50       10 if ($mode == COUNTRYSHORT) {
569 3         25 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_COUNTRY_POSITION[$dbtype]), 4)));
570             }
571 0 0       0 if ($mode == COUNTRYLONG) {
572 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_COUNTRY_POSITION[$dbtype]), 4)) + 3);
573             }
574 0 0       0 if ($mode == REGION) {
575 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_REGION_POSITION[$dbtype]), 4)));
576             }
577 0 0       0 if ($mode == CITY) {
578 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_CITY_POSITION[$dbtype]), 4)));
579             }
580 0 0       0 if ($mode == ISP) {
581 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_ISP_POSITION[$dbtype]), 4)));
582             }
583 0 0       0 if ($mode == PROXYTYPE) {
584 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_PROXYTYPE_POSITION[$dbtype]), 4)));
585             }
586 0 0       0 if ($mode == DOMAIN) {
587 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_DOMAIN_POSITION[$dbtype]), 4)));
588             }
589 0 0       0 if ($mode == USAGETYPE) {
590 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_USAGETYPE_POSITION[$dbtype]), 4)));
591             }
592 0 0       0 if ($mode == ASN) {
593 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_ASN_POSITION[$dbtype]), 4)));
594             }
595 0 0       0 if ($mode == AS) {
596 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_AS_POSITION[$dbtype]), 4)));
597             }
598 0 0       0 if ($mode == LASTSEEN) {
599 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_LASTSEEN_POSITION[$dbtype]), 4)));
600             }
601 0 0       0 if ($mode == THREAT) {
602 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_THREAT_POSITION[$dbtype]), 4)));
603             }
604 0 0       0 if ($mode == PROVIDER) {
605 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_PROVIDER_POSITION[$dbtype]), 4)));
606             }
607              
608 0 0       0 if ($mode == ISPROXY) {
609 0         0 my $countryshort = NOT_SUPPORTED;
610 0         0 my $proxytype = NOT_SUPPORTED;
611 0         0 my $isproxy = NOT_SUPPORTED;
612 0 0       0 if ($IPV6_PROXYTYPE_POSITION[$dbtype] == 0) {
613             # PX1, use country as detection
614 0         0 $countryshort = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_COUNTRY_POSITION[$dbtype]), 4)));
615             } else {
616 0         0 $proxytype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 8 + 4 * ($IPV6_PROXYTYPE_POSITION[$dbtype]), 4)));
617             }
618 0 0 0     0 if (($countryshort eq "-") || ($proxytype eq "-")) {
619 0         0 $isproxy = 0;
620             } else {
621 0 0 0     0 if (($proxytype eq "DCH") || ($proxytype eq "SES")) {
622 0         0 $isproxy = 2;
623             } else {
624 0         0 $isproxy = 1;
625             }
626             }
627 0         0 return $isproxy;
628             }
629             } else {
630 1 50       96 if ($ipno < $ipfrom) {
631 1         88 $high = $mid - 1;
632             } else {
633 0         0 $low = $mid + 1;
634             }
635             }
636             }
637 0 0       0 if ($mode == ALL) {
638 0         0 return (-1, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
639             } else {
640 0 0       0 if ($mode == ISPROXY) {
641 0         0 return -1;
642             } else {
643 0         0 return UNKNOWN;
644             }
645             }
646             }
647              
648             sub getIPv4Record {
649 3     3 0 6 my $obj = shift(@_);
650 3         5 my $ipnum = shift(@_);
651 3         3 my $mode = shift(@_);
652 3         8 my $dbtype= $obj->{"databasetype"};
653              
654 3 50       8 if ($ipnum eq "") {
655 0 0       0 if ($mode == ALL) {
656 0         0 return (-1, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP);
657             } else {
658 0 0       0 if ($mode == ISPROXY) {
659 0         0 return -1;
660             } else {
661 0         0 return NO_IP;
662             }
663             }
664             }
665            
666 3 50 33     13 if (($mode == COUNTRYSHORT) && ($IPV4_COUNTRY_POSITION[$dbtype] == 0)) {
667 0         0 return NOT_SUPPORTED;
668             }
669 3 50 33     17 if (($mode == COUNTRYLONG) && ($IPV4_COUNTRY_POSITION[$dbtype] == 0)) {
670 0         0 return NOT_SUPPORTED;
671             }
672 3 50 33     8 if (($mode == REGION) && ($IPV4_REGION_POSITION[$dbtype] == 0)) {
673 0         0 return NOT_SUPPORTED;
674             }
675 3 50 33     9 if (($mode == CITY) && ($IPV4_CITY_POSITION[$dbtype] == 0)) {
676 0         0 return NOT_SUPPORTED;
677             }
678 3 50 33     7 if (($mode == ISP) && ($IPV4_ISP_POSITION[$dbtype] == 0)) {
679 0         0 return NOT_SUPPORTED;
680             }
681 3 50 33     8 if (($mode == PROXYTYPE) && ($IPV4_PROXYTYPE_POSITION[$dbtype] == 0)) {
682 0         0 return NOT_SUPPORTED;
683             }
684 3 50 33     8 if (($mode == DOMAIN) && ($IPV4_DOMAIN_POSITION[$dbtype] == 0)) {
685 0         0 return NOT_SUPPORTED;
686             }
687 3 50 33     9 if (($mode == USAGETYPE) && ($IPV4_USAGETYPE_POSITION[$dbtype] == 0)) {
688 0         0 return NOT_SUPPORTED;
689             }
690 3 50 33     6 if (($mode == ASN) && ($IPV4_ASN_POSITION[$dbtype] == 0)) {
691 0         0 return NOT_SUPPORTED;
692             }
693 3 50 33     16 if (($mode == AS) && ($IPV4_AS_POSITION[$dbtype] == 0)) {
694 0         0 return NOT_SUPPORTED;
695             }
696 3 50 33     18 if (($mode == LASTSEEN) && ($IPV4_LASTSEEN_POSITION[$dbtype] == 0)) {
697 0         0 return NOT_SUPPORTED;
698             }
699 3 50 33     9 if (($mode == THREAT) && ($IPV4_THREAT_POSITION[$dbtype] == 0)) {
700 0         0 return NOT_SUPPORTED;
701             }
702 3 50 33     8 if (($mode == PROVIDER) && ($IPV4_PROVIDER_POSITION[$dbtype] == 0)) {
703 0         0 return NOT_SUPPORTED;
704             }
705              
706 3         5 my $realipno = $ipnum;
707 3         7 my $handle = $obj->{"filehandle"};
708 3         5 my $baseaddr = $obj->{"ipv4databaseaddr"};
709 3         4 my $dbcount = $obj->{"ipv4databasecount"};
710 3         4 my $dbcolumn = $obj->{"databasecolumn"};
711 3         4 my $indexbaseaddr = $obj->{"ipv4indexbaseaddr"};
712              
713 3         6 my $ipnum1_2 = int($ipnum >> 16);
714 3         5 my $indexaddr = $indexbaseaddr + ($ipnum1_2 << 3);
715              
716 3         4 my $low = 0;
717 3         5 my $high = $dbcount;
718 3 50       8 if ($indexbaseaddr > 0) {
719 3         9 $low = $obj->read32($handle, $indexaddr);
720 3         10 $high = $obj->read32($handle, $indexaddr + 4);
721             }
722 3         5 my $mid = 0;
723 3         3 my $ipfrom = 0;
724 3         5 my $ipto = 0;
725 3         4 my $ipno = 0;
726              
727 3 50       7 if ($realipno == MAX_IPV4_RANGE) {
728 0         0 $ipno = $realipno - 1;
729             } else {
730 3         5 $ipno = $realipno;
731             }
732              
733 3         15 while ($low <= $high) {
734 15         18 $mid = int(($low + $high) >> 1);
735 15         31 $ipfrom = $obj->read32($handle, $baseaddr + $mid * $dbcolumn * 4);
736 15         38 $ipto = $obj->read32($handle, $baseaddr + ($mid + 1) * $dbcolumn * 4);
737 15 100 100     43 if (($ipno >= $ipfrom) && ($ipno < $ipto)) {
738             # read whole results string into temp string and parse results from memory
739 3         5 my $raw_positions_row;
740 3         27 seek($handle, ($baseaddr + $mid * $dbcolumn * 4) - 1, 0);
741 3         23 read($handle, $raw_positions_row, $dbcolumn * 4);
742            
743 3 50       10 if ($mode == ALL) {
744 0         0 my $countryshort = NOT_SUPPORTED;
745 0         0 my $countrylong = NOT_SUPPORTED;
746 0         0 my $region = NOT_SUPPORTED;
747 0         0 my $city = NOT_SUPPORTED;
748 0         0 my $isp = NOT_SUPPORTED;
749 0         0 my $proxytype = NOT_SUPPORTED;
750 0         0 my $domain = NOT_SUPPORTED;
751 0         0 my $usagetype = NOT_SUPPORTED;
752 0         0 my $asn = NOT_SUPPORTED;
753 0         0 my $as = NOT_SUPPORTED;
754 0         0 my $lastseen = NOT_SUPPORTED;
755 0         0 my $threat = NOT_SUPPORTED;
756 0         0 my $provider = NOT_SUPPORTED;
757 0         0 my $isproxy = -1;
758              
759 0 0       0 if ($IPV4_COUNTRY_POSITION[$dbtype] != 0) {
760 0         0 my $pos = unpack("V", substr($raw_positions_row, 4 * ($IPV4_COUNTRY_POSITION[$dbtype]-1), 4));
761 0         0 $countryshort = $obj->readStr($handle, $pos);
762 0         0 $countrylong = $obj->readStr($handle, $pos + 3);
763             }
764 0 0       0 if ($IPV4_REGION_POSITION[$dbtype] != 0) {
765 0         0 $region = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_REGION_POSITION[$dbtype]-1), 4)));
766             }
767 0 0       0 if ($IPV4_CITY_POSITION[$dbtype] != 0) {
768 0         0 $city = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_CITY_POSITION[$dbtype]-1), 4)));
769             }
770 0 0       0 if ($IPV4_ISP_POSITION[$dbtype] != 0) {
771 0         0 $isp = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_ISP_POSITION[$dbtype]-1), 4)));
772             }
773 0 0       0 if ($IPV4_PROXYTYPE_POSITION[$dbtype] != 0) {
774 0         0 $proxytype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_PROXYTYPE_POSITION[$dbtype]-1), 4)));
775             }
776 0 0       0 if ($IPV4_DOMAIN_POSITION[$dbtype] != 0) {
777 0         0 $domain = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_DOMAIN_POSITION[$dbtype]-1), 4)));
778             }
779 0 0       0 if ($IPV4_USAGETYPE_POSITION[$dbtype] != 0) {
780 0         0 $usagetype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_USAGETYPE_POSITION[$dbtype]-1), 4)));
781             }
782 0 0       0 if ($IPV4_ASN_POSITION[$dbtype] != 0) {
783 0         0 $asn = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_ASN_POSITION[$dbtype]-1), 4)));
784             }
785 0 0       0 if ($IPV4_AS_POSITION[$dbtype] != 0) {
786 0         0 $as = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_AS_POSITION[$dbtype]-1), 4)));
787             }
788 0 0       0 if ($IPV4_LASTSEEN_POSITION[$dbtype] != 0) {
789 0         0 $lastseen = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_LASTSEEN_POSITION[$dbtype]-1), 4)));
790             }
791 0 0       0 if ($IPV4_THREAT_POSITION[$dbtype] != 0) {
792 0         0 $threat = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_THREAT_POSITION[$dbtype]-1), 4)));
793             }
794 0 0       0 if ($IPV4_PROVIDER_POSITION[$dbtype] != 0) {
795 0         0 $provider = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_PROVIDER_POSITION[$dbtype]-1), 4)));
796             }
797 0 0       0 if ($countryshort eq "-") {
798 0         0 $isproxy = 0;
799             } else {
800 0 0 0     0 if (($proxytype eq "DCH") || ($proxytype eq "SES")) {
801 0         0 $isproxy = 2;
802             } else {
803 0         0 $isproxy = 1;
804             }
805             }
806 0         0 return ($isproxy, $proxytype, $countryshort, $countrylong, $region, $city, $isp, $domain, $usagetype, $asn, $as, $lastseen, $threat, $provider);
807             }
808 3 50       8 if ($mode == COUNTRYSHORT) {
809 3         20 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_COUNTRY_POSITION[$dbtype]-1), 4)));
810             }
811 0 0       0 if ($mode == COUNTRYLONG) {
812 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_COUNTRY_POSITION[$dbtype]-1), 4))+3);
813             }
814 0 0       0 if ($mode == REGION) {
815 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_REGION_POSITION[$dbtype]-1), 4)));
816             }
817 0 0       0 if ($mode == CITY) {
818 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_CITY_POSITION[$dbtype]-1), 4)));
819             }
820 0 0       0 if ($mode == ISP) {
821 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_ISP_POSITION[$dbtype]-1), 4)));
822             }
823 0 0       0 if ($mode == PROXYTYPE) {
824 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_PROXYTYPE_POSITION[$dbtype]-1), 4)));
825             }
826 0 0       0 if ($mode == DOMAIN) {
827 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_DOMAIN_POSITION[$dbtype]-1), 4)));
828             }
829 0 0       0 if ($mode == USAGETYPE) {
830 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_USAGETYPE_POSITION[$dbtype]-1), 4)));
831             }
832 0 0       0 if ($mode == ASN) {
833 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_ASN_POSITION[$dbtype]-1), 4)));
834             }
835 0 0       0 if ($mode == AS) {
836 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_AS_POSITION[$dbtype]-1), 4)));
837             }
838 0 0       0 if ($mode == LASTSEEN) {
839 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_LASTSEEN_POSITION[$dbtype]-1), 4)));
840             }
841 0 0       0 if ($mode == THREAT) {
842 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_THREAT_POSITION[$dbtype]-1), 4)));
843             }
844 0 0       0 if ($mode == PROVIDER) {
845 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_PROVIDER_POSITION[$dbtype]-1), 4)));
846             }
847 0 0       0 if ($mode == ISPROXY) {
848 0         0 my $countryshort = NOT_SUPPORTED;
849 0         0 my $proxytype = NOT_SUPPORTED;
850 0         0 my $isproxy = NOT_SUPPORTED;
851 0 0       0 if ($IPV4_PROXYTYPE_POSITION[$dbtype] == 0) {
852             # PX1, use country as detection
853 0         0 $countryshort = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_COUNTRY_POSITION[$dbtype]-1), 4)));
854             } else {
855 0         0 $proxytype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV4_PROXYTYPE_POSITION[$dbtype]-1), 4)));
856             }
857 0 0 0     0 if (($countryshort eq "-") || ($proxytype eq "-")) {
858 0         0 $isproxy = 0;
859             } else {
860 0 0 0     0 if (($proxytype eq "DCH") || ($proxytype eq "SES")) {
861 0         0 $isproxy = 2;
862             } else {
863 0         0 $isproxy = 1;
864             }
865             }
866 0         0 return $isproxy;
867             }
868             } else {
869 12 100       17 if ($ipno < $ipfrom) {
870 9         18 $high = $mid - 1;
871             } else {
872 3         9 $low = $mid + 1;
873             }
874             }
875             }
876 0 0       0 if ($mode == ALL) {
877 0         0 return (-1, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
878             } else {
879 0 0       0 if ($mode == ISPROXY) {
880 0         0 return -1;
881             } else {
882 0         0 return UNKNOWN;
883             }
884             }
885             }
886              
887             sub read128 {
888 8     8 0 17 my ($obj, $handle, $position) = @_;
889 8         11 my $data = "";
890 8         91 seek($handle, $position-1, 0);
891 8         70 read($handle, $data, 16);
892 8         53 return &bytesInt($data);
893             }
894              
895             sub read32 {
896 56     56 0 473 my ($obj, $handle, $position) = @_;
897 56         69 my $data = "";
898 56         498 seek($handle, $position-1, 0);
899 56         1627 read($handle, $data, 4);
900 56         711 return unpack("V", $data);
901             }
902              
903             sub read8 {
904 14     14 0 27 my ($obj, $handle, $position) = @_;
905 14         17 my $data = "";
906 14         119 seek($handle, $position-1, 0);
907 14         171 read($handle, $data, 1);
908 14         65 return unpack("C", $data);
909             }
910              
911             sub readStr {
912 6     6 0 13 my ($obj, $handle, $position) = @_;
913 6         9 my $data = "";
914 6         8 my $string = "";
915 6         58 seek($handle, $position, 0);
916 6         52 read($handle, $data, 1);
917 6         27 read($handle, $string, unpack("C", $data));
918 6         262 return $string;
919             }
920              
921             sub readFloat {
922 0     0 0 0 my ($obj, $handle, $position) = @_;
923 0         0 my $data = "";
924 0         0 seek($handle, $position-1, 0);
925 0         0 read($handle, $data, 4);
926              
927 0         0 my $is_little_endian = unpack("h*", pack("s", 1));
928 0 0       0 if ($is_little_endian =~ m/^1/) {
929             # "LITTLE ENDIAN - x86\n";
930 0         0 return unpack("f", $data);
931             } else {
932             # "BIG ENDIAN - MAC\n";
933 0         0 return unpack("f", reverse($data));
934             }
935             }
936              
937             sub bytesInt {
938 8     8 0 16 my $binip = shift(@_);
939 8         38 my @array = split(//, $binip);
940 8 50       33 return 0 if ($#array != 15);
941 8         29 my $ip96_127 = unpack("V", $array[0] . $array[1] . $array[2] . $array[3]);
942 8         17 my $ip64_95 = unpack("V", $array[4] . $array[5] . $array[6] . $array[7]);
943 8         22 my $ip32_63 = unpack("V", $array[8] . $array[9] . $array[10] . $array[11]);
944 8         20 my $ip1_31 = unpack("V", $array[12] . $array[13] . $array[14] . $array[15]);
945              
946 8         33 my $big1 = Math::BigInt->new("$ip96_127");
947 8         353 my $big2 = Math::BigInt->new("$ip64_95")->blsft(32);
948 8         1672 my $big3 = Math::BigInt->new("$ip32_63")->blsft(64);
949 8         1727 my $big4 = Math::BigInt->new("$ip1_31")->blsft(96);
950 8         1851 $big1 = $big1->badd($big2)->badd($big3)->badd($big4);
951            
952 8         1052 return $big1->bstr();
953             }
954              
955             sub validateIP {
956 6     6 0 11 my $obj = shift(@_);
957 6         13 my $ip = shift(@_);
958 6         56 my $ipv = -1;
959 6         12 my $ipnum = -1;
960            
961             #name server lookup if domain name
962 6         26 $ip = $obj->nameIP($ip);
963            
964 6 100       21 if ($obj->isIPv4($ip)) {
965             #ipv4 address
966 3         6 $ipv = 4;
967 3         8 $ipnum = $obj->ipNo($ip);
968             } else {
969             #expand ipv6 address
970 3         14 $ip = $obj->expandIPv6Address($ip);
971 3 50       9 if ($obj->isIPv6($ip)) {
972             #ipv6 address
973 3         6 $ipv = 6;
974 3         7 $ipnum = $obj->hexInt($ip);
975            
976             #reformat ipv4 address in ipv6
977 3 50 66     11 if (($ipnum >= 281470681743360) && ($ipnum <= 281474976710655)) {
978 0         0 $ipv = 4;
979 0         0 $ipnum = $ipnum - 281470681743360;
980             }
981             #reformat 6to4 address to ipv4 address 2002:: to 2002:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
982 3 50 66     616 if (($ipnum >= 42545680458834377588178886921629466624) && ($ipnum <= 42550872755692912415807417417958686719)) {
983 0         0 $ipv = 4;
984             #bitshift right 80 bits
985 0         0 $ipnum->brsft(80);
986             #bitwise modulus to get the last 32 bit
987 0         0 $ipnum->bmod(4294967296);
988             }
989             #reformat Teredo address to ipv4 address 2001:0000:: to 2001:0000:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:
990 3 50 66     1240 if (($ipnum >= 42540488161975842760550356425300246528) && ($ipnum <= 42540488241204005274814694018844196863)) {
991 0         0 $ipv = 4;
992 0         0 $ipnum = Math::BigInt->new($ipnum);
993             #bitwise not to invert binary
994 0         0 $ipnum->bnot();
995             #bitwise modulus to get the last 32 bit
996 0         0 $ipnum->bmod(4294967296);
997             }
998             } else {
999             #not IPv4 and IPv6
1000             }
1001             }
1002 6         1028 return ($ipv, $ipnum);
1003             }
1004              
1005             sub expandIPv6Address {
1006 3     3 0 6 my $obj = shift(@_);
1007 3         4 my $ip = shift(@_);
1008 3         9 $ip =~ s/\:\:/\:Z\:/;
1009 3         16 my @ip = split(/\:/, $ip);
1010 3         7 my $num = scalar(@ip);
1011              
1012 3         3 my $l = 8;
1013 3 50       12 if ($ip[$#ip] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
1014 0         0 my $a = sprintf("%x", ($1*256 + $2));
1015 0         0 my $b = sprintf("%x", ($3*256 + $4));
1016 0         0 $ip[$#ip] = $a;
1017 0         0 $ip[$#ip+1] = $b;
1018 0         0 $l--;
1019             }
1020              
1021 3 50       9 if ($#ip == 8) {
1022 0         0 shift(@ip);
1023 0         0 $l++;
1024             }
1025              
1026 3         10 foreach (0..(scalar(@ip)-1)) {
1027 24         41 $ip[$_] = ('0'x(4-length ($ip[$_]))).$ip[$_];
1028             }
1029              
1030 3         7 foreach (0..(scalar(@ip)-1)) {
1031 24 50       40 next unless ($ip[$_] eq '000Z');
1032 0         0 my @empty = map { $_ = '0'x4 } (0..7);
  0         0  
1033 0         0 $ip[$_] = join(':', @empty[0..$l-$num]);
1034 0         0 last;
1035             }
1036              
1037 3         15 return (uc(join ':', @ip));
1038             }
1039              
1040             sub hexInt {
1041 3     3 0 5 my $obj = shift(@_);
1042 3         6 my $hexip = shift(@_);
1043              
1044 3         12 $hexip =~ s/\://g;
1045              
1046 3 50       7 unless (length($hexip) == 32) {
1047 0         0 return 0;
1048             };
1049              
1050 3         23 my $binip = unpack('B128', pack('H32', $hexip));
1051 3         16 my ($n, $dec) = (Math::BigInt->new(1), Math::BigInt->new(0));
1052              
1053 3         522 foreach (reverse (split('', $binip))) {
1054 384 100       40844 $_ && ($dec += $n);
1055 384         1707 $n *= 2;
1056             }
1057              
1058 3         378 $dec =~ s/^\+//;
1059 3         123 return $dec;
1060             }
1061              
1062             sub ipNo {
1063 3     3 0 5 my $obj = shift(@_);
1064 3         5 my $ip = shift(@_);
1065 3         9 my @block = split(/\./, $ip);
1066 3         4 my $no = 0;
1067 3         7 $no = $block[3];
1068 3         8 $no = $no + $block[2] * 256;
1069 3         7 $no = $no + $block[1] * 256 * 256;
1070 3         7 $no = $no + $block[0] * 256 * 256 * 256;
1071 3         7 return $no;
1072             }
1073              
1074             sub nameIP {
1075 6     6 0 51 my $obj = shift(@_);
1076 6         17 my $host = shift(@_);
1077 6         12 my $ip_address = "";
1078 6 50 66     611 if (($host =~ m/^$IPv4_re$/) || ($host =~ m/^$IPv6_re$/) || ($host =~ m/^\:\:$/)) {
      33        
1079 6         17 $ip_address = $host;
1080             } else {
1081             # TO_DO: Can we return IPv6 address too?
1082 0         0 $ip_address = join('.', unpack('C4',(gethostbyname($host))[4]));
1083             }
1084 6         24 return $ip_address;
1085             }
1086              
1087             sub isIPv4 {
1088 6     6 0 12 my $obj = shift(@_);
1089 6         9 my $ip = shift(@_);
1090 6 100       61 if ($ip =~ m/^$IPv4_re$/) {
1091 3         13 my @octet = split(/\./, $ip);
1092 3         14 foreach my $i (0 .. $#octet) {
1093 12 50 33     63 return 0 if (($octet[$i] > 255) || ($octet[$i] < 0));
1094             }
1095 3         12 return 1;
1096             } else {
1097 3         13 return 0;
1098             }
1099             }
1100              
1101             sub isIPv6 {
1102 3     3 0 6 my $obj = shift(@_);
1103 3         6 my $ip = shift(@_);
1104 3 50 33     431 if (($ip =~ m/^$IPv6_re$/) || ($ip =~ m/^$IPv4_re$/)) {
1105 3         12 return 1;
1106             } else {
1107 0           return 0;
1108             }
1109             }
1110              
1111             1;
1112             __END__