xref: /onnv-gate/usr/src/common/openssl/apps/s_socket.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* apps/s_socket.c -  socket-related functions used by s_client and s_server */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include <stdlib.h>
610Sstevel@tonic-gate #include <string.h>
620Sstevel@tonic-gate #include <errno.h>
630Sstevel@tonic-gate #include <signal.h>
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /* With IPv6, it looks like Digital has mixed up the proper order of
660Sstevel@tonic-gate    recursive header file inclusion, resulting in the compiler complaining
670Sstevel@tonic-gate    that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which
680Sstevel@tonic-gate    is needed to have fileno() declared correctly...  So let's define u_int */
690Sstevel@tonic-gate #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
700Sstevel@tonic-gate #define __U_INT
710Sstevel@tonic-gate typedef unsigned int u_int;
720Sstevel@tonic-gate #endif
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #define USE_SOCKETS
750Sstevel@tonic-gate #define NON_MAIN
760Sstevel@tonic-gate #include "apps.h"
770Sstevel@tonic-gate #undef USE_SOCKETS
780Sstevel@tonic-gate #undef NON_MAIN
790Sstevel@tonic-gate #include "s_apps.h"
800Sstevel@tonic-gate #include <openssl/ssl.h>
810Sstevel@tonic-gate 
82*2139Sjp161948 #ifdef FLAT_INC
83*2139Sjp161948 #include "e_os.h"
84*2139Sjp161948 #else
85*2139Sjp161948 #include "../e_os.h"
86*2139Sjp161948 #endif
87*2139Sjp161948 
88*2139Sjp161948 #ifndef OPENSSL_NO_SOCK
89*2139Sjp161948 
90*2139Sjp161948 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
91*2139Sjp161948 #include "netdb.h"
92*2139Sjp161948 #endif
93*2139Sjp161948 
940Sstevel@tonic-gate static struct hostent *GetHostByName(char *name);
95*2139Sjp161948 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
960Sstevel@tonic-gate static void ssl_sock_cleanup(void);
970Sstevel@tonic-gate #endif
980Sstevel@tonic-gate static int ssl_sock_init(void);
99*2139Sjp161948 static int init_client_ip(int *sock,unsigned char ip[4], int port, int type);
100*2139Sjp161948 static int init_server(int *sock, int port, int type);
101*2139Sjp161948 static int init_server_long(int *sock, int port,char *ip, int type);
1020Sstevel@tonic-gate static int do_accept(int acc_sock, int *sock, char **host);
1030Sstevel@tonic-gate static int host_ip(char *str, unsigned char ip[4]);
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
1060Sstevel@tonic-gate #define SOCKET_PROTOCOL	0 /* more microsoft stupidity */
1070Sstevel@tonic-gate #else
1080Sstevel@tonic-gate #define SOCKET_PROTOCOL	IPPROTO_TCP
1090Sstevel@tonic-gate #endif
1100Sstevel@tonic-gate 
111*2139Sjp161948 #if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
112*2139Sjp161948 static int wsa_init_done=0;
113*2139Sjp161948 #endif
114*2139Sjp161948 
1150Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
1160Sstevel@tonic-gate static struct WSAData wsa_state;
1170Sstevel@tonic-gate static int wsa_init_done=0;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
1200Sstevel@tonic-gate static HWND topWnd=0;
1210Sstevel@tonic-gate static FARPROC lpTopWndProc=NULL;
1220Sstevel@tonic-gate static FARPROC lpTopHookProc=NULL;
1230Sstevel@tonic-gate extern HINSTANCE _hInstance;  /* nice global CRT provides */
1240Sstevel@tonic-gate 
topHookProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)1250Sstevel@tonic-gate static LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam,
1260Sstevel@tonic-gate 	     LPARAM lParam)
1270Sstevel@tonic-gate 	{
1280Sstevel@tonic-gate 	if (hwnd == topWnd)
1290Sstevel@tonic-gate 		{
1300Sstevel@tonic-gate 		switch(message)
1310Sstevel@tonic-gate 			{
1320Sstevel@tonic-gate 		case WM_DESTROY:
1330Sstevel@tonic-gate 		case WM_CLOSE:
1340Sstevel@tonic-gate 			SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc);
1350Sstevel@tonic-gate 			ssl_sock_cleanup();
1360Sstevel@tonic-gate 			break;
1370Sstevel@tonic-gate 			}
1380Sstevel@tonic-gate 		}
1390Sstevel@tonic-gate 	return CallWindowProc(lpTopWndProc,hwnd,message,wParam,lParam);
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 
enumproc(HWND hwnd,LPARAM lParam)1420Sstevel@tonic-gate static BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam)
1430Sstevel@tonic-gate 	{
1440Sstevel@tonic-gate 	topWnd=hwnd;
1450Sstevel@tonic-gate 	return(FALSE);
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate #endif /* OPENSSL_SYS_WIN32 */
1490Sstevel@tonic-gate #endif /* OPENSSL_SYS_WINDOWS */
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
ssl_sock_cleanup(void)1520Sstevel@tonic-gate static void ssl_sock_cleanup(void)
1530Sstevel@tonic-gate 	{
1540Sstevel@tonic-gate 	if (wsa_init_done)
1550Sstevel@tonic-gate 		{
1560Sstevel@tonic-gate 		wsa_init_done=0;
1570Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINCE
1580Sstevel@tonic-gate 		WSACancelBlockingCall();
1590Sstevel@tonic-gate #endif
1600Sstevel@tonic-gate 		WSACleanup();
1610Sstevel@tonic-gate 		}
1620Sstevel@tonic-gate 	}
163*2139Sjp161948 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
sock_cleanup(void)164*2139Sjp161948 static void sock_cleanup(void)
165*2139Sjp161948     {
166*2139Sjp161948     if (wsa_init_done)
167*2139Sjp161948         {
168*2139Sjp161948         wsa_init_done=0;
169*2139Sjp161948 		WSACleanup();
170*2139Sjp161948 		}
171*2139Sjp161948 	}
1720Sstevel@tonic-gate #endif
1730Sstevel@tonic-gate 
ssl_sock_init(void)1740Sstevel@tonic-gate static int ssl_sock_init(void)
1750Sstevel@tonic-gate 	{
1760Sstevel@tonic-gate #ifdef WATT32
1770Sstevel@tonic-gate 	extern int _watt_do_exit;
1780Sstevel@tonic-gate 	_watt_do_exit = 0;
1790Sstevel@tonic-gate 	if (sock_init())
1800Sstevel@tonic-gate 		return (0);
1810Sstevel@tonic-gate #elif defined(OPENSSL_SYS_WINDOWS)
1820Sstevel@tonic-gate 	if (!wsa_init_done)
1830Sstevel@tonic-gate 		{
1840Sstevel@tonic-gate 		int err;
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate #ifdef SIGINT
1870Sstevel@tonic-gate 		signal(SIGINT,(void (*)(int))ssl_sock_cleanup);
1880Sstevel@tonic-gate #endif
1890Sstevel@tonic-gate 		wsa_init_done=1;
1900Sstevel@tonic-gate 		memset(&wsa_state,0,sizeof(wsa_state));
1910Sstevel@tonic-gate 		if (WSAStartup(0x0101,&wsa_state)!=0)
1920Sstevel@tonic-gate 			{
1930Sstevel@tonic-gate 			err=WSAGetLastError();
1940Sstevel@tonic-gate 			BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err);
1950Sstevel@tonic-gate 			return(0);
1960Sstevel@tonic-gate 			}
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
1990Sstevel@tonic-gate 		EnumTaskWindows(GetCurrentTask(),enumproc,0L);
2000Sstevel@tonic-gate 		lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC);
2010Sstevel@tonic-gate 		lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance);
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 		SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc);
2040Sstevel@tonic-gate #endif /* OPENSSL_SYS_WIN16 */
2050Sstevel@tonic-gate 		}
206*2139Sjp161948 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
207*2139Sjp161948    WORD wVerReq;
208*2139Sjp161948    WSADATA wsaData;
209*2139Sjp161948    int err;
210*2139Sjp161948 
211*2139Sjp161948    if (!wsa_init_done)
212*2139Sjp161948       {
213*2139Sjp161948 
214*2139Sjp161948 # ifdef SIGINT
215*2139Sjp161948       signal(SIGINT,(void (*)(int))sock_cleanup);
216*2139Sjp161948 # endif
217*2139Sjp161948 
218*2139Sjp161948       wsa_init_done=1;
219*2139Sjp161948       wVerReq = MAKEWORD( 2, 0 );
220*2139Sjp161948       err = WSAStartup(wVerReq,&wsaData);
221*2139Sjp161948       if (err != 0)
222*2139Sjp161948          {
223*2139Sjp161948          BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err);
224*2139Sjp161948          return(0);
225*2139Sjp161948          }
226*2139Sjp161948       }
2270Sstevel@tonic-gate #endif /* OPENSSL_SYS_WINDOWS */
2280Sstevel@tonic-gate 	return(1);
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 
init_client(int * sock,char * host,int port,int type)231*2139Sjp161948 int init_client(int *sock, char *host, int port, int type)
2320Sstevel@tonic-gate 	{
2330Sstevel@tonic-gate 	unsigned char ip[4];
2340Sstevel@tonic-gate 	short p=0;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	if (!host_ip(host,&(ip[0])))
2370Sstevel@tonic-gate 		{
2380Sstevel@tonic-gate 		return(0);
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 	if (p != 0) port=p;
241*2139Sjp161948 	return(init_client_ip(sock,ip,port,type));
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
init_client_ip(int * sock,unsigned char ip[4],int port,int type)244*2139Sjp161948 static int init_client_ip(int *sock, unsigned char ip[4], int port, int type)
2450Sstevel@tonic-gate 	{
2460Sstevel@tonic-gate 	unsigned long addr;
2470Sstevel@tonic-gate 	struct sockaddr_in them;
2480Sstevel@tonic-gate 	int s,i;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if (!ssl_sock_init()) return(0);
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	memset((char *)&them,0,sizeof(them));
2530Sstevel@tonic-gate 	them.sin_family=AF_INET;
2540Sstevel@tonic-gate 	them.sin_port=htons((unsigned short)port);
2550Sstevel@tonic-gate 	addr=(unsigned long)
2560Sstevel@tonic-gate 		((unsigned long)ip[0]<<24L)|
2570Sstevel@tonic-gate 		((unsigned long)ip[1]<<16L)|
2580Sstevel@tonic-gate 		((unsigned long)ip[2]<< 8L)|
2590Sstevel@tonic-gate 		((unsigned long)ip[3]);
2600Sstevel@tonic-gate 	them.sin_addr.s_addr=htonl(addr);
2610Sstevel@tonic-gate 
262*2139Sjp161948 	if (type == SOCK_STREAM)
263*2139Sjp161948 		s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
264*2139Sjp161948 	else /* ( type == SOCK_DGRAM) */
265*2139Sjp161948 		s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
266*2139Sjp161948 
2670Sstevel@tonic-gate 	if (s == INVALID_SOCKET) { perror("socket"); return(0); }
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate #ifndef OPENSSL_SYS_MPE
270*2139Sjp161948 	if (type == SOCK_STREAM)
271*2139Sjp161948 		{
272*2139Sjp161948 		i=0;
273*2139Sjp161948 		i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
274*2139Sjp161948 		if (i < 0) { perror("keepalive"); return(0); }
275*2139Sjp161948 		}
2760Sstevel@tonic-gate #endif
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
2790Sstevel@tonic-gate 		{ close(s); perror("connect"); return(0); }
2800Sstevel@tonic-gate 	*sock=s;
2810Sstevel@tonic-gate 	return(1);
2820Sstevel@tonic-gate 	}
2830Sstevel@tonic-gate 
do_server(int port,int type,int * ret,int (* cb)(char * hostname,int s,unsigned char * context),unsigned char * context)284*2139Sjp161948 int do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context)
2850Sstevel@tonic-gate 	{
2860Sstevel@tonic-gate 	int sock;
287*2139Sjp161948 	char *name = NULL;
2880Sstevel@tonic-gate 	int accept_socket;
2890Sstevel@tonic-gate 	int i;
2900Sstevel@tonic-gate 
291*2139Sjp161948 	if (!init_server(&accept_socket,port,type)) return(0);
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	if (ret != NULL)
2940Sstevel@tonic-gate 		{
2950Sstevel@tonic-gate 		*ret=accept_socket;
2960Sstevel@tonic-gate 		/* return(1);*/
2970Sstevel@tonic-gate 		}
298*2139Sjp161948   	for (;;)
299*2139Sjp161948   		{
300*2139Sjp161948 		if (type==SOCK_STREAM)
3010Sstevel@tonic-gate 			{
302*2139Sjp161948 			if (do_accept(accept_socket,&sock,&name) == 0)
303*2139Sjp161948 				{
304*2139Sjp161948 				SHUTDOWN(accept_socket);
305*2139Sjp161948 				return(0);
306*2139Sjp161948 				}
3070Sstevel@tonic-gate 			}
308*2139Sjp161948 		else
309*2139Sjp161948 			sock = accept_socket;
3100Sstevel@tonic-gate 		i=(*cb)(name,sock, context);
3110Sstevel@tonic-gate 		if (name != NULL) OPENSSL_free(name);
312*2139Sjp161948 		if (type==SOCK_STREAM)
313*2139Sjp161948 			SHUTDOWN2(sock);
3140Sstevel@tonic-gate 		if (i < 0)
3150Sstevel@tonic-gate 			{
3160Sstevel@tonic-gate 			SHUTDOWN2(accept_socket);
3170Sstevel@tonic-gate 			return(i);
3180Sstevel@tonic-gate 			}
3190Sstevel@tonic-gate 		}
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate 
init_server_long(int * sock,int port,char * ip,int type)322*2139Sjp161948 static int init_server_long(int *sock, int port, char *ip, int type)
3230Sstevel@tonic-gate 	{
3240Sstevel@tonic-gate 	int ret=0;
3250Sstevel@tonic-gate 	struct sockaddr_in server;
3260Sstevel@tonic-gate 	int s= -1,i;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	if (!ssl_sock_init()) return(0);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	memset((char *)&server,0,sizeof(server));
3310Sstevel@tonic-gate 	server.sin_family=AF_INET;
3320Sstevel@tonic-gate 	server.sin_port=htons((unsigned short)port);
3330Sstevel@tonic-gate 	if (ip == NULL)
3340Sstevel@tonic-gate 		server.sin_addr.s_addr=INADDR_ANY;
3350Sstevel@tonic-gate 	else
3360Sstevel@tonic-gate /* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
3370Sstevel@tonic-gate #ifndef BIT_FIELD_LIMITS
3380Sstevel@tonic-gate 		memcpy(&server.sin_addr.s_addr,ip,4);
3390Sstevel@tonic-gate #else
3400Sstevel@tonic-gate 		memcpy(&server.sin_addr,ip,4);
3410Sstevel@tonic-gate #endif
342*2139Sjp161948 
343*2139Sjp161948 		if (type == SOCK_STREAM)
344*2139Sjp161948 			s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
345*2139Sjp161948 		else /* type == SOCK_DGRAM */
346*2139Sjp161948 			s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	if (s == INVALID_SOCKET) goto err;
3490Sstevel@tonic-gate #if defined SOL_SOCKET && defined SO_REUSEADDR
3500Sstevel@tonic-gate 		{
3510Sstevel@tonic-gate 		int j = 1;
3520Sstevel@tonic-gate 		setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
3530Sstevel@tonic-gate 			   (void *) &j, sizeof j);
3540Sstevel@tonic-gate 		}
3550Sstevel@tonic-gate #endif
3560Sstevel@tonic-gate 	if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
3570Sstevel@tonic-gate 		{
3580Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINDOWS
3590Sstevel@tonic-gate 		perror("bind");
3600Sstevel@tonic-gate #endif
3610Sstevel@tonic-gate 		goto err;
3620Sstevel@tonic-gate 		}
3630Sstevel@tonic-gate 	/* Make it 128 for linux */
364*2139Sjp161948 	if (type==SOCK_STREAM && listen(s,128) == -1) goto err;
3650Sstevel@tonic-gate 	i=0;
3660Sstevel@tonic-gate 	*sock=s;
3670Sstevel@tonic-gate 	ret=1;
3680Sstevel@tonic-gate err:
3690Sstevel@tonic-gate 	if ((ret == 0) && (s != -1))
3700Sstevel@tonic-gate 		{
3710Sstevel@tonic-gate 		SHUTDOWN(s);
3720Sstevel@tonic-gate 		}
3730Sstevel@tonic-gate 	return(ret);
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 
init_server(int * sock,int port,int type)376*2139Sjp161948 static int init_server(int *sock, int port, int type)
3770Sstevel@tonic-gate 	{
378*2139Sjp161948 	return(init_server_long(sock, port, NULL, type));
3790Sstevel@tonic-gate 	}
3800Sstevel@tonic-gate 
do_accept(int acc_sock,int * sock,char ** host)3810Sstevel@tonic-gate static int do_accept(int acc_sock, int *sock, char **host)
3820Sstevel@tonic-gate 	{
3830Sstevel@tonic-gate 	int ret,i;
3840Sstevel@tonic-gate 	struct hostent *h1,*h2;
3850Sstevel@tonic-gate 	static struct sockaddr_in from;
3860Sstevel@tonic-gate 	int len;
3870Sstevel@tonic-gate /*	struct linger ling; */
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	if (!ssl_sock_init()) return(0);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINDOWS
3920Sstevel@tonic-gate redoit:
3930Sstevel@tonic-gate #endif
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	memset((char *)&from,0,sizeof(from));
3960Sstevel@tonic-gate 	len=sizeof(from);
3970Sstevel@tonic-gate 	/* Note: under VMS with SOCKETSHR the fourth parameter is currently
3980Sstevel@tonic-gate 	 * of type (int *) whereas under other systems it is (void *) if
3990Sstevel@tonic-gate 	 * you don't have a cast it will choke the compiler: if you do
4000Sstevel@tonic-gate 	 * have a cast then you can either go for (int *) or (void *).
4010Sstevel@tonic-gate 	 */
4020Sstevel@tonic-gate 	ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
4030Sstevel@tonic-gate 	if (ret == INVALID_SOCKET)
4040Sstevel@tonic-gate 		{
405*2139Sjp161948 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
4060Sstevel@tonic-gate 		i=WSAGetLastError();
4070Sstevel@tonic-gate 		BIO_printf(bio_err,"accept error %d\n",i);
4080Sstevel@tonic-gate #else
4090Sstevel@tonic-gate 		if (errno == EINTR)
4100Sstevel@tonic-gate 			{
4110Sstevel@tonic-gate 			/*check_timeout(); */
4120Sstevel@tonic-gate 			goto redoit;
4130Sstevel@tonic-gate 			}
4140Sstevel@tonic-gate 		fprintf(stderr,"errno=%d ",errno);
4150Sstevel@tonic-gate 		perror("accept");
4160Sstevel@tonic-gate #endif
4170Sstevel@tonic-gate 		return(0);
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate 	ling.l_onoff=1;
4220Sstevel@tonic-gate 	ling.l_linger=0;
4230Sstevel@tonic-gate 	i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
4240Sstevel@tonic-gate 	if (i < 0) { perror("linger"); return(0); }
4250Sstevel@tonic-gate 	i=0;
4260Sstevel@tonic-gate 	i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
4270Sstevel@tonic-gate 	if (i < 0) { perror("keepalive"); return(0); }
4280Sstevel@tonic-gate */
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	if (host == NULL) goto end;
4310Sstevel@tonic-gate #ifndef BIT_FIELD_LIMITS
4320Sstevel@tonic-gate 	/* I should use WSAAsyncGetHostByName() under windows */
4330Sstevel@tonic-gate 	h1=gethostbyaddr((char *)&from.sin_addr.s_addr,
4340Sstevel@tonic-gate 		sizeof(from.sin_addr.s_addr),AF_INET);
4350Sstevel@tonic-gate #else
4360Sstevel@tonic-gate 	h1=gethostbyaddr((char *)&from.sin_addr,
4370Sstevel@tonic-gate 		sizeof(struct in_addr),AF_INET);
4380Sstevel@tonic-gate #endif
4390Sstevel@tonic-gate 	if (h1 == NULL)
4400Sstevel@tonic-gate 		{
4410Sstevel@tonic-gate 		BIO_printf(bio_err,"bad gethostbyaddr\n");
4420Sstevel@tonic-gate 		*host=NULL;
4430Sstevel@tonic-gate 		/* return(0); */
4440Sstevel@tonic-gate 		}
4450Sstevel@tonic-gate 	else
4460Sstevel@tonic-gate 		{
4470Sstevel@tonic-gate 		if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL)
4480Sstevel@tonic-gate 			{
4490Sstevel@tonic-gate 			perror("OPENSSL_malloc");
4500Sstevel@tonic-gate 			return(0);
4510Sstevel@tonic-gate 			}
4520Sstevel@tonic-gate 		BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1);
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 		h2=GetHostByName(*host);
4550Sstevel@tonic-gate 		if (h2 == NULL)
4560Sstevel@tonic-gate 			{
4570Sstevel@tonic-gate 			BIO_printf(bio_err,"gethostbyname failure\n");
4580Sstevel@tonic-gate 			return(0);
4590Sstevel@tonic-gate 			}
4600Sstevel@tonic-gate 		i=0;
4610Sstevel@tonic-gate 		if (h2->h_addrtype != AF_INET)
4620Sstevel@tonic-gate 			{
4630Sstevel@tonic-gate 			BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
4640Sstevel@tonic-gate 			return(0);
4650Sstevel@tonic-gate 			}
4660Sstevel@tonic-gate 		}
4670Sstevel@tonic-gate end:
4680Sstevel@tonic-gate 	*sock=ret;
4690Sstevel@tonic-gate 	return(1);
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 
extract_host_port(char * str,char ** host_ptr,unsigned char * ip,short * port_ptr)4720Sstevel@tonic-gate int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
4730Sstevel@tonic-gate 	     short *port_ptr)
4740Sstevel@tonic-gate 	{
4750Sstevel@tonic-gate 	char *h,*p;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	h=str;
4780Sstevel@tonic-gate 	p=strchr(str,':');
4790Sstevel@tonic-gate 	if (p == NULL)
4800Sstevel@tonic-gate 		{
4810Sstevel@tonic-gate 		BIO_printf(bio_err,"no port defined\n");
4820Sstevel@tonic-gate 		return(0);
4830Sstevel@tonic-gate 		}
4840Sstevel@tonic-gate 	*(p++)='\0';
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	if ((ip != NULL) && !host_ip(str,ip))
4870Sstevel@tonic-gate 		goto err;
4880Sstevel@tonic-gate 	if (host_ptr != NULL) *host_ptr=h;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	if (!extract_port(p,port_ptr))
4910Sstevel@tonic-gate 		goto err;
4920Sstevel@tonic-gate 	return(1);
4930Sstevel@tonic-gate err:
4940Sstevel@tonic-gate 	return(0);
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
host_ip(char * str,unsigned char ip[4])4970Sstevel@tonic-gate static int host_ip(char *str, unsigned char ip[4])
4980Sstevel@tonic-gate 	{
4990Sstevel@tonic-gate 	unsigned int in[4];
5000Sstevel@tonic-gate 	int i;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
5030Sstevel@tonic-gate 		{
5040Sstevel@tonic-gate 		for (i=0; i<4; i++)
5050Sstevel@tonic-gate 			if (in[i] > 255)
5060Sstevel@tonic-gate 				{
5070Sstevel@tonic-gate 				BIO_printf(bio_err,"invalid IP address\n");
5080Sstevel@tonic-gate 				goto err;
5090Sstevel@tonic-gate 				}
5100Sstevel@tonic-gate 		ip[0]=in[0];
5110Sstevel@tonic-gate 		ip[1]=in[1];
5120Sstevel@tonic-gate 		ip[2]=in[2];
5130Sstevel@tonic-gate 		ip[3]=in[3];
5140Sstevel@tonic-gate 		}
5150Sstevel@tonic-gate 	else
5160Sstevel@tonic-gate 		{ /* do a gethostbyname */
5170Sstevel@tonic-gate 		struct hostent *he;
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 		if (!ssl_sock_init()) return(0);
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 		he=GetHostByName(str);
5220Sstevel@tonic-gate 		if (he == NULL)
5230Sstevel@tonic-gate 			{
5240Sstevel@tonic-gate 			BIO_printf(bio_err,"gethostbyname failure\n");
5250Sstevel@tonic-gate 			goto err;
5260Sstevel@tonic-gate 			}
5270Sstevel@tonic-gate 		/* cast to short because of win16 winsock definition */
5280Sstevel@tonic-gate 		if ((short)he->h_addrtype != AF_INET)
5290Sstevel@tonic-gate 			{
5300Sstevel@tonic-gate 			BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
5310Sstevel@tonic-gate 			return(0);
5320Sstevel@tonic-gate 			}
5330Sstevel@tonic-gate 		ip[0]=he->h_addr_list[0][0];
5340Sstevel@tonic-gate 		ip[1]=he->h_addr_list[0][1];
5350Sstevel@tonic-gate 		ip[2]=he->h_addr_list[0][2];
5360Sstevel@tonic-gate 		ip[3]=he->h_addr_list[0][3];
5370Sstevel@tonic-gate 		}
5380Sstevel@tonic-gate 	return(1);
5390Sstevel@tonic-gate err:
5400Sstevel@tonic-gate 	return(0);
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 
extract_port(char * str,short * port_ptr)5430Sstevel@tonic-gate int extract_port(char *str, short *port_ptr)
5440Sstevel@tonic-gate 	{
5450Sstevel@tonic-gate 	int i;
5460Sstevel@tonic-gate 	struct servent *s;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	i=atoi(str);
5490Sstevel@tonic-gate 	if (i != 0)
5500Sstevel@tonic-gate 		*port_ptr=(unsigned short)i;
5510Sstevel@tonic-gate 	else
5520Sstevel@tonic-gate 		{
5530Sstevel@tonic-gate 		s=getservbyname(str,"tcp");
5540Sstevel@tonic-gate 		if (s == NULL)
5550Sstevel@tonic-gate 			{
5560Sstevel@tonic-gate 			BIO_printf(bio_err,"getservbyname failure for %s\n",str);
5570Sstevel@tonic-gate 			return(0);
5580Sstevel@tonic-gate 			}
5590Sstevel@tonic-gate 		*port_ptr=ntohs((unsigned short)s->s_port);
5600Sstevel@tonic-gate 		}
5610Sstevel@tonic-gate 	return(1);
5620Sstevel@tonic-gate 	}
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate #define GHBN_NUM	4
5650Sstevel@tonic-gate static struct ghbn_cache_st
5660Sstevel@tonic-gate 	{
5670Sstevel@tonic-gate 	char name[128];
5680Sstevel@tonic-gate 	struct hostent ent;
5690Sstevel@tonic-gate 	unsigned long order;
5700Sstevel@tonic-gate 	} ghbn_cache[GHBN_NUM];
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate static unsigned long ghbn_hits=0L;
5730Sstevel@tonic-gate static unsigned long ghbn_miss=0L;
5740Sstevel@tonic-gate 
GetHostByName(char * name)5750Sstevel@tonic-gate static struct hostent *GetHostByName(char *name)
5760Sstevel@tonic-gate 	{
5770Sstevel@tonic-gate 	struct hostent *ret;
5780Sstevel@tonic-gate 	int i,lowi=0;
5790Sstevel@tonic-gate 	unsigned long low= (unsigned long)-1;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	for (i=0; i<GHBN_NUM; i++)
5820Sstevel@tonic-gate 		{
5830Sstevel@tonic-gate 		if (low > ghbn_cache[i].order)
5840Sstevel@tonic-gate 			{
5850Sstevel@tonic-gate 			low=ghbn_cache[i].order;
5860Sstevel@tonic-gate 			lowi=i;
5870Sstevel@tonic-gate 			}
5880Sstevel@tonic-gate 		if (ghbn_cache[i].order > 0)
5890Sstevel@tonic-gate 			{
5900Sstevel@tonic-gate 			if (strncmp(name,ghbn_cache[i].name,128) == 0)
5910Sstevel@tonic-gate 				break;
5920Sstevel@tonic-gate 			}
5930Sstevel@tonic-gate 		}
5940Sstevel@tonic-gate 	if (i == GHBN_NUM) /* no hit*/
5950Sstevel@tonic-gate 		{
5960Sstevel@tonic-gate 		ghbn_miss++;
5970Sstevel@tonic-gate 		ret=gethostbyname(name);
5980Sstevel@tonic-gate 		if (ret == NULL) return(NULL);
5990Sstevel@tonic-gate 		/* else add to cache */
6000Sstevel@tonic-gate 		if(strlen(name) < sizeof ghbn_cache[0].name)
6010Sstevel@tonic-gate 			{
6020Sstevel@tonic-gate 			strcpy(ghbn_cache[lowi].name,name);
6030Sstevel@tonic-gate 			memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent));
6040Sstevel@tonic-gate 			ghbn_cache[lowi].order=ghbn_miss+ghbn_hits;
6050Sstevel@tonic-gate 			}
6060Sstevel@tonic-gate 		return(ret);
6070Sstevel@tonic-gate 		}
6080Sstevel@tonic-gate 	else
6090Sstevel@tonic-gate 		{
6100Sstevel@tonic-gate 		ghbn_hits++;
6110Sstevel@tonic-gate 		ret= &(ghbn_cache[i].ent);
6120Sstevel@tonic-gate 		ghbn_cache[i].order=ghbn_miss+ghbn_hits;
6130Sstevel@tonic-gate 		return(ret);
6140Sstevel@tonic-gate 		}
6150Sstevel@tonic-gate 	}
616*2139Sjp161948 
617*2139Sjp161948 #endif
618