C program to get a domain’s whois information using sockets on Linux

Whois

A whois client is a program that will simply fetch the whois information for a domain/ip address from the whois servers. The code over here works according to the algorithm discussed here.

Code

/*
 * @brief
 * Whois client program
 * 
 * @details
 * This program shall perform whois for a domain and get you the whois data of that domain
 * 
 * @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 get_whois_data(char * , char **);
int hostname_to_ip(char * , char *);
int whois_query(char * , char * , char **);
char *str_replace(char *search , char *replace , char *subject );

int main(int argc , char *argv[])
{
	char domain[100] , *data = NULL;
	
	printf("Enter domain name to whois : ");
	scanf("%s" , domain);
	
	get_whois_data(domain , &data);
	
	//puts(data);
	return 0;
}

/*
 * Get the whois data of a domain
 * */
int get_whois_data(char *domain , char **data)
{
	char ext[1024] , *pch , *response = NULL , *response_2 = NULL , *wch , *dt;

	//remove "http://" and "www."
	domain = str_replace("http://" , "" , domain);
	domain = str_replace("www." , "" , domain);

	//get the extension , com , org , edu
	dt = strdup(domain);
	if(dt == NULL)
	{
		printf("strdup failed");
	}
	pch = (char*)strtok(dt , ".");
	while(pch != NULL)
	{
		strcpy(ext , pch);
		pch = strtok(NULL , ".");
	}
	
	//This will tell the whois server for the particular TLD like com , org
	if(whois_query("whois.iana.org" , ext , &response))
	{
		printf("Whois query failed");
	}
	
	//Now analysze the response :)
	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");
	}

	
	
	//Now we have the TLD whois server in wch , query again
	//This will provide minimal whois information along with the parent whois server of the specific domain :)
	free(response);
	//This should not be necessary , but segmentation fault without this , why ?
	response = NULL;
	if(wch != NULL)
	{
		printf("\nTLD Whois server is : %s" , wch);
		if(whois_query(wch , domain , &response))
		{
			printf("Whois query failed");
		}
	}
	else
	{
		printf("\nTLD whois server for %s not found" , ext);
		return 1;
	}
	
	response_2 = strdup(response);

	//Again search for a whois server in this response. :)
	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 a registrar whois server is found then query it
	 * */
	if(wch)
	{
		//Now we have the registrar whois server , this has the direct full information of the particular domain
		//so lets query again
		
		printf("\nRegistrar Whois server is : %s" , wch);
		
		if(whois_query(wch , domain , &response))
		{
			printf("Whois query failed");
		}
		
		printf("\n%s" , response);
	}
	
	/*
	 * otherwise echo the output from the previous whois result
	 * */
	else
	{
		printf("%s" , response_2);
	}
	return 0;
}

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

/*
 * Search and replace a string with another string , in a string
 * */
char *str_replace(char *search , char *replace , char *subject)
{
	char  *p = NULL , *old = NULL , *new_subject = NULL ;
	int c = 0 , search_size;
	
	search_size = strlen(search);
	
	//Count how many occurences
	for(p = strstr(subject , search) ; p != NULL ; p = strstr(p + search_size , search))
	{
		c++;
	}
	
	//Final size
	c = ( strlen(replace) - search_size )*c + strlen(subject);
	
	//New subject with new size
	new_subject = malloc( c );
	
	//Set it to blank
	strcpy(new_subject , "");
	
	//The start position
	old = subject;
	
	for(p = strstr(subject , search) ; p != NULL ; p = strstr(p + search_size , search))
	{
		//move ahead and copy some text from original subject , from a certain position
		strncpy(new_subject + strlen(new_subject) , old , p - old);
		
		//move ahead and copy the replacement text
		strcpy(new_subject + strlen(new_subject) , replace);
		
		//The new start position after this search match
		old = p + search_size;
	}
	
	//Copy the part after the last search match
	strcpy(new_subject + strlen(new_subject) , old);
	
	return new_subject;
}







hostname_to_ip - This is a simple function to get an IP of a domain.
str_replace - This is a generic string processing function that is used to search for a string in another big string and replace it with another string.

Output

Enter domain name to whois : www.wikipedia.org

Resolving whois.iana.org...192.0.47.59
Querying for ... org ...Done
TLD Whois server is : whois.pir.org
Resolving whois.pir.org...149.17.192.7
Querying for ... wikipedia.org ...DoneAccess to .ORG WHOIS information is provided to assist persons in 
determining the contents of a domain name registration record in the 
Public Interest Registry registry database. The data in this record is provided by 
Public Interest Registry for informational purposes only, and Public Interest Registry does not 
guarantee its accuracy.  This service is intended only for query-based 
access. You agree that you will use this data only for lawful purposes 
and that, under no circumstances will you use this data to: (a) allow, 
enable, or otherwise support the transmission by e-mail, telephone, or 
facsimile of mass unsolicited, commercial advertising or solicitations 
to entities other than the data recipient's own existing customers; or 
(b) enable high volume, automated, electronic processes that send 
queries or data to the systems of Registry Operator, a Registrar, or 
Afilias except as reasonably necessary to register domain names or 
modify existing registrations. All rights reserved. Public Interest Registry reserves 
the right to modify these terms at any time. By submitting this query, 
you agree to abide by this policy. 

Domain ID:D51687756-LROR
Domain Name:WIKIPEDIA.ORG
Created On:13-Jan-2001 00:12:14 UTC
Last Updated On:02-Dec-2009 20:57:17 UTC
Expiration Date:13-Jan-2015 00:12:14 UTC
Sponsoring Registrar:GoDaddy.com, Inc. (R91-LROR)
Status:CLIENT DELETE PROHIBITED
Status:CLIENT RENEW PROHIBITED
Status:CLIENT TRANSFER PROHIBITED
Status:CLIENT UPDATE PROHIBITED
Registrant ID:CR31094073
Registrant Name:DNS Admin
Registrant Organization:Wikimedia Foundation, Inc.
Registrant Street1:149 New Montgomery Street
Registrant Street2:Third Floor
Registrant Street3:
Registrant City:San Francisco
Registrant State/Province:California
Registrant Postal Code:94105
Registrant Country:US
Registrant Phone:+1.4158396885
Registrant Phone Ext.:
Registrant FAX:+1.4158820495
Registrant FAX Ext.:
Registrant Email:[email protected]
Admin ID:CR31094075
Admin Name:DNS Admin
Admin Organization:Wikimedia Foundation, Inc.
Admin Street1:149 New Montgomery Street
Admin Street2:Third Floor
Admin Street3:
Admin City:San Francisco
Admin State/Province:California
Admin Postal Code:94105
Admin Country:US
Admin Phone:+1.4158396885
Admin Phone Ext.:
Admin FAX:+1.4158820495
Admin FAX Ext.:
Admin Email:[email protected]
Tech ID:CR31094074
Tech Name:DNS Admin
Tech Organization:Wikimedia Foundation, Inc.
Tech Street1:149 New Montgomery Street
Tech Street2:Third Floor
Tech Street3:
Tech City:San Francisco
Tech State/Province:California
Tech Postal Code:94105
Tech Country:US
Tech Phone:+1.4158396885
Tech Phone Ext.:
Tech FAX:+1.4158820495
Tech FAX Ext.:
Tech Email:[email protected]
Name Server:NS0.WIKIMEDIA.ORG
Name Server:NS1.WIKIMEDIA.ORG
Name Server:NS2.WIKIMEDIA.ORG
Name Server: 
Name Server: 
Name Server: 
Name Server: 
Name Server: 
Name Server: 
Name Server: 
Name Server: 
Name Server: 
Name Server: 
DNSSEC:Unsigned
Last Updated On : 28th November 2012

Subscribe to get updates delivered to your inbox

4 Comments + Add Comment

  • In the whois information, I’ve got creation date of the domain.
    But different whois server responses has different date format of creation date.
    Is there any way to get that date in a specific date format?

  • Very great work sir,got lots of information from your work…..thank you very much…..i Need your help sir……can you please give me code or the way/idea to find / detect the operating system of remote system most preferably in winsock…..inux also no problem.
    I am building a port scanner for my academic project…..waiting for your reply

    • to find out the os of the remote system is called “os fingerprinting” and can be done by reading various fields of the tcp header from the packets of the remote system. Fields like ttl, window size etc.

      this will require some raw socket programming/packet sniffing.
      google for more information.

      • THANK YOU VERY MUCH SIR…….sorry for being late

Leave a comment