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