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
83static int wsa_init_done=0;
84#endif
85
86#if 0
87static unsigned long BIO_ghbn_hits=0L;
88static unsigned long BIO_ghbn_miss=0L;
89
90#define GHBN_NUM	4
91static 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
99static int get_ip(const char *str,unsigned char *ip);
100#if 0
101static void ghbn_free(struct hostent *a);
102static struct hostent *ghbn_dup(struct hostent *a);
103#endif
104int 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
159int 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
217int 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
236long 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
276static 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		{
321err:
322		if (ret != NULL)
323			ghbn_free(ret);
324		ret=NULL;
325		}
326	MemCheck_on();
327	return(ret);
328	}
329
330static 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
355struct 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		}
438end:
439#  if 0
440	CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
441#  endif
442	return(ret);
443#endif
444	}
445
446
447int 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
479void 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
495int 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 :-( */
512static 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
547int 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
604again:
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;
664err:
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
674int 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	BIO_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);
718end:
719	return(ret);
720	}
721
722int 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
742int 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