C code to perform IP whois

Theory

The whois information of an ip address provides various details like its network, range, isp etc. This information is maintained by various regional registry servers. Read the wikipedia article on regional internet registries for more information.


There are a total of 5 regional registries spanning various geographical regions of the world. For example if an ip address is allocated to some isp in USA then the ARIN registry would provide its whois information.

To get the whois data of an ip address, all that needs to be done is to query the particular registry server and send a query. However first we need to know under registry is the ip address currently allocated. The iana whois server has this information and will provide us for free.

So first whois.iana.org is queried to find out the regional internet registry of the specified IP address.
Then the whois server of the corresponding RIR is queried to get the actual whois information about the ip.

Code

Following is a whois program implemented in C. Note that it will work on Linux.

/*
 * @brief
 * Whois client program
 * 
 * @details
 * This program shall fetch whois data for a IPv4 address.
 * 
 * @author Silver Moon ( [email protected] )
 * */

#include<stdio.h>	//scanf , printf
#include<string.h>	//strtok
#include<stdlib.h>	//realloc
#include<sys/socket.h>	//socket
#include<netinet/in.h> //sockaddr_in
#include<arpa/inet.h>	//getsockname
#include<netdb.h>	//hostent
#include<unistd.h>	//close

int main(int argc , char *argv[])
{
	char ip[100] , *data = NULL;
	
	printf("Enter ip address to whois : ");
	scanf("%s" , ip);
	
	get_whois(ip , &data);
	printf("\n\n");
	puts(data);
	
	free(data);
	return 0;
}

/**
	Get the whois content of an ip
	by selecting the correct server
*/
void get_whois(char *ip , char **data) 
{
	char *wch = NULL, *pch , *response = NULL;
	
	if(whois_query("whois.iana.org" , ip , &response))
	{
		printf("Whois query failed");
	}
	
	pch = strtok(response , "\n");
	
	while(pch != NULL)
	{
		//Check if whois line
		wch = strstr(pch , "whois.");
		if(wch != NULL)
		{
			break;
		}

		//Next line please
		pch = strtok(NULL , "\n");
	}
	
	if(wch != NULL)
	{
		printf("\nWhois server is : %s" , wch);
		whois_query(wch , ip , data);
	}
	else
	{
		*data = malloc(100);
		strcpy(*data , "No whois data");
	}
	
	return;
}

/*
 * Perform a whois query to a server and record the response
 * */
int whois_query(char *server , char *query , char **response)
{
	char ip[32] , message[100] , buffer[1500];
	int sock , read_size , total_size = 0;
	struct sockaddr_in dest;
	 
	sock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
     
    //Prepare connection structures :)
    memset( &dest , 0 , sizeof(dest) );
    dest.sin_family = AF_INET;
     
	printf("\nResolving %s..." , server);
	if(hostname_to_ip(server , ip))
	{
		printf("Failed");
		return 1;
	}
	printf("%s" , ip);    
	dest.sin_addr.s_addr = inet_addr( ip );
	dest.sin_port = htons( 43 );

	//Now connect to remote server
	if(connect( sock , (const struct sockaddr*) &dest , sizeof(dest) ) < 0)
	{
		perror("connect failed");
	}
	
	//Now send some data or message
	printf("\nQuerying for ... %s ..." , query);
	sprintf(message , "%s\r\n" , query);
	if( send(sock , message , strlen(message) , 0) < 0)
	{
		perror("send failed");
	}
	
	//Now receive the response
	while( (read_size = recv(sock , buffer , sizeof(buffer) , 0) ) )
	{
		*response = realloc(*response , read_size + total_size);
		if(*response == NULL)
		{
			printf("realloc failed");
		}
		memcpy(*response + total_size , buffer , read_size);
		total_size += read_size;
	}
	printf("Done");
	fflush(stdout);
	
	*response = realloc(*response , total_size + 1);
	*(*response + total_size) = '\0';
	
	close(sock);
	return 0;
}

/*
 * @brief
 * Get the ip address of a given hostname
 * 
 * */
int hostname_to_ip(char * hostname , char* ip)
{
	struct hostent *he;
	struct in_addr **addr_list;
	int i;
		
	if ( (he = gethostbyname( hostname ) ) == NULL) 
	{
		// get the host info
		herror("gethostbyname");
		return 1;
	}

	addr_list = (struct in_addr **) he->h_addr_list;
	
	for(i = 0; addr_list[i] != NULL; i++) 
	{
		//Return the first one;
		strcpy(ip , inet_ntoa(*addr_list[i]) );
		return 0;
	}
	
	return 0;
}







Compile and Run

The gcc compiler can be used to compile the program. So start a terminal and issue the following command. It will compile the above program and also run it. It first asks for an ip address and then tries to retrive its whois information as described in the theory previously.

$ gcc whois_ip.c && ./a.out 
Enter ip address to whois : 77.65.12.44

Resolving whois.iana.org...192.0.47.59
Querying for ... 77.65.12.44 ...Done
Whois server is : whois.ripe.net
Resolving whois.ripe.net...193.0.6.135
Querying for ... 77.65.12.44 ...Done

% This is the RIPE Database query service.
% The objects are in RPSL format.
%
% The RIPE Database is subject to Terms and Conditions.
% See http://www.ripe.net/db/support/db-terms-conditions.pdf

% Note: this output has been filtered.
%       To receive output for a database update, use the "-B" flag.

% Information related to '77.65.0.0 - 77.65.23.255'

inetnum:        77.65.0.0 - 77.65.23.255
netname:        ICPNET-5
descr:          ICP Network
descr:          static assignment address space
country:        PL
admin-c:        GTW-RIPE
tech-c:         GTW-RIPE
status:         ASSIGNED PA
mnt-by:         ICP-MNT
mnt-lower:      ICP-MNT
mnt-routes:     ICP-MNT
source:         RIPE # Filtered

person:         Grupa trzymajaca wladze
address:        INEA S. A.
address:        ul. Klaudyny Potockiej 25
address:        60-211 Poznan
address:        Poland
phone:          +48 61 2222222
fax-no:         +48 61 2221241
nic-hdl:        GTW-RIPE
e-mail:         [email protected]
remarks:        *************************************************
remarks:        no remarks, sorry.
remarks:        *************************************************
mnt-by:         ICP-MNT
source:         RIPE # Filtered

% Information related to '77.65.0.0/17AS13110'

route:          77.65.0.0/17
descr:          PL-ICP
descr:          Poznan
origin:         AS13110
mnt-by:         ICP-MNT
source:         RIPE # Filtered

The part from "% This is the RIPE Database query service." is the whois information.

Just like ip addresses, domains also have whois information. The process to find the whois information of a domain is also quite similar to the above one. In another article we shall see how to fetch the whois data of a domain.

Last Updated On : 21st September 2012

Subscribe to get updates delivered to your inbox

Leave a comment