Code:
/*
* whois.c
*
* (c) Feb 2000 by Gandalf
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define WIN32_LEAN_AND_MEAN /* define win 32 only */
#include <windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
#define BUF_LEN 10000 /* Buffer size for transfers */
void handle_error(void); /* Error handler routine */
void write_file(char *buf); /* Write details to log file */
int main (int argc, char **argv)
{
WORD wVersionRequested; /* socket dll version info */
WSADATA wsaData; /* data for socket lib initialisation */
SOCKET sock; /* socket details */
struct sockaddr_in address; /* socket address stuff */
struct hostent * host; /* host stuff */
int err; /* error trapping */
float socklib_ver; /* socket dll version */
char File_Buf[BUF_LEN]; /* file buffer */
char DomainName[100]; /* domain name from user */
char HostName[100]; /* host name from user */
time_t now; /* for date and time */
if (argc < 2) /* check we have command line options */
{
printf("\nUseage: whois domainname [whois.server]\n");
exit(0);
}
strcat(DomainName, argv[1]); /* get domain name from command line */
strcat(DomainName, "\r\n"); /* add crlf as whois servers expect it */
if (argc == 3)
strcat(HostName, argv[2]); /* get host name from command line */
else
strcat(HostName, "whois.internic.net");
wVersionRequested = MAKEWORD( 1, 1 );
/*
* We need to call the WSAStartup routine BEFORE we try to use any of
* the Winsock dll calls.
*/
if ( WSAStartup( wVersionRequested, &wsaData ) != 0 )
handle_error();
/* Check socket DLL supports 1.1 or higher */
socklib_ver = HIBYTE( wsaData.wVersion ) / 10.0;
socklib_ver += LOBYTE( wsaData.wVersion );
if ( socklib_ver < 1.1 )
{
printf ("\nError: socket library must support 1.1 or greater.\n");
WSACleanup(); /* clean up before exit */
exit(0);
}
/* write current date and time to log file and screen */
time(&now);
sprintf(File_Buf, "Whois Session Started %.24s.\n\n", ctime(&now));
write_file(File_Buf);
/*
* Open a socket. The AF_INET parameter tells windows we want to use the
* internet. Other parameters for different networking can be chosen e.g.
* for netbios, IPX etc. The SOCK_STREAM parameter lets windows know we want
* to use TCP rather than UDP, and the final parameter will always be
* zero for what we want to do and tells windows to use whatever
* default communication protocol has been established (eg PPP and IP)
*/
if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
handle_error();
/* We now need to initialise a couple of variables in the address
* structure. Once again, to tell windows we are using the internet,
* and also what port we want to use when connecting to a remote
* computer. In this case it is port 43 which is the standard port for
* whois. The htons routine is used to convert the way Intel chips
* store data in memory, which is different compared to many other computers.
* The standard is based on Motorola format.
*/
address.sin_family=AF_INET; /* internet */
address.sin_port = htons(43); /* port 43 for whois */
/* write to the log file and screen */
sprintf(File_Buf,"Connecting to %s\n", HostName);
write_file(File_Buf);
/*
* host is a pointer to a structure of the predefined type hostent. We
* need to call gethostbyname with the DNS name we want to use to return
* a pointer to a hostent structure. This is so we can resolve an IP
* address from our ISP's nameserver.
*/
if ( (host=gethostbyname(HostName)) == NULL )
handle_error();
/* we then initialise the address structure with the resolved IP address */
address.sin_addr.s_addr=*((unsigned long *) host->h_addr);
/* Now we're ready to actually connect to the whois server itself */
if ( (connect(sock,(struct sockaddr *) &address, sizeof(address))) != 0)
handle_error();
/*
* We should be connected to the whois server at this point
* so we need to send the domain name and wait for the response. The send
* and recv routines are always used with TCP. These enable handshaking
* compared to the sendto and recvfrom routines which are used for UDP
* protocol, ie without handshaking.
*/
strcpy(File_Buf, DomainName);
err=send(sock,File_Buf,strlen(File_Buf),0); /* send domain name */
err=recv(sock,File_Buf,BUF_LEN,0); /* discard first response */
err=recv(sock,File_Buf,BUF_LEN,0); /* get query results back */
write_file(File_Buf);
/* Always call WSACleanup before exiting */
WSACleanup(); /* clean up before exit */
exit(0);
}
void handle_error(void)
{
/*
* Errors are handled by calling the WSAGetLastError routine which
* will return the last error as one of the following. As we develop
* this tutorial, we will go into much more detail on what they mean
* and what caused them.
*/
switch ( WSAGetLastError() )
{
case WSANOTINITIALISED :
printf("Unable to initialise socket.\n");
break;
case WSAEAFNOSUPPORT :
printf("The specified address family is not supported.\n");
break;
case WSAEADDRNOTAVAIL :
printf("Specified address is not available from the local machine.\n");
break;
case WSAECONNREFUSED :
printf("The attempt to connect was forcefully rejected.\n");
break;
case WSAEDESTADDRREQ :
printf("address destination address is required.\n");
break;
case WSAEFAULT :
printf("The namelen argument is incorrect.\n");
break;
case WSAEINVAL :
printf("The socket is not already bound to an address.\n");
break;
case WSAEISCONN :
printf("The socket is already connected.\n");
break;
case WSAEADDRINUSE :
printf("The specified address is already in use.\n");
break;
case WSAEMFILE :
printf("No more file descriptors are available.\n");
break;
case WSAENOBUFS :
printf("No buffer space available. The socket cannot be created.\n");
break;
case WSAEPROTONOSUPPORT :
printf("The specified protocol is not supported.\n");
break;
case WSAEPROTOTYPE :
printf("The specified protocol is the wrong type for this socket.\n");
break;
case WSAENETUNREACH :
printf("The network can't be reached from this host at this time.\n");
break;
case WSAENOTSOCK :
printf("The descriptor is not a socket.\n");
break;
case WSAETIMEDOUT :
printf("Attempt timed out without establishing a connection.\n");
break;
case WSAESOCKTNOSUPPORT :
printf("Socket type is not supported in this address family.\n");
break;
case WSAENETDOWN :
printf("Network subsystem failure.\n");
break;
case WSAHOST_NOT_FOUND :
printf("Authoritative Answer Host not found.\n");
break;
case WSATRY_AGAIN :
printf("Non-Authoritative Host not found or SERVERFAIL.\n");
break;
case WSANO_RECOVERY :
printf("Non recoverable errors, FORMERR, REFUSED, NOTIMP.\n");
break;
case WSANO_DATA :
printf("Valid name, no data record of requested type.\n");
break;
case WSAEINPROGRESS :
printf("address blocking Windows Sockets operation is in progress.\n");
break;
case WSAEINTR :
printf("The (blocking) call was canceled via WSACancelBlockingCall().\n");
break;
default :
printf("Unknown error.\n");
break;
}
WSACleanup();
exit(0);
}
void write_file(char *buf)
{
/* writes results to a log file and also to the screen */
FILE *fp=fopen("whoislog.txt","a+");
fprintf(fp,"%s\n",buf);
fclose(fp);
printf("%s\n",buf);
}