159191Skris/* apps/s_socket.c -  socket-related functions used by s_client and s_server */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <stdlib.h>
6155714Skris#include <string.h>
6255714Skris#include <errno.h>
6355714Skris#include <signal.h>
6455714Skris
65205128Ssimon#ifdef FLAT_INC
66205128Ssimon#include "e_os2.h"
67205128Ssimon#else
68205128Ssimon#include "../e_os2.h"
69205128Ssimon#endif
70205128Ssimon
7155714Skris/* With IPv6, it looks like Digital has mixed up the proper order of
7255714Skris   recursive header file inclusion, resulting in the compiler complaining
7355714Skris   that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which
7455714Skris   is needed to have fileno() declared correctly...  So let's define u_int */
75109998Smarkm#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
7655714Skris#define __U_INT
7755714Skristypedef unsigned int u_int;
7855714Skris#endif
7955714Skris
8055714Skris#define USE_SOCKETS
8155714Skris#define NON_MAIN
8255714Skris#include "apps.h"
8355714Skris#undef USE_SOCKETS
8455714Skris#undef NON_MAIN
8555714Skris#include "s_apps.h"
8655714Skris#include <openssl/ssl.h>
8755714Skris
88160814Ssimon#ifdef FLAT_INC
89160814Ssimon#include "e_os.h"
90160814Ssimon#else
91160814Ssimon#include "../e_os.h"
92160814Ssimon#endif
93160814Ssimon
94160814Ssimon#ifndef OPENSSL_NO_SOCK
95160814Ssimon
96160814Ssimon#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
97160814Ssimon#include "netdb.h"
98160814Ssimon#endif
99160814Ssimon
10059191Skrisstatic struct hostent *GetHostByName(char *name);
101160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
102109998Smarkmstatic void ssl_sock_cleanup(void);
10355714Skris#endif
104109998Smarkmstatic int ssl_sock_init(void);
105160814Ssimonstatic int init_client_ip(int *sock,unsigned char ip[4], int port, int type);
106160814Ssimonstatic int init_server(int *sock, int port, int type);
107160814Ssimonstatic int init_server_long(int *sock, int port,char *ip, int type);
10859191Skrisstatic int do_accept(int acc_sock, int *sock, char **host);
10959191Skrisstatic int host_ip(char *str, unsigned char ip[4]);
11055714Skris
111109998Smarkm#ifdef OPENSSL_SYS_WIN16
11255714Skris#define SOCKET_PROTOCOL	0 /* more microsoft stupidity */
11355714Skris#else
11455714Skris#define SOCKET_PROTOCOL	IPPROTO_TCP
11555714Skris#endif
11655714Skris
117160814Ssimon#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
118160814Ssimonstatic int wsa_init_done=0;
119160814Ssimon#endif
120160814Ssimon
121109998Smarkm#ifdef OPENSSL_SYS_WINDOWS
12255714Skrisstatic struct WSAData wsa_state;
12355714Skrisstatic int wsa_init_done=0;
12455714Skris
125109998Smarkm#ifdef OPENSSL_SYS_WIN16
12655714Skrisstatic HWND topWnd=0;
12755714Skrisstatic FARPROC lpTopWndProc=NULL;
12855714Skrisstatic FARPROC lpTopHookProc=NULL;
12955714Skrisextern HINSTANCE _hInstance;  /* nice global CRT provides */
13055714Skris
13155714Skrisstatic LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam,
13255714Skris	     LPARAM lParam)
13355714Skris	{
13455714Skris	if (hwnd == topWnd)
13555714Skris		{
13655714Skris		switch(message)
13755714Skris			{
13855714Skris		case WM_DESTROY:
13955714Skris		case WM_CLOSE:
14055714Skris			SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc);
141109998Smarkm			ssl_sock_cleanup();
14255714Skris			break;
14355714Skris			}
14455714Skris		}
14555714Skris	return CallWindowProc(lpTopWndProc,hwnd,message,wParam,lParam);
14655714Skris	}
14755714Skris
14855714Skrisstatic BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam)
14955714Skris	{
15055714Skris	topWnd=hwnd;
15155714Skris	return(FALSE);
15255714Skris	}
15355714Skris
154109998Smarkm#endif /* OPENSSL_SYS_WIN32 */
155109998Smarkm#endif /* OPENSSL_SYS_WINDOWS */
15655714Skris
157109998Smarkm#ifdef OPENSSL_SYS_WINDOWS
158109998Smarkmstatic void ssl_sock_cleanup(void)
15955714Skris	{
16055714Skris	if (wsa_init_done)
16155714Skris		{
16255714Skris		wsa_init_done=0;
163109998Smarkm#ifndef OPENSSL_SYS_WINCE
16455714Skris		WSACancelBlockingCall();
165109998Smarkm#endif
16655714Skris		WSACleanup();
16755714Skris		}
16859191Skris	}
169160814Ssimon#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
170160814Ssimonstatic void sock_cleanup(void)
171160814Ssimon    {
172160814Ssimon    if (wsa_init_done)
173160814Ssimon        {
174160814Ssimon        wsa_init_done=0;
175160814Ssimon		WSACleanup();
176160814Ssimon		}
177160814Ssimon	}
17855714Skris#endif
17955714Skris
180109998Smarkmstatic int ssl_sock_init(void)
18155714Skris	{
182109998Smarkm#ifdef WATT32
183109998Smarkm	extern int _watt_do_exit;
184109998Smarkm	_watt_do_exit = 0;
185109998Smarkm	if (sock_init())
186109998Smarkm		return (0);
187109998Smarkm#elif defined(OPENSSL_SYS_WINDOWS)
18855714Skris	if (!wsa_init_done)
18955714Skris		{
19055714Skris		int err;
19155714Skris
19255714Skris#ifdef SIGINT
193109998Smarkm		signal(SIGINT,(void (*)(int))ssl_sock_cleanup);
19455714Skris#endif
19555714Skris		wsa_init_done=1;
19655714Skris		memset(&wsa_state,0,sizeof(wsa_state));
19755714Skris		if (WSAStartup(0x0101,&wsa_state)!=0)
19855714Skris			{
19955714Skris			err=WSAGetLastError();
20055714Skris			BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err);
20155714Skris			return(0);
20255714Skris			}
20355714Skris
204109998Smarkm#ifdef OPENSSL_SYS_WIN16
20555714Skris		EnumTaskWindows(GetCurrentTask(),enumproc,0L);
20655714Skris		lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC);
20755714Skris		lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance);
20855714Skris
20955714Skris		SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc);
210109998Smarkm#endif /* OPENSSL_SYS_WIN16 */
21155714Skris		}
212160814Ssimon#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
213160814Ssimon   WORD wVerReq;
214160814Ssimon   WSADATA wsaData;
215160814Ssimon   int err;
216160814Ssimon
217160814Ssimon   if (!wsa_init_done)
218160814Ssimon      {
219160814Ssimon
220160814Ssimon# ifdef SIGINT
221160814Ssimon      signal(SIGINT,(void (*)(int))sock_cleanup);
222160814Ssimon# endif
223160814Ssimon
224160814Ssimon      wsa_init_done=1;
225160814Ssimon      wVerReq = MAKEWORD( 2, 0 );
226160814Ssimon      err = WSAStartup(wVerReq,&wsaData);
227160814Ssimon      if (err != 0)
228160814Ssimon         {
229160814Ssimon         BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err);
230160814Ssimon         return(0);
231160814Ssimon         }
232160814Ssimon      }
233109998Smarkm#endif /* OPENSSL_SYS_WINDOWS */
23455714Skris	return(1);
23555714Skris	}
23655714Skris
237160814Ssimonint init_client(int *sock, char *host, int port, int type)
23855714Skris	{
23955714Skris	unsigned char ip[4];
24055714Skris
241238405Sjkim	memset(ip, '\0', sizeof ip);
24255714Skris	if (!host_ip(host,&(ip[0])))
243238405Sjkim		return 0;
244238405Sjkim	return init_client_ip(sock,ip,port,type);
24555714Skris	}
24655714Skris
247160814Ssimonstatic int init_client_ip(int *sock, unsigned char ip[4], int port, int type)
24855714Skris	{
24955714Skris	unsigned long addr;
25055714Skris	struct sockaddr_in them;
25155714Skris	int s,i;
25255714Skris
253109998Smarkm	if (!ssl_sock_init()) return(0);
25455714Skris
25555714Skris	memset((char *)&them,0,sizeof(them));
25655714Skris	them.sin_family=AF_INET;
25755714Skris	them.sin_port=htons((unsigned short)port);
25855714Skris	addr=(unsigned long)
25955714Skris		((unsigned long)ip[0]<<24L)|
26055714Skris		((unsigned long)ip[1]<<16L)|
26155714Skris		((unsigned long)ip[2]<< 8L)|
26255714Skris		((unsigned long)ip[3]);
26355714Skris	them.sin_addr.s_addr=htonl(addr);
26455714Skris
265160814Ssimon	if (type == SOCK_STREAM)
266160814Ssimon		s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
267160814Ssimon	else /* ( type == SOCK_DGRAM) */
268160814Ssimon		s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
269160814Ssimon
27055714Skris	if (s == INVALID_SOCKET) { perror("socket"); return(0); }
27155714Skris
272238405Sjkim#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
273160814Ssimon	if (type == SOCK_STREAM)
274160814Ssimon		{
275160814Ssimon		i=0;
276160814Ssimon		i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
277279264Sdelphij		if (i < 0) { closesocket(s); perror("keepalive"); return(0); }
278160814Ssimon		}
27968651Skris#endif
28055714Skris
28155714Skris	if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
282238405Sjkim		{ closesocket(s); perror("connect"); return(0); }
28355714Skris	*sock=s;
28455714Skris	return(1);
28555714Skris	}
28655714Skris
287160814Ssimonint do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context)
28855714Skris	{
28955714Skris	int sock;
290160814Ssimon	char *name = NULL;
291238405Sjkim	int accept_socket = 0;
29255714Skris	int i;
29355714Skris
294160814Ssimon	if (!init_server(&accept_socket,port,type)) return(0);
29555714Skris
29655714Skris	if (ret != NULL)
29755714Skris		{
29855714Skris		*ret=accept_socket;
29955714Skris		/* return(1);*/
30055714Skris		}
301160814Ssimon  	for (;;)
302160814Ssimon  		{
303160814Ssimon		if (type==SOCK_STREAM)
30455714Skris			{
305160814Ssimon			if (do_accept(accept_socket,&sock,&name) == 0)
306160814Ssimon				{
307160814Ssimon				SHUTDOWN(accept_socket);
308160814Ssimon				return(0);
309160814Ssimon				}
31055714Skris			}
311160814Ssimon		else
312160814Ssimon			sock = accept_socket;
31355714Skris		i=(*cb)(name,sock, context);
31468651Skris		if (name != NULL) OPENSSL_free(name);
315160814Ssimon		if (type==SOCK_STREAM)
316160814Ssimon			SHUTDOWN2(sock);
31755714Skris		if (i < 0)
31855714Skris			{
31955714Skris			SHUTDOWN2(accept_socket);
32055714Skris			return(i);
32155714Skris			}
32255714Skris		}
32355714Skris	}
32455714Skris
325160814Ssimonstatic int init_server_long(int *sock, int port, char *ip, int type)
32655714Skris	{
32755714Skris	int ret=0;
32855714Skris	struct sockaddr_in server;
329215697Ssimon	int s= -1;
33055714Skris
331109998Smarkm	if (!ssl_sock_init()) return(0);
33255714Skris
33355714Skris	memset((char *)&server,0,sizeof(server));
33455714Skris	server.sin_family=AF_INET;
33555714Skris	server.sin_port=htons((unsigned short)port);
33655714Skris	if (ip == NULL)
33755714Skris		server.sin_addr.s_addr=INADDR_ANY;
33855714Skris	else
33955714Skris/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
34055714Skris#ifndef BIT_FIELD_LIMITS
34155714Skris		memcpy(&server.sin_addr.s_addr,ip,4);
34255714Skris#else
34355714Skris		memcpy(&server.sin_addr,ip,4);
34455714Skris#endif
345160814Ssimon
346160814Ssimon		if (type == SOCK_STREAM)
347160814Ssimon			s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
348160814Ssimon		else /* type == SOCK_DGRAM */
349160814Ssimon			s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
35055714Skris
35155714Skris	if (s == INVALID_SOCKET) goto err;
35255714Skris#if defined SOL_SOCKET && defined SO_REUSEADDR
35355714Skris		{
35455714Skris		int j = 1;
35555714Skris		setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
35655714Skris			   (void *) &j, sizeof j);
35755714Skris		}
35855714Skris#endif
35955714Skris	if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
36055714Skris		{
361109998Smarkm#ifndef OPENSSL_SYS_WINDOWS
36255714Skris		perror("bind");
36355714Skris#endif
36455714Skris		goto err;
36555714Skris		}
36655714Skris	/* Make it 128 for linux */
367160814Ssimon	if (type==SOCK_STREAM && listen(s,128) == -1) goto err;
36855714Skris	*sock=s;
36955714Skris	ret=1;
37055714Skriserr:
37155714Skris	if ((ret == 0) && (s != -1))
37255714Skris		{
37355714Skris		SHUTDOWN(s);
37455714Skris		}
37555714Skris	return(ret);
37655714Skris	}
37755714Skris
378160814Ssimonstatic int init_server(int *sock, int port, int type)
37955714Skris	{
380160814Ssimon	return(init_server_long(sock, port, NULL, type));
38155714Skris	}
38255714Skris
38359191Skrisstatic int do_accept(int acc_sock, int *sock, char **host)
38455714Skris	{
385215697Ssimon	int ret;
38655714Skris	struct hostent *h1,*h2;
38755714Skris	static struct sockaddr_in from;
38855714Skris	int len;
38955714Skris/*	struct linger ling; */
39055714Skris
391109998Smarkm	if (!ssl_sock_init()) return(0);
39255714Skris
393109998Smarkm#ifndef OPENSSL_SYS_WINDOWS
39455714Skrisredoit:
39555714Skris#endif
39655714Skris
39755714Skris	memset((char *)&from,0,sizeof(from));
39855714Skris	len=sizeof(from);
39955714Skris	/* Note: under VMS with SOCKETSHR the fourth parameter is currently
40055714Skris	 * of type (int *) whereas under other systems it is (void *) if
40155714Skris	 * you don't have a cast it will choke the compiler: if you do
40255714Skris	 * have a cast then you can either go for (int *) or (void *).
40355714Skris	 */
40455714Skris	ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
40555714Skris	if (ret == INVALID_SOCKET)
40655714Skris		{
407160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
408215697Ssimon		int i;
40955714Skris		i=WSAGetLastError();
41055714Skris		BIO_printf(bio_err,"accept error %d\n",i);
41155714Skris#else
41255714Skris		if (errno == EINTR)
41355714Skris			{
41455714Skris			/*check_timeout(); */
41555714Skris			goto redoit;
41655714Skris			}
41755714Skris		fprintf(stderr,"errno=%d ",errno);
41855714Skris		perror("accept");
41955714Skris#endif
42055714Skris		return(0);
42155714Skris		}
42255714Skris
42355714Skris/*
42455714Skris	ling.l_onoff=1;
42555714Skris	ling.l_linger=0;
42655714Skris	i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
42755714Skris	if (i < 0) { perror("linger"); return(0); }
42855714Skris	i=0;
42955714Skris	i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
43055714Skris	if (i < 0) { perror("keepalive"); return(0); }
43155714Skris*/
43255714Skris
43355714Skris	if (host == NULL) goto end;
43455714Skris#ifndef BIT_FIELD_LIMITS
43555714Skris	/* I should use WSAAsyncGetHostByName() under windows */
43655714Skris	h1=gethostbyaddr((char *)&from.sin_addr.s_addr,
43755714Skris		sizeof(from.sin_addr.s_addr),AF_INET);
43855714Skris#else
43955714Skris	h1=gethostbyaddr((char *)&from.sin_addr,
44055714Skris		sizeof(struct in_addr),AF_INET);
44155714Skris#endif
44255714Skris	if (h1 == NULL)
44355714Skris		{
44455714Skris		BIO_printf(bio_err,"bad gethostbyaddr\n");
44555714Skris		*host=NULL;
44655714Skris		/* return(0); */
44755714Skris		}
44855714Skris	else
44955714Skris		{
45068651Skris		if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL)
45155714Skris			{
45268651Skris			perror("OPENSSL_malloc");
453279264Sdelphij			closesocket(ret);
45455714Skris			return(0);
45555714Skris			}
456127128Snectar		BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1);
45755714Skris
45855714Skris		h2=GetHostByName(*host);
45955714Skris		if (h2 == NULL)
46055714Skris			{
46155714Skris			BIO_printf(bio_err,"gethostbyname failure\n");
462279264Sdelphij			closesocket(ret);
46355714Skris			return(0);
46455714Skris			}
46555714Skris		if (h2->h_addrtype != AF_INET)
46655714Skris			{
46755714Skris			BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
468279264Sdelphij			closesocket(ret);
46955714Skris			return(0);
47055714Skris			}
47155714Skris		}
47255714Skrisend:
47355714Skris	*sock=ret;
47455714Skris	return(1);
47555714Skris	}
47655714Skris
47755714Skrisint extract_host_port(char *str, char **host_ptr, unsigned char *ip,
47855714Skris	     short *port_ptr)
47955714Skris	{
48055714Skris	char *h,*p;
48155714Skris
48255714Skris	h=str;
48355714Skris	p=strchr(str,':');
48455714Skris	if (p == NULL)
48555714Skris		{
48655714Skris		BIO_printf(bio_err,"no port defined\n");
48755714Skris		return(0);
48855714Skris		}
48955714Skris	*(p++)='\0';
49055714Skris
49155714Skris	if ((ip != NULL) && !host_ip(str,ip))
49255714Skris		goto err;
49355714Skris	if (host_ptr != NULL) *host_ptr=h;
49455714Skris
49555714Skris	if (!extract_port(p,port_ptr))
49655714Skris		goto err;
49755714Skris	return(1);
49855714Skriserr:
49955714Skris	return(0);
50055714Skris	}
50155714Skris
50259191Skrisstatic int host_ip(char *str, unsigned char ip[4])
50355714Skris	{
50455714Skris	unsigned int in[4];
50555714Skris	int i;
50655714Skris
50755714Skris	if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
50855714Skris		{
50955714Skris		for (i=0; i<4; i++)
51055714Skris			if (in[i] > 255)
51155714Skris				{
51255714Skris				BIO_printf(bio_err,"invalid IP address\n");
51355714Skris				goto err;
51455714Skris				}
51555714Skris		ip[0]=in[0];
51655714Skris		ip[1]=in[1];
51755714Skris		ip[2]=in[2];
51855714Skris		ip[3]=in[3];
51955714Skris		}
52055714Skris	else
52155714Skris		{ /* do a gethostbyname */
52255714Skris		struct hostent *he;
52355714Skris
524109998Smarkm		if (!ssl_sock_init()) return(0);
52555714Skris
52655714Skris		he=GetHostByName(str);
52755714Skris		if (he == NULL)
52855714Skris			{
52955714Skris			BIO_printf(bio_err,"gethostbyname failure\n");
53055714Skris			goto err;
53155714Skris			}
53255714Skris		/* cast to short because of win16 winsock definition */
53355714Skris		if ((short)he->h_addrtype != AF_INET)
53455714Skris			{
53555714Skris			BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
53655714Skris			return(0);
53755714Skris			}
53855714Skris		ip[0]=he->h_addr_list[0][0];
53955714Skris		ip[1]=he->h_addr_list[0][1];
54055714Skris		ip[2]=he->h_addr_list[0][2];
54155714Skris		ip[3]=he->h_addr_list[0][3];
54255714Skris		}
54355714Skris	return(1);
54455714Skriserr:
54555714Skris	return(0);
54655714Skris	}
54755714Skris
54855714Skrisint extract_port(char *str, short *port_ptr)
54955714Skris	{
55055714Skris	int i;
55155714Skris	struct servent *s;
55255714Skris
55355714Skris	i=atoi(str);
55455714Skris	if (i != 0)
55555714Skris		*port_ptr=(unsigned short)i;
55655714Skris	else
55755714Skris		{
55855714Skris		s=getservbyname(str,"tcp");
55955714Skris		if (s == NULL)
56055714Skris			{
56155714Skris			BIO_printf(bio_err,"getservbyname failure for %s\n",str);
56255714Skris			return(0);
56355714Skris			}
56455714Skris		*port_ptr=ntohs((unsigned short)s->s_port);
56555714Skris		}
56655714Skris	return(1);
56755714Skris	}
56855714Skris
56955714Skris#define GHBN_NUM	4
57055714Skrisstatic struct ghbn_cache_st
57155714Skris	{
57255714Skris	char name[128];
57355714Skris	struct hostent ent;
57455714Skris	unsigned long order;
57555714Skris	} ghbn_cache[GHBN_NUM];
57655714Skris
57755714Skrisstatic unsigned long ghbn_hits=0L;
57855714Skrisstatic unsigned long ghbn_miss=0L;
57955714Skris
58055714Skrisstatic struct hostent *GetHostByName(char *name)
58155714Skris	{
58255714Skris	struct hostent *ret;
58355714Skris	int i,lowi=0;
58455714Skris	unsigned long low= (unsigned long)-1;
58555714Skris
58655714Skris	for (i=0; i<GHBN_NUM; i++)
58755714Skris		{
58855714Skris		if (low > ghbn_cache[i].order)
58955714Skris			{
59055714Skris			low=ghbn_cache[i].order;
59155714Skris			lowi=i;
59255714Skris			}
59355714Skris		if (ghbn_cache[i].order > 0)
59455714Skris			{
59555714Skris			if (strncmp(name,ghbn_cache[i].name,128) == 0)
59655714Skris				break;
59755714Skris			}
59855714Skris		}
59955714Skris	if (i == GHBN_NUM) /* no hit*/
60055714Skris		{
60155714Skris		ghbn_miss++;
60255714Skris		ret=gethostbyname(name);
60355714Skris		if (ret == NULL) return(NULL);
60455714Skris		/* else add to cache */
605109998Smarkm		if(strlen(name) < sizeof ghbn_cache[0].name)
606109998Smarkm			{
607109998Smarkm			strcpy(ghbn_cache[lowi].name,name);
608109998Smarkm			memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent));
609109998Smarkm			ghbn_cache[lowi].order=ghbn_miss+ghbn_hits;
610109998Smarkm			}
61155714Skris		return(ret);
61255714Skris		}
61355714Skris	else
61455714Skris		{
61555714Skris		ghbn_hits++;
61655714Skris		ret= &(ghbn_cache[i].ent);
61755714Skris		ghbn_cache[i].order=ghbn_miss+ghbn_hits;
61855714Skris		return(ret);
61955714Skris		}
62055714Skris	}
621160814Ssimon
622160814Ssimon#endif
623