File Coverage

blib/lib/Geo/IP2Proxy.pm
Criterion Covered Total %
statement 317 669 47.3
branch 65 302 21.5
condition 41 123 33.3
subroutine 45 63 71.4
pod 18 35 51.4
total 486 1192 40.7


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