How to Get IP Whois Data in C with Sockets on Linux – Code Example

By | August 7, 2020

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.

/*
    This program shall fetch whois data for a IPv4 address.
*/

#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

void get_whois(char *ip , char **data);
int whois_query(char *server , char *query , char **response);
int hostname_to_ip(char * hostname , char* ip);

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 EXIT_SUCCESS;
}

/*
	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 EXIT_FAILURE;
	}
	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;
}

/*
    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 EXIT_FAILURE;
	}

	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 EXIT_SUCCESS;
	}
	
	return EXIT_SUCCESS;
}

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.

$ gcc whois_ip.c

It first asks for an ip address and then tries to retrive its whois information as described in the theory previously.

$ ./a.out
Enter ip address to whois : 77.65.12.44
Resolving whois.iana.org...192.0.32.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'
% Abuse contact for '77.65.0.0 - 77.65.23.255' is '[email protected]'
inetnum:        77.65.0.0 - 77.65.23.255
netname:        ICPNET-5
descr:          ICP Network
descr:          static assignment address space
country:        PL
admin-c:        INEA-RIPE
tech-c:         INEA-RIPE
status:         ASSIGNED PA
mnt-by:         INEA-MNT
mnt-lower:      INEA-MNT
mnt-routes:     INEA-MNT
created:        2010-12-01T15:14:27Z
last-modified:  2015-01-09T14:19:28Z
source:         RIPE
role:           INEA S.A.
address:        ul. Klaudyny Potockiej 25
address:        60-211 Poznan
nic-hdl:        INEA-RIPE
mnt-by:         INEA-MNT
admin-c:        PA7317-RIPE
tech-c:         PA7317-RIPE
tech-c:         PSZY
created:        2014-07-14T09:26:21Z
last-modified:  2015-01-21T10:25:56Z
source:         RIPE # Filtered
% Information related to '77.65.0.0/17AS13110'
route:          77.65.0.0/17
descr:          INEA S.A.
descr:          Poznan
origin:         AS13110
mnt-by:         INEA-MNT
created:        2007-02-12T09:03:39Z
last-modified:  2015-01-27T10:14:29Z
source:         RIPE
% This query was served by the RIPE Database Query Service version 1.97.2 (HEREFORD)

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

Conclusion

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.

Check out the following post

How to Get Domain Whois Data in C with Sockets on Linux - Code Example

Further Reading:

http://en.wikipedia.org/wiki/Regional_Internet_registry
About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

Leave a Reply

Your email address will not be published. Required fields are marked *