xref: /onnv-gate/usr/src/common/openssl/crypto/bio/b_sock.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /* crypto/bio/b_sock.c */
2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3*0Sstevel@tonic-gate  * All rights reserved.
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * This package is an SSL implementation written
6*0Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
7*0Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
10*0Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
11*0Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
12*0Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13*0Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
14*0Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
17*0Sstevel@tonic-gate  * the code are not to be removed.
18*0Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
19*0Sstevel@tonic-gate  * as the author of the parts of the library used.
20*0Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
21*0Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
22*0Sstevel@tonic-gate  *
23*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
24*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
25*0Sstevel@tonic-gate  * are met:
26*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
27*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
28*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
29*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
30*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
31*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
32*0Sstevel@tonic-gate  *    must display the following acknowledgement:
33*0Sstevel@tonic-gate  *    "This product includes cryptographic software written by
34*0Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
35*0Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
36*0Sstevel@tonic-gate  *    being used are not cryptographic related :-).
37*0Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
38*0Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
39*0Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40*0Sstevel@tonic-gate  *
41*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42*0Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*0Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*0Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*0Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*0Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*0Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*0Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*0Sstevel@tonic-gate  * SUCH DAMAGE.
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
54*0Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55*0Sstevel@tonic-gate  * copied and put under another distribution licence
56*0Sstevel@tonic-gate  * [including the GNU Public Licence.]
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate #ifndef OPENSSL_NO_SOCK
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate #include <stdio.h>
62*0Sstevel@tonic-gate #include <stdlib.h>
63*0Sstevel@tonic-gate #include <errno.h>
64*0Sstevel@tonic-gate #define USE_SOCKETS
65*0Sstevel@tonic-gate #include "cryptlib.h"
66*0Sstevel@tonic-gate #include <openssl/bio.h>
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
69*0Sstevel@tonic-gate #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
70*0Sstevel@tonic-gate #else
71*0Sstevel@tonic-gate #define SOCKET_PROTOCOL IPPROTO_TCP
72*0Sstevel@tonic-gate #endif
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate #ifdef SO_MAXCONN
75*0Sstevel@tonic-gate #define MAX_LISTEN  SO_MAXCONN
76*0Sstevel@tonic-gate #elif defined(SOMAXCONN)
77*0Sstevel@tonic-gate #define MAX_LISTEN  SOMAXCONN
78*0Sstevel@tonic-gate #else
79*0Sstevel@tonic-gate #define MAX_LISTEN  32
80*0Sstevel@tonic-gate #endif
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
83*0Sstevel@tonic-gate static int wsa_init_done=0;
84*0Sstevel@tonic-gate #endif
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate #if 0
87*0Sstevel@tonic-gate static unsigned long BIO_ghbn_hits=0L;
88*0Sstevel@tonic-gate static unsigned long BIO_ghbn_miss=0L;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate #define GHBN_NUM	4
91*0Sstevel@tonic-gate static struct ghbn_cache_st
92*0Sstevel@tonic-gate 	{
93*0Sstevel@tonic-gate 	char name[129];
94*0Sstevel@tonic-gate 	struct hostent *ent;
95*0Sstevel@tonic-gate 	unsigned long order;
96*0Sstevel@tonic-gate 	} ghbn_cache[GHBN_NUM];
97*0Sstevel@tonic-gate #endif
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate static int get_ip(const char *str,unsigned char *ip);
100*0Sstevel@tonic-gate #if 0
101*0Sstevel@tonic-gate static void ghbn_free(struct hostent *a);
102*0Sstevel@tonic-gate static struct hostent *ghbn_dup(struct hostent *a);
103*0Sstevel@tonic-gate #endif
104*0Sstevel@tonic-gate int BIO_get_host_ip(const char *str, unsigned char *ip)
105*0Sstevel@tonic-gate 	{
106*0Sstevel@tonic-gate 	int i;
107*0Sstevel@tonic-gate 	int err = 1;
108*0Sstevel@tonic-gate 	int locked = 0;
109*0Sstevel@tonic-gate 	struct hostent *he;
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	i=get_ip(str,ip);
112*0Sstevel@tonic-gate 	if (i < 0)
113*0Sstevel@tonic-gate 		{
114*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
115*0Sstevel@tonic-gate 		goto err;
116*0Sstevel@tonic-gate 		}
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	/* At this point, we have something that is most probably correct
119*0Sstevel@tonic-gate 	   in some way, so let's init the socket. */
120*0Sstevel@tonic-gate 	if (BIO_sock_init() != 1)
121*0Sstevel@tonic-gate 		return 0; /* don't generate another error code here */
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 	/* If the string actually contained an IP address, we need not do
124*0Sstevel@tonic-gate 	   anything more */
125*0Sstevel@tonic-gate 	if (i > 0) return(1);
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	/* do a gethostbyname */
128*0Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
129*0Sstevel@tonic-gate 	locked = 1;
130*0Sstevel@tonic-gate 	he=BIO_gethostbyname(str);
131*0Sstevel@tonic-gate 	if (he == NULL)
132*0Sstevel@tonic-gate 		{
133*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
134*0Sstevel@tonic-gate 		goto err;
135*0Sstevel@tonic-gate 		}
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	/* cast to short because of win16 winsock definition */
138*0Sstevel@tonic-gate 	if ((short)he->h_addrtype != AF_INET)
139*0Sstevel@tonic-gate 		{
140*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
141*0Sstevel@tonic-gate 		goto err;
142*0Sstevel@tonic-gate 		}
143*0Sstevel@tonic-gate 	for (i=0; i<4; i++)
144*0Sstevel@tonic-gate 		ip[i]=he->h_addr_list[0][i];
145*0Sstevel@tonic-gate 	err = 0;
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate  err:
148*0Sstevel@tonic-gate 	if (locked)
149*0Sstevel@tonic-gate 		CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
150*0Sstevel@tonic-gate 	if (err)
151*0Sstevel@tonic-gate 		{
152*0Sstevel@tonic-gate 		ERR_add_error_data(2,"host=",str);
153*0Sstevel@tonic-gate 		return 0;
154*0Sstevel@tonic-gate 		}
155*0Sstevel@tonic-gate 	else
156*0Sstevel@tonic-gate 		return 1;
157*0Sstevel@tonic-gate 	}
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate int BIO_get_port(const char *str, unsigned short *port_ptr)
160*0Sstevel@tonic-gate 	{
161*0Sstevel@tonic-gate 	int i;
162*0Sstevel@tonic-gate 	struct servent *s;
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	if (str == NULL)
165*0Sstevel@tonic-gate 		{
166*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
167*0Sstevel@tonic-gate 		return(0);
168*0Sstevel@tonic-gate 		}
169*0Sstevel@tonic-gate 	i=atoi(str);
170*0Sstevel@tonic-gate 	if (i != 0)
171*0Sstevel@tonic-gate 		*port_ptr=(unsigned short)i;
172*0Sstevel@tonic-gate 	else
173*0Sstevel@tonic-gate 		{
174*0Sstevel@tonic-gate 		CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
175*0Sstevel@tonic-gate 		/* Note: under VMS with SOCKETSHR, it seems like the first
176*0Sstevel@tonic-gate 		 * parameter is 'char *', instead of 'const char *'
177*0Sstevel@tonic-gate 		 */
178*0Sstevel@tonic-gate  		s=getservbyname(
179*0Sstevel@tonic-gate #ifndef CONST_STRICT
180*0Sstevel@tonic-gate 		    (char *)
181*0Sstevel@tonic-gate #endif
182*0Sstevel@tonic-gate 		    str,"tcp");
183*0Sstevel@tonic-gate 		if(s != NULL)
184*0Sstevel@tonic-gate 			*port_ptr=ntohs((unsigned short)s->s_port);
185*0Sstevel@tonic-gate 		CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
186*0Sstevel@tonic-gate 		if(s == NULL)
187*0Sstevel@tonic-gate 			{
188*0Sstevel@tonic-gate 			if (strcmp(str,"http") == 0)
189*0Sstevel@tonic-gate 				*port_ptr=80;
190*0Sstevel@tonic-gate 			else if (strcmp(str,"telnet") == 0)
191*0Sstevel@tonic-gate 				*port_ptr=23;
192*0Sstevel@tonic-gate 			else if (strcmp(str,"socks") == 0)
193*0Sstevel@tonic-gate 				*port_ptr=1080;
194*0Sstevel@tonic-gate 			else if (strcmp(str,"https") == 0)
195*0Sstevel@tonic-gate 				*port_ptr=443;
196*0Sstevel@tonic-gate 			else if (strcmp(str,"ssl") == 0)
197*0Sstevel@tonic-gate 				*port_ptr=443;
198*0Sstevel@tonic-gate 			else if (strcmp(str,"ftp") == 0)
199*0Sstevel@tonic-gate 				*port_ptr=21;
200*0Sstevel@tonic-gate 			else if (strcmp(str,"gopher") == 0)
201*0Sstevel@tonic-gate 				*port_ptr=70;
202*0Sstevel@tonic-gate #if 0
203*0Sstevel@tonic-gate 			else if (strcmp(str,"wais") == 0)
204*0Sstevel@tonic-gate 				*port_ptr=21;
205*0Sstevel@tonic-gate #endif
206*0Sstevel@tonic-gate 			else
207*0Sstevel@tonic-gate 				{
208*0Sstevel@tonic-gate 				SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
209*0Sstevel@tonic-gate 				ERR_add_error_data(3,"service='",str,"'");
210*0Sstevel@tonic-gate 				return(0);
211*0Sstevel@tonic-gate 				}
212*0Sstevel@tonic-gate 			}
213*0Sstevel@tonic-gate 		}
214*0Sstevel@tonic-gate 	return(1);
215*0Sstevel@tonic-gate 	}
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate int BIO_sock_error(int sock)
218*0Sstevel@tonic-gate 	{
219*0Sstevel@tonic-gate 	int j,i;
220*0Sstevel@tonic-gate 	int size;
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate 	size=sizeof(int);
223*0Sstevel@tonic-gate 	/* Note: under Windows the third parameter is of type (char *)
224*0Sstevel@tonic-gate 	 * whereas under other systems it is (void *) if you don't have
225*0Sstevel@tonic-gate 	 * a cast it will choke the compiler: if you do have a cast then
226*0Sstevel@tonic-gate 	 * you can either go for (char *) or (void *).
227*0Sstevel@tonic-gate 	 */
228*0Sstevel@tonic-gate 	i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size);
229*0Sstevel@tonic-gate 	if (i < 0)
230*0Sstevel@tonic-gate 		return(1);
231*0Sstevel@tonic-gate 	else
232*0Sstevel@tonic-gate 		return(j);
233*0Sstevel@tonic-gate 	}
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate #if 0
236*0Sstevel@tonic-gate long BIO_ghbn_ctrl(int cmd, int iarg, char *parg)
237*0Sstevel@tonic-gate 	{
238*0Sstevel@tonic-gate 	int i;
239*0Sstevel@tonic-gate 	char **p;
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 	switch (cmd)
242*0Sstevel@tonic-gate 		{
243*0Sstevel@tonic-gate 	case BIO_GHBN_CTRL_HITS:
244*0Sstevel@tonic-gate 		return(BIO_ghbn_hits);
245*0Sstevel@tonic-gate 		/* break; */
246*0Sstevel@tonic-gate 	case BIO_GHBN_CTRL_MISSES:
247*0Sstevel@tonic-gate 		return(BIO_ghbn_miss);
248*0Sstevel@tonic-gate 		/* break; */
249*0Sstevel@tonic-gate 	case BIO_GHBN_CTRL_CACHE_SIZE:
250*0Sstevel@tonic-gate 		return(GHBN_NUM);
251*0Sstevel@tonic-gate 		/* break; */
252*0Sstevel@tonic-gate 	case BIO_GHBN_CTRL_GET_ENTRY:
253*0Sstevel@tonic-gate 		if ((iarg >= 0) && (iarg <GHBN_NUM) &&
254*0Sstevel@tonic-gate 			(ghbn_cache[iarg].order > 0))
255*0Sstevel@tonic-gate 			{
256*0Sstevel@tonic-gate 			p=(char **)parg;
257*0Sstevel@tonic-gate 			if (p == NULL) return(0);
258*0Sstevel@tonic-gate 			*p=ghbn_cache[iarg].name;
259*0Sstevel@tonic-gate 			ghbn_cache[iarg].name[128]='\0';
260*0Sstevel@tonic-gate 			return(1);
261*0Sstevel@tonic-gate 			}
262*0Sstevel@tonic-gate 		return(0);
263*0Sstevel@tonic-gate 		/* break; */
264*0Sstevel@tonic-gate 	case BIO_GHBN_CTRL_FLUSH:
265*0Sstevel@tonic-gate 		for (i=0; i<GHBN_NUM; i++)
266*0Sstevel@tonic-gate 			ghbn_cache[i].order=0;
267*0Sstevel@tonic-gate 		break;
268*0Sstevel@tonic-gate 	default:
269*0Sstevel@tonic-gate 		return(0);
270*0Sstevel@tonic-gate 		}
271*0Sstevel@tonic-gate 	return(1);
272*0Sstevel@tonic-gate 	}
273*0Sstevel@tonic-gate #endif
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate #if 0
276*0Sstevel@tonic-gate static struct hostent *ghbn_dup(struct hostent *a)
277*0Sstevel@tonic-gate 	{
278*0Sstevel@tonic-gate 	struct hostent *ret;
279*0Sstevel@tonic-gate 	int i,j;
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	MemCheck_off();
282*0Sstevel@tonic-gate 	ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent));
283*0Sstevel@tonic-gate 	if (ret == NULL) return(NULL);
284*0Sstevel@tonic-gate 	memset(ret,0,sizeof(struct hostent));
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 	for (i=0; a->h_aliases[i] != NULL; i++)
287*0Sstevel@tonic-gate 		;
288*0Sstevel@tonic-gate 	i++;
289*0Sstevel@tonic-gate 	ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *));
290*0Sstevel@tonic-gate 	if (ret->h_aliases == NULL)
291*0Sstevel@tonic-gate 		goto err;
292*0Sstevel@tonic-gate 	memset(ret->h_aliases, 0, i*sizeof(char *));
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	for (i=0; a->h_addr_list[i] != NULL; i++)
295*0Sstevel@tonic-gate 		;
296*0Sstevel@tonic-gate 	i++;
297*0Sstevel@tonic-gate 	ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *));
298*0Sstevel@tonic-gate 	if (ret->h_addr_list == NULL)
299*0Sstevel@tonic-gate 		goto err;
300*0Sstevel@tonic-gate 	memset(ret->h_addr_list, 0, i*sizeof(char *));
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	j=strlen(a->h_name)+1;
303*0Sstevel@tonic-gate 	if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err;
304*0Sstevel@tonic-gate 	memcpy((char *)ret->h_name,a->h_name,j);
305*0Sstevel@tonic-gate 	for (i=0; a->h_aliases[i] != NULL; i++)
306*0Sstevel@tonic-gate 		{
307*0Sstevel@tonic-gate 		j=strlen(a->h_aliases[i])+1;
308*0Sstevel@tonic-gate 		if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err;
309*0Sstevel@tonic-gate 		memcpy(ret->h_aliases[i],a->h_aliases[i],j);
310*0Sstevel@tonic-gate 		}
311*0Sstevel@tonic-gate 	ret->h_length=a->h_length;
312*0Sstevel@tonic-gate 	ret->h_addrtype=a->h_addrtype;
313*0Sstevel@tonic-gate 	for (i=0; a->h_addr_list[i] != NULL; i++)
314*0Sstevel@tonic-gate 		{
315*0Sstevel@tonic-gate 		if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL)
316*0Sstevel@tonic-gate 			goto err;
317*0Sstevel@tonic-gate 		memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
318*0Sstevel@tonic-gate 		}
319*0Sstevel@tonic-gate 	if (0)
320*0Sstevel@tonic-gate 		{
321*0Sstevel@tonic-gate err:
322*0Sstevel@tonic-gate 		if (ret != NULL)
323*0Sstevel@tonic-gate 			ghbn_free(ret);
324*0Sstevel@tonic-gate 		ret=NULL;
325*0Sstevel@tonic-gate 		}
326*0Sstevel@tonic-gate 	MemCheck_on();
327*0Sstevel@tonic-gate 	return(ret);
328*0Sstevel@tonic-gate 	}
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate static void ghbn_free(struct hostent *a)
331*0Sstevel@tonic-gate 	{
332*0Sstevel@tonic-gate 	int i;
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	if(a == NULL)
335*0Sstevel@tonic-gate 	    return;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	if (a->h_aliases != NULL)
338*0Sstevel@tonic-gate 		{
339*0Sstevel@tonic-gate 		for (i=0; a->h_aliases[i] != NULL; i++)
340*0Sstevel@tonic-gate 			OPENSSL_free(a->h_aliases[i]);
341*0Sstevel@tonic-gate 		OPENSSL_free(a->h_aliases);
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate 	if (a->h_addr_list != NULL)
344*0Sstevel@tonic-gate 		{
345*0Sstevel@tonic-gate 		for (i=0; a->h_addr_list[i] != NULL; i++)
346*0Sstevel@tonic-gate 			OPENSSL_free(a->h_addr_list[i]);
347*0Sstevel@tonic-gate 		OPENSSL_free(a->h_addr_list);
348*0Sstevel@tonic-gate 		}
349*0Sstevel@tonic-gate 	if (a->h_name != NULL) OPENSSL_free(a->h_name);
350*0Sstevel@tonic-gate 	OPENSSL_free(a);
351*0Sstevel@tonic-gate 	}
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate #endif
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate struct hostent *BIO_gethostbyname(const char *name)
356*0Sstevel@tonic-gate 	{
357*0Sstevel@tonic-gate #if 1
358*0Sstevel@tonic-gate 	/* Caching gethostbyname() results forever is wrong,
359*0Sstevel@tonic-gate 	 * so we have to let the true gethostbyname() worry about this */
360*0Sstevel@tonic-gate 	return gethostbyname(name);
361*0Sstevel@tonic-gate #else
362*0Sstevel@tonic-gate 	struct hostent *ret;
363*0Sstevel@tonic-gate 	int i,lowi=0,j;
364*0Sstevel@tonic-gate 	unsigned long low= (unsigned long)-1;
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate #  if 0
368*0Sstevel@tonic-gate 	/* It doesn't make sense to use locking here: The function interface
369*0Sstevel@tonic-gate 	 * is not thread-safe, because threads can never be sure when
370*0Sstevel@tonic-gate 	 * some other thread destroys the data they were given a pointer to.
371*0Sstevel@tonic-gate 	 */
372*0Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
373*0Sstevel@tonic-gate #  endif
374*0Sstevel@tonic-gate 	j=strlen(name);
375*0Sstevel@tonic-gate 	if (j < 128)
376*0Sstevel@tonic-gate 		{
377*0Sstevel@tonic-gate 		for (i=0; i<GHBN_NUM; i++)
378*0Sstevel@tonic-gate 			{
379*0Sstevel@tonic-gate 			if (low > ghbn_cache[i].order)
380*0Sstevel@tonic-gate 				{
381*0Sstevel@tonic-gate 				low=ghbn_cache[i].order;
382*0Sstevel@tonic-gate 				lowi=i;
383*0Sstevel@tonic-gate 				}
384*0Sstevel@tonic-gate 			if (ghbn_cache[i].order > 0)
385*0Sstevel@tonic-gate 				{
386*0Sstevel@tonic-gate 				if (strncmp(name,ghbn_cache[i].name,128) == 0)
387*0Sstevel@tonic-gate 					break;
388*0Sstevel@tonic-gate 				}
389*0Sstevel@tonic-gate 			}
390*0Sstevel@tonic-gate 		}
391*0Sstevel@tonic-gate 	else
392*0Sstevel@tonic-gate 		i=GHBN_NUM;
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	if (i == GHBN_NUM) /* no hit*/
395*0Sstevel@tonic-gate 		{
396*0Sstevel@tonic-gate 		BIO_ghbn_miss++;
397*0Sstevel@tonic-gate 		/* Note: under VMS with SOCKETSHR, it seems like the first
398*0Sstevel@tonic-gate 		 * parameter is 'char *', instead of 'const char *'
399*0Sstevel@tonic-gate 		 */
400*0Sstevel@tonic-gate 		ret=gethostbyname(
401*0Sstevel@tonic-gate #  ifndef CONST_STRICT
402*0Sstevel@tonic-gate 		    (char *)
403*0Sstevel@tonic-gate #  endif
404*0Sstevel@tonic-gate 		    name);
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 		if (ret == NULL)
407*0Sstevel@tonic-gate 			goto end;
408*0Sstevel@tonic-gate 		if (j > 128) /* too big to cache */
409*0Sstevel@tonic-gate 			{
410*0Sstevel@tonic-gate #  if 0
411*0Sstevel@tonic-gate 			/* If we were trying to make this function thread-safe (which
412*0Sstevel@tonic-gate 			 * is bound to fail), we'd have to give up in this case
413*0Sstevel@tonic-gate 			 * (or allocate more memory). */
414*0Sstevel@tonic-gate 			ret = NULL;
415*0Sstevel@tonic-gate #  endif
416*0Sstevel@tonic-gate 			goto end;
417*0Sstevel@tonic-gate 			}
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 		/* else add to cache */
420*0Sstevel@tonic-gate 		if (ghbn_cache[lowi].ent != NULL)
421*0Sstevel@tonic-gate 			ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */
422*0Sstevel@tonic-gate 		ghbn_cache[lowi].name[0] = '\0';
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 		if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
425*0Sstevel@tonic-gate 			{
426*0Sstevel@tonic-gate 			BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
427*0Sstevel@tonic-gate 			goto end;
428*0Sstevel@tonic-gate 			}
429*0Sstevel@tonic-gate 		strncpy(ghbn_cache[lowi].name,name,128);
430*0Sstevel@tonic-gate 		ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
431*0Sstevel@tonic-gate 		}
432*0Sstevel@tonic-gate 	else
433*0Sstevel@tonic-gate 		{
434*0Sstevel@tonic-gate 		BIO_ghbn_hits++;
435*0Sstevel@tonic-gate 		ret= ghbn_cache[i].ent;
436*0Sstevel@tonic-gate 		ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
437*0Sstevel@tonic-gate 		}
438*0Sstevel@tonic-gate end:
439*0Sstevel@tonic-gate #  if 0
440*0Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
441*0Sstevel@tonic-gate #  endif
442*0Sstevel@tonic-gate 	return(ret);
443*0Sstevel@tonic-gate #endif
444*0Sstevel@tonic-gate 	}
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate int BIO_sock_init(void)
448*0Sstevel@tonic-gate 	{
449*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
450*0Sstevel@tonic-gate 	static struct WSAData wsa_state;
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	if (!wsa_init_done)
453*0Sstevel@tonic-gate 		{
454*0Sstevel@tonic-gate 		int err;
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate #ifdef SIGINT
457*0Sstevel@tonic-gate 		signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
458*0Sstevel@tonic-gate #endif
459*0Sstevel@tonic-gate 		wsa_init_done=1;
460*0Sstevel@tonic-gate 		memset(&wsa_state,0,sizeof(wsa_state));
461*0Sstevel@tonic-gate 		if (WSAStartup(0x0101,&wsa_state)!=0)
462*0Sstevel@tonic-gate 			{
463*0Sstevel@tonic-gate 			err=WSAGetLastError();
464*0Sstevel@tonic-gate 			SYSerr(SYS_F_WSASTARTUP,err);
465*0Sstevel@tonic-gate 			BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
466*0Sstevel@tonic-gate 			return(-1);
467*0Sstevel@tonic-gate 			}
468*0Sstevel@tonic-gate 		}
469*0Sstevel@tonic-gate #endif /* OPENSSL_SYS_WINDOWS */
470*0Sstevel@tonic-gate #ifdef WATT32
471*0Sstevel@tonic-gate 	extern int _watt_do_exit;
472*0Sstevel@tonic-gate 	_watt_do_exit = 0;    /* don't make sock_init() call exit() */
473*0Sstevel@tonic-gate 	if (sock_init())
474*0Sstevel@tonic-gate 		return (-1);
475*0Sstevel@tonic-gate #endif
476*0Sstevel@tonic-gate 	return(1);
477*0Sstevel@tonic-gate 	}
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate void BIO_sock_cleanup(void)
480*0Sstevel@tonic-gate 	{
481*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
482*0Sstevel@tonic-gate 	if (wsa_init_done)
483*0Sstevel@tonic-gate 		{
484*0Sstevel@tonic-gate 		wsa_init_done=0;
485*0Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINCE
486*0Sstevel@tonic-gate 		WSACancelBlockingCall();
487*0Sstevel@tonic-gate #endif
488*0Sstevel@tonic-gate 		WSACleanup();
489*0Sstevel@tonic-gate 		}
490*0Sstevel@tonic-gate #endif
491*0Sstevel@tonic-gate 	}
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000
494*0Sstevel@tonic-gate 
495*0Sstevel@tonic-gate int BIO_socket_ioctl(int fd, long type, void *arg)
496*0Sstevel@tonic-gate 	{
497*0Sstevel@tonic-gate 	int i;
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate #ifdef __DJGPP__
500*0Sstevel@tonic-gate 	i=ioctlsocket(fd,type,(char *)arg);
501*0Sstevel@tonic-gate #else
502*0Sstevel@tonic-gate 	i=ioctlsocket(fd,type,arg);
503*0Sstevel@tonic-gate #endif /* __DJGPP__ */
504*0Sstevel@tonic-gate 	if (i < 0)
505*0Sstevel@tonic-gate 		SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
506*0Sstevel@tonic-gate 	return(i);
507*0Sstevel@tonic-gate 	}
508*0Sstevel@tonic-gate #endif /* __VMS_VER */
509*0Sstevel@tonic-gate 
510*0Sstevel@tonic-gate /* The reason I have implemented this instead of using sscanf is because
511*0Sstevel@tonic-gate  * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
512*0Sstevel@tonic-gate static int get_ip(const char *str, unsigned char ip[4])
513*0Sstevel@tonic-gate 	{
514*0Sstevel@tonic-gate 	unsigned int tmp[4];
515*0Sstevel@tonic-gate 	int num=0,c,ok=0;
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 	tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 	for (;;)
520*0Sstevel@tonic-gate 		{
521*0Sstevel@tonic-gate 		c= *(str++);
522*0Sstevel@tonic-gate 		if ((c >= '0') && (c <= '9'))
523*0Sstevel@tonic-gate 			{
524*0Sstevel@tonic-gate 			ok=1;
525*0Sstevel@tonic-gate 			tmp[num]=tmp[num]*10+c-'0';
526*0Sstevel@tonic-gate 			if (tmp[num] > 255) return(0);
527*0Sstevel@tonic-gate 			}
528*0Sstevel@tonic-gate 		else if (c == '.')
529*0Sstevel@tonic-gate 			{
530*0Sstevel@tonic-gate 			if (!ok) return(-1);
531*0Sstevel@tonic-gate 			if (num == 3) return(0);
532*0Sstevel@tonic-gate 			num++;
533*0Sstevel@tonic-gate 			ok=0;
534*0Sstevel@tonic-gate 			}
535*0Sstevel@tonic-gate 		else if (c == '\0' && (num == 3) && ok)
536*0Sstevel@tonic-gate 			break;
537*0Sstevel@tonic-gate 		else
538*0Sstevel@tonic-gate 			return(0);
539*0Sstevel@tonic-gate 		}
540*0Sstevel@tonic-gate 	ip[0]=tmp[0];
541*0Sstevel@tonic-gate 	ip[1]=tmp[1];
542*0Sstevel@tonic-gate 	ip[2]=tmp[2];
543*0Sstevel@tonic-gate 	ip[3]=tmp[3];
544*0Sstevel@tonic-gate 	return(1);
545*0Sstevel@tonic-gate 	}
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate int BIO_get_accept_socket(char *host, int bind_mode)
548*0Sstevel@tonic-gate 	{
549*0Sstevel@tonic-gate 	int ret=0;
550*0Sstevel@tonic-gate 	struct sockaddr_in server,client;
551*0Sstevel@tonic-gate 	int s=INVALID_SOCKET,cs;
552*0Sstevel@tonic-gate 	unsigned char ip[4];
553*0Sstevel@tonic-gate 	unsigned short port;
554*0Sstevel@tonic-gate 	char *str=NULL,*e;
555*0Sstevel@tonic-gate 	const char *h,*p;
556*0Sstevel@tonic-gate 	unsigned long l;
557*0Sstevel@tonic-gate 	int err_num;
558*0Sstevel@tonic-gate 
559*0Sstevel@tonic-gate 	if (BIO_sock_init() != 1) return(INVALID_SOCKET);
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 	if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 	h=p=NULL;
564*0Sstevel@tonic-gate 	h=str;
565*0Sstevel@tonic-gate 	for (e=str; *e; e++)
566*0Sstevel@tonic-gate 		{
567*0Sstevel@tonic-gate 		if (*e == ':')
568*0Sstevel@tonic-gate 			{
569*0Sstevel@tonic-gate 			p= &(e[1]);
570*0Sstevel@tonic-gate 			*e='\0';
571*0Sstevel@tonic-gate 			}
572*0Sstevel@tonic-gate 		else if (*e == '/')
573*0Sstevel@tonic-gate 			{
574*0Sstevel@tonic-gate 			*e='\0';
575*0Sstevel@tonic-gate 			break;
576*0Sstevel@tonic-gate 			}
577*0Sstevel@tonic-gate 		}
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	if (p == NULL)
580*0Sstevel@tonic-gate 		{
581*0Sstevel@tonic-gate 		p=h;
582*0Sstevel@tonic-gate 		h="*";
583*0Sstevel@tonic-gate 		}
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate 	if (!BIO_get_port(p,&port)) goto err;
586*0Sstevel@tonic-gate 
587*0Sstevel@tonic-gate 	memset((char *)&server,0,sizeof(server));
588*0Sstevel@tonic-gate 	server.sin_family=AF_INET;
589*0Sstevel@tonic-gate 	server.sin_port=htons(port);
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 	if (strcmp(h,"*") == 0)
592*0Sstevel@tonic-gate 		server.sin_addr.s_addr=INADDR_ANY;
593*0Sstevel@tonic-gate 	else
594*0Sstevel@tonic-gate 		{
595*0Sstevel@tonic-gate                 if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
596*0Sstevel@tonic-gate 		l=(unsigned long)
597*0Sstevel@tonic-gate 			((unsigned long)ip[0]<<24L)|
598*0Sstevel@tonic-gate 			((unsigned long)ip[1]<<16L)|
599*0Sstevel@tonic-gate 			((unsigned long)ip[2]<< 8L)|
600*0Sstevel@tonic-gate 			((unsigned long)ip[3]);
601*0Sstevel@tonic-gate 		server.sin_addr.s_addr=htonl(l);
602*0Sstevel@tonic-gate 		}
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate again:
605*0Sstevel@tonic-gate 	s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
606*0Sstevel@tonic-gate 	if (s == INVALID_SOCKET)
607*0Sstevel@tonic-gate 		{
608*0Sstevel@tonic-gate 		SYSerr(SYS_F_SOCKET,get_last_socket_error());
609*0Sstevel@tonic-gate 		ERR_add_error_data(3,"port='",host,"'");
610*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
611*0Sstevel@tonic-gate 		goto err;
612*0Sstevel@tonic-gate 		}
613*0Sstevel@tonic-gate 
614*0Sstevel@tonic-gate #ifdef SO_REUSEADDR
615*0Sstevel@tonic-gate 	if (bind_mode == BIO_BIND_REUSEADDR)
616*0Sstevel@tonic-gate 		{
617*0Sstevel@tonic-gate 		int i=1;
618*0Sstevel@tonic-gate 
619*0Sstevel@tonic-gate 		ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
620*0Sstevel@tonic-gate 		bind_mode=BIO_BIND_NORMAL;
621*0Sstevel@tonic-gate 		}
622*0Sstevel@tonic-gate #endif
623*0Sstevel@tonic-gate 	if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
624*0Sstevel@tonic-gate 		{
625*0Sstevel@tonic-gate #ifdef SO_REUSEADDR
626*0Sstevel@tonic-gate 		err_num=get_last_socket_error();
627*0Sstevel@tonic-gate 		if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
628*0Sstevel@tonic-gate 			(err_num == EADDRINUSE))
629*0Sstevel@tonic-gate 			{
630*0Sstevel@tonic-gate 			memcpy((char *)&client,(char *)&server,sizeof(server));
631*0Sstevel@tonic-gate 			if (strcmp(h,"*") == 0)
632*0Sstevel@tonic-gate 				client.sin_addr.s_addr=htonl(0x7F000001);
633*0Sstevel@tonic-gate 			cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
634*0Sstevel@tonic-gate 			if (cs != INVALID_SOCKET)
635*0Sstevel@tonic-gate 				{
636*0Sstevel@tonic-gate 				int ii;
637*0Sstevel@tonic-gate 				ii=connect(cs,(struct sockaddr *)&client,
638*0Sstevel@tonic-gate 					sizeof(client));
639*0Sstevel@tonic-gate 				closesocket(cs);
640*0Sstevel@tonic-gate 				if (ii == INVALID_SOCKET)
641*0Sstevel@tonic-gate 					{
642*0Sstevel@tonic-gate 					bind_mode=BIO_BIND_REUSEADDR;
643*0Sstevel@tonic-gate 					closesocket(s);
644*0Sstevel@tonic-gate 					goto again;
645*0Sstevel@tonic-gate 					}
646*0Sstevel@tonic-gate 				/* else error */
647*0Sstevel@tonic-gate 				}
648*0Sstevel@tonic-gate 			/* else error */
649*0Sstevel@tonic-gate 			}
650*0Sstevel@tonic-gate #endif
651*0Sstevel@tonic-gate 		SYSerr(SYS_F_BIND,err_num);
652*0Sstevel@tonic-gate 		ERR_add_error_data(3,"port='",host,"'");
653*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
654*0Sstevel@tonic-gate 		goto err;
655*0Sstevel@tonic-gate 		}
656*0Sstevel@tonic-gate 	if (listen(s,MAX_LISTEN) == -1)
657*0Sstevel@tonic-gate 		{
658*0Sstevel@tonic-gate 		SYSerr(SYS_F_BIND,get_last_socket_error());
659*0Sstevel@tonic-gate 		ERR_add_error_data(3,"port='",host,"'");
660*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
661*0Sstevel@tonic-gate 		goto err;
662*0Sstevel@tonic-gate 		}
663*0Sstevel@tonic-gate 	ret=1;
664*0Sstevel@tonic-gate err:
665*0Sstevel@tonic-gate 	if (str != NULL) OPENSSL_free(str);
666*0Sstevel@tonic-gate 	if ((ret == 0) && (s != INVALID_SOCKET))
667*0Sstevel@tonic-gate 		{
668*0Sstevel@tonic-gate 		closesocket(s);
669*0Sstevel@tonic-gate 		s= INVALID_SOCKET;
670*0Sstevel@tonic-gate 		}
671*0Sstevel@tonic-gate 	return(s);
672*0Sstevel@tonic-gate 	}
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate int BIO_accept(int sock, char **addr)
675*0Sstevel@tonic-gate 	{
676*0Sstevel@tonic-gate 	int ret=INVALID_SOCKET;
677*0Sstevel@tonic-gate 	static struct sockaddr_in from;
678*0Sstevel@tonic-gate 	unsigned long l;
679*0Sstevel@tonic-gate 	unsigned short port;
680*0Sstevel@tonic-gate 	int len;
681*0Sstevel@tonic-gate 	char *p;
682*0Sstevel@tonic-gate 
683*0Sstevel@tonic-gate 	memset((char *)&from,0,sizeof(from));
684*0Sstevel@tonic-gate 	len=sizeof(from);
685*0Sstevel@tonic-gate 	/* Note: under VMS with SOCKETSHR the fourth parameter is currently
686*0Sstevel@tonic-gate 	 * of type (int *) whereas under other systems it is (void *) if
687*0Sstevel@tonic-gate 	 * you don't have a cast it will choke the compiler: if you do
688*0Sstevel@tonic-gate 	 * have a cast then you can either go for (int *) or (void *).
689*0Sstevel@tonic-gate 	 */
690*0Sstevel@tonic-gate 	ret=accept(sock,(struct sockaddr *)&from,(void *)&len);
691*0Sstevel@tonic-gate 	if (ret == INVALID_SOCKET)
692*0Sstevel@tonic-gate 		{
693*0Sstevel@tonic-gate 		if(BIO_sock_should_retry(ret)) return -2;
694*0Sstevel@tonic-gate 		SYSerr(SYS_F_ACCEPT,get_last_socket_error());
695*0Sstevel@tonic-gate 		BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
696*0Sstevel@tonic-gate 		goto end;
697*0Sstevel@tonic-gate 		}
698*0Sstevel@tonic-gate 
699*0Sstevel@tonic-gate 	if (addr == NULL) goto end;
700*0Sstevel@tonic-gate 
701*0Sstevel@tonic-gate 	l=ntohl(from.sin_addr.s_addr);
702*0Sstevel@tonic-gate 	port=ntohs(from.sin_port);
703*0Sstevel@tonic-gate 	if (*addr == NULL)
704*0Sstevel@tonic-gate 		{
705*0Sstevel@tonic-gate 		if ((p=OPENSSL_malloc(24)) == NULL)
706*0Sstevel@tonic-gate 			{
707*0Sstevel@tonic-gate 			BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
708*0Sstevel@tonic-gate 			goto end;
709*0Sstevel@tonic-gate 			}
710*0Sstevel@tonic-gate 		*addr=p;
711*0Sstevel@tonic-gate 		}
712*0Sstevel@tonic-gate 	BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d",
713*0Sstevel@tonic-gate 		     (unsigned char)(l>>24L)&0xff,
714*0Sstevel@tonic-gate 		     (unsigned char)(l>>16L)&0xff,
715*0Sstevel@tonic-gate 		     (unsigned char)(l>> 8L)&0xff,
716*0Sstevel@tonic-gate 		     (unsigned char)(l     )&0xff,
717*0Sstevel@tonic-gate 		     port);
718*0Sstevel@tonic-gate end:
719*0Sstevel@tonic-gate 	return(ret);
720*0Sstevel@tonic-gate 	}
721*0Sstevel@tonic-gate 
722*0Sstevel@tonic-gate int BIO_set_tcp_ndelay(int s, int on)
723*0Sstevel@tonic-gate 	{
724*0Sstevel@tonic-gate 	int ret=0;
725*0Sstevel@tonic-gate #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
726*0Sstevel@tonic-gate 	int opt;
727*0Sstevel@tonic-gate 
728*0Sstevel@tonic-gate #ifdef SOL_TCP
729*0Sstevel@tonic-gate 	opt=SOL_TCP;
730*0Sstevel@tonic-gate #else
731*0Sstevel@tonic-gate #ifdef IPPROTO_TCP
732*0Sstevel@tonic-gate 	opt=IPPROTO_TCP;
733*0Sstevel@tonic-gate #endif
734*0Sstevel@tonic-gate #endif
735*0Sstevel@tonic-gate 
736*0Sstevel@tonic-gate 	ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
737*0Sstevel@tonic-gate #endif
738*0Sstevel@tonic-gate 	return(ret == 0);
739*0Sstevel@tonic-gate 	}
740*0Sstevel@tonic-gate #endif
741*0Sstevel@tonic-gate 
742*0Sstevel@tonic-gate int BIO_socket_nbio(int s, int mode)
743*0Sstevel@tonic-gate 	{
744*0Sstevel@tonic-gate 	int ret= -1;
745*0Sstevel@tonic-gate 	int l;
746*0Sstevel@tonic-gate 
747*0Sstevel@tonic-gate 	l=mode;
748*0Sstevel@tonic-gate #ifdef FIONBIO
749*0Sstevel@tonic-gate 	ret=BIO_socket_ioctl(s,FIONBIO,&l);
750*0Sstevel@tonic-gate #endif
751*0Sstevel@tonic-gate 	return(ret == 0);
752*0Sstevel@tonic-gate 	}
753