30 static
int initSocketPool(
void );
31 static void endSocketPool(
void );
40 #pragma warning( disable: 4127 )
47 static INSTANCE_HANDLE hTCP, hIPv6;
50 SOCKET ( SOCKET_API *ACCEPT )(
IN SOCKET
s,
OUT struct sockaddr *addr,
53 int ( SOCKET_API *BIND )(
IN SOCKET
s,
54 const struct sockaddr
FAR *addr,
57 int ( SOCKET_API *CONNECT )(
IN SOCKET
s,
IN_BUFFER( namelen ) \
58 const
struct sockaddr *
name,
61 int ( SOCKET_API *GETSOCKOPT )(
IN SOCKET
s,
IN int level,
66 int ( SOCKET_API *LISTEN )(
IN SOCKET s,
IN int backlog );
68 int ( SOCKET_API *RECV )(
IN SOCKET s,
72 int ( SOCKET_API *SELECT )(
IN int nfds,
INOUT_OPT fd_set *readfds,
74 INOUT fd_set *exceptfds,
75 const struct timeval *timeout );
77 int ( SOCKET_API *SEND )(
IN SOCKET s,
80 typedef STDC_NONNULL_ARG( ( 4 ) ) \
81 int ( SOCKET_API *SETSOCKOPT )(
IN SOCKET s,
IN int level, \
85 typedef
int ( SOCKET_API *SHUTDOWN )(
IN SOCKET s,
IN int how );
87 SOCKET ( SOCKET_API *SOCKETFN )(
IN int af,
IN int type,
90 typedef int ( SOCKET_API *CLOSESOCKET )(
IN SOCKET
s );
92 int ( SOCKET_API *FDISSETFN )(
IN SOCKET
s, fd_set *fds );
94 int ( SOCKET_API *IOCTLSOCKET )(
IN SOCKET
s,
IN long cmd,
96 typedef int ( SOCKET_API *WSACLEANUP )( void );
97 typedef CHECK_RETVAL \
98 int ( SOCKET_API *WSAGETLASTERROR )( void );
99 typedef CHECK_RETVAL \
100 int ( SOCKET_API *WSASTARTUP )(
IN WORD wVersionRequested,
101 OUT LPWSADATA lpWSAData );
103 static ACCEPT paccept = NULL;
104 static BIND pbind = NULL;
105 static CONNECT pconnect = NULL;
106 static GETSOCKOPT pgetsockopt = NULL;
107 static LISTEN plisten = NULL;
108 static RECV precv = NULL;
109 static SELECT pselect = NULL;
110 static SEND psend = NULL;
111 static SETSOCKOPT psetsockopt = NULL;
112 static SHUTDOWN pshutdown = NULL;
113 static SOCKETFN psocket = NULL;
115 static CLOSESOCKET pclosesocket = NULL;
116 static FDISSETFN pFDISSETfn = NULL;
117 static IOCTLSOCKET pioctlsocket = NULL;
118 static WSACLEANUP pWSACleanup = NULL;
119 static WSAGETLASTERROR pWSAGetLastError = NULL;
120 static WSASTARTUP pWSAStartup = NULL;
122 #if ( defined( sun ) && OSVERSION > 4 )
123 static int *h_errnoPtr;
125 #undef getHostErrorCode
126 #define getHostErrorCode() *h_errnoPtr
129 #define accept paccept
131 #define connect pconnect
132 #define getsockopt pgetsockopt
133 #define listen plisten
135 #define select pselect
137 #define setsockopt psetsockopt
138 #define shutdown pshutdown
139 #define socket psocket
141 #define closesocket pclosesocket
142 #define __WSAFDIsSet pFDISSETfn
143 #define ioctlsocket pioctlsocket
144 #define WSACleanup pWSACleanup
145 #ifndef WSAGetLastError
148 #define WSAGetLastError pWSAGetLastError
149 #define DYNLOAD_WSAGETLASTERROR
151 #define WSAStartup pWSAStartup
161 #define TCP_LIBNAME "winsock.dll"
162 #elif defined( __WIN32__ )
163 #define TCP_LIBNAME TEXT( "ws2_32.dll" )
164 #define WINSOCK_OLD_LIBNAME TEXT( "wsock32.dll" )
165 #elif defined( __WINCE__ )
166 #define TCP_LIBNAME TEXT( "ws2.dll" )
168 #error Unknown Windows variant encountered
171 #define TCP_LIBNAME "libsocket.so"
189 hTCP = hIPv6 = NULL_INSTANCE;
190 #if defined( __WIN16__ )
191 errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
192 hTCP = DynamicLoad( TCP_LIBNAME );
193 SetErrorMode( errorMode );
194 if( hTCP < HINSTANCE_ERROR )
196 hTCP = NULL_INSTANCE;
199 #elif defined( __WIN32__ )
200 if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE && \
201 ( hTCP = DynamicLoad( WINSOCK_OLD_LIBNAME ) ) == NULL_INSTANCE )
203 if( DynamicBind( hTCP,
"getaddrinfo" ) != NULL )
210 hIPv6 = DynamicLoad(
"wship6.dll" );
212 #elif defined( __WINCE__ )
213 if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE )
215 if( DynamicBind( hTCP,
TEXT(
"getaddrinfo" ) ) != NULL )
219 if( ( hTCP = DynamicLoad( TCP_LIBNAME ) ) == NULL_INSTANCE )
224 accept = ( ACCEPT ) DynamicBind( hTCP,
TEXT(
"accept" ) );
225 bind = ( BIND ) DynamicBind( hTCP,
TEXT(
"bind" ) );
226 connect = ( CONNECT ) DynamicBind( hTCP,
TEXT(
"connect" ) );
227 getsockopt = ( GETSOCKOPT ) DynamicBind( hTCP,
TEXT(
"getsockopt" ) );
228 listen = ( LISTEN ) DynamicBind( hTCP,
TEXT(
"listen" ) );
229 recv = ( RECV ) DynamicBind( hTCP,
TEXT(
"recv" ) );
230 select = ( SELECT ) DynamicBind( hTCP,
TEXT(
"select" ) );
231 send = ( SEND ) DynamicBind( hTCP,
TEXT(
"send" ) );
232 setsockopt = ( SETSOCKOPT ) DynamicBind( hTCP,
TEXT(
"setsockopt" ) );
233 shutdown = ( SHUTDOWN ) DynamicBind( hTCP,
TEXT(
"shutdown" ) );
234 socket = ( SOCKETFN ) DynamicBind( hTCP,
TEXT(
"socket" ) );
236 closesocket = ( CLOSESOCKET ) DynamicBind( hTCP,
TEXT(
"closesocket" ) );
237 __WSAFDIsSet = ( FDISSETFN ) DynamicBind( hTCP,
TEXT(
"__WSAFDIsSet" ) );
238 ioctlsocket = ( IOCTLSOCKET ) DynamicBind( hTCP,
TEXT(
"ioctlsocket" ) );
239 WSACleanup = ( WSACLEANUP ) DynamicBind( hTCP,
TEXT(
"WSACleanup" ) );
240 #ifdef DYNLOAD_WSAGETLASTERROR
241 WSAGetLastError = ( WSAGETLASTERROR ) DynamicBind( hTCP,
TEXT(
"WSAGetLastError" ) );
243 WSAStartup = ( WSASTARTUP ) DynamicBind( hTCP,
TEXT(
"WSAStartup" ) );
244 if( ip6inWinsock || hIPv6 != NULL_INSTANCE )
245 status = initDNS( hTCP, ip6inWinsock ? hTCP : hIPv6 );
247 status = initDNS( hTCP, NULL_INSTANCE );
250 if( hIPv6 != NULL_INSTANCE )
252 DynamicUnload( hIPv6 );
253 hIPv6 = NULL_INSTANCE;
255 DynamicUnload( hTCP );
256 hTCP = NULL_INSTANCE;
260 #if ( defined( sun ) && OSVERSION > 4 )
261 h_errnoPtr = (
int * ) DynamicBind( hTCP,
"h_errno" );
262 if( h_errnoPtr == NULL )
264 DynamicUnload( hTCP );
265 hTCP = NULL_INSTANCE;
271 if( accept == NULL || bind == NULL || connect == NULL || \
272 getsockopt == NULL || listen == NULL || recv == NULL || \
273 select == NULL || send == NULL || setsockopt == NULL || \
274 shutdown == NULL || socket == NULL )
277 DynamicUnload( hTCP );
278 hTCP = NULL_INSTANCE;
279 if( hIPv6 != NULL_INSTANCE )
281 DynamicUnload( hIPv6 );
282 hIPv6 = NULL_INSTANCE;
288 if( closesocket == NULL || __WSAFDIsSet == NULL || \
289 ioctlsocket == NULL || WSACleanup == NULL ||
290 #ifdef DYNLOAD_WSAGETLASTERROR
291 WSAGetLastError == NULL ||
293 WSAStartup == NULL || \
294 ( WSAStartup( 2, &wsaData ) && WSAStartup( 1, &wsaData ) ) )
297 DynamicUnload( hTCP );
298 hTCP = NULL_INSTANCE;
299 if( hIPv6 != NULL_INSTANCE )
301 DynamicUnload( hIPv6 );
302 hIPv6 = NULL_INSTANCE;
309 return( initSocketPool() );
318 if( hIPv6 != NULL_INSTANCE )
319 DynamicUnload( hIPv6 );
320 if( hTCP != NULL_INSTANCE )
326 DynamicUnload( hTCP );
328 hTCP = hIPv6 = NULL_INSTANCE;
334 static
BOOLEAN transportOKFunction(
void )
336 return( hTCP != NULL_INSTANCE ?
TRUE :
FALSE );
343 #ifdef __SCO_VERSION__
344 struct sigaction act, oact;
354 memset( &act, 0,
sizeof( act ) );
355 act.sa_handler = SIG_IGN;
356 sigemptyset( &act.sa_mask );
357 if( sigaction( SIGIO, &act, &oact ) < 0 )
362 fprintf( stderr,
"cryptlib: sigaction failed, errno = %d, "
363 "file = %s, line = %d.\n", errno, __FILE__, __LINE__ );
368 if( oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN )
372 fprintf( stderr,
"Warning: Conflicting SIGIO handling detected in "
373 "UnixWare socket bug\n workaround, file " __FILE__
374 ", line %d. This may cause\n false SIGIO/SIGPOLL "
375 "errors.\n", __LINE__ );
376 sigaction( SIGIO, &oact, &act );
381 return( initSocketPool() );
389 #ifdef __SCO_VERSION__
390 signal( SIGIO, SIG_DFL );
395 static
BOOLEAN transportOKFunction(
void )
397 #if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )
411 netSocket = socket( PF_INET, SOCK_STREAM, 0 );
412 if( !isBadSocket( netSocket ) )
414 closesocket( netSocket );
418 return( transportOK );
438 const int cryptSpecificCode;
442 const int errorStringLength;
447 static const SOCKETERROR_INFO
FAR_BSS socketErrorInfo[] = {
449 "WSAECONNREFUSED: The attempt to connect was rejected", 52 },
451 "WSAEADDRNOTAVAIL: The remote address is not a valid address", 59 },
453 "WSAECONNABORTED: Connection was terminated due to a time-out or "
454 "other failure", 77 },
456 "WSAECONNRESET: Connection was reset by the remote host executing "
459 "WSAEHOSTUNREACH: Remote host cannot be reached from this host at "
462 "WSAEMSGSIZE: Message is larger than the maximum supported by the "
463 "underlying transport", 85 },
465 "WSAENETDOWN: The network subsystem has failed", 45 },
467 "WSAENETRESET: Connection was broken due to keep-alive detecting a "
468 "failure while operation was in progress", 105 },
470 "WSAENETUNREACH: Network cannot be reached from this host at this "
473 "WSAENOBUFS: No buffer space available", 37 },
475 "WSAENOTCONN: Socket is not connected", 36 },
477 "WSAETIMEDOUT: Function timed out before completion", 50 },
479 "WSAHOST_NOT_FOUND: Host not found", 34 },
481 "WSATRY_AGAIN: Host not found (non-authoritative)", 48 },
483 "WSANO_ADDRESS: No address record available for this name", 56 },
485 "WSANO_DATA: Valid name, no data record of requested type", 56 },
488 #define hostErrorInfo socketErrorInfo
490 #define TIMEOUT_ERROR WSAETIMEDOUT
494 static const SOCKETERROR_INFO
FAR_BSS socketErrorInfo[] = {
496 "EACCES: Permission denied", 25 },
498 "EADDRINUSE: Address in use", 26 },
500 "EADDRNOTAVAIL: Specified address is not available from the local "
503 "EAFNOSUPPORT: Address family not supported", 42 },
505 "EALREADY: Connection already in progress", 41 },
507 "EBADF: Bad file descriptor", 26 },
508 #if !( defined( __PALMOS__ ) || defined( __SYMBIAN32__ ) )
510 "ECONNABORTED: Software caused connection abort", 46 },
512 "ECONNRESET: Connection was forcibly closed by remote host", 57 },
515 "ECONNREFUSED: Attempt to connect was rejected", 45 },
517 "EINPROGRESS: Operation in progress", 34 },
519 "EINTR: Function was interrupted by a signal", 43 },
521 "EIO: Input/output error", 24 },
523 "EISCONN: Socket is connected", 28 },
525 "EMFILE: Per-process descriptor table is full", 44 },
526 #ifndef __SYMBIAN32__
528 "EMSGSIZE: Message is too large to be sent all at once", 53 },
530 "ENETUNREACH: No route to the network or host is present", 55 },
532 "ENOBUFS: Insufficient system resources available to complete the "
535 "ENODEV: No such device", 22 },
537 "ENOPROTOOPT: Protocol not available", 35 },
539 "ENOTCONN: Socket is not connected", 33 },
541 "ENOTSOCK: Not a socket", 22 },
544 "EPERM: Operation not permitted", 30 },
546 "EPROTOTYPE: Protocol wrong type for socket", 42 },
548 "ETIMEDOUT: Function timed out before completion", 47 },
550 "HOST_NOT_FOUND: Not an official hostname or alias", 49 },
553 "NO_ADDRESS: Name is valid but does not have an IP address at the "
557 "TRY_AGAIN: Local server did not receive a response from an "
558 "authoritative server", 79 },
562 #define TIMEOUT_ERROR ETIMEDOUT
564 static const SOCKETERROR_INFO
FAR_BSS hostErrorInfo[] = {
566 "HOST_NOT_FOUND: Host not found", 30 },
569 "NO_ADDRESS: No address record available for this name", 53 },
572 "NO_DATA: Valid name, no data record of requested type", 53 },
574 "TRY_AGAIN: Local server did not receive a response from an "
575 "authoritative server", 79 },
594 const int netStreamErrorCode,
595 const BOOLEAN useHostErrorInfo,
599 useHostErrorInfo ? hostErrorInfo : socketErrorInfo;
600 const int errorInfoSize = useHostErrorInfo ? \
601 FAILSAFE_ARRAYSIZE( hostErrorInfo, SOCKETERROR_INFO ) : \
609 if( netStreamErrorCode == 0 )
615 for( i = 0; i < errorInfoSize && \
618 if( errorInfo[ i ].
errorCode == netStreamErrorCode )
620 REQUIRES( errorInfo[ i ].errorStringLength > 16 && \
621 errorInfo[ i ].errorStringLength < 150 );
623 errorInfo[ i ].errorStringLength );
624 if( errorInfo[ i ].cryptSpecificCode !=
CRYPT_OK )
628 status = errorInfo[ i ].cryptSpecificCode;
630 if( errorInfo[ i ].isFatal )
633 netStream->persistentStatus =
status;
651 assert(
isWritePtr( socketErrorCode,
sizeof(
int ) ) );
659 return( mapError( netStream, errorCode,
FALSE, status ) );
672 return( mapError( netStream, getHostErrorCode(),
TRUE, status ) );
677 IN_BUFFER( errorMessageLength )
const char *errorMessage,
684 REQUIRES( errorMessageLength > 16 && \
693 netStream->persistentStatus =
status;
706 #define MAX_DRIVERS 1024
711 INSTANCE_HANDLE hPSAPI = NULL_INSTANCE;
712 typedef BOOL ( WINAPI *ENUMDEVICEDRIVERS )( LPVOID *lpImageBase,
DWORD cb,
713 LPDWORD lpcbNeeded );
714 typedef DWORD ( WINAPI *GETDEVICEDRIVERBASENAME )( LPVOID ImageBase,
717 ENUMDEVICEDRIVERS pEnumDeviceDrivers;
718 GETDEVICEDRIVERBASENAME pGetDeviceDriverBaseName;
719 LPVOID drivers[ MAX_DRIVERS + 8 ];
731 if( ( hPSAPI = DynamicLoad(
"psapi.dll" ) ) == NULL_INSTANCE )
733 pEnumDeviceDrivers = ( ENUMDEVICEDRIVERS ) \
734 GetProcAddress( hPSAPI,
"EnumDeviceDrivers" );
735 pGetDeviceDriverBaseName = ( GETDEVICEDRIVERBASENAME ) \
736 GetProcAddress( hPSAPI,
"GetDeviceDriverBaseNameA" );
737 if( pEnumDeviceDrivers == NULL || \
738 pGetDeviceDriverBaseName == NULL || \
739 !pEnumDeviceDrivers( drivers, MAX_DRIVERS *
sizeof(
DWORD ),
742 DynamicUnload( hPSAPI );
747 for( i = 0; i < cbNeeded /
sizeof(
DWORD ); i++ )
754 static const DRIVER_INFO driverInfoTbl[] = {
755 {
"firelm01.sys", 8,
TRUE },
756 {
"firehk4x.sys", 8,
TRUE },
757 {
"firehk5x.sys", 8,
TRUE },
758 {
"fw220.sys", 5,
TRUE },
759 {
"mpfirewall.sys", 10,
TRUE },
760 {
"symtdi.sys", 6,
FALSE },
761 {
"spbbcdrv.sys", 8,
FALSE },
764 char driverName[ 256 + 8 ];
765 int driverNameLen, driverIndex;
767 driverNameLen = pGetDeviceDriverBaseName( drivers[ i ],
769 if( driverNameLen <= 0 )
771 for( driverIndex = 0;
772 driverInfoTbl[ driverIndex ].name != NULL && \
777 if( driverNameLen >= driverInfoTbl[ driverIndex ].
nameLen && \
778 !strnicmp( driverName, driverInfoTbl[ driverIndex ].name,
779 driverInfoTbl[ driverIndex ].
nameLen ) )
781 DynamicUnload( hPSAPI );
784 "Network data transfer blocked, probably due to "
785 "%s firewall software installed on the PC",
786 driverInfoTbl[ driverIndex ].isMcafee ? \
787 "McAfee" :
"Symantec/Norton" ) );
791 DynamicUnload( hPSAPI );
796 #define checkFirewallError( netStream ) CRYPT_ERROR_TIMEOUT
799 #if defined( __BEOS__ ) && !defined( BONE_VERSION )
807 static int my_select(
int socket_range,
struct fd_set *read_bits,
808 struct fd_set *write_bits,
809 struct fd_set *exception_bits,
810 struct timeval *timeout )
816 if( read_bits != NULL && write_bits != NULL )
822 if( read_bits == NULL && write_bits != NULL )
824 if( exception_bits != NULL )
825 FD_ZERO( exception_bits );
832 if( write_bits != NULL )
833 FD_ZERO( write_bits );
834 if( exception_bits != NULL )
835 FD_ZERO( exception_bits );
837 return( select( socket_range, read_bits, NULL, NULL, timeout ) );
840 #define select( sockets, readFD, writeFD, exceptFD, timeout ) \
841 my_select( sockets, readFD, writeFD, exceptFD, timeout )
843 static int my_setsockopt(
int socket,
int level,
int option,
846 if( option != SO_NONBLOCK && option != SO_REUSEADDR )
848 return( setsockopt( socket, level, option, data, size ) );
851 static int my_getsockopt(
int socket,
int level,
int option,
852 void *data, uint *size )
856 if( option != SO_ERROR )
858 *( (
int * ) data ) = 0;
863 return( setsockopt( socket, level, option, data, *size ) );
867 count = recv( socket, buffer, 0, 0 );
868 printf(
"recv( 0 ) = %d, errno = %d.\n", count, errno );
870 *( (
int * ) data ) = errno;
920 #ifdef CONFIG_CONSERVE_MEMORY
921 #define SOCKETPOOL_SIZE 16
923 #define SOCKETPOOL_SIZE 256
930 BYTE iData[ 32 + 8 ];
934 static SOCKET_INFO *socketInfo;
935 static const SOCKET_INFO SOCKET_INFO_TEMPLATE = \
936 { INVALID_SOCKET, 0, 0, { 0 }, 0 };
941 static
int initSocketPool(
void )
947 clAlloc(
"initSocketPool", SOCKETPOOL_SIZE * \
948 sizeof( SOCKET_INFO ) ) ) == NULL )
950 for( i = 0; i < SOCKETPOOL_SIZE; i++ )
951 socketInfo[ i ] = SOCKET_INFO_TEMPLATE;
956 static void endSocketPool(
void )
958 clFree(
"endSocketPool", socketInfo );
967 static
int newSocket(
OUT SOCKET *newSocketPtr,
968 const struct addrinfo *addrInfoPtr,
974 assert(
isWritePtr( newSocketPtr,
sizeof( SOCKET ) ) );
975 assert(
isReadPtr( addrInfoPtr,
sizeof(
struct addrinfo ) ) );
978 *newSocketPtr = INVALID_SOCKET;
983 iCheck = checksumData( addrInfoPtr->ai_addr,
984 addrInfoPtr->ai_addrlen );
1004 for( i = 0; i < SOCKETPOOL_SIZE; i++ )
1006 if( socketInfo[ i ].
refCount > 0 && \
1007 socketInfo[ i ].iChecksum == iCheck && \
1008 socketInfo[ i ].iDataLen == addrInfoPtr->ai_addrlen && \
1009 !memcmp( socketInfo[ i ].iData, addrInfoPtr->ai_addr,
1010 addrInfoPtr->ai_addrlen ) )
1012 if( socketInfo[ i ].
refCount >= 10000 )
1015 DEBUG_DIAG((
"Socket in pool has reference count > 10,000" ));
1020 socketInfo[ i ].
refCount < 10000 );
1021 ENSURES( !isBadSocket( socketInfo[ i ].netSocket ) );
1022 socketInfo[ i ].refCount++;
1023 *newSocketPtr = socketInfo[ i ].netSocket;
1034 for( i = 0; i < SOCKETPOOL_SIZE; i++ )
1041 if( socketInfo[ i ].
refCount <= 0 && \
1042 !isBadSocket( socketInfo[ i ].netSocket ) )
1044 status = closesocket( socketInfo[ i ].netSocket );
1045 if( !isSocketError( status ) )
1046 socketInfo[ i ] = SOCKET_INFO_TEMPLATE;
1049 if( isBadSocket( socketInfo[ i ].netSocket ) )
1052 if( i >= SOCKETPOOL_SIZE )
1055 DEBUG_DIAG((
"Tried to add more than %d sockets to socket pool",
1060 netSocket = socket( addrInfoPtr->ai_family,
1061 addrInfoPtr->ai_socktype, 0 );
1062 if( isBadSocket( netSocket ) )
1067 socketInfo[ i ].netSocket = netSocket;
1070 const int addrInfoSize =
min( addrInfoPtr->ai_addrlen, 32 );
1074 socketInfo[ i ].iChecksum = checksumData( addrInfoPtr->ai_addr,
1075 addrInfoPtr->ai_addrlen );
1076 memcpy( socketInfo[ i ].iData, addrInfoPtr->ai_addr,
1078 socketInfo[ i ].iDataLen = addrInfoSize;
1080 socketInfo[ i ].refCount = 1;
1081 *newSocketPtr = netSocket;
1098 static void newSocketDone(
void )
1106 static
int addSocket(
const SOCKET netSocket )
1110 REQUIRES( !isBadSocket( netSocket ) );
1117 for( i = 0; i < SOCKETPOOL_SIZE; i++ )
1119 if( isBadSocket( socketInfo[ i ].netSocket ) )
1122 if( i >= SOCKETPOOL_SIZE )
1125 DEBUG_DIAG((
"Tried to add more than %d sockets to socket pool",
1130 socketInfo[ i ] = SOCKET_INFO_TEMPLATE;
1131 socketInfo[ i ].netSocket = netSocket;
1132 socketInfo[ i ].refCount = 1;
1139 static void deleteSocket(
const SOCKET netSocket )
1152 for( i = 0; i < SOCKETPOOL_SIZE; i++ )
1154 if( socketInfo[ i ].netSocket == netSocket )
1157 if( i >= SOCKETPOOL_SIZE )
1165 socketInfo[ i ].refCount--;
1166 if( socketInfo[ i ].
refCount <= 0 )
1170 status = closesocket( socketInfo[ i ].netSocket );
1171 if( isSocketError( status ) )
1177 socketInfo[ i ].iChecksum = 0;
1178 memset( socketInfo[ i ].iData, 0,
1179 sizeof( socketInfo[ i ].iData ) );
1180 socketInfo[ i ].iDataLen = 0;
1182 DEBUG_DIAG((
"Couldn't close socket pool socket" ));
1186 socketInfo[ i ] = SOCKET_INFO_TEMPLATE;
1229 for( i = 0; i < SOCKETPOOL_SIZE; i++ )
1231 if( !isBadSocket( socketInfo[ i ].netSocket ) )
1233 closesocket( socketInfo[ i ].netSocket );
1234 socketInfo[ i ] = SOCKET_INFO_TEMPLATE;
1289 const BOOLEAN previousDataRead,
1290 IN_ENUM( IOWAIT )
const IOWAIT_TYPE type )
1292 static const struct {
1305 fd_set readfds, writefds, exceptfds;
1306 fd_set *readFDPtr = ( type == IOWAIT_READ || \
1307 type == IOWAIT_CONNECT || \
1308 type == IOWAIT_ACCEPT ) ? &readfds : NULL;
1309 fd_set *writeFDPtr = ( type == IOWAIT_WRITE || \
1310 type == IOWAIT_CONNECT ) ? &writefds : NULL;
1311 int selectIterations = 0,
status;
1316 REQUIRES( type > IOWAIT_NONE && type < IOWAIT_LAST );
1353 status = setMonoTimer( &timerInfo, timeout );
1358 if( readFDPtr != NULL )
1360 FD_ZERO( readFDPtr );
1361 FD_SET( netStream->netSocket, readFDPtr );
1363 if( writeFDPtr != NULL )
1365 FD_ZERO( writeFDPtr );
1366 FD_SET( netStream->netSocket, writeFDPtr );
1368 FD_ZERO( &exceptfds );
1369 FD_SET( netStream->netSocket, &exceptfds );
1370 tv.tv_sec = timeout;
1371 tv.tv_usec = ( timeout <= 0 ) ? 5000 : 0;
1374 status = select( netStream->netSocket + 1, readFDPtr, writeFDPtr,
1380 if( isSocketError( status ) && !isRestartableError() )
1384 return( getSocketError( netStream, errorInfo[ type ].status,
1388 while( isSocketError( status ) && \
1389 !checkMonoTimerExpired( &timerInfo ) && \
1393 char errorMessage[ 128 + 8 ];
1394 int errorMessageLength;
1403 DEBUG_DIAG((
"select() went through %d iterations without "
1406 errorMessageLength =
sprintf_s( errorMessage, 128,
1407 "select() on %s went through %d "
1408 "iterations without returning a "
1412 return( setSocketError( netStream, errorMessage, errorMessageLength,
1419 if( status == 0 || isSocketError( status ) )
1421 char errorMessage[ 128 + 8 ];
1422 int errorMessageLength;
1427 if( previousDataRead )
1438 errorMessageLength =
sprintf_s( errorMessage, 128,
1439 "Timeout on %s (select()) after %d "
1443 return( setSocketError( netStream, errorMessage, errorMessageLength,
1459 if( FD_ISSET( netStream->netSocket, &exceptfds ) )
1461 int socketErrorCode;
1463 status = getSocketError( netStream, errorInfo[ type ].status,
1465 if( socketErrorCode == 0 )
1492 if( type == IOWAIT_CONNECT )
1494 ( void ) mapError( netStream, 0,
FALSE,
1499 ( void ) mapError( netStream, TIMEOUT_ERROR,
FALSE,
1508 ENSURES( ( type == IOWAIT_READ && \
1509 FD_ISSET( netStream->netSocket, &readfds ) ) || \
1510 ( type == IOWAIT_WRITE && \
1511 FD_ISSET( netStream->netSocket, &writefds ) ) || \
1512 ( type == IOWAIT_CONNECT && \
1513 ( FD_ISSET( netStream->netSocket, &readfds ) || \
1514 FD_ISSET( netStream->netSocket, &writefds ) ) ) || \
1515 ( type == IOWAIT_ACCEPT ) );
1538 IN_BUFFER( hostNameLen )
const char *host,
1543 struct addrinfo *addrInfoPtr, *addrInfoCursor;
1545 int addressCount,
status;
1548 assert(
isReadPtr( host, hostNameLen ) );
1551 REQUIRES( port >= 22 && port < 65536L );
1557 status = getAddressInfo( netStream, &addrInfoPtr, host, hostNameLen, port,
1574 for( addrInfoCursor = addrInfoPtr, addressCount = 0;
1575 addrInfoCursor != NULL && addressCount < IP_ADDR_COUNT;
1576 addrInfoCursor = addrInfoCursor->ai_next, addressCount++ )
1578 status = newSocket( &netSocket, addrInfoCursor,
FALSE );
1581 setSocketNonblocking( netSocket );
1582 status = connect( netSocket, addrInfoCursor->ai_addr,
1583 addrInfoCursor->ai_addrlen );
1584 nonBlockWarning = isNonblockWarning();
1585 if( status >= 0 || nonBlockWarning )
1590 deleteSocket( netSocket );
1592 if( addressCount >= IP_ADDR_COUNT )
1597 DEBUG_DIAG((
"Iterated through %d server addresses without being "
1598 "able to connect", IP_ADDR_COUNT ));
1602 freeAddressInfo( addrInfoPtr );
1603 if( status < 0 && !nonBlockWarning )
1607 return( mapError( netStream, getErrorCode(),
FALSE,
1615 netStream->netSocket = netSocket;
1622 netStream->netSocket = netSocket;
1630 static const int trueValue = 1;
1631 SIZE_TYPE intLength =
sizeof( int );
1646 status = ioWait( netStream,
min( netStream->timeout, 500000L ),
FALSE,
1650 netStream->transportDisconnectFunction( netStream,
TRUE );
1668 status = getsockopt( netStream->netSocket, SOL_SOCKET, SO_ERROR,
1669 (
void * ) &value, &intLength );
1676 netStream->transportDisconnectFunction( netStream,
TRUE );
1683 if( isSocketError( status ) )
1688 netStream->transportDisconnectFunction( netStream,
TRUE );
1700 setsockopt( netStream->netSocket, IPPROTO_TCP, TCP_NODELAY,
1701 (
void * ) &trueValue,
sizeof(
int ) );
1702 setSocketBlocking( netStream->netSocket );
1716 SOCKADDR_STORAGE clientAddr;
1717 struct addrinfo *addrInfoPtr, *addrInfoCursor;
1718 static const int trueValue = 1;
1719 static const int falseValue = 0;
1720 SIZE_TYPE clientAddrLen =
sizeof( SOCKADDR_STORAGE );
1722 int addressCount, errorCode = 0,
status;
1725 assert( ( host == NULL && hostNameLen == 0 ) || \
1728 REQUIRES( ( host == NULL && hostNameLen == 0 ) || \
1731 REQUIRES( port >= 22 && port < 65536L );
1742 memcpy( hostNameBuffer, host, hostNameLen );
1743 hostNameBuffer[ hostNameLen ] =
'\0';
1744 host = hostNameBuffer;
1789 status = getAddressInfo( netStream, &addrInfoPtr, host, hostNameLen,
1805 for( addrInfoCursor = addrInfoPtr, addressCount = 0;
1806 addrInfoCursor != NULL && addressCount < IP_ADDR_COUNT;
1807 addrInfoCursor = addrInfoCursor->ai_next, addressCount++ )
1809 SIZE_TYPE
valueLen =
sizeof( int );
1812 status = newSocket( &listenSocket, addrInfoCursor,
TRUE );
1846 if( addrInfoCursor->ai_family == PF_INET6 && \
1847 getsockopt( listenSocket, IPPROTO_IPV6, IPV6_V6ONLY,
1848 (
char * ) &value, &valueLen ) == 0 && value == 1 )
1850 setsockopt( listenSocket, IPPROTO_IPV6, IPV6_V6ONLY,
1851 (
char * ) &falseValue,
sizeof(
int ) );
1859 if( setsockopt( listenSocket, SOL_SOCKET, SO_REUSEADDR,
1860 (
char * ) &trueValue,
sizeof(
int ) ) || \
1861 bind( listenSocket, addrInfoCursor->ai_addr,
1862 addrInfoCursor->ai_addrlen ) || \
1863 listen( listenSocket, 5 ) )
1867 errorCode = getErrorCode();
1872 deleteSocket( listenSocket );
1884 freeAddressInfo( addrInfoPtr );
1885 if( addressCount >= IP_ADDR_COUNT )
1890 DEBUG_DIAG((
"Iterated through %d server addresses without being "
1891 "able to listen", IP_ADDR_COUNT ));
1899 return( mapError( netStream,
1900 ( errorCode == 0 ) ? getErrorCode() : errorCode,
1914 netStream->netSocket = listenSocket;
1915 status = ioWait( netStream,
min( netStream->timeout, 30000000L ),
FALSE,
1948 setSocketNonblocking( listenSocket );
1949 netSocket = accept( listenSocket, (
struct sockaddr * ) &clientAddr,
1951 if( isBadSocket( netSocket ) )
1953 if( isNonblockWarning() )
1955 status = setSocketError( netStream,
1956 "Remote system closed the connection "
1957 "after completing the TCP handshake",
1966 setSocketBlocking( listenSocket );
1967 deleteSocket( listenSocket );
1970 setSocketBlocking( listenSocket );
1971 setSocketBlocking( netSocket );
1980 ( void ) getNameInfo( (
const struct sockaddr * ) &clientAddr,
1981 clientAddrLen, netStream->clientAddress,
1983 &netStream->clientAddressLen,
1984 &netStream->clientPort );
1989 status = addSocket( netSocket );
1995 closesocket( netSocket );
1996 return( setSocketError( netStream,
1997 "Couldn't add socket to socket pool", 34,
2000 netStream->netSocket = netSocket;
2001 netStream->listenSocket = listenSocket;
2004 setsockopt( netStream->netSocket, IPPROTO_TCP, TCP_NODELAY,
2005 (
void * ) &trueValue,
sizeof(
int ) );
2019 assert( ( hostName == NULL && hostNameLen == 0 ) || \
2022 REQUIRES( ( hostName == NULL && hostNameLen == 0 ) || \
2023 ( hostName != NULL && \
2025 REQUIRES( port >= 22 && port < 65536L );
2032 const int savedTimeout = netStream->timeout;
2043 status = openServerSocket( netStream, hostName, hostNameLen, port );
2044 netStream->timeout = savedTimeout;
2048 ENSURES( hostName != NULL && \
2055 status = preOpenSocket( netStream, hostName, hostNameLen, port );
2057 status = completeOpen( netStream );
2118 const BOOLEAN fullDisconnect )
2125 if( !fullDisconnect )
2128 shutdown( netStream->netSocket, SHUT_WR );
2138 deleteSocket( netStream->netSocket );
2140 deleteSocket( netStream->listenSocket );
2141 netStream->netSocket = netStream->listenSocket =
CRYPT_ERROR;
2157 getSocketNonblockingStatus( netStream->netSocket, value );
2158 if( isSocketError( value ) )
2166 return( setSocketError( netStream,
"Socket is non-blocking", 22,
2222 BYTE *bufPtr = buffer;
2225 max( 30, netStream->timeout ) : netStream->timeout;
2226 int bytesToRead, byteCount = 0, iterationCount,
status;
2230 assert(
isWritePtr( length,
sizeof(
int ) ) );
2234 REQUIRES_S( ( ( flags & TRANSPORT_FLAG_NONBLOCKING ) && \
2236 ( !( flags & TRANSPORT_FLAG_NONBLOCKING ) && \
2239 flags == TRANSPORT_FLAG_NONBLOCKING || \
2245 status = setMonoTimer( &timerInfo, timeout );
2248 for( bytesToRead = maxLength, iterationCount = 0;
2249 bytesToRead > 0 && \
2250 ( timeout <= 0 || !checkMonoTimerExpired( &timerInfo ) ) && \
2257 status = ioWait( netStream, timeout,
2258 ( byteCount > 0 ) ?
TRUE :
FALSE, IOWAIT_READ );
2265 *length = byteCount;
2282 return( checkFirewallError( netStream ) );
2288 bytesRead = recv( netStream->netSocket, bufPtr, bytesToRead, 0 );
2289 if( isSocketError( bytesRead ) )
2295 if( isRestartableError() )
2297 assert( !
"Restartable read, recv() indicated error" );
2304 if( bytesRead <= 0 )
2332 if( isRestartableError() )
2334 assert( !
"Restartable read, recv() indicated no error" );
2347 status = ioWait( stream, 0, 0, IOWAIT_READ );
2357 bufPtr += bytesRead;
2358 bytesToRead -= bytesRead;
2359 byteCount += bytesRead;
2385 if( ( byteCount / timeout ) >= 1000 && \
2386 checkMonoTimerExpiryImminent( &timerInfo, 5 ) )
2388 extendMonoTimer( &timerInfo,
2389 ( getRandomInteger() % 5 ) + 2 );
2394 if( maxLength > 0 && byteCount <= 0 )
2399 return( setSocketError( netStream,
2400 "No data was read because the remote system "
2401 "closed the connection (recv() == 0)", 78,
2404 *length = byteCount;
2410 static
int writeSocketFunction(
INOUT STREAM *stream,
2418 const BYTE *bufPtr = buffer;
2419 const int timeout = ( flags & TRANSPORT_FLAG_NONBLOCKING ) ? 0 : \
2421 max( 30, netStream->timeout ) : netStream->timeout;
2422 int bytesToWrite, byteCount = 0, iterationCount,
status;
2425 assert(
isReadPtr( buffer, maxLength ) );
2426 assert(
isWritePtr( length,
sizeof(
int ) ) );
2430 REQUIRES_S( ( ( flags & TRANSPORT_FLAG_NONBLOCKING ) && \
2432 ( !( flags & TRANSPORT_FLAG_NONBLOCKING ) && \
2435 flags == TRANSPORT_FLAG_NONBLOCKING || \
2436 flags == TRANSPORT_FLAG_BLOCKING );
2464 status = setMonoTimer( &timerInfo, timeout );
2467 for( bytesToWrite = maxLength, iterationCount = 0;
2468 bytesToWrite > 0 && \
2469 ( timeout <= 0 || !checkMonoTimerExpired( &timerInfo ) ) && \
2476 status = ioWait( netStream, timeout,
2477 ( byteCount > 0 ) ?
TRUE :
FALSE, IOWAIT_WRITE );
2485 *length = byteCount;
2495 bytesWritten = send( netStream->netSocket, bufPtr, bytesToWrite,
2497 if( isSocketError( bytesWritten ) )
2504 if( isRestartableError() )
2506 assert( !
"Restartable write, send() indicated error" );
2512 if( WSAGetLastError() < WSABASEERR )
2514 assert( !
"send() failed but WSAGetLastError() indicated no "
2515 "error, ignoring" );
2523 bufPtr += bytesWritten;
2524 bytesToWrite -= bytesWritten;
2525 byteCount += bytesWritten;
2530 *length = byteCount;
2541 netStream->transportConnectFunction = openSocketFunction;
2542 netStream->transportDisconnectFunction = closeSocketFunction;
2543 netStream->transportReadFunction = readSocketFunction;
2544 netStream->transportWriteFunction = writeSocketFunction;
2545 netStream->transportOKFunction = transportOKFunction;
2546 netStream->transportCheckFunction = checkSocketFunction;