More VMS synchronisation
[openssl.git] / crypto / bio / b_sock.c
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 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 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  SOMAXCONN
76 #elif defined(SO_MAXCONN)
77 #define MAX_LISTEN  SO_MAXCONN
78 #else
79 #define MAX_LISTEN  32
80 #endif
81
82 #ifdef WINDOWS
83 static int wsa_init_done=0;
84 #endif
85
86 static unsigned long BIO_ghbn_hits=0L;
87 static unsigned long BIO_ghbn_miss=0L;
88
89 #define GHBN_NUM        4
90 static struct ghbn_cache_st
91         {
92         char name[129];
93         struct hostent *ent;
94         unsigned long order;
95         } ghbn_cache[GHBN_NUM];
96
97 static int get_ip(const char *str,unsigned char *ip);
98 static void ghbn_free(struct hostent *a);
99 static struct hostent *ghbn_dup(struct hostent *a);
100 int BIO_get_host_ip(const char *str, unsigned char *ip)
101         {
102         int i;
103         int err = 1;
104         int locked = 0;
105         struct hostent *he;
106
107         i=get_ip(str,ip);
108         if (i < 0)
109                 {
110                 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
111                 goto err;
112                 }
113
114         /* At this point, we have something that is most probably correct
115            in some way, so let's init the socket. */
116         if (!BIO_sock_init())
117                 return(0); /* don't generate another error code here */
118
119         /* If the string actually contained an IP address, we need not do
120            anything more */
121         if (i > 0) return(1);
122
123         /* do a gethostbyname */
124         CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
125         locked = 1;
126         he=BIO_gethostbyname(str);
127         if (he == NULL)
128                 {
129                 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
130                 goto err;
131                 }
132
133         /* cast to short because of win16 winsock definition */
134         if ((short)he->h_addrtype != AF_INET)
135                 {
136                 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
137                 goto err;
138                 }
139         for (i=0; i<4; i++)
140                 ip[i]=he->h_addr_list[0][i];
141         err = 0;
142
143  err:
144         if (locked)
145                 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
146         if (err)
147                 {
148                 ERR_add_error_data(2,"host=",str);
149                 return 0;
150                 }
151         else
152                 return 1;
153         }
154
155 int BIO_get_port(const char *str, unsigned short *port_ptr)
156         {
157         int i;
158         struct servent *s;
159
160         if (str == NULL)
161                 {
162                 BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
163                 return(0);
164                 }
165         i=atoi(str);
166         if (i != 0)
167                 *port_ptr=(unsigned short)i;
168         else
169                 {
170                 CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
171                 /* Note: under VMS with SOCKETSHR, it seems like the first
172                  * parameter is 'char *', instead of 'const char *'
173                  */
174                 s=getservbyname(
175 #ifndef CONST_STRICT
176                     (char *)
177 #endif
178                     str,"tcp");
179                 if(s != NULL)
180                         *port_ptr=ntohs((unsigned short)s->s_port);
181                 CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
182                 if(s == NULL)
183                         {
184                         if (strcmp(str,"http") == 0)
185                                 *port_ptr=80;
186                         else if (strcmp(str,"telnet") == 0)
187                                 *port_ptr=23;
188                         else if (strcmp(str,"socks") == 0)
189                                 *port_ptr=1080;
190                         else if (strcmp(str,"https") == 0)
191                                 *port_ptr=443;
192                         else if (strcmp(str,"ssl") == 0)
193                                 *port_ptr=443;
194                         else if (strcmp(str,"ftp") == 0)
195                                 *port_ptr=21;
196                         else if (strcmp(str,"gopher") == 0)
197                                 *port_ptr=70;
198 #if 0
199                         else if (strcmp(str,"wais") == 0)
200                                 *port_ptr=21;
201 #endif
202                         else
203                                 {
204                                 SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
205                                 ERR_add_error_data(3,"service='",str,"'");
206                                 return(0);
207                                 }
208                         }
209                 }
210         return(1);
211         }
212
213 int BIO_sock_error(int sock)
214         {
215         int j,i;
216         int size;
217                  
218         size=sizeof(int);
219         /* Note: under Windows the third parameter is of type (char *)
220          * whereas under other systems it is (void *) if you don't have
221          * a cast it will choke the compiler: if you do have a cast then
222          * you can either go for (char *) or (void *).
223          */
224         i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size);
225         if (i < 0)
226                 return(1);
227         else
228                 return(j);
229         }
230
231 long BIO_ghbn_ctrl(int cmd, int iarg, char *parg)
232         {
233         int i;
234         char **p;
235
236         switch (cmd)
237                 {
238         case BIO_GHBN_CTRL_HITS:
239                 return(BIO_ghbn_hits);
240                 /* break; */
241         case BIO_GHBN_CTRL_MISSES:
242                 return(BIO_ghbn_miss);
243                 /* break; */
244         case BIO_GHBN_CTRL_CACHE_SIZE:
245                 return(GHBN_NUM);
246                 /* break; */
247         case BIO_GHBN_CTRL_GET_ENTRY:
248                 if ((iarg >= 0) && (iarg <GHBN_NUM) &&
249                         (ghbn_cache[iarg].order > 0))
250                         {
251                         p=(char **)parg;
252                         if (p == NULL) return(0);
253                         *p=ghbn_cache[iarg].name;
254                         ghbn_cache[iarg].name[128]='\0';
255                         return(1);
256                         }
257                 return(0);
258                 /* break; */
259         case BIO_GHBN_CTRL_FLUSH:
260                 for (i=0; i<GHBN_NUM; i++)
261                         ghbn_cache[i].order=0;
262                 break;
263         default:
264                 return(0);
265                 }
266         return(1);
267         }
268
269 static struct hostent *ghbn_dup(struct hostent *a)
270         {
271         struct hostent *ret;
272         int i,j;
273
274         MemCheck_off();
275         ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent));
276         if (ret == NULL) return(NULL);
277         memset(ret,0,sizeof(struct hostent));
278
279         for (i=0; a->h_aliases[i] != NULL; i++)
280                 ;
281         i++;
282         ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *));
283         if (ret->h_aliases == NULL)
284                 goto err;
285         memset(ret->h_aliases, 0, i*sizeof(char *));
286
287         for (i=0; a->h_addr_list[i] != NULL; i++)
288                 ;
289         i++;
290         ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *));
291         if (ret->h_addr_list == NULL)
292                 goto err;
293         memset(ret->h_addr_list, 0, i*sizeof(char *));
294
295         j=strlen(a->h_name)+1;
296         if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err;
297         memcpy((char *)ret->h_name,a->h_name,j);
298         for (i=0; a->h_aliases[i] != NULL; i++)
299                 {
300                 j=strlen(a->h_aliases[i])+1;
301                 if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err;
302                 memcpy(ret->h_aliases[i],a->h_aliases[i],j);
303                 }
304         ret->h_length=a->h_length;
305         ret->h_addrtype=a->h_addrtype;
306         for (i=0; a->h_addr_list[i] != NULL; i++)
307                 {
308                 if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL)
309                         goto err;
310                 memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
311                 }
312         if (0)
313                 {
314 err:    
315                 if (ret != NULL)
316                         ghbn_free(ret);
317                 ret=NULL;
318                 }
319         MemCheck_on();
320         return(ret);
321         }
322
323 static void ghbn_free(struct hostent *a)
324         {
325         int i;
326
327         if(a == NULL)
328             return;
329
330         if (a->h_aliases != NULL)
331                 {
332                 for (i=0; a->h_aliases[i] != NULL; i++)
333                         OPENSSL_free(a->h_aliases[i]);
334                 OPENSSL_free(a->h_aliases);
335                 }
336         if (a->h_addr_list != NULL)
337                 {
338                 for (i=0; a->h_addr_list[i] != NULL; i++)
339                         OPENSSL_free(a->h_addr_list[i]);
340                 OPENSSL_free(a->h_addr_list);
341                 }
342         if (a->h_name != NULL) OPENSSL_free(a->h_name);
343         OPENSSL_free(a);
344         }
345
346 struct hostent *BIO_gethostbyname(const char *name)
347         {
348         struct hostent *ret;
349         int i,lowi=0,j;
350         unsigned long low= (unsigned long)-1;
351
352 /*      return(gethostbyname(name)); */
353
354 #if 0 /* It doesn't make sense to use locking here: The function interface
355            * is not thread-safe, because threads can never be sure when
356            * some other thread destroys the data they were given a pointer to.
357            */
358         CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
359 #endif
360         j=strlen(name);
361         if (j < 128)
362                 {
363                 for (i=0; i<GHBN_NUM; i++)
364                         {
365                         if (low > ghbn_cache[i].order)
366                                 {
367                                 low=ghbn_cache[i].order;
368                                 lowi=i;
369                                 }
370                         if (ghbn_cache[i].order > 0)
371                                 {
372                                 if (strncmp(name,ghbn_cache[i].name,128) == 0)
373                                         break;
374                                 }
375                         }
376                 }
377         else
378                 i=GHBN_NUM;
379
380         if (i == GHBN_NUM) /* no hit*/
381                 {
382                 BIO_ghbn_miss++;
383                 /* Note: under VMS with SOCKETSHR, it seems like the first
384                  * parameter is 'char *', instead of 'const char *'
385                  */
386                 ret=gethostbyname(
387 #ifndef CONST_STRICT
388                     (char *)
389 #endif
390                     name);
391
392                 if (ret == NULL)
393                         goto end;
394                 if (j > 128) /* too big to cache */
395                         {
396 #if 0 /* If we were trying to make this function thread-safe (which
397            * is bound to fail), we'd have to give up in this case
398            * (or allocate more memory). */
399                         ret = NULL;
400 #endif
401                         goto end;
402                         }
403
404                 /* else add to cache */
405                 if (ghbn_cache[lowi].ent != NULL)
406                         ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */
407                 ghbn_cache[lowi].name[0] = '\0';
408
409                 if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
410                         {
411                         BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
412                         goto end;
413                         }
414                 strncpy(ghbn_cache[lowi].name,name,128);
415                 ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
416                 }
417         else
418                 {
419                 BIO_ghbn_hits++;
420                 ret= ghbn_cache[i].ent;
421                 ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
422                 }
423 end:
424 #if 0
425         CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
426 #endif
427         return(ret);
428         }
429
430 int BIO_sock_init(void)
431         {
432 #ifdef WINDOWS
433         static struct WSAData wsa_state;
434
435         if (!wsa_init_done)
436                 {
437                 int err;
438           
439 #ifdef SIGINT
440                 signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
441 #endif
442                 wsa_init_done=1;
443                 memset(&wsa_state,0,sizeof(wsa_state));
444                 if (WSAStartup(0x0101,&wsa_state)!=0)
445                         {
446                         err=WSAGetLastError();
447                         SYSerr(SYS_F_WSASTARTUP,err);
448                         BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
449                         return(-1);
450                         }
451                 }
452 #endif /* WINDOWS */
453         return(1);
454         }
455
456 void BIO_sock_cleanup(void)
457         {
458 #ifdef WINDOWS
459         if (wsa_init_done)
460                 {
461                 wsa_init_done=0;
462                 WSACancelBlockingCall();
463                 WSACleanup();
464                 }
465 #endif
466         }
467
468 #if !defined(VMS) || __VMS_VER >= 70000000
469
470 int BIO_socket_ioctl(int fd, long type, unsigned long *arg)
471         {
472         int i;
473
474         i=ioctlsocket(fd,type,arg);
475         if (i < 0)
476                 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
477         return(i);
478         }
479 #endif /* __VMS_VER */
480
481 /* The reason I have implemented this instead of using sscanf is because
482  * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
483 static int get_ip(const char *str, unsigned char ip[4])
484         {
485         unsigned int tmp[4];
486         int num=0,c,ok=0;
487
488         tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
489
490         for (;;)
491                 {
492                 c= *(str++);
493                 if ((c >= '0') && (c <= '9'))
494                         {
495                         ok=1;
496                         tmp[num]=tmp[num]*10+c-'0';
497                         if (tmp[num] > 255) return(-1);
498                         }
499                 else if (c == '.')
500                         {
501                         if (!ok) return(-1);
502                         if (num == 3) break;
503                         num++;
504                         ok=0;
505                         }
506                 else if ((num == 3) && ok)
507                         break;
508                 else
509                         return(0);
510                 }
511         ip[0]=tmp[0];
512         ip[1]=tmp[1];
513         ip[2]=tmp[2];
514         ip[3]=tmp[3];
515         return(1);
516         }
517
518 int BIO_get_accept_socket(char *host, int bind_mode)
519         {
520         int ret=0;
521         struct sockaddr_in server,client;
522         int s= -1,cs;
523         unsigned char ip[4];
524         unsigned short port;
525         char *str,*e;
526         const char *h,*p;
527         unsigned long l;
528         int err_num;
529
530         if (!BIO_sock_init()) return(INVALID_SOCKET);
531
532         if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
533
534         h=p=NULL;
535         h=str;
536         for (e=str; *e; e++)
537                 {
538                 if (*e == ':')
539                         {
540                         p= &(e[1]);
541                         *e='\0';
542                         }
543                 else if (*e == '/')
544                         {
545                         *e='\0';
546                         break;
547                         }
548                 }
549
550         if (p == NULL)
551                 {
552                 p=h;
553                 h="*";
554                 }
555
556         if (!BIO_get_port(p,&port)) return(INVALID_SOCKET);
557
558         memset((char *)&server,0,sizeof(server));
559         server.sin_family=AF_INET;
560         server.sin_port=htons(port);
561
562         if (strcmp(h,"*") == 0)
563                 server.sin_addr.s_addr=INADDR_ANY;
564         else
565                 {
566                 if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET);
567                 l=(unsigned long)
568                         ((unsigned long)ip[0]<<24L)|
569                         ((unsigned long)ip[1]<<16L)|
570                         ((unsigned long)ip[2]<< 8L)|
571                         ((unsigned long)ip[3]);
572                 server.sin_addr.s_addr=htonl(l);
573                 }
574
575 again:
576         s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
577         if (s == INVALID_SOCKET)
578                 {
579                 SYSerr(SYS_F_SOCKET,get_last_socket_error());
580                 ERR_add_error_data(3,"port='",host,"'");
581                 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
582                 goto err;
583                 }
584
585 #ifdef SO_REUSEADDR
586         if (bind_mode == BIO_BIND_REUSEADDR)
587                 {
588                 int i=1;
589
590                 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
591                 bind_mode=BIO_BIND_NORMAL;
592                 }
593 #endif
594         if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
595                 {
596 #ifdef SO_REUSEADDR
597                 err_num=get_last_socket_error();
598                 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
599                         (err_num == EADDRINUSE))
600                         {
601                         memcpy((char *)&client,(char *)&server,sizeof(server));
602                         if (strcmp(h,"*") == 0)
603                                 client.sin_addr.s_addr=htonl(0x7F000001);
604                         cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
605                         if (cs != INVALID_SOCKET)
606                                 {
607                                 int ii;
608                                 ii=connect(cs,(struct sockaddr *)&client,
609                                         sizeof(client));
610                                 closesocket(cs);
611                                 if (ii == INVALID_SOCKET)
612                                         {
613                                         bind_mode=BIO_BIND_REUSEADDR;
614                                         closesocket(s);
615                                         goto again;
616                                         }
617                                 /* else error */
618                                 }
619                         /* else error */
620                         }
621 #endif
622                 SYSerr(SYS_F_BIND,err_num);
623                 ERR_add_error_data(3,"port='",host,"'");
624                 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
625                 goto err;
626                 }
627         if (listen(s,MAX_LISTEN) == -1)
628                 {
629                 SYSerr(SYS_F_BIND,get_last_socket_error());
630                 ERR_add_error_data(3,"port='",host,"'");
631                 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
632                 goto err;
633                 }
634         ret=1;
635 err:
636         if (str != NULL) OPENSSL_free(str);
637         if ((ret == 0) && (s != INVALID_SOCKET))
638                 {
639                 closesocket(s);
640                 s= INVALID_SOCKET;
641                 }
642         return(s);
643         }
644
645 int BIO_accept(int sock, char **addr)
646         {
647         int ret=INVALID_SOCKET;
648         static struct sockaddr_in from;
649         unsigned long l;
650         unsigned short port;
651         int len;
652         char *p;
653
654         memset((char *)&from,0,sizeof(from));
655         len=sizeof(from);
656         /* Note: under VMS with SOCKETSHR the fourth parameter is currently
657          * of type (int *) whereas under other systems it is (void *) if
658          * you don't have a cast it will choke the compiler: if you do
659          * have a cast then you can either go for (int *) or (void *).
660          */
661         ret=accept(sock,(struct sockaddr *)&from,(void *)&len);
662         if (ret == INVALID_SOCKET)
663                 {
664                 SYSerr(SYS_F_ACCEPT,get_last_socket_error());
665                 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
666                 goto end;
667                 }
668
669         if (addr == NULL) goto end;
670
671         l=ntohl(from.sin_addr.s_addr);
672         port=ntohs(from.sin_port);
673         if (*addr == NULL)
674                 {
675                 if ((p=OPENSSL_malloc(24)) == NULL)
676                         {
677                         BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
678                         goto end;
679                         }
680                 *addr=p;
681                 }
682         sprintf(*addr,"%d.%d.%d.%d:%d",
683                 (unsigned char)(l>>24L)&0xff,
684                 (unsigned char)(l>>16L)&0xff,
685                 (unsigned char)(l>> 8L)&0xff,
686                 (unsigned char)(l     )&0xff,
687                 port);
688 end:
689         return(ret);
690         }
691
692 int BIO_set_tcp_ndelay(int s, int on)
693         {
694         int ret=0;
695 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
696         int opt;
697
698 #ifdef SOL_TCP
699         opt=SOL_TCP;
700 #else
701 #ifdef IPPROTO_TCP
702         opt=IPPROTO_TCP;
703 #endif
704 #endif
705         
706         ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
707 #endif
708         return(ret == 0);
709         }
710 #endif
711
712 int BIO_socket_nbio(int s, int mode)
713         {
714         int ret= -1;
715         unsigned long l;
716
717         l=mode;
718 #ifdef FIONBIO
719         ret=BIO_socket_ioctl(s,FIONBIO,&l);
720 #endif
721         return(ret == 0);
722         }