/**************************************************************************/ // resolver.h - header file for resolver.cpp /*************************************************************************** * The Dawn of Time v1.69r (c)1997-2003 Michael Garratt * * >> A number of people have contributed to the Dawn codebase, with the * * majority of code written by Michael Garratt - www.dawnoftime.org * * >> To use this source code, you must fully comply with the dawn license * * in licenses.txt... In particular, you may not remove this copyright * * notice. * **************************************************************************/ #ifndef __RESOLVER_H__ #define __RESOLVER_H__ #ifndef __IN_RESOLVER_CPP__ #error This file "resolver.h" should only be included by resolver.cpp #endif #if defined(__APPLE__) && defined(__MACH__) // mac os-x // __APPLE__ by itself, is a mac that isn't based on an Mach kernel. #define unix #endif #if defined(__unix__) && !defined(unix) // we expect to see unix #define unix __unix__ #endif /**************************************************************************/ // windows compiler work to figure out what winsock components we need #ifdef WIN32 #include "../wincfg.h" #define WIN32_LEAN_AND_MEAN // Speed up the compiling process #ifdef WIN32_IPV6 // Incomplete IPv6 support requires winsock2 #define WIN32_USE_WINSOCK2 #endif // are we using winsock v1 or winsock v2 #ifdef WIN32_USE_WINSOCK2 #include <winsock2.h> #include <winsock.h> #pragma comment( lib, "ws2_32.lib") // saves adding the library to the project :) #else #include <winsock.h> #pragma comment( lib, "wsock32.lib") // saves adding the library to the project :) #endif // are we using ipv6 #ifdef WIN32_IPV6 #define IPV6_SUPPORT_ENABLED #include <ws2tcpip.h> #include <tpipv6.h> #endif #endif // extern globals /**************************************************************************/ #include <assert.h> #ifndef DEBUG #define DEBUG #endif #ifdef WIN32 #include <time.h> #include <sys/timeb.h> #else #include "../config.h" #ifdef TIME_WITH_SYS_TIME #include <sys/time.h> #include <time.h> #else #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #else #include <time.h> #endif #endif #include <sys/resource.h> #include <unistd.h> #include <sys/socket.h> #endif #include <sys/types.h> #include <errno.h> #include <ctype.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef unix #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <errno.h> typedef int SOCKET; typedef struct sockaddr_in SOCKADDR_IN; #define SOCKET_ERROR (-1) #define INVALID_SOCKET (SOCKET)(~0) #define closesocket(sock) close(sock) #endif #ifdef WIN32 // compatiblity macros #define vsnprintf(buf, len, fmt, args) _vsnprintf(buf, len, fmt, args) #define popen(command, mode) _popen(command,mode) #define pclose(fp) _pclose(fp) #define getcwd(dir, size) _getcwd(dir, size) #define chdir(dir) _chdir(dir) #define mkdir(dir) _mkdir(dir) #define snprintf _snprintf typedef int socklen_t; #endif /**************************************************************************/ // structs //typedef unsigned long ip_address; #ifdef IPV6_SUPPORT_ENABLED typedef sockaddr_storage sockaddr_type; #else typedef sockaddr_in sockaddr_type; #endif /**************************************************************************/ char *convert_sockaddr_into_textip(const struct sockaddr* sa, socklen_t salen); char *shortdate(time_t *tm); #ifdef WIN32 #define get_socket_error_text(errorcode) get_winsock_error_text(errorcode) const char *get_winsock_error_text(int errorcode); #else #define get_socket_error_text(errorcode) gai_strerror(errorcode) #endif /**************************************************************************/ class hnode { public: sockaddr_type socket_address; size_t address_length; char *szAddr; char *hostname; char *ident_result; time_t reresolve_after; int ident_failure_count; // true if an ident from this port has failed in the past time_t retry_ident_after; // doubles each time 1 minute, 2minutes, 4minutes hnode *next; public: hnode(sockaddr_type *ipaddr, socklen_t ipaddress_len); // ~hnode(); }; /**************************************************************************/ // Class Constructor - technically this shouldn't go in here, but // since resolver.h is only included by one file, we get away with it. // and it makes the resolver.cpp file cleaner. hnode::hnode(sockaddr_type *ipaddr, socklen_t ipaddress_len) { memcpy(&socket_address, ipaddr, sizeof(sockaddr_type)); // convert the ip address into a string address_length=ipaddress_len; szAddr=strdup(convert_sockaddr_into_textip((const struct sockaddr *)&socket_address, address_length)); reresolve_after=0; hostname=NULL; ident_result=NULL; ident_failure_count=0; retry_ident_after=0; next=NULL; } /**************************************************************************/ // response to a command -> stdout void resolver_response(const char *str) { #ifndef RESOLVER_DEBUG_BRACKETS fprintf(stdout, "%s\n", str); fflush(stdout); #else fprintf(stdout, "STDOUT[[[%s]]]\n", str); fflush(stdout); fprintf(stderr, "STDERR COPY OF STDOUT[[[%s]]]\n", str); fflush(stderr); #endif } /**************************************************************************/ // response to a command -> stdout void resolver_responsef(char * fmt, ...) { char buf[1024]; va_list args; va_start(args, fmt); vsnprintf(buf, 1014, fmt, args); va_end(args); resolver_response(buf); } /**************************************************************************/ // general logging and debugging information -> stderr void resolver_log(int verbose, const char *str) { if(verbose>VERBOSE_LEVEL){ return; } #ifndef RESOLVER_DEBUG_BRACKETS fprintf(stderr, "%s:resolver: %s\n", shortdate(NULL)+4, str); #else fprintf(stderr, "STDERR{%d}[[[%s:resolver: %s]]]\n", verbose, shortdate(NULL)+4, str); #endif fflush(stderr); } /**************************************************************************/ // general logging and debugging information -> stderr void resolver_logf(int verbose, char * fmt, ...) { if(verbose>VERBOSE_LEVEL){ return; } char buf[1024]; va_list args; va_start(args, fmt); vsnprintf(buf, 1014, fmt, args); va_end(args); resolver_log(verbose, buf); } bool init_network(); // macros for working smarter not harder :) #define IS_NULLSTR(str) ((str)==NULL || *(str)=='\0') #define HHK (55) // hosts hash key hnode * hosts_table[HHK]; /**************************************************************************/ int get_hash_key(sockaddr_type *ip_address, size_t address_length) { unsigned int key; int total=0; unsigned char *p; p=(unsigned char *)ip_address; for(size_t i=0;i<address_length; i++){ total+=p[i]; } key=total%HHK; return key; } /**************************************************************************/ char *convert_sockaddr_into_textip(const struct sockaddr* sa, socklen_t salen) { static int i; static char buf[4][8196]; ++i%=4; #ifdef IPV6_SUPPORT_ENABLED char sz_host[NI_MAXHOST+1], sz_serv[NI_MAXSERV+1]; int hostlen = NI_MAXHOST, servlen = NI_MAXSERV, result; result = getnameinfo( sa, salen, sz_host, hostlen, sz_serv, servlen, NI_NUMERICHOST | NI_NUMERICSERV); if(result!=0){ sprintf(buf[i],"convert_sockaddr_into_textip()-error_%d(%s)_while_converting_address", result, get_socket_error_text(result)); }else{ strcpy(buf[i], sz_host); } #else const struct sockaddr_in *sa2=(struct sockaddr_in*)sa; strcpy(buf[i],inet_ntoa(sa2->sin_addr)); #endif return buf[i]; } /**************************************************************************/ // winsockError() prints to stderr the laston winsock error #ifdef WIN32 const char *get_winsock_error_text(int errorcode) { static char result[8196]; // This function is only for use in WIN32 #define WEM_CASE(m) case m: pszMsg = #m ; break const char *pszMsg; int iError=0; if(errorcode!=0){ iError=errorcode; }else{ iError=WSAGetLastError(); } switch(iError){ WEM_CASE(WSABASEERR); WEM_CASE(WSAEINTR); WEM_CASE(WSAEBADF); WEM_CASE(WSAEACCES); WEM_CASE(WSAEFAULT); WEM_CASE(WSAEINVAL); WEM_CASE(WSAEMFILE); WEM_CASE(WSAEWOULDBLOCK); WEM_CASE(WSAEINPROGRESS); WEM_CASE(WSAEALREADY); WEM_CASE(WSAENOTSOCK); WEM_CASE(WSAEDESTADDRREQ); WEM_CASE(WSAEMSGSIZE); WEM_CASE(WSAEPROTOTYPE); WEM_CASE(WSAENOPROTOOPT); WEM_CASE(WSAEPROTONOSUPPORT); WEM_CASE(WSAESOCKTNOSUPPORT); WEM_CASE(WSAEOPNOTSUPP); WEM_CASE(WSAEPFNOSUPPORT); WEM_CASE(WSAEAFNOSUPPORT); WEM_CASE(WSAEADDRINUSE); WEM_CASE(WSAEADDRNOTAVAIL); WEM_CASE(WSAENETDOWN); WEM_CASE(WSAENETUNREACH); WEM_CASE(WSAENETRESET); WEM_CASE(WSAECONNABORTED); WEM_CASE(WSAECONNRESET); WEM_CASE(WSAENOBUFS); WEM_CASE(WSAEISCONN); WEM_CASE(WSAENOTCONN); WEM_CASE(WSAESHUTDOWN); WEM_CASE(WSAETOOMANYREFS); WEM_CASE(WSAETIMEDOUT); WEM_CASE(WSAECONNREFUSED); WEM_CASE(WSAELOOP); WEM_CASE(WSAENAMETOOLONG); WEM_CASE(WSAEHOSTDOWN); WEM_CASE(WSAEHOSTUNREACH); WEM_CASE(WSAENOTEMPTY); WEM_CASE(WSAEPROCLIM); WEM_CASE(WSAEUSERS); WEM_CASE(WSAEDQUOT); WEM_CASE(WSAESTALE); WEM_CASE(WSAEREMOTE); WEM_CASE(WSAEDISCON); WEM_CASE(WSASYSNOTREADY); WEM_CASE(WSAVERNOTSUPPORTED); WEM_CASE(WSANOTINITIALISED); WEM_CASE(WSAHOST_NOT_FOUND); WEM_CASE(WSATRY_AGAIN); WEM_CASE(WSANO_RECOVERY); WEM_CASE(WSANO_DATA); default: pszMsg=NULL; } if(pszMsg){ sprintf(result,"%s(%d)", pszMsg, iError); }else{ sprintf(result,"unknown winsock error value %d.", iError); } return result; } #endif /**************************************************************************/ void socket_error(const char *text) { #ifdef unix perror(text); return; #endif #ifdef WIN32 resolver_logf(2, "%s - %s", text, get_winsock_error_text(0)); return; #endif } /**************************************************************************/ void sleep_seconds(int seconds) { #ifdef WIN32 Sleep( seconds*1000); #else sleep( seconds); #endif } /**************************************************************************/ #ifdef WIN32 void gettimeofday( struct timeval *tp, void *tzp ) { tp->tv_sec = time( NULL ); tp->tv_usec = 0; } #endif /**************************************************************************/ // returns true if successful, only called if running on WIN32 #ifdef WIN32 bool init_winsock() { // Startup winsock support in windows #ifdef WIN32_USE_WINSOCK2 WORD wVersionRequested = MAKEWORD( 2, 0 ); #else WORD wVersionRequested = MAKEWORD( 1, 1 ); #endif WSADATA wsaData; if ( WSAStartup( wVersionRequested, &wsaData ) ){ #ifdef WIN32_USE_WINSOCK2 socket_error("Couldn't get any Winsock version 2 support!"); #else socket_error("Couldn't get any Winsock version 1.1 support!"); #endif return false; } resolver_logf(2, "winsock started"); return true; } #endif /**************************************************************************/ // exits if network initialisation fails bool init_network() { #ifdef WIN32 return init_winsock(); #endif return true; } /**************************************************************************/ // returns true if successful, only called if running on WIN32 #ifdef WIN32 bool close_winsock() { if ( WSACleanup() ){ socket_error("WSACleanup() error."); return false; } return true; } #endif /**************************************************************************/ // exits if network initialisation fails void close_network() { #ifdef WIN32 if(!close_winsock()){ exit(1); } #endif } /**************************************************************************/ // get the current time time_t current_time(void) { struct timeval this_time; gettimeofday( &this_time, NULL ); return this_time.tv_sec; } /**************************************************************************/ char *shortdate(time_t *tm) // kalahn - sept 97 { #ifndef DATE_IN_LOGS return ""; #endif static int i; static char result[3][30]; // rotate buffers ++i= i%3; result[i][0] = '\0'; struct timeval last_time; gettimeofday( &last_time, NULL ); time_t current_time = (time_t) last_time.tv_sec; if(!tm){ tm=¤t_time; } char *tbuf = ctime( tm ); tbuf[strlen(tbuf)-6] = '\0'; strcpy(result[i], tbuf); return(result[i]); } #endif // __RESOLVER_H__ /**************************************************************************/ /**************************************************************************/