File Coverage

blib/lib/Net/Whois/IP.pm
Criterion Covered Total %
statement 41 127 32.2
branch 2 50 4.0
condition 1 36 2.7
subroutine 10 12 83.3
pod 0 2 0.0
total 54 227 23.7


line stmt bran cond sub pod time code
1             package Net::Whois::IP;
2              
3              
4             ########################################
5             #$Id: IP.pm,v 1.21 2007-03-07 16:49:36 ben Exp $
6             ########################################
7              
8 2     2   1478 use strict;
  2         3  
  2         77  
9 2     2   11 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  2         3  
  2         177  
10 2     2   1968 use IO::Socket;
  2         61097  
  2         11  
11 2     2   3143 use Regexp::IPv6 qw($IPv6_re);
  2         2207  
  2         261  
12 2     2   14 use File::Spec;
  2         3  
  2         60  
13             require Exporter;
14 2     2   12 use Carp;
  2         3  
  2         4222  
15              
16             @ISA = qw(Exporter AutoLoader);
17             @EXPORT = qw(
18             whoisip_query
19             );
20             $VERSION = '1.18';
21              
22             my %whois_servers = (
23             "RIPE"=>"whois.ripe.net",
24             "APNIC"=>"whois.apnic.net",
25             "KRNIC"=>"whois.krnic.net",
26             "LACNIC"=>"whois.lacnic.net",
27             "ARIN"=>"whois.arin.net",
28             "AFRINIC"=>"whois.afrinic.net",
29             );
30              
31             ######################################
32             # Public Subs
33             ######################################
34              
35             sub whoisip_query {
36 2     2 0 50 my($ip,$reg,$multiple_flag,$raw_flag,$search_options) = @_;
37             # It allows to set the first registry to query
38 2 0 33     20 if(($ip !~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) && ($ip !~ /^$IPv6_re$/) ) {
39 0         0 croak("$ip is not a valid ip address");
40             }
41             #DO_DEBUG("looking up $ip");
42 2         9 my($response) = _do_lookup($ip,$reg,$multiple_flag,$raw_flag,$search_options);
43 0         0 return($response);
44             }
45              
46              
47             ######################################
48             #Private Subs
49             ######################################
50             sub _do_lookup {
51 2     2   5 my($ip,$registrar,$multiple_flag,$raw_flag,$search_options) = @_;
52             #DO_DEBUG("do lookup $ip at $registrar");
53             #let's not beat up on them too much
54 2         6 my $extraflag = "1";
55 2         3 my $whois_response;
56             my $whois_raw_response;
57 0         0 my $whois_response_hash;
58 0         0 my @whois_response_array;
59 2         10 LOOP: while($extraflag ne "") {
60             #DO_DEBUG("Entering loop $extraflag");
61 2         219 my $lookup_host = $whois_servers{$registrar};
62 2         12 ($whois_response,$whois_response_hash) = _do_query($lookup_host,$ip,$multiple_flag);
63 0         0 push(@whois_response_array,$whois_response_hash);
64 0         0 push(@{$whois_raw_response}, @{$whois_response});
  0         0  
  0         0  
65 0         0 my($new_ip,$new_registrar) = _do_processing($whois_response,$registrar,$ip,$whois_response_hash,$search_options);
66 0 0 0     0 if(($new_ip ne $ip) || ($new_registrar ne $registrar) ) {
67             #DO_DEBUG("ip was $ip -- new ip is $new_ip");
68             #DO_DEBUG("registrar was $registrar -- new registrar is $new_registrar");
69 0         0 $ip = $new_ip;
70 0         0 $registrar = $new_registrar;
71 0         0 $extraflag++;
72 0         0 next LOOP;
73             }else{
74 0         0 $extraflag="";
75 0         0 last LOOP;
76             }
77             }
78            
79             # Return raw response from registrar
80 0 0 0     0 if( ($raw_flag) && ($raw_flag ne "") ) {
81 0         0 return ($whois_raw_response);
82             }
83              
84              
85 0 0       0 if(%{$whois_response_hash}) {
  0         0  
86 0         0 foreach (sort keys(%{$whois_response_hash}) ) {
  0         0  
87             #DO_DEBUG("sub -- $_ -- $whois_response_hash->{$_}");
88             }
89 0         0 return($whois_response_hash,\@whois_response_array);
90             }else{
91 0         0 return($whois_response,\@whois_response_array);
92             }
93             }
94              
95             sub _do_query{
96 2     2   6 my($registrar,$ip,$multiple_flag) = @_;
97 2         4 my @response;
98 2         4 my $i =0;
99 2         4 LOOP:while(1) {
100 2         8 $i++;
101 2         9 my $sock = _get_connect($registrar);
102             # Replaced by: if ARIN add n param, if RIPE or Afrinic add -B param
103 0 0 0     0 if ($registrar eq 'whois.arin.net') {
    0          
104 0         0 print $sock "n $ip\n";
105             } elsif ($registrar eq 'whois.ripe.net' or $registrar eq "whois.afrinic.net") {
106 0         0 print $sock "-B $ip\n";
107             } else {
108 0         0 print $sock "$ip\n";
109             }
110 0         0 @response = <$sock>;
111 0         0 close($sock);
112 0 0       0 if($#response < 0) {
113             #DO_DEBUG("No valid response recieved from $registrar -- attempt $i ");
114 0 0       0 if($i <=3) {
115 0         0 next LOOP;
116             }else{
117 0         0 croak("No valid response for 4th time... dying....");
118             }
119             }else{
120 0         0 last LOOP;
121             }
122             }
123             #Prevent killing the whois.arin.net --- they will disable an ip if greater than 40 queries per minute
124 0         0 sleep(1);
125 0         0 my %hash_response;
126             #DO_DEBUG("multiple flag = |$multiple_flag|");
127 0         0 foreach my $line (@response) {
128 0 0       0 if($line =~ /^(.+):\s+(.+)$/) {
129 0 0 0     0 if( ($multiple_flag) && ($multiple_flag ne "") ) {
130             #Multiple_flag is set, so get all responses for a given record item
131             #DO_DEBUG("Flag set ");
132 0         0 push @{ $hash_response{$1} }, $2;
  0         0  
133             }else{
134             #Multiple_flag is not set, so only the last entry for any given record item
135             #DO_DEBUG("Flag not set");
136 0         0 $hash_response{$1} = $2;
137             }
138             }
139             }
140 0         0 return(\@response,\%hash_response);
141             }
142              
143             sub _do_processing {
144 0     0   0 my($response,$registrar,$ip,$hash_response,$search_options) = @_;
145              
146             #Response to comment.
147             #Bug report stating the search method will work better with different options. Easy way to do it now.
148             #this way a reference to an array can be passed in, the defaults will still
149             #be TechPhone and OrgTechPhone
150 0         0 my $pattern1 = "TechPhone";
151 0         0 my $pattern2 = "OrgTechPhone";
152 0 0 0     0 if(($search_options) && ($search_options->[0] ne "") ) {
153 0         0 $pattern1 = $search_options->[0];
154 0         0 $pattern2 = $search_options->[1];
155             }
156             #DO_DEBUG("pattern1 = $pattern1 || pattern2 == $pattern2");
157            
158            
159              
160 0         0 LOOP:foreach (@{$response}) {
  0         0  
161 0 0 0     0 if (/Contact information can be found in the (\S+)\s+database/) {
    0 0        
    0 0        
    0 0        
162 0         0 $registrar = $1;
163             #DO_DEBUG("Contact -- registrar = $registrar -- trying again");
164 0         0 last LOOP;
165              
166             }elsif((/OrgID:\s+(\S+)/i) || (/source:\s+(\S+)/i) && (!defined($hash_response->{$pattern1})) ) {
167 0         0 my $val = $1;
168             #DO_DEBUG("Orgname match: value was $val if not RIPE,APNIC,KRNIC,or LACNIC.. will skip");
169 0 0       0 if($val =~ /^(?:RIPE|APNIC|KRNIC|LACNIC|AFRINIC)$/) {
170 0         0 $registrar = $val;
171             #DO_DEBUG(" RIPE - APNIC match --> $registrar --> trying again ");
172 0         0 last LOOP;
173             }
174             }elsif(/Parent:\s+(\S+)/) {
175             # Modif: if(($1 ne "") && (!defined($hash_response->{'TechPhone'})) && (!defined($hash_response->{$pattern2})) ) {
176             # Use $pattern1 instead of default TechPhone
177 0 0 0     0 if(($1 ne "") && (!defined($hash_response->{$pattern1})) && (!defined($hash_response->{$pattern2})) ) {
      0        
178             # End Modif
179 0         0 $ip = $1;
180             #DO_DEBUG(" Parent match ip will be $ip --> trying again");
181 0         0 last LOOP;
182             }
183             #Test Loop via Jason Kirk -- Thanks
184             }elsif($registrar eq 'ARIN' && (/.+\((.+)\).+$/) && ($_ !~ /.+\:.+/)) {
185             ##Change 3-1-07
186             # my $origIp = $ip;$ip = '! '.$1;
187             # if ($ip !~ /\d{1,3}\-\d{1,3}\-\d{1,3}\-\d{1,3}/){
188             # $ip = $origIp;
189             # }
190 0         0 my $origIp = $ip;$ip = '! '.$1;
  0         0  
191             # Modif: Keep the smallest block
192 0 0       0 if ($origIp =~ /! NET-(\d{1,3}\-\d{1,3}\-\d{1,3}\-\d{1,3})/) {
193 0         0 my $orIP = $1;
194 0 0       0 if ($ip =~ /! NET-(\d{1,3}\-\d{1,3}\-\d{1,3}\-\d{1,3})/) {
195 0         0 my $nwIP = $1;
196 0 0       0 if (pack('C4', split(/\-/,$orIP)) ge pack('C4', split(/\-/,$nwIP))) {
197 0         0 $ip = $origIp;
198             }
199             }
200             }
201 0 0       0 if ($ip !~ /\d{1,3}\-\d{1,3}\-\d{1,3}\-\d{1,3}/){
202 0         0 $ip = $origIp;
203             }
204             # }elsif((/.+\((.+)\).+$/) && ($_ !~ /.+\:.+/)) {
205             # $ip = $1;
206             # $registrar = "ARIN";
207             #DO_DEBUG("parens match $ip $registrar --> trying again");
208             }else{
209 0         0 $ip = $ip;
210 0         0 $registrar = $registrar;
211             }
212             }
213 0         0 return($ip,$registrar);
214             }
215            
216            
217              
218             sub _get_connect {
219 2     2   5 my($whois_registrar) = @_;
220 2         27 my $sock = IO::Socket::INET->new(
221             PeerAddr=>$whois_registrar,
222             PeerPort=>'43',
223             Timeout=>'60',
224             # Blocking=>'0',
225             );
226 2 50       849 unless($sock) {
227 2         594 carp("Failed to Connect to $whois_registrar at port print -$@");
228 2         10000302 sleep(5);
229 2         78 $sock = IO::Socket::INET->new(
230             PeerAddr=>$whois_registrar,
231             PeerPort=>'43',
232             Timeout=>'60',
233             # Blocking=>'0',
234             );
235 2 50       1168 unless($sock) {
236 2           croak("Failed to Connect to $whois_registrar at port 43 for the second time - $@");
237             }
238             }
239 0           return($sock);
240             }
241              
242             sub DO_DEBUG {
243 0     0 0   my(@stuff) = @_;
244 0           my $date = scalar localtime;
245 0           my $tmp_dir = File::Spec->tmpdir();
246 0 0         if(!defined($tmp_dir)) {
247 0           $tmp_dir = "/tmp/";
248             }
249 0           my $outdebug = $tmp_dir . "/Net.WhoisIP.log";
250 0 0         open(DEBUG,">>$outdebug") or warn "Unable to open $outdebug";
251 0           foreach my $item ( @stuff) {
252 0           print DEBUG "$date|$item|\n";
253             }
254 0           close(DEBUG);
255             }
256              
257              
258             1;
259             __END__