📄 net_tcp.c
字号:
#define isRecoverableError( status ) ( ( status ) == ECONNRESET )
#define isRestartableError() ( errno == EINTR || errno == EAGAIN )
#define isTimeoutError() ( errno == ETIMEDOUT )
#endif /* OS-specific status codes */
/****************************************************************************
* *
* 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 */
static INSTANCE_HANDLE hTCP = NULL_INSTANCE;
static INSTANCE_HANDLE hDNS = NULL_INSTANCE;
static INSTANCE_HANDLE hIPv6 = NULL_INSTANCE;
#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 struct hostent FAR * ( SOCKET_API *GETHOSTNAME )( char FAR * name,
int namelen );
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_long ( SOCKET_API *NTOHL )( u_long netlong );
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 int ( SOCKET_API *SHUTDOWN )( SOCKET s, int how );
typedef SOCKET ( SOCKET_API *SOCKETFN )( int af, int type, int protocol );
#ifdef __WINDOWS__
typedef int ( SOCKET_API *CLOSESOCKET )( SOCKET s );
typedef int ( SOCKET_API *FDISSETFN )( SOCKET, fd_set * );
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 DNS_STATUS ( WINAPI *DNSQUERY )( const LPSTR lpstrName,
const WORD wType, const DWORD fOptions,
const PIP4_ARRAY aipServers,
PDNS_RECORD *ppQueryResultsSet,
PVOID *pReserved );
typedef DNS_STATUS ( WINAPI *DNSQUERYCONFIG )( const DNS_CONFIG_TYPE Config,
const DWORD Flag,
const PWSTR pwsAdapterName,
PVOID pReserved, PVOID pBuffer,
PDWORD pBufferLength );
typedef VOID ( WINAPI *DNSRECORDLISTFREE )( PDNS_RECORD pRecordList,
DNS_FREE_TYPE FreeType );
#endif /* __WINDOWS__ */
typedef void ( SOCKET_API *FREEADDRINFO )( struct addrinfo *ai );
typedef int ( SOCKET_API *GETADDRINFO )( const char *nodename,
const char *servname,
const struct addrinfo *hints,
struct addrinfo **res );
typedef int ( SOCKET_API *GETNAMEINFO )( const struct sockaddr *sa,
SIZE_TYPE salen, char *node,
SIZE_TYPE nodelen, char *service,
SIZE_TYPE servicelen, int flags );
static ACCEPT paccept = NULL;
static BIND pbind = NULL;
static CONNECT pconnect = NULL;
static GETHOSTBYNAME pgethostbyname = NULL;
static GETHOSTNAME pgethostname = 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 NTOHL pntohl = NULL;
static NTOHS pntohs = 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;
static DNSQUERY pDnsQuery = NULL;
static DNSQUERYCONFIG pDnsQueryConfig = NULL;
static DNSRECORDLISTFREE pDnsRecordListFree = NULL;
#endif /* __WINDOWS__ */
static FREEADDRINFO pfreeaddrinfo = NULL;
static GETADDRINFO pgetaddrinfo = NULL;
static GETNAMEINFO pgetnameinfo = NULL;
#if ( defined( sun ) && OSVERSION > 4 )
static int *h_errnoPtr;
#undef getHostErrorCode
#define getHostErrorCode() *h_errnoPtr
#undef htonl /* Slowaris has defines that conflict with our ones */
#undef htons
#undef ntohl
#undef ntohs
#endif /* Slowaris */
#define accept paccept
#define bind pbind
#define connect pconnect
#define gethostbyname pgethostbyname
#define gethostname pgethostname
#define getsockopt pgetsockopt
#define htonl phtonl
#define htons phtons
#define inet_addr pinet_addr
#define inet_ntoa pinet_ntoa
#define listen plisten
#define ntohl pntohl
#define ntohs pntohs
#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
#define WSAGetLastError pWSAGetLastError
#define WSAStartup pWSAStartup
#define DnsQuery pDnsQuery
#define DnsQueryConfig pDnsQueryConfig
#define DnsRecordListFree pDnsRecordListFree
#endif /* __WINDOWS__ */
#define freeaddrinfo pfreeaddrinfo
#define getaddrinfo pgetaddrinfo
#define getnameinfo pgetnameinfo
/* 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 */
int netInitTCP( void )
{
STATIC_FN int initSocketPool( void );
#ifdef __WINDOWS__
WSADATA wsaData;
#ifdef __WIN16__
UINT errorMode;
#endif /* __WIN16__ */
BOOLEAN ip6inWinsock = FALSE;
#endif /* __WINDOWS__ */
/* Obtain a handle to the modules 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( CRYPT_ERROR );
}
#else
if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE && \
( hTCP = DynamicLoad( WINSOCK_OLD_LIBNAME ) ) == NULL_INSTANCE )
return( CRYPT_ERROR );
hDNS = DynamicLoad( "dnsapi.dll" );
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" );
#endif /* Win16 vs.Win32 */
#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, "accept" );
bind = ( BIND ) DynamicBind( hTCP, "bind" );
connect = ( CONNECT ) DynamicBind( hTCP, "connect" );
gethostbyname = ( GETHOSTBYNAME ) DynamicBind( hTCP, "gethostbyname" );
gethostname = ( GETHOSTNAME ) DynamicBind( hTCP, "gethostname" );
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" );
ntohl = ( NTOHL ) DynamicBind( hTCP, "ntohl" );
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" );
shutdown = ( SHUTDOWN ) DynamicBind( hTCP, "shutdown" );
socket = ( SOCKETFN ) DynamicBind( hTCP, "socket" );
#ifdef __WINDOWS__
closesocket = ( CLOSESOCKET ) DynamicBind( hTCP, "closesocket" );
__WSAFDIsSet = ( FDISSETFN ) DynamicBind( hTCP, "__WSAFDIsSet" );
ioctlsocket = ( IOCTLSOCKET ) DynamicBind( hTCP, "ioctlsocket" );
WSACleanup = ( WSACLEANUP ) DynamicBind( hTCP, "WSACleanup" );
WSAGetLastError = ( WSAGETLASTERROR ) DynamicBind( hTCP, "WSAGetLastError" );
WSAStartup = ( WSASTARTUP ) DynamicBind( hTCP, "WSAStartup" );
if( hDNS != NULL_INSTANCE )
{
DnsQuery = ( DNSQUERY ) DynamicBind( hDNS, "DnsQuery_A" );
DnsQueryConfig = ( DNSQUERYCONFIG ) DynamicBind( hDNS, "DnsQueryConfig" );
DnsRecordListFree = ( DNSRECORDLISTFREE ) DynamicBind( hDNS, "DnsRecordListFree" );
if( DnsQuery == NULL || DnsQueryConfig == NULL || \
DnsRecordListFree == NULL )
{
DynamicUnload( hDNS );
hDNS = NULL_INSTANCE;
}
}
if( ip6inWinsock || hIPv6 != NULL_INSTANCE )
{
INSTANCE_HANDLE hAddr = ip6inWinsock ? hTCP : hIPv6;
freeaddrinfo = ( FREEADDRINFO ) DynamicBind( hAddr, "freeaddrinfo" );
getaddrinfo = ( GETADDRINFO ) DynamicBind( hAddr, "getaddrinfo" );
getnameinfo = ( GETNAMEINFO ) DynamicBind( hAddr, "getnameinfo" );
if( freeaddrinfo == NULL || getaddrinfo == NULL || \
getnameinfo == NULL )
{
if( hIPv6 != NULL_INSTANCE )
{
DynamicUnload( hIPv6 );
hIPv6 = NULL_INSTANCE;
}
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
return( CRYPT_ERROR );
}
}
#endif /* __WINDOWS__ */
if( freeaddrinfo == NULL )
{
static int my_getaddrinfo( const char *nodename, const char *servname,
const struct addrinfo *hints,
struct addrinfo **res );
static void my_freeaddrinfo( struct addrinfo *ai );
static int my_getnameinfo( const struct sockaddr *sa, SIZE_TYPE salen,
char *node, SIZE_TYPE nodelen,
char *service, SIZE_TYPE servicelen,
int flags );
/* If we couldn't dynamically bind the IPv6 name/address functions,
use a local emulation */
getaddrinfo = ( GETADDRINFO ) my_getaddrinfo;
freeaddrinfo = ( FREEADDRINFO ) my_freeaddrinfo;
getnameinfo = ( GETNAMEINFO ) my_getnameinfo;
}
#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 || \
gethostbyname == NULL || gethostname == NULL || \
getsockopt == NULL || htonl == NULL || htons == NULL || \
inet_addr == NULL || inet_ntoa == NULL || listen == NULL || \
ntohl == NULL || ntohs == NULL || recv == NULL || \
select == NULL || send == NULL || setsockopt == NULL || \
shutdown == NULL || socket == NULL )
{
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
if( hDNS != NULL_INSTANCE )
{
DynamicUnload( hDNS );
hDNS = 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 || \
WSAGetLastError == NULL || WSAStartup == NULL || \
( WSAStartup( 2, &wsaData ) && WSAStartup( 1, &wsaData ) ) )
{
DynamicUnload( hTCP );
hTCP = NULL_INSTANCE;
if( hDNS != NULL_INSTANCE )
{
DynamicUnload( hDNS );
hDNS = NULL_INSTANCE;
}
if( hIPv6 != NULL_INSTANCE )
{
DynamicUnload( hIPv6 );
hIPv6 = NULL_INSTANCE;
}
return( CRYPT_ERROR );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -