File Coverage

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