⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dns.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						cryptlib DNS Interface Routines						*
*						Copyright Peter Gutmann 1998-2007					*
*																			*
****************************************************************************/

#include <ctype.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "stream_int.h"
  #include "tcp.h"
#else
  #include "crypt.h"
  #include "io/stream_int.h"
  #include "io/tcp.h"
#endif /* Compiler-specific includes */

#ifdef USE_TCP

/****************************************************************************
*																			*
*						 		Init/Shutdown Routines						*
*																			*
****************************************************************************/

#ifdef __WINDOWS__

/* Global function pointers.  These are necessary because the functions need
   to be dynamically linked since not all systems contain the necessary
   libraries */

#if ( defined( sun ) && OSVERSION > 4 )
#undef htonl		/* Slowaris has defines that conflict with our ones */
#undef htons
#undef ntohl
#undef ntohs
#endif /* Slowaris */

#ifndef TEXT
  #define TEXT		/* Win32 windows.h defines this, but not the Win16 one */
#endif /* TEXT */

#if defined( _MSC_VER ) && defined( _PREFAST_ ) 
  #define OUT_STRING_OPT	__out_bcount_z
#else
  #define OUT_STRING_OPT( size )
#endif /* Additional markups for Win32 API functions */

typedef void ( SOCKET_API *FREEADDRINFO )( INOUT struct addrinfo *ai ) \
						STDC_NONNULL_ARG( ( 1 ) );
typedef CHECK_RETVAL int ( SOCKET_API *GETADDRINFO )\
						( IN_STRING const char *nodename, 
						  IN_STRING const char *servname, 
						  const struct addrinfo *hints,
						  OUT_PTR struct addrinfo **res );
typedef CHECK_RETVAL struct hostent FAR * ( SOCKET_API *GETHOSTBYNAME )\
						( IN_STRING const char FAR *name ) \
						STDC_NONNULL_ARG( ( 1 ) );
typedef CHECK_RETVAL int ( SOCKET_API *GETNAMEINFO )\
						( IN_BUFFER( salen ) const struct sockaddr *sa, 
						  IN SIZE_TYPE salen,
						  OUT_BUFFER_FIXED( nodelen ) char *node, 
						  IN SIZE_TYPE nodelen,
						  OUT_STRING_OPT( servicelen ) char *service, 
						  IN SIZE_TYPE servicelen, int flags ) \
						STDC_NONNULL_ARG( ( 1, 3, 5 ) );
typedef CHECK_RETVAL u_long ( SOCKET_API *HTONL )( u_long hostlong );
typedef CHECK_RETVAL u_short ( SOCKET_API *HTONS )( u_short hostshort );
typedef CHECK_RETVAL unsigned long ( SOCKET_API *INET_ADDR )\
						( IN_STRING const char FAR *cp ) \
						STDC_NONNULL_ARG( ( 1 ) );
typedef CHECK_RETVAL char FAR * ( SOCKET_API *INET_NTOA )( struct in_addr in );
typedef CHECK_RETVAL u_long ( SOCKET_API *NTOHL )( u_long netlong );
typedef CHECK_RETVAL u_short ( SOCKET_API *NTOHS )( u_short netshort );
typedef int ( SOCKET_API *WSAGETLASTERROR )( void );

static FREEADDRINFO pfreeaddrinfo = NULL;
static GETADDRINFO pgetaddrinfo = NULL;
static GETHOSTBYNAME pgethostbyname = NULL;
static GETNAMEINFO pgetnameinfo = NULL;
static HTONL phtonl = NULL;
static HTONS phtons = NULL;
static INET_ADDR pinet_addr = NULL;
static INET_NTOA pinet_ntoa = NULL;
static NTOHL pntohl = NULL;
static NTOHS pntohs = NULL;
static WSAGETLASTERROR pWSAGetLastError = NULL;

#define freeaddrinfo		pfreeaddrinfo
#define getaddrinfo			pgetaddrinfo
#define gethostbyname		pgethostbyname
#define getnameinfo			pgetnameinfo
#define htonl				phtonl
#define htons				phtons
#define inet_addr			pinet_addr
#define inet_ntoa			pinet_ntoa
#define ntohl				pntohl
#define ntohs				pntohs
#ifndef WSAGetLastError
  /* In some environments WSAGetLastError() is a macro that maps to
     GetLastError() */
  #define WSAGetLastError	pWSAGetLastError
  #define DYNLOAD_WSAGETLASTERROR
#endif /* WSAGetLastError */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
static int SOCKET_API my_getaddrinfo( IN_STRING const char *nodename,
									  IN_STRING const char *servname,
									  const struct addrinfo *hints,
									  OUT_PTR struct addrinfo **res );
STDC_NONNULL_ARG( ( 1 ) ) \
static void SOCKET_API my_freeaddrinfo( IN struct addrinfo *ai );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
static int SOCKET_API my_getnameinfo( IN_BUFFER( salen ) \
									  const struct sockaddr *sa,
									  IN SIZE_TYPE salen, 
									  OUT_BUFFER_FIXED( nodelen ) char *node, 
									  IN SIZE_TYPE nodelen, 
									  OUT_BUFFER_FIXED( servicelen ) \
									  char *service, 
									  IN SIZE_TYPE servicelen, IN int flags );

CHECK_RETVAL \
int initDNS( const INSTANCE_HANDLE hTCP, const INSTANCE_HANDLE hAddr )
	{
	/* Get the required TCP/IP functions */
	gethostbyname = ( GETHOSTBYNAME ) DynamicBind( hTCP, TEXT( "gethostbyname" ) );
	htonl = ( HTONL ) DynamicBind( hTCP, TEXT( "htonl" ) );
	htons = ( HTONS ) DynamicBind( hTCP, TEXT( "htons" ) );
	inet_addr = ( INET_ADDR ) DynamicBind( hTCP, TEXT( "inet_addr" ) );
	inet_ntoa = ( INET_NTOA ) DynamicBind( hTCP, TEXT( "inet_ntoa" ) );
	ntohl = ( NTOHL ) DynamicBind( hTCP, TEXT( "ntohl" ) );
	ntohs = ( NTOHS ) DynamicBind( hTCP, TEXT( "ntohs" ) );
  #ifdef DYNLOAD_WSAGETLASTERROR
	WSAGetLastError = ( WSAGETLASTERROR ) DynamicBind( hTCP, TEXT( "WSAGetLastError" ) );
  #endif /* DYNLOAD_WSAGETLASTERROR */
	if( gethostbyname == NULL || htonl == NULL || htons == NULL || \
		inet_addr == NULL || inet_ntoa == NULL || ntohl == NULL || \
		ntohs == NULL )
		return( CRYPT_ERROR );

	/* Set up the IPv6-style name/address functions */
	if( hAddr != NULL_INSTANCE )
		{
		freeaddrinfo = ( FREEADDRINFO ) DynamicBind( hAddr, TEXT( "freeaddrinfo" ) );
		getaddrinfo = ( GETADDRINFO ) DynamicBind( hAddr, TEXT( "getaddrinfo" ) );
		getnameinfo = ( GETNAMEINFO ) DynamicBind( hAddr, TEXT( "getnameinfo" ) );
		if( freeaddrinfo == NULL || getaddrinfo == NULL || \
			getnameinfo == NULL )
			return( CRYPT_ERROR );
		}
	else
		{
		/* If we couldn't dynamically bind the IPv6 name/address functions,
		   use a local emulation */
		getaddrinfo = my_getaddrinfo;
		freeaddrinfo = my_freeaddrinfo;
		getnameinfo = my_getnameinfo;
		}

	/* If the DNS SRV init fails it's not a serious problem, we can continue 
	   without it */
	( void ) initDNSSRV( hTCP );

	return( CRYPT_OK );
	}

void endDNS( const INSTANCE_HANDLE hTCP )
	{
	endDNSSRV( hTCP );
	}
#endif /* __WINDOWS__ */

/****************************************************************************
*																			*
*						 		IPv6 Emulation								*
*																			*
****************************************************************************/

/* Emulation of IPv6 networking functions.  We include these unconditionally
   under Windows because with dynamic binding we can't be sure whether 
   they're needed or not */

#if !defined( IPv6 ) || defined( __WINDOWS__ )

CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \
static int addAddrInfo( INOUT_OPT struct addrinfo *prevAddrInfoPtr,
						OUT_PTR struct addrinfo **addrInfoPtrPtr,
						IN_BUFFER( addrLen ) const void *address, 
						IN_RANGE( IP_ADDR_SIZE, IP_ADDR_SIZE ) \
						const int addrLen,  IN_PORT const int port )
	{
	struct addrinfo *addrInfoPtr;
	struct sockaddr_in *sockAddrPtr;

	assert( prevAddrInfoPtr == NULL || \
			isWritePtr( prevAddrInfoPtr, sizeof( struct addrinfo ) ) );
	assert( isWritePtr( addrInfoPtrPtr, sizeof( struct addrinfo * ) ) );
	assert( isReadPtr( address, addrLen ) );
	
	REQUIRES( addrLen == IP_ADDR_SIZE );
	REQUIRES( port >= 22 && port < 65536L );

	/* Clear return value */
	*addrInfoPtrPtr = NULL;

	/* Allocate the new element, clear it, and set fixed fields for IPv4 */
	if( ( addrInfoPtr = clAlloc( "addAddrInfo", \
								 sizeof( struct addrinfo ) ) ) == NULL || \
		( sockAddrPtr = clAlloc( "addAddrInfo", \
								 sizeof( struct sockaddr ) ) ) == NULL )
		{
		if( addrInfoPtr != NULL )
			clFree( "addAddrInfo", addrInfoPtr );
		return( -1 );
		}
	memset( addrInfoPtr, 0, sizeof( struct addrinfo ) );
	memset( sockAddrPtr, 0, sizeof( struct sockaddr ) );
	if( prevAddrInfoPtr != NULL )
		prevAddrInfoPtr->ai_next = addrInfoPtr;
	addrInfoPtr->ai_family = PF_INET;
	addrInfoPtr->ai_socktype = SOCK_STREAM;
	addrInfoPtr->ai_protocol = IPPROTO_TCP;
	addrInfoPtr->ai_addrlen = sizeof( struct sockaddr_in );
	addrInfoPtr->ai_addr = ( struct sockaddr * ) sockAddrPtr;

	/* Set the port and address information.  In general we'd copy the
	   address to the sockAddrPtr->sin_addr.s_addr member, however on
	   Crays, which don't have 32-bit data types, this is a 32-bit
	   bitfield, so we have to use the encapsulating struct */
	sockAddrPtr->sin_family = AF_INET;
	sockAddrPtr->sin_port = htons( ( in_port_t ) port );
	memcpy( &sockAddrPtr->sin_addr, address, addrLen );
	*addrInfoPtrPtr = addrInfoPtr;
	return( 0 );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
static int SOCKET_API my_getaddrinfo( IN_STRING const char *nodename,
									  IN_STRING const char *servname,
									  const struct addrinfo *hints,
									  OUT_PTR struct addrinfo **res )
	{
	struct hostent *pHostent;
	struct addrinfo *currentAddrInfoPtr = NULL;
	const int port = atoi( servname );
	int hostErrno, i;
	gethostbyname_vars();

	assert( nodename != NULL || ( hints->ai_flags & AI_PASSIVE ) );
	assert( servname != NULL );
	assert( isReadPtr( hints, sizeof( struct addrinfo ) ) );
	assert( isWritePtr( res, sizeof( struct addrinfo * ) ) );
	assert( sizeof( in_addr_t ) == IP_ADDR_SIZE );

	/* Clear return value */
	*res = NULL;

	/* Perform basic error checking.  Since this is supposed to be an 
	   emulation of a (normally) built-in function we don't perform any 
	   REQUIRES()-style checking but only apply the basic checks that the 
	   normal built-in form does */
	if( ( nodename == NULL && !( hints->ai_flags & AI_PASSIVE ) ) || \
		servname == NULL || hints == NULL || res == NULL )
		return( -1 );

	/* If there's no interface specified and we're creating a server-side
	   socket, prepare to listen on any interface.  Note that BeOS can only
	   bind to one interface at a time, so INADDR_ANY actually binds to the
	   first interface that it finds */
	if( nodename == NULL && ( hints->ai_flags & AI_PASSIVE ) )
		{
		const in_addr_t address = INADDR_ANY;

		return( addAddrInfo( NULL, res, &address, sizeof( in_addr_t  ), 
							 port ) );
		}

	/* If it's a dotted address, there's a single address, convert it to
	   in_addr form and return it.  Note for EBCDIC use that since this is
	   an emulation of an OS function the string is already in EBCDIC form,
	   so we don't use the cryptlib-internal functions for this */
	if( isdigit( *nodename ) )
		{
		const in_addr_t address = inet_addr( nodename );

		if( isBadAddress( address ) )
			return( -1 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -