#!/usr/bin/perl
#
# GeekTools Whois Proxy v2.0
# Code mangled by Robb Ballard <robb@centergate.com>
# Copyright 1999 CenterGate Research Group, LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

use IO::Socket;

# TLD/NIC List
$rslist = "/home/robb/who/rslist";

$query_in = <STDIN>;
chomp $query_in;

@query_array = split /\./, $query_in;
$query_elements = @query_array;

# Preprocessing - convert to lowercase
$query_in =~ tr/A-Z/a-z/;
@suffix_array = split /\ /, $query_in;
$suffix_elements = @suffix_array - 1;
$suffix_array[$suffix_elements] =~ tr/a-z.,0-9\-//cd;
$query_in =~ tr/a-z.,0-9\-\@\!//cd;

if ($query_in eq "") {
   nodata();
   exit 1;
}

$conv = "";

# 
# Data dissection
#

#
# Suffix Queries
#

if ($suffix_array[$suffix_elements] eq "ra") {
   $addup = 0;
   $suffix_query = "";
   while ($addup < $suffix_elements) {
	  $suffix_query = $suffix_query . " " . $suffix_array[$addup];
	  $addup++
   }
   whois("whois.ra.net", "$suffix_query");
   exit 0;
}

if ($suffix_array[$suffix_elements] eq "arin") {
   $addup = 0;
   $suffix_query = "";
   while ($addup < $suffix_elements) {
          $suffix_query = $suffix_query . " " . $suffix_array[$addup];
          $addup++
   }
   whois("whois.arin.net", "$suffix_query");
   exit 0;
}

if ($suffix_array[$suffix_elements] eq "apnic") {
   $addup = 0;
   $suffix_query = "";
   while ($addup < $suffix_elements) {
          $suffix_query = $suffix_query . " " . $suffix_array[$addup];
          $addup++
   }
   whois("whois.apnic.net", "$suffix_query");
   exit 0;
}

if ($suffix_array[$suffix_elements] eq "aunic") {
   $addup = 0;
   $suffix_query = "";
   while ($addup < $suffix_elements) {
          $suffix_query = $suffix_query . " " . $suffix_array[$addup];
          $addup++
   }
   whois("whois.aunic.net", "$suffix_query");
   exit 0;
}

if ($suffix_array[$suffix_elements] eq "ripe") {
   $addup = 0;
   $suffix_query = "";
   while ($addup < $suffix_elements) {
          $suffix_query = $suffix_query . " " . $suffix_array[$addup];
          $addup++
   }
   whois("whois.ripe.net", "$suffix_query");
   exit 0;
}

if ($suffix_array[$suffix_elements] eq "internic") {
   $addup = 0;
   $suffix_query = "";
   while ($addup < $suffix_elements) {
          $suffix_query = $suffix_query . " " . $suffix_array[$addup];
          $addup++
   }
   whois("whois.internic.net", "$suffix_query");
   exit 0;
}

#
# Single Element Queries
#

if ($query_elements eq 1) {
        #
        # Single numerics are interpreted as AS numbers.
        #
        if ($query_in !~  /[^0-9]/) {
           check_as($query_in);
           #
           # Structure the query like the server wants it
           #
           if ($nicserv eq "whois.apnic.net") {
                  $asquery = "AS$query_in";
           }
           if ($nicserv eq "whois.ripe.net") {
                  $asquery = "AS$query_in";
           }
           if ($nicserv eq "whois.arin.net") {
                  $asquery = "AS $query_in";
           }
           whois("$nicserv","$asquery");
           exit 0;
    }
        #
        # Does it contain a hyphen?
        #
        ($check1,$check2) = split(/-/,$query_in);
        if ($check2 eq "arin") {
           whois("whois.arin.net", "$query_in");
           exit 0;
        }
        if ($check1 eq "asn") {
           whois("whois.arin.net", "$query_in");
           exit 0;
        }
        if ($check2 eq "ripe") {
           whois("whois.ripe.net", "$query_in");
           exit 0;
        }
        if ($check2 eq "ap") {
           whois("whois.apnic.net", "$query_in");
           exit 0;
        }
        if ($check1 eq "net") {
           whois("whois.arin.net", "$query_in");
           exit 0;
        }
        if ($check1 eq "netblk") {
           whois("whois.arin.net", "$query_in");
           exit 0;
        }
}



#
# A single IP address
#

if ($query_in !~ /[^0-9\.]/) {
   ($a, $b, $c, $d, $e) = $query_in =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)(.*)/;
   if ($a > 255 || $b > 255 || $c > 255 || $d > 255 || $e ne '') {
	  showerror("Unable to decipher your entry.");
	  exit 1;
   }
   ipcheck("$query_in");
   exit 0;
} else {
   domaincheck("$query_in");
   exit 0;
}



#
# Subroutines
#

sub ipcheck
{
   @lookfor = (
	[".*NETBLK-RIPE.*", "whois.ripe.net"],
	[".*NET-RIPE.*", "whois.ripe.net"],
	[".*APNIC.*", "whois.apnic.net"]
        );
   $myquery = $_[0];
   $nicserv = "whois.arin.net";
   REPEAT: while ($myquery) {  
   $port = getservbyname 'whois', 'tcp';
   $remote = IO::Socket::INET->new( Proto=>'tcp',
                                    PeerAddr=>$nicserv,
                                    PeerPort=>$port,
                                    Timeout=>'15' );
   if (!$remote) {
           print "Unable to connect.\n";
   }
   if ($nicserv eq "whois.arin.net") {
      print $remote "NE $myquery\t\n";
   } else {
      print $remote "$myquery\r\n";
   }
   @result = <$remote>;
   close $remote;
   foreach $resline (@lookfor) {
	   if ($result[0] =~ m/@{$resline}[0]/) {
	      $nicserv = @{$resline}[1];
	      print "Querying: $nicserv\n";
              next REPEAT;

	   }
  
   }
   last;
   }
   foreach $resline (@result) {
	   print $resline;
   }
}
   
sub whois
{
	$nicserv = $_[0];
	$myquery = $_[1];

	$port = getservbyname 'whois', 'tcp';
	$remote = IO::Socket::INET->new( Proto=>'tcp',
				  	 PeerAddr=>$nicserv,
					 PeerPort=>$port,
					 Timeout=>'15' );
	if (!$remote) {
		print "Unable to connect.\n";
	}
	print $remote "$myquery\r\n";
	@result = <$remote>;
	close $remote;
	print "Server used for this query: $nicserv\n";
	foreach $resline (@result) {
		print $resline;
	}
}

sub silent_whois
{
	$nicserv = $_[0];
	$myquery = $_[1];
	$result = "";

	$port = getservbyname 'whois', 'tcp';
	$remote = IO::Socket::INET->new( Proto=>'tcp',
			        	 PeerAddr=>$nicserv,
					 PeerPort=>$port,
					 Timeout=>'15');
	if (!$remote) {
		print "Unable to connect.\n";
	}
	print $remote "$myquery\r\n";
	@silent_result = <$remote>;
	close $remote;
	foreach $resline (@silent_result) {
	   $result = $result . $resline;
	}
}

sub showerror
{
   $errmsg = $_[0];
   print "\n\nQuery failed:  $errmsg\n\n";
} 


sub check_as
{
   # Kludge kludge kludge...
   $as = $_[0];
   if ($as >= 1 && $as <= 1876) { $nicserv = "whois.arin.net";  }
   if ($as >= 1877  && $as <= 1901) { $nicserv = "whois.ripe.net";  }
   if ($as >= 1902 && $as <= 2042) { $nicserv = "whois.arin.net";  }
   if ($as == 2043) { $nicserv = "whois.ripe.net";  }
   if ($as >= 2044 && $as <= 2046) { $nicserv = "whois.arin.net";  }
   if ($as == 2047) { $nicserv = "whois.ripe.net";  }
   if ($as >= 2048 && $as <= 2106) { $nicserv = "whois.arin.net";  }
   if ($as >= 2107 && $as <= 2136) { $nicserv = "whois.ripe.net";  }
   if ($as >= 2137 && $as <= 2584) { $nicserv = "whois.arin.net";  }
   if ($as >= 2585 && $as <= 2614) { $nicserv = "whois.ripe.net";  }
   if ($as >= 2615 && $as <= 2772) { $nicserv = "whois.arin.net";  }
   if ($as >= 2773 && $as <= 2822) { $nicserv = "whois.ripe.net";  }
   if ($as >= 2823 && $as <= 2829) { $nicserv = "whois.arin.net";  }
   if ($as >= 2830 && $as <= 2879) { $nicserv = "whois.ripe.net";  }
   if ($as >= 2880 && $as <= 3153) { $nicserv = "whois.arin.net";  }
   if ($as >= 3154 && $as <= 3353) { $nicserv = "whois.ripe.net";  }
   if ($as >= 3354 && $as <= 4607) { $nicserv = "whois.arin.net";  }
   if ($as >= 4608 && $as <= 4864) { $nicserv = "whois.apnic.net";  }
   if ($as >= 4865 && $as <= 5376) { $nicserv = "whois.arin.net";  }
   if ($as >= 5377 && $as <= 5631) { $nicserv = "whois.ripe.net";  }
   if ($as >= 5632 && $as <= 6655) { $nicserv = "whois.arin.net";  }
   if ($as >= 6656 && $as <= 6911) { $nicserv = "whois.ripe.net";  }
   if ($as >= 6912 && $as <= 7466) { $nicserv = "whois.arin.net";  }
   if ($as >= 7467 && $as <= 7722) { $nicserv = "whois.apnic.net";  }
   if ($as >= 7723 && $as <= 8191) { $nicserv = "whois.arin.net";  }
   if ($as >= 8192 && $as <= 9215) { $nicserv = "whois.ripe.net";  }
   if ($as >= 9216 && $as <= 10239) { $nicserv = "whois.apnic.net";  }
   if ($as >= 10240 && $as <= 11263) { $nicserv = "whois.arin.net";  }
   if ($as >= 11264 && $as <= 12287) { $nicserv = "whois.arin.net";  }
   if ($as >= 12288 && $as <= 13311) { $nicserv = "whois.ripe.net";  }
}


sub domaincheck
{
   $domain_query = $_[0];
   @domarray = split /\./, $domain_query;
   $elements = @domarray;
   --$elements;
   $tld = $domarray[$elements];
   open (RSLIST, $rslist) || die "Can't open file rslist ($rslist): $!\n";
   while ($data = <RSLIST>) {
        chomp $data;
        ($table_tld,$table_nicserv) = split(/:/,$data);
        if ($tld eq $table_tld) { $nicserv = $table_nicserv; }
   }
   close RSLIST;
  
   # So we get English text rather than Japanese
   if ($nicserv eq "whois.nic.ad.jp") { $conv = "/e"; }
   
   # Customizations for strange TLD's
   # for ac.uk
   if ($tld eq "uk") {
     if ($domarray[--$elements] eq "ac") {
         $nicserv = "whois.ja.net";
     }
   }
   # for net.au
   if ($tld eq "au") {
     if ($domarray[--$elements] eq "net") {
         $nicserv = "whois.connect.com.au";
     }
   }
  
   if ($nicserv eq "") {
      # print "$domain_query isn't a TLD for which I have information.\n";
      print "Defaulting to whois.internic.net for query.\n";
      $nicserv = "whois.internic.net";
   } else {
      print "Server used for this query: $nicserv\n";
   }
   

   silent_whois("$nicserv","$domain_query$conv");

   # See if we got something valid.  Internic (and nic.uk) style first...
   @nullcheck = split /\ /, $result;
   if ($nullcheck[1] eq "match") {
     if ($nullcheck[2] eq "for") {
       print "No match found for $domain_query.\n";
       # Should we truncate and try again?
       while ($elements > 1) {
            chopit();
            if ($nquery ne $tld) {
	    silent_whois("$nicserv","$nquery$conv");
            @nullcheck = split /\ /, $result;
            if ($nullcheck[1] eq "match") {
              if ($nullcheck[2] eq "for") {
              print "No match found for $nquery.\n";
              }
            } else {
            print "\nMatch obtained for $nquery:\n";
            print "$result\n";
            exit 0;
            }
            } else {
              print "\nUnable to obtain a match for your query '$domain_query'.\n";
            }
       }
     }
   } elsif ($nullcheck[7] eq "No"){
     # RIPE style response
     if ($nullcheck[8] eq "entries") {
       print "No match found for $domain_query.\n";
       # Should we truncate and try again?
       while ($elements > 1) {
            chopit();
            if ($nquery ne $tld) {
   	    silent_whois("$nicserv","$nquery$conv");
            @nullcheck = split /\ /, $result;
            if ($nullcheck[7] eq "No") {
              if ($nullcheck[8] eq "entries") {
              print "No match found for $nquery.\n";
              }
            } else {
            print "\nMatch obtained for $nquery:\n";
            print "$result\n";
	    exit 0;
            }
            }
       }
  
     }
   } elsif ($nullcheck[12] eq "entries"){
      # nic.ch style response
      if ($nullcheck[13] eq "found") {
       print "No match found for $domain_query.\n";
       # Should we truncate and try again?
       while ($elements > 1) {
            chopit();
            if ($nquery ne $tld) {
	    silent_whois("$nicserv","$nquery$conv");
            @nullcheck = split /\ /, $result;
            if ($nullcheck[12] eq "No") {
              if ($nullcheck[13] eq "entries") {
              print "No match found for $nquery.\n";
              }
            } else {
            print "\nMatch obtained for $nquery:\n";
            print "$result\n";
	    exit 0;
            }
            }
       }
     }
   } else {
     print "$result";
     exit 0;
   }
}
   
sub nodata
{
   print "\n\% GeekTools Whois Proxy v2.0.\n";
   print "\%\n";
   print "\% This is a work in progress.  Please bear with us as we work \n";
   print "\% to refine it.\n";
   print "\% \n";
   print "\% You did not enter any data that could be used for a query. \n";
   print "\% If you are trying to perform an AS number search, please send \n";
   print "\% it as a number without any prefix such as \"AS\" (AS\#\#\#).\n";
   print "\% \n";
   print "\% Queries may be forced to go to certain whois servers by using\n";
   print "\% the following suffix at the end of your query:\n";
   print "\% \n";
   print "\% query INTERNIC         - Force query to INTERNIC.\n";
   print "\% query RIPE             - Force query to RIPE.\n";
   print "\% query APNIC            - Force query to APNIC.\n";
   print "\% query AUNIC            - Force query to AUNIC.\n";
   print "\% query ARIN             - Force query to ARIN.\n";
   print "\% query RA               - Force query to RADB.\n";
   print "\% \n";
   print "\% Thanks for using the GeekTools Whois Proxy!\n\n";
}

sub chopit
{
   $max=0;
   shift @query_array;
   $elements = @query_array;
   $nquery = "";
   while ($elements != $max) {
    if ($nquery ne "") {
       $nquery = $nquery . "." . $query_array[$max];
       } else {
           $nquery =  $query_array[$max];
       }
       ++$max;
    }
}
