]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/bio/b_sock.c
Add BeOS support.
[thirdparty/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 #include <stdio.h>
60 #include <stdlib.h>
61 #include <errno.h>
62 #define USE_SOCKETS
63 #include "cryptlib.h"
64 #include <openssl/bio.h>
65 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
66 #include "netdb.h"
67 #endif
68
69 #ifndef OPENSSL_NO_SOCK
70
71 #include <openssl/dso.h>
72
73 #define SOCKET_PROTOCOL IPPROTO_TCP
74
75 #ifdef SO_MAXCONN
76 #define MAX_LISTEN SO_MAXCONN
77 #elif defined(SOMAXCONN)
78 #define MAX_LISTEN SOMAXCONN
79 #else
80 #define MAX_LISTEN 32
81 #endif
82
83 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
84 static int wsa_init_done=0;
85 #endif
86
87 #if defined(OPENSSL_SYS_BEOS_BONE)
88 /* BONE's IP6 support is incomplete */
89 #undef AF_INET6
90 #endif
91
92 #if 0
93 static unsigned long BIO_ghbn_hits=0L;
94 static unsigned long BIO_ghbn_miss=0L;
95
96 #define GHBN_NUM 4
97 static struct ghbn_cache_st
98 {
99 char name[129];
100 struct hostent *ent;
101 unsigned long order;
102 } ghbn_cache[GHBN_NUM];
103 #endif
104
105 static int get_ip(const char *str,unsigned char *ip);
106 #if 0
107 static void ghbn_free(struct hostent *a);
108 static struct hostent *ghbn_dup(struct hostent *a);
109 #endif
110 int BIO_get_host_ip(const char *str, unsigned char *ip)
111 {
112 int i;
113 int err = 1;
114 int locked = 0;
115 struct hostent *he;
116
117 i=get_ip(str,ip);
118 if (i < 0)
119 {
120 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
121 goto err;
122 }
123
124 /* At this point, we have something that is most probably correct
125 in some way, so let's init the socket. */
126 if (BIO_sock_init() != 1)
127 return 0; /* don't generate another error code here */
128
129 /* If the string actually contained an IP address, we need not do
130 anything more */
131 if (i > 0) return(1);
132
133 /* do a gethostbyname */
134 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
135 locked = 1;
136 he=BIO_gethostbyname(str);
137 if (he == NULL)
138 {
139 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
140 goto err;
141 }
142
143 /* cast to short because of win16 winsock definition */
144 if ((short)he->h_addrtype != AF_INET)
145 {
146 BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
147 goto err;
148 }
149 for (i=0; i<4; i++)
150 ip[i]=he->h_addr_list[0][i];
151 err = 0;
152
153 err:
154 if (locked)
155 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
156 if (err)
157 {
158 ERR_add_error_data(2,"host=",str);
159 return 0;
160 }
161 else
162 return 1;
163 }
164
165 int BIO_get_port(const char *str, unsigned short *port_ptr)
166 {
167 int i;
168 struct servent *s;
169
170 if (str == NULL)
171 {
172 BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
173 return(0);
174 }
175 i=atoi(str);
176 if (i != 0)
177 *port_ptr=(unsigned short)i;
178 else
179 {
180 CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
181 /* Note: under VMS with SOCKETSHR, it seems like the first
182 * parameter is 'char *', instead of 'const char *'
183 */
184 s=getservbyname(
185 #ifndef CONST_STRICT
186 (char *)
187 #endif
188 str,"tcp");
189 if(s != NULL)
190 *port_ptr=ntohs((unsigned short)s->s_port);
191 CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
192 if(s == NULL)
193 {
194 if (strcmp(str,"http") == 0)
195 *port_ptr=80;
196 else if (strcmp(str,"telnet") == 0)
197 *port_ptr=23;
198 else if (strcmp(str,"socks") == 0)
199 *port_ptr=1080;
200 else if (strcmp(str,"https") == 0)
201 *port_ptr=443;
202 else if (strcmp(str,"ssl") == 0)
203 *port_ptr=443;
204 else if (strcmp(str,"ftp") == 0)
205 *port_ptr=21;
206 else if (strcmp(str,"gopher") == 0)
207 *port_ptr=70;
208 #if 0
209 else if (strcmp(str,"wais") == 0)
210 *port_ptr=21;
211 #endif
212 else
213 {
214 SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
215 ERR_add_error_data(3,"service='",str,"'");
216 return(0);
217 }
218 }
219 }
220 return(1);
221 }
222
223 int BIO_sock_error(int sock)
224 {
225 int j,i;
226 int size;
227
228 #if defined(OPENSSL_SYS_BEOS_R5)
229 return 0;
230 #endif
231
232 size=sizeof(int);
233 /* Note: under Windows the third parameter is of type (char *)
234 * whereas under other systems it is (void *) if you don't have
235 * a cast it will choke the compiler: if you do have a cast then
236 * you can either go for (char *) or (void *).
237 */
238 i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size);
239 if (i < 0)
240 return(1);
241 else
242 return(j);
243 }
244
245 #if 0
246 long BIO_ghbn_ctrl(int cmd, int iarg, char *parg)
247 {
248 int i;
249 char **p;
250
251 switch (cmd)
252 {
253 case BIO_GHBN_CTRL_HITS:
254 return(BIO_ghbn_hits);
255 /* break; */
256 case BIO_GHBN_CTRL_MISSES:
257 return(BIO_ghbn_miss);
258 /* break; */
259 case BIO_GHBN_CTRL_CACHE_SIZE:
260 return(GHBN_NUM);
261 /* break; */
262 case BIO_GHBN_CTRL_GET_ENTRY:
263 if ((iarg >= 0) && (iarg <GHBN_NUM) &&
264 (ghbn_cache[iarg].order > 0))
265 {
266 p=(char **)parg;
267 if (p == NULL) return(0);
268 *p=ghbn_cache[iarg].name;
269 ghbn_cache[iarg].name[128]='\0';
270 return(1);
271 }
272 return(0);
273 /* break; */
274 case BIO_GHBN_CTRL_FLUSH:
275 for (i=0; i<GHBN_NUM; i++)
276 ghbn_cache[i].order=0;
277 break;
278 default:
279 return(0);
280 }
281 return(1);
282 }
283 #endif
284
285 #if 0
286 static struct hostent *ghbn_dup(struct hostent *a)
287 {
288 struct hostent *ret;
289 int i,j;
290
291 MemCheck_off();
292 ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent));
293 if (ret == NULL) return(NULL);
294 memset(ret,0,sizeof(struct hostent));
295
296 for (i=0; a->h_aliases[i] != NULL; i++)
297 ;
298 i++;
299 ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *));
300 if (ret->h_aliases == NULL)
301 goto err;
302 memset(ret->h_aliases, 0, i*sizeof(char *));
303
304 for (i=0; a->h_addr_list[i] != NULL; i++)
305 ;
306 i++;
307 ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *));
308 if (ret->h_addr_list == NULL)
309 goto err;
310 memset(ret->h_addr_list, 0, i*sizeof(char *));
311
312 j=strlen(a->h_name)+1;
313 if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err;
314 memcpy((char *)ret->h_name,a->h_name,j);
315 for (i=0; a->h_aliases[i] != NULL; i++)
316 {
317 j=strlen(a->h_aliases[i])+1;
318 if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err;
319 memcpy(ret->h_aliases[i],a->h_aliases[i],j);
320 }
321 ret->h_length=a->h_length;
322 ret->h_addrtype=a->h_addrtype;
323 for (i=0; a->h_addr_list[i] != NULL; i++)
324 {
325 if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL)
326 goto err;
327 memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
328 }
329 if (0)
330 {
331 err:
332 if (ret != NULL)
333 ghbn_free(ret);
334 ret=NULL;
335 }
336 MemCheck_on();
337 return(ret);
338 }
339
340 static void ghbn_free(struct hostent *a)
341 {
342 int i;
343
344 if(a == NULL)
345 return;
346
347 if (a->h_aliases != NULL)
348 {
349 for (i=0; a->h_aliases[i] != NULL; i++)
350 OPENSSL_free(a->h_aliases[i]);
351 OPENSSL_free(a->h_aliases);
352 }
353 if (a->h_addr_list != NULL)
354 {
355 for (i=0; a->h_addr_list[i] != NULL; i++)
356 OPENSSL_free(a->h_addr_list[i]);
357 OPENSSL_free(a->h_addr_list);
358 }
359 if (a->h_name != NULL) OPENSSL_free(a->h_name);
360 OPENSSL_free(a);
361 }
362
363 #endif
364
365 struct hostent *BIO_gethostbyname(const char *name)
366 {
367 #if 1
368 /* Caching gethostbyname() results forever is wrong,
369 * so we have to let the true gethostbyname() worry about this */
370 return gethostbyname(name);
371 #else
372 struct hostent *ret;
373 int i,lowi=0,j;
374 unsigned long low= (unsigned long)-1;
375
376
377 # if 0
378 /* It doesn't make sense to use locking here: The function interface
379 * is not thread-safe, because threads can never be sure when
380 * some other thread destroys the data they were given a pointer to.
381 */
382 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
383 # endif
384 j=strlen(name);
385 if (j < 128)
386 {
387 for (i=0; i<GHBN_NUM; i++)
388 {
389 if (low > ghbn_cache[i].order)
390 {
391 low=ghbn_cache[i].order;
392 lowi=i;
393 }
394 if (ghbn_cache[i].order > 0)
395 {
396 if (strncmp(name,ghbn_cache[i].name,128) == 0)
397 break;
398 }
399 }
400 }
401 else
402 i=GHBN_NUM;
403
404 if (i == GHBN_NUM) /* no hit*/
405 {
406 BIO_ghbn_miss++;
407 /* Note: under VMS with SOCKETSHR, it seems like the first
408 * parameter is 'char *', instead of 'const char *'
409 */
410 ret=gethostbyname(
411 # ifndef CONST_STRICT
412 (char *)
413 # endif
414 name);
415
416 if (ret == NULL)
417 goto end;
418 if (j > 128) /* too big to cache */
419 {
420 # if 0
421 /* If we were trying to make this function thread-safe (which
422 * is bound to fail), we'd have to give up in this case
423 * (or allocate more memory). */
424 ret = NULL;
425 # endif
426 goto end;
427 }
428
429 /* else add to cache */
430 if (ghbn_cache[lowi].ent != NULL)
431 ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */
432 ghbn_cache[lowi].name[0] = '\0';
433
434 if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
435 {
436 BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
437 goto end;
438 }
439 strncpy(ghbn_cache[lowi].name,name,128);
440 ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
441 }
442 else
443 {
444 BIO_ghbn_hits++;
445 ret= ghbn_cache[i].ent;
446 ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
447 }
448 end:
449 # if 0
450 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
451 # endif
452 return(ret);
453 #endif
454 }
455
456
457 int BIO_sock_init(void)
458 {
459 #ifdef OPENSSL_SYS_WINDOWS
460 static struct WSAData wsa_state;
461
462 if (!wsa_init_done)
463 {
464 int err;
465
466 #ifdef SIGINT
467 signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
468 #endif
469 wsa_init_done=1;
470 memset(&wsa_state,0,sizeof(wsa_state));
471 /* Not making wsa_state available to the rest of the
472 * code is formally wrong. But the structures we use
473 * are [beleived to be] invariable among Winsock DLLs,
474 * while API availability is [expected to be] probed
475 * at run-time with DSO_global_lookup. */
476 if (WSAStartup(0x0202,&wsa_state)!=0)
477 {
478 err=WSAGetLastError();
479 SYSerr(SYS_F_WSASTARTUP,err);
480 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
481 return(-1);
482 }
483 }
484 #endif /* OPENSSL_SYS_WINDOWS */
485 #ifdef WATT32
486 extern int _watt_do_exit;
487 _watt_do_exit = 0; /* don't make sock_init() call exit() */
488 if (sock_init())
489 return (-1);
490 #endif
491
492 #if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
493 WORD wVerReq;
494 WSADATA wsaData;
495 int err;
496
497 if (!wsa_init_done)
498 {
499
500 # ifdef SIGINT
501 signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
502 # endif
503
504 wsa_init_done=1;
505 wVerReq = MAKEWORD( 2, 0 );
506 err = WSAStartup(wVerReq,&wsaData);
507 if (err != 0)
508 {
509 SYSerr(SYS_F_WSASTARTUP,err);
510 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
511 return(-1);
512 }
513 }
514 #endif
515
516 return(1);
517 }
518
519 void BIO_sock_cleanup(void)
520 {
521 #ifdef OPENSSL_SYS_WINDOWS
522 if (wsa_init_done)
523 {
524 wsa_init_done=0;
525 #ifndef OPENSSL_SYS_WINCE
526 WSACancelBlockingCall();
527 #endif
528 WSACleanup();
529 }
530 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
531 if (wsa_init_done)
532 {
533 wsa_init_done=0;
534 WSACleanup();
535 }
536 #endif
537 }
538
539 #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000
540
541 int BIO_socket_ioctl(int fd, long type, void *arg)
542 {
543 int i;
544
545 #ifdef __DJGPP__
546 i=ioctlsocket(fd,type,(char *)arg);
547 #else
548 i=ioctlsocket(fd,type,arg);
549 #endif /* __DJGPP__ */
550 if (i < 0)
551 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
552 return(i);
553 }
554 #endif /* __VMS_VER */
555
556 /* The reason I have implemented this instead of using sscanf is because
557 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
558 static int get_ip(const char *str, unsigned char ip[4])
559 {
560 unsigned int tmp[4];
561 int num=0,c,ok=0;
562
563 tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
564
565 for (;;)
566 {
567 c= *(str++);
568 if ((c >= '0') && (c <= '9'))
569 {
570 ok=1;
571 tmp[num]=tmp[num]*10+c-'0';
572 if (tmp[num] > 255) return(0);
573 }
574 else if (c == '.')
575 {
576 if (!ok) return(-1);
577 if (num == 3) return(0);
578 num++;
579 ok=0;
580 }
581 else if (c == '\0' && (num == 3) && ok)
582 break;
583 else
584 return(0);
585 }
586 ip[0]=tmp[0];
587 ip[1]=tmp[1];
588 ip[2]=tmp[2];
589 ip[3]=tmp[3];
590 return(1);
591 }
592
593 int BIO_get_accept_socket(char *host, int bind_mode)
594 {
595 int ret=0;
596 struct sockaddr server,client;
597 struct sockaddr_in *sa_in;
598 int s=INVALID_SOCKET,cs;
599 unsigned char ip[4];
600 unsigned short port;
601 char *str=NULL,*e;
602 char *h,*p;
603 unsigned long l;
604 int err_num;
605
606 if (BIO_sock_init() != 1) return(INVALID_SOCKET);
607
608 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
609
610 h=p=NULL;
611 h=str;
612 for (e=str; *e; e++)
613 {
614 if (*e == ':')
615 {
616 p=e;
617 }
618 else if (*e == '/')
619 {
620 *e='\0';
621 break;
622 }
623 }
624 if (p) *p++='\0'; /* points at last ':', '::port' is special [see below] */
625 else p=h,h=NULL;
626
627 #ifdef EAI_FAMILY
628 do {
629 static union { void *p;
630 int (*f)(const char *,const char *,
631 const struct addrinfo *,
632 struct addrinfo **);
633 } p_getaddrinfo = {NULL};
634 static union { void *p;
635 void (*f)(struct addrinfo *);
636 } p_freeaddrinfo = {NULL};
637 struct addrinfo *res,hint;
638
639 if (p_getaddrinfo.p==NULL)
640 {
641 if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL ||
642 (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL)
643 p_getaddrinfo.p=(void*)-1;
644 }
645 if (p_getaddrinfo.p==(void *)-1) break;
646
647 /* '::port' enforces IPv6 wildcard listener. Some OSes,
648 * e.g. Solaris, default to IPv6 without any hint. Also
649 * note that commonly IPv6 wildchard socket can service
650 * IPv4 connections just as well... */
651 memset(&hint,0,sizeof(hint));
652 if (h)
653 {
654 if (strchr(h,':'))
655 {
656 if (h[1]=='\0') h=NULL;
657 #ifdef AF_INET6
658 hint.ai_family = AF_INET6;
659 #else
660 h=NULL;
661 #endif
662 }
663 else if (h[0]=='*' && h[1]=='\0')
664 h=NULL;
665 }
666
667 if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break;
668 server = *res->ai_addr;
669 (*p_freeaddrinfo.f)(res);
670 goto again;
671 } while (0);
672 #endif
673
674 if (!BIO_get_port(p,&port)) goto err;
675
676 memset((char *)&server,0,sizeof(server));
677 sa_in = (struct sockaddr_in *)&server;
678 sa_in->sin_family=AF_INET;
679 sa_in->sin_port=htons(port);
680
681 if (h == NULL || strcmp(h,"*") == 0)
682 sa_in->sin_addr.s_addr=INADDR_ANY;
683 else
684 {
685 if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
686 l=(unsigned long)
687 ((unsigned long)ip[0]<<24L)|
688 ((unsigned long)ip[1]<<16L)|
689 ((unsigned long)ip[2]<< 8L)|
690 ((unsigned long)ip[3]);
691 sa_in->sin_addr.s_addr=htonl(l);
692 }
693
694 again:
695 s=socket(server.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
696 if (s == INVALID_SOCKET)
697 {
698 SYSerr(SYS_F_SOCKET,get_last_socket_error());
699 ERR_add_error_data(3,"port='",host,"'");
700 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
701 goto err;
702 }
703
704 #ifdef SO_REUSEADDR
705 if (bind_mode == BIO_BIND_REUSEADDR)
706 {
707 int i=1;
708
709 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
710 bind_mode=BIO_BIND_NORMAL;
711 }
712 #endif
713 if (bind(s,&server,sizeof(server)) == -1)
714 {
715 #ifdef SO_REUSEADDR
716 err_num=get_last_socket_error();
717 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
718 (err_num == EADDRINUSE))
719 {
720 client = server;
721 if (h == NULL || strcmp(h,"*") == 0)
722 {
723 #ifdef AF_INET6
724 if (client.sa_family == AF_INET6)
725 {
726 struct sockaddr_in6 *sin6 =
727 (struct sockaddr_in6 *)&client;
728 memset(&sin6->sin6_addr,0,sizeof(sin6->sin6_addr));
729 sin6->sin6_addr.s6_addr[15]=1;
730 }
731 else
732 #endif
733 if (client.sa_family == AF_INET)
734 {
735 struct sockaddr_in *sin6 =
736 (struct sockaddr_in *)&client;
737 sin6->sin_addr.s_addr=htonl(0x7F000001);
738 }
739 else goto err;
740 }
741 cs=socket(client.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
742 if (cs != INVALID_SOCKET)
743 {
744 int ii;
745 ii=connect(cs,(struct sockaddr *)&client,
746 sizeof(client));
747 closesocket(cs);
748 if (ii == INVALID_SOCKET)
749 {
750 bind_mode=BIO_BIND_REUSEADDR;
751 closesocket(s);
752 goto again;
753 }
754 /* else error */
755 }
756 /* else error */
757 }
758 #endif
759 SYSerr(SYS_F_BIND,err_num);
760 ERR_add_error_data(3,"port='",host,"'");
761 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
762 goto err;
763 }
764 if (listen(s,MAX_LISTEN) == -1)
765 {
766 SYSerr(SYS_F_BIND,get_last_socket_error());
767 ERR_add_error_data(3,"port='",host,"'");
768 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
769 goto err;
770 }
771 ret=1;
772 err:
773 if (str != NULL) OPENSSL_free(str);
774 if ((ret == 0) && (s != INVALID_SOCKET))
775 {
776 closesocket(s);
777 s= INVALID_SOCKET;
778 }
779 return(s);
780 }
781
782 int BIO_accept(int sock, char **addr)
783 {
784 int ret=INVALID_SOCKET;
785 struct sockaddr from;
786 struct sockaddr_in *sa_in;
787 unsigned long l;
788 unsigned short port;
789 int len;
790 char *p;
791
792 memset(&from,0,sizeof(from));
793 len=sizeof(from);
794 /* Note: under VMS with SOCKETSHR the fourth parameter is currently
795 * of type (int *) whereas under other systems it is (void *) if
796 * you don't have a cast it will choke the compiler: if you do
797 * have a cast then you can either go for (int *) or (void *).
798 */
799 ret=accept(sock,&from,(void *)&len);
800 if (ret == INVALID_SOCKET)
801 {
802 if(BIO_sock_should_retry(ret)) return -2;
803 SYSerr(SYS_F_ACCEPT,get_last_socket_error());
804 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
805 goto end;
806 }
807
808 if (addr == NULL) goto end;
809
810 #ifdef EAI_FAMILY
811 # if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_BEOS_BONE)
812 # define SOCKLEN_T size_t
813 # else
814 # define SOCKLEN_T socklen_t
815 #endif
816 do {
817 char h[NI_MAXHOST],s[NI_MAXSERV];
818 size_t nl;
819 static union { void *p;
820 int (*f)(const struct sockaddr *,SOCKLEN_T,
821 char *,size_t,char *,size_t,int);
822 } p_getnameinfo = {NULL};
823
824 if (p_getnameinfo.p==NULL)
825 {
826 if ((p_getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL)
827 p_getnameinfo.p=(void*)-1;
828 }
829 if (p_getnameinfo.p==(void *)-1) break;
830
831 if ((*p_getnameinfo.f)(&from,sizeof(from),h,sizeof(h),s,sizeof(s),
832 NI_NUMERICHOST|NI_NUMERICSERV)) break;
833 nl = strlen(h)+strlen(s)+2; if (len<24) len=24;
834 p = *addr;
835 if (p) { *p = '\0'; p = OPENSSL_realloc(p,nl); }
836 else { p = OPENSSL_malloc(nl); }
837 if (p==NULL)
838 {
839 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
840 goto end;
841 }
842 *addr = p;
843 BIO_snprintf(*addr,nl,"%s:%s",h,s);
844 goto end;
845 } while(0);
846 #endif
847 if (from.sa_family != AF_INET) goto end;
848 sa_in = (struct sockaddr_in *)&from;
849 l=ntohl(sa_in->sin_addr.s_addr);
850 port=ntohs(sa_in->sin_port);
851 if (*addr == NULL)
852 {
853 if ((p=OPENSSL_malloc(24)) == NULL)
854 {
855 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
856 goto end;
857 }
858 *addr=p;
859 }
860 BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d",
861 (unsigned char)(l>>24L)&0xff,
862 (unsigned char)(l>>16L)&0xff,
863 (unsigned char)(l>> 8L)&0xff,
864 (unsigned char)(l )&0xff,
865 port);
866 end:
867 return(ret);
868 }
869
870 int BIO_set_tcp_ndelay(int s, int on)
871 {
872 int ret=0;
873 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
874 int opt;
875
876 #ifdef SOL_TCP
877 opt=SOL_TCP;
878 #else
879 #ifdef IPPROTO_TCP
880 opt=IPPROTO_TCP;
881 #endif
882 #endif
883
884 ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
885 #endif
886 return(ret == 0);
887 }
888 #endif
889
890 int BIO_socket_nbio(int s, int mode)
891 {
892 int ret= -1;
893 int l;
894
895 l=mode;
896 #ifdef FIONBIO
897 ret=BIO_socket_ioctl(s,FIONBIO,&l);
898 #endif
899 return(ret == 0);
900 }