📄 tcp.c
字号:
/****************************************************************************
* *
* cryptlib TCP/IP 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 *
* *
****************************************************************************/
/* Forward declarations for socket pool functions */
CHECK_RETVAL \
static int initSocketPool( void );
static void endSocketPool( void );
#ifdef __WINDOWS__
#ifndef TEXT
#define TEXT /* Win32 windows.h defines this, but not the Win16 one */
#endif /* TEXT */
/* Global function pointers. These are necessary because the functions need
to be dynamically linked since not all systems contain the necessary
libraries */
static INSTANCE_HANDLE hTCP, hIPv6;
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \
SOCKET ( SOCKET_API *ACCEPT )( IN SOCKET s, OUT struct sockaddr *addr,
INOUT int *addrlen );
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int ( SOCKET_API *BIND )( IN SOCKET s,
const struct sockaddr FAR *addr,
IN_LENGTH_DNS int namelen );
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int ( SOCKET_API *CONNECT )( IN SOCKET s, IN_BUFFER( namelen ) \
const struct sockaddr *name,
IN_LENGTH_DNS int namelen );
typedef STDC_NONNULL_ARG( ( 4, 5 ) ) \
int ( SOCKET_API *GETSOCKOPT )( IN SOCKET s, IN int level,
IN int optname,
OUT_BUFFER_FIXED( *optlen ) char *optval,
INOUT int FAR *optlen );
typedef CHECK_RETVAL \
int ( SOCKET_API *LISTEN )( IN SOCKET s, IN int backlog );
typedef CHECK_RETVAL RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int ( SOCKET_API *RECV )( IN SOCKET s,
OUT_BUFFER( len, return ) char *buf,
IN_LENGTH int len, IN int flags );
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 4, 5 ) ) \
int ( SOCKET_API *SELECT )( IN int nfds, INOUT_OPT fd_set *readfds,
INOUT_OPT fd_set *writefds,
INOUT fd_set *exceptfds,
const struct timeval *timeout );
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int ( SOCKET_API *SEND )( IN SOCKET s,
IN_BUFFER( len ) const char *buf,
IN_LENGTH int len, IN int flags );
typedef STDC_NONNULL_ARG( ( 4 ) ) \
int ( SOCKET_API *SETSOCKOPT )( IN SOCKET s, IN int level, \
IN int optname,
IN_BUFFER( optlen ) char *optval,
IN int optlen );
typedef int ( SOCKET_API *SHUTDOWN )( IN SOCKET s, IN int how );
typedef CHECK_RETVAL \
SOCKET ( SOCKET_API *SOCKETFN )( IN int af, IN int type,
IN int protocol );
#ifdef __WINDOWS__
typedef int ( SOCKET_API *CLOSESOCKET )( IN SOCKET s );
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int ( SOCKET_API *FDISSETFN )( IN SOCKET s, fd_set *fds );
typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int ( SOCKET_API *IOCTLSOCKET )( IN SOCKET s, IN long cmd,
INOUT u_long FAR *argp );
typedef int ( SOCKET_API *WSACLEANUP )( void );
typedef CHECK_RETVAL \
int ( SOCKET_API *WSAGETLASTERROR )( void );
typedef CHECK_RETVAL \
int ( SOCKET_API *WSASTARTUP )( IN WORD wVersionRequested,
OUT LPWSADATA lpWSAData );
#endif /* __WINDOWS__ */
static ACCEPT paccept = NULL;
static BIND pbind = NULL;
static CONNECT pconnect = NULL;
static GETSOCKOPT pgetsockopt = NULL;
static LISTEN plisten = NULL;
static RECV precv = NULL;
static SELECT pselect = NULL;
static SEND psend = NULL;
static SETSOCKOPT psetsockopt = NULL;
static SHUTDOWN pshutdown = NULL;
static SOCKETFN psocket = NULL;
#ifdef __WINDOWS__
static CLOSESOCKET pclosesocket = NULL;
static FDISSETFN pFDISSETfn = NULL;
static IOCTLSOCKET pioctlsocket = NULL;
static WSACLEANUP pWSACleanup = NULL;
static WSAGETLASTERROR pWSAGetLastError = NULL;
static WSASTARTUP pWSAStartup = NULL;
#endif /* __WINDOWS__ */
#if ( defined( sun ) && OSVERSION > 4 )
static int *h_errnoPtr;
#undef getHostErrorCode
#define getHostErrorCode() *h_errnoPtr
#endif /* Slowaris */
#define accept paccept
#define bind pbind
#define connect pconnect
#define getsockopt pgetsockopt
#define listen plisten
#define recv precv
#define select pselect
#define send psend
#define setsockopt psetsockopt
#define shutdown pshutdown
#define socket psocket
#ifdef __WINDOWS__
#define closesocket pclosesocket
#define __WSAFDIsSet pFDISSETfn
#define ioctlsocket pioctlsocket
#define WSACleanup pWSACleanup
#ifndef WSAGetLastError
/* In some environments WSAGetLastError() is a macro that maps to
GetLastError() */
#define WSAGetLastError pWSAGetLastError
#define DYNLOAD_WSAGETLASTERROR
#endif /* WSAGetLastError */
#define WSAStartup pWSAStartup
#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 use Winsock 2 but we allow for Winsock 1 as
well just in case */
#ifdef __WINDOWS__
#ifdef __WIN16__
#define TCP_LIBNAME "winsock.dll"
#elif defined( __WIN32__ )
#define TCP_LIBNAME TEXT( "ws2_32.dll" )
#define WINSOCK_OLD_LIBNAME TEXT( "wsock32.dll" )
#elif defined( __WINCE__ )
#define TCP_LIBNAME TEXT( "ws2.dll" )
#else
#error Unknown Windows variant encountered
#endif /* Win16/Win32/WinCE */
#else
#define TCP_LIBNAME "libsocket.so"
#define TEXT( x ) x
#endif /* OS-specific TCP/IP library naming */
RETVAL \
int netInitTCP( void )
{
#ifdef __WINDOWS__
WSADATA wsaData;
#ifdef __WIN16__
UINT errorMode;
#endif /* __WIN16__ */
BOOLEAN ip6inWinsock = FALSE;
int status;
#endif /* __WINDOWS__ */
/* Obtain a handle to the modules containing the TCP/IP functions */
#ifdef __WINDOWS__
hTCP = hIPv6 = NULL_INSTANCE;
#if defined( __WIN16__ )
errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
hTCP = DynamicLoad( TCP_LIBNAME );
SetErrorMode( errorMode );
if( hTCP < HINSTANCE_ERROR )
{
hTCP = NULL_INSTANCE;
return( CRYPT_ERROR );
}
#elif defined( __WIN32__ )
if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE && \
( hTCP = DynamicLoad( WINSOCK_OLD_LIBNAME ) ) == NULL_INSTANCE )
return( CRYPT_ERROR );
if( DynamicBind( hTCP, "getaddrinfo" ) != NULL )
ip6inWinsock = TRUE;
else
{
/* Newer releases of Windows put the IPv6 functions in the Winsock 2
library, older (non-IPv6-enabled) releases had it available as an
experimental add-on using the IPv6 Technology Preview library */
hIPv6 = DynamicLoad( "wship6.dll" );
}
#elif defined( __WINCE__ )
if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE )
return( CRYPT_ERROR );
if( DynamicBind( hTCP, TEXT( "getaddrinfo" ) ) != NULL )
ip6inWinsock = TRUE;
#endif /* Win16/Win32/WinCE */
#else
if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE )
return( CRYPT_ERROR );
#endif /* OS-specific dynamic load */
/* Now get pointers to the functions */
accept = ( ACCEPT ) DynamicBind( hTCP, TEXT( "accept" ) );
bind = ( BIND ) DynamicBind( hTCP, TEXT( "bind" ) );
connect = ( CONNECT ) DynamicBind( hTCP, TEXT( "connect" ) );
getsockopt = ( GETSOCKOPT ) DynamicBind( hTCP, TEXT( "getsockopt" ) );
listen = ( LISTEN ) DynamicBind( hTCP, TEXT( "listen" ) );
recv = ( RECV ) DynamicBind( hTCP, TEXT( "recv" ) );
select = ( SELECT ) DynamicBind( hTCP, TEXT( "select" ) );
send = ( SEND ) DynamicBind( hTCP, TEXT( "send" ) );
setsockopt = ( SETSOCKOPT ) DynamicBind( hTCP, TEXT( "setsockopt" ) );
shutdown = ( SHUTDOWN ) DynamicBind( hTCP, TEXT( "shutdown" ) );
socket = ( SOCKETFN ) DynamicBind( hTCP, TEXT( "socket" ) );
#ifdef __WINDOWS__
closesocket = ( CLOSESOCKET ) DynamicBind( hTCP, TEXT( "closesocket" ) );
__WSAFDIsSet = ( FDISSETFN ) DynamicBind( hTCP, TEXT( "__WSAFDIsSet" ) );
ioctlsocket = ( IOCTLSOCKET ) DynamicBind( hTCP, TEXT( "ioctlsocket" ) );
WSACleanup = ( WSACLEANUP ) DynamicBind( hTCP, TEXT( "WSACleanup" ) );
#ifdef DYNLOAD_WSAGETLASTERROR
WSAGetLastError = ( WSAGETLASTERROR ) DynamicBind( hTCP, TEXT( "WSAGetLastError" ) );
#endif /* DYNLOAD_WSAGETLASTERROR */
WSAStartup = ( WSASTARTUP ) DynamicBind( hTCP, TEXT( "WSAStartup" ) );
if( ip6inWinsock || hIPv6 != NULL_INSTANCE )
status = initDNS( hTCP, ip6inWinsock ? hTCP : hIPv6 );
else
status = initDNS( hTCP, NULL_INSTANCE );
if( cryptStatusError( status ) )
{
if( hIPv6 != NULL_INSTANCE )
{
DynamicUnload( hIPv6 );
hIPv6 = NULL_INSTANCE;
}
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
return( CRYPT_ERROR );
}
#endif /* __WINDOWS__ */
#if ( defined( sun ) && OSVERSION > 4 )
h_errnoPtr = ( int * ) DynamicBind( hTCP, "h_errno" );
if( h_errnoPtr == NULL )
{
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
return( CRYPT_ERROR );
}
#endif /* Slowaris */
/* Make sure that we got valid pointers for every TCP/IP function */
if( accept == NULL || bind == NULL || connect == NULL || \
getsockopt == NULL || listen == NULL || recv == NULL || \
select == NULL || send == NULL || setsockopt == NULL || \
shutdown == NULL || socket == NULL )
{
endDNS( hTCP );
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
if( hIPv6 != NULL_INSTANCE )
{
DynamicUnload( hIPv6 );
hIPv6 = NULL_INSTANCE;
}
return( CRYPT_ERROR );
}
#ifdef __WINDOWS__
if( closesocket == NULL || __WSAFDIsSet == NULL || \
ioctlsocket == NULL || WSACleanup == NULL ||
#ifdef DYNLOAD_WSAGETLASTERROR
WSAGetLastError == NULL ||
#endif /* DYNLOAD_WSAGETLASTERROR */
WSAStartup == NULL || \
( WSAStartup( 2, &wsaData ) && WSAStartup( 1, &wsaData ) ) )
{
endDNS( hTCP );
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
if( hIPv6 != NULL_INSTANCE )
{
DynamicUnload( hIPv6 );
hIPv6 = NULL_INSTANCE;
}
return( CRYPT_ERROR );
}
#endif /* __WINDOWS__ */
/* Set up the socket pool state information */
return( initSocketPool() );
}
void netEndTCP( void )
{
/* Clean up the socket pool state information */
endSocketPool();
endDNS( hTCP );
if( hIPv6 != NULL_INSTANCE )
DynamicUnload( hIPv6 );
if( hTCP != NULL_INSTANCE )
{
#ifdef __WINDOWS__
/* Wipe the Sheets Afterwards and Cleanup */
WSACleanup();
#endif /* __WINDOWS__ */
DynamicUnload( hTCP );
}
hTCP = hIPv6 = NULL_INSTANCE;
}
/* Return the status of the network interface */
CHECK_RETVAL_BOOL \
static BOOLEAN transportOKFunction( void )
{
return( hTCP != NULL_INSTANCE ? TRUE : FALSE );
}
#else
RETVAL \
int netInitTCP( void )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -