File Coverage

blib/lib/Geo/IP2Proxy.pm
Criterion Covered Total %
statement 340 738 46.0
branch 69 322 21.4
condition 44 132 33.3
subroutine 48 71 67.6
pod 20 41 48.7
total 521 1304 39.9


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