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

📄 net_tcp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						cryptlib TCP/IP Interface Routines					*
*						Copyright Peter Gutmann 1998-2001					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "stream.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../keymgmt/stream.h"
#else
  #include "crypt.h"
  #include "keymgmt/stream.h"
#endif /* Compiler-specific includes */

#ifdef NET_TCP

#if defined( __WINDOWS__ )
  #include <winsock.h>
#elif defined( __UNIX__ )
  #undef C_IN			/* Defined via some versions of netdb.h */
  #include <errno.h>
  #include <fcntl.h>
  #include <netdb.h>
  #if ( defined( sun ) && OSVERSION <= 4 ) || defined( __hpux ) || \
	  defined( __bsdi__ ) || defined( __FreeBSD__ ) || \
	  defined( __OpenBSD__ )
	#include <netinet/in.h>
  #endif /* SunOS 4.x || PHUX || *BSDs */
  #include <arpa/inet.h>
  #ifdef __SCO_VERSION__
	#include <signal.h>
	#ifndef SIGIO
	  #include <sys/signal.h>
	#endif /* SIGIO not defined in signal.h - only from SCO */
  #endif /* UnixWare/SCO */
  #ifdef _AIX
	#include <sys/select.h>
  #endif /* Aches */
  #include <sys/socket.h>
  #include <sys/time.h>
  #include <sys/types.h>
#endif /* OS-specific includes and defines */

/* Portability defines */

#ifdef __WINDOWS__
  #define isBadSocket( socket )		( ( socket ) == INVALID_SOCKET )
  #define isSocketError( status )	( ( status ) == SOCKET_ERROR )
  #define isBadAddress( address )	( ( address ) == INADDR_NONE )
  #define isNonblockWarning()		( WSAGetLastError() == WSAEWOULDBLOCK )

  #define getErrorCode()			WSAGetLastError()
  #define getHostErrorCode()		WSAGetLastError()

  /* Windows doesn't define in_*_t's */
  #define in_addr_t					u_long
  #define in_port_t					u_short
#else
  #define INVALID_SOCKET			-1
  #define isBadSocket( socket )		( ( socket ) == -1 )
  #define isSocketError( status )	( ( status ) == -1 )
  #define isBadAddress( address )	( ( address ) == ( in_addr_t ) -1 )
  #define isNonblockWarning()		( errno == EINPROGRESS )

  #define getErrorCode()			errno
  #define getHostErrorCode()		h_errno

  /* Many older Unixen don't define the in_*_t's */
  #if ( defined( sun ) && OSVERSION <= 4 ) || defined( __hpux ) || \
	  defined( __bsdi__ ) || defined( __FreeBSD__ ) || \
	  defined( __OpenBSD__ ) || defined( __linux__ )
	#ifndef in_addr_t
	  #define in_addr_t				u_long
	  #define in_port_t				u_short
	#endif /* in_addr_t */
  #endif /* SunOS 4.x || PHUX || *BSDs || Linux */

  /* PHUX generally doesn't define h_errno, we have to be careful here since
     later versions may use macros to get around threading issues so we check
	 for the existence of a macro with the given name before defining our own
	 version */
  #if defined( __hpux ) && !defined( h_errno )
	/* Usually missing from netdb.h */
	extern int h_errno;
  #endif /* PHUX && !h_errno */

  /* Windows uses a distinct socket handle type and requires the use of
     separate closesocket() and ioctlsocket() functions because socket
	 handles aren't the same as standard Windows handles */
  #define SOCKET					int
  #define closesocket				close
  #define ioctlsocket				ioctl
#endif /* OS-specific portability defines */

/* The traditional way to set a descriptor to nonblocking mode was an
   ioctl with FIONBIO, however Posix prefers the O_NONBLOCK flag for fcntl
   so we use this if it's available */

#if defined( F_GETFL ) && defined( F_SETFL ) && defined( O_NONBLOCK )
  #define setSocketNonblocking( socket ) \
			{ \
			int flags; \
			\
			fcntl( socket, F_GETFL, &flags ); \
			fcntl( socket, F_SETFL, flags | O_NONBLOCK ); \
			}
#else
  #define setSocketNonblocking( socket ) \
			{ \
			long nonBlock = TRUE; \
			\
			ioctlsocket( socket, FIONBIO, &nonBlock ); \
			}
#endif /* F_GETFL && F_SETFL && O_NONBLOCK */

/* For some connections which involve long-running sessions we need to be
   able to gracefully recover from errors such as the remote process or
   host crashing and restarting, which we can do by closing and re-opening
   the connection.  The various situations are:

	Process crashes and restarts:
		Write: Remote host sends a RST in response to an attempt to continue
				a TCP session which it doesn't remember, which is reported
				locally as the dreaded (if you ssh or NNTP to remote hosts a
				lot) connection reset by peer error.
		Read: Remote host sends a FIN, we read 0 bytes.

	Network problem:
		Write: Data is resent, if a read is pending it returns ETIMEDOUT,
				otherwise write returns EPIPE or SIGPIPE (some
				implementations may return ENETUNREACH or EHOSTUNREACH if
				they receive the right ICMP information).
		Read: See above, without the write sematics.

	Host crashes and restarts:
		Write: Looks like a network outage until host is restarted, then gets
				an EPIPE/SIGPIPE.
		Read: As for write, but gets a ECONNRESET.

   The following macros check for error conditions which are currently
   defined as recoverable, in the future we may want to address some of the
   others listed above as well */

#ifdef __WINDOWS__
  #define isRecoverableError( status )	( ( status ) == WSAECONNRESET )
#else
  #define isRecoverableError( status )	( ( status ) == ECONNRESET )
#endif /* OS-specific status codes */

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

/* Dynamically bind in the networking code.  This is required under
   Windows (the Winsock DLLs) and Slowaris (which doesn't have sockets
   support in libc) */

#if defined( __WINDOWS__ ) || ( defined( sun ) && OSVERSION > 4 )

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

INSTANCE_HANDLE hTCP;

#ifdef __WINDOWS__
  #ifdef WSAAPI
	#define SOCKET_API	WSAAPI
  #else
    #define SOCKET_API	FAR PASCAL
  #endif /* WSAAPI */
#else
  #define SOCKET_API
  #define FAR
#endif /* Different socket API calling conventions */

typedef SOCKET ( SOCKET_API *ACCEPT )( SOCKET s, struct sockaddr *addr,
									   int *addrlen );
typedef int ( SOCKET_API *BIND )( SOCKET s, const struct sockaddr FAR *addr,
								  int namelen );
typedef int ( SOCKET_API *CONNECT )( SOCKET s, const struct sockaddr *name,
									 int namelen );
typedef struct hostent FAR * ( SOCKET_API *GETHOSTBYNAME )( const char FAR * name );
typedef int ( SOCKET_API *GETSOCKOPT )( SOCKET s, int level, int optname,
										char *optval, int FAR *optlen );
typedef u_long ( SOCKET_API *HTONL )( u_long hostlong );
typedef u_short ( SOCKET_API *HTONS )( u_short hostshort );
typedef unsigned long ( SOCKET_API *INET_ADDR )( const char FAR * cp );
typedef char FAR * ( SOCKET_API *INET_NTOA )( struct in_addr in );
typedef int ( SOCKET_API *LISTEN )( SOCKET s, int backlog );
typedef u_short ( SOCKET_API *NTOHS )( u_short netshort );
typedef int ( SOCKET_API *RECV )( SOCKET s, char *buf, int len, int flags );
typedef int ( SOCKET_API *SELECT )( int nfds, fd_set *readfds,
									fd_set *writefds, fd_set *exceptfds,
									const struct timeval *timeout );
typedef int ( SOCKET_API *SEND )( SOCKET s, const char *buf, int len,
								  int flags );
typedef int ( SOCKET_API *SETSOCKOPT )( SOCKET s, int level, int optname,
										char *optval, int optlen );
typedef SOCKET ( SOCKET_API *SOCKETFN )( int af, int type, int protocol );
#ifdef __WINDOWS__
typedef int ( SOCKET_API *CLOSESOCKET )( SOCKET s );
typedef int ( SOCKET_API *IOCTLSOCKET )( SOCKET s, long cmd,
										u_long FAR *argp );
typedef int ( SOCKET_API *WSACLEANUP )( void );
typedef int ( SOCKET_API *WSAGETLASTERROR )( void );
typedef int ( SOCKET_API *WSASTARTUP )( WORD wVersionRequested,
										LPWSADATA lpWSAData );
typedef int ( SOCKET_API *FDISSETFN )( SOCKET, fd_set * );
#endif /* __WINDOWS__ */

static ACCEPT paccept = NULL;
static BIND pbind = NULL;
static CONNECT pconnect = NULL;
static GETHOSTBYNAME pgethostbyname = NULL;
static GETSOCKOPT pgetsockopt = NULL;
static HTONL phtonl = NULL;
static HTONS phtons = NULL;
static INET_ADDR pinet_addr = NULL;
static INET_NTOA pinet_ntoa = NULL;
static LISTEN plisten = NULL;
static NTOHS pntohs = NULL;
static RECV precv = NULL;
static SELECT pselect = NULL;
static SEND psend = NULL;
static SETSOCKOPT psetsockopt = NULL;
static SOCKETFN psocket = NULL;
#ifdef __WINDOWS__
static CLOSESOCKET pclosesocket = NULL;
static IOCTLSOCKET pioctlsocket = NULL;
static WSACLEANUP pWSACleanup = NULL;
static WSAGETLASTERROR pWSAGetLastError = NULL;
static WSASTARTUP pWSAStartup = NULL;
static FDISSETFN pFDISSETfn = NULL;
#endif /* __WINDOWS__ */
#if ( defined( sun ) && OSVERSION > 4 )
static int *h_errnoPtr;

#undef getHostErrorCode
#define getHostErrorCode()	*h_errnoPtr

#undef htonl	/* Slowaris has defines which conflict with our ones */
#undef htons
#undef ntohs
#endif /* Slowaris */

#define accept				paccept
#define bind				pbind
#define connect				pconnect
#define gethostbyname		pgethostbyname
#define getsockopt			pgetsockopt
#define htonl				phtonl
#define htons				phtons
#define inet_addr			pinet_addr
#define inet_ntoa			pinet_ntoa
#define listen				plisten
#define ntohs				pntohs
#define recv				precv
#define select				pselect
#define send				psend
#define setsockopt			psetsockopt
#define socket				psocket
#ifdef __WINDOWS__
#define closesocket			pclosesocket
#define ioctlsocket			pioctlsocket
#define WSACleanup			pWSACleanup
#define WSAGetLastError		pWSAGetLastError
#define WSAStartup			pWSAStartup
#define __WSAFDIsSet		pFDISSETfn
#endif /* __WINDOWS__ */

/* Dynamically load and unload any necessary TCP/IP libraries.  Under Windows
   the dynamic loading is complicated by the existence of Winsock 1 vs
   Winsock 2, all recent systems will use Winsock 2 but we allow for Winsock 1
   as well just in case, and for use on 16-bit systems */

#ifdef __WINDOWS__
  #ifdef __WIN16__
	#define TCP_LIBNAME			"winsock.dll"
  #else
	#define TCP_LIBNAME			"ws2_32.dll"
	#define WINSOCK_OLD_LIBNAME	"wsock32.dll"
  #endif /* __WIN16__ */
#else
  #define TCP_LIBNAME			"libsocket.so"
#endif /* OS-specific TCP/IP library naming */

void netInitTCP( void )
	{
	STATIC_FN int initSocketPool( void );
#ifdef __WINDOWS__
	WSADATA wsaData;
  #ifdef __WIN16__
	UINT errorMode;
  #endif /* __WIN16__ */
#endif /* __WINDOWS__ */

	/* Obtain a handle to the module containing the TCP/IP functions */
#ifdef __WINDOWS__
  #ifdef __WIN16__
	errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
	hTCP = DynamicLoad( TCP_LIBNAME );
	SetErrorMode( errorMode );
	if( hTCP < HINSTANCE_ERROR )
		{
		hTCP = NULL_INSTANCE;
		return;
		}
  #else
	if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE && \
		( hTCP = DynamicLoad( WINSOCK_OLD_LIBNAME ) ) == NULL_INSTANCE )
		return;
  #endif /* Win16 vs Win32 */
#else
	if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE )
		return;
#endif /* OS-specific dynamic load */

	/* Now get pointers to the functions */
	accept = ( ACCEPT ) DynamicBind( hTCP, "accept" );
	bind = ( BIND ) DynamicBind( hTCP, "bind" );
	connect = ( CONNECT ) DynamicBind( hTCP, "connect" );
	gethostbyname = ( GETHOSTBYNAME ) DynamicBind( hTCP, "gethostbyname" );
	getsockopt = ( GETSOCKOPT ) DynamicBind( hTCP, "getsockopt" );
	htonl = ( HTONL ) DynamicBind( hTCP, "htonl" );
	htons = ( HTONS ) DynamicBind( hTCP, "htons" );
	inet_addr = ( INET_ADDR ) DynamicBind( hTCP, "inet_addr" );
	inet_ntoa = ( INET_NTOA ) DynamicBind( hTCP, "inet_ntoa" );
	listen = ( LISTEN ) DynamicBind( hTCP, "listen" );
	ntohs = ( NTOHS ) DynamicBind( hTCP, "ntohs" );
	recv = ( RECV ) DynamicBind( hTCP, "recv" );
	select = ( SELECT ) DynamicBind( hTCP, "select" );
	send = ( SEND ) DynamicBind( hTCP, "send" );
	setsockopt = ( SETSOCKOPT ) DynamicBind( hTCP, "setsockopt" );
	socket = ( SOCKETFN ) DynamicBind( hTCP, "socket" );
#ifdef __WINDOWS__
	closesocket = ( CLOSESOCKET ) DynamicBind( hTCP, "closesocket" );
	ioctlsocket = ( IOCTLSOCKET ) DynamicBind( hTCP, "ioctlsocket" );
	WSACleanup = ( WSACLEANUP ) DynamicBind( hTCP, "WSACleanup" );
	WSAGetLastError = ( WSAGETLASTERROR ) DynamicBind( hTCP, "WSAGetLastError" );
	WSAStartup = ( WSASTARTUP ) DynamicBind( hTCP, "WSAStartup" );
	__WSAFDIsSet = ( FDISSETFN ) DynamicBind( hTCP, "__WSAFDIsSet" );
#endif /* __WINDOWS__ */
#if ( defined( sun ) && OSVERSION > 4 )
	h_errnoPtr = ( int * ) DynamicBind( hTCP, "h_errno" );
	if( h_errnoPtr == NULL )
		{
		DynamicUnload( hTCP );
		hTCP = NULL_INSTANCE;
		return;
		}
#endif /* Slowaris */

	/* Make sure we got valid pointers for every TCP/IP function */
	if( accept == NULL || bind == NULL || connect == NULL || \
		gethostbyname == NULL || getsockopt == NULL || htonl == NULL || \
		htons == NULL || inet_addr == NULL || inet_ntoa == NULL || \
		listen == NULL || ntohs == NULL || recv == NULL || select == NULL || \
		send == NULL || setsockopt == NULL || socket == NULL )
		{
		DynamicUnload( hTCP );
		hTCP = NULL_INSTANCE;
		return;
		}

#ifdef __WINDOWS__
	if( closesocket == NULL || ioctlsocket == NULL || WSACleanup == NULL || \
		WSAGetLastError == NULL || WSAStartup == NULL || \
		__WSAFDIsSet == NULL || \
		( WSAStartup( 2, &wsaData ) && WSAStartup( 1, &wsaData ) ) )
		{
		DynamicUnload( hTCP );
		hTCP = NULL_INSTANCE;
		}
#endif /* __WINDOWS__ */

	/* Set up the socket pool state information */
	initSocketPool();
	}

void netEndTCP( void )
	{
	STATIC_FN void endSocketPool( void );

⌨️ 快捷键说明

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