File Coverage

blib/lib/Net/Whois/IP.pm
Criterion Covered Total %
statement 41 126 32.5
branch 2 48 4.1
condition 1 33 3.0
subroutine 10 12 83.3
pod 0 2 0.0
total 54 221 24.4


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