OLD | NEW |
1 /* crypto/bio/b_sock.c */ | 1 /* crypto/bio/b_sock.c */ |
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * This package is an SSL implementation written | 5 * This package is an SSL implementation written |
6 * by Eric Young (eay@cryptsoft.com). | 6 * by Eric Young (eay@cryptsoft.com). |
7 * The implementation was written so as to conform with Netscapes SSL. | 7 * The implementation was written so as to conform with Netscapes SSL. |
8 * | 8 * |
9 * This library is free for commercial and non-commercial use as long as | 9 * This library is free for commercial and non-commercial use as long as |
10 * the following conditions are aheared to. The following conditions | 10 * the following conditions are aheared to. The following conditions |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) | 65 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) |
66 #include <netdb.h> | 66 #include <netdb.h> |
67 #if defined(NETWARE_CLIB) | 67 #if defined(NETWARE_CLIB) |
68 #include <sys/ioctl.h> | 68 #include <sys/ioctl.h> |
69 NETDB_DEFINE_CONTEXT | 69 NETDB_DEFINE_CONTEXT |
70 #endif | 70 #endif |
71 #endif | 71 #endif |
72 | 72 |
73 #ifndef OPENSSL_NO_SOCK | 73 #ifndef OPENSSL_NO_SOCK |
74 | 74 |
75 #ifdef OPENSSL_SYS_WIN16 | 75 #include <openssl/dso.h> |
76 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ | 76 |
77 #else | |
78 #define SOCKET_PROTOCOL IPPROTO_TCP | 77 #define SOCKET_PROTOCOL IPPROTO_TCP |
79 #endif | |
80 | 78 |
81 #ifdef SO_MAXCONN | 79 #ifdef SO_MAXCONN |
82 #define MAX_LISTEN SO_MAXCONN | 80 #define MAX_LISTEN SO_MAXCONN |
83 #elif defined(SOMAXCONN) | 81 #elif defined(SOMAXCONN) |
84 #define MAX_LISTEN SOMAXCONN | 82 #define MAX_LISTEN SOMAXCONN |
85 #else | 83 #else |
86 #define MAX_LISTEN 32 | 84 #define MAX_LISTEN 32 |
87 #endif | 85 #endif |
88 | 86 |
89 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NE
TWARE_BSDSOCK)) | 87 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NE
TWARE_BSDSOCK)) |
90 static int wsa_init_done=0; | 88 static int wsa_init_done=0; |
91 #endif | 89 #endif |
92 | 90 |
| 91 /* |
| 92 * WSAAPI specifier is required to make indirect calls to run-time |
| 93 * linked WinSock 2 functions used in this module, to be specific |
| 94 * [get|free]addrinfo and getnameinfo. This is because WinSock uses |
| 95 * uses non-C calling convention, __stdcall vs. __cdecl, on x86 |
| 96 * Windows. On non-WinSock platforms WSAAPI needs to be void. |
| 97 */ |
| 98 #ifndef WSAAPI |
| 99 #define WSAAPI |
| 100 #endif |
| 101 |
93 #if 0 | 102 #if 0 |
94 static unsigned long BIO_ghbn_hits=0L; | 103 static unsigned long BIO_ghbn_hits=0L; |
95 static unsigned long BIO_ghbn_miss=0L; | 104 static unsigned long BIO_ghbn_miss=0L; |
96 | 105 |
97 #define GHBN_NUM 4 | 106 #define GHBN_NUM 4 |
98 static struct ghbn_cache_st | 107 static struct ghbn_cache_st |
99 { | 108 { |
100 char name[129]; | 109 char name[129]; |
101 struct hostent *ent; | 110 struct hostent *ent; |
102 unsigned long order; | 111 unsigned long order; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 } | 228 } |
220 } | 229 } |
221 return(1); | 230 return(1); |
222 } | 231 } |
223 | 232 |
224 int BIO_sock_error(int sock) | 233 int BIO_sock_error(int sock) |
225 { | 234 { |
226 int j,i; | 235 int j,i; |
227 int size; | 236 int size; |
228 | 237 |
| 238 #if defined(OPENSSL_SYS_BEOS_R5) |
| 239 return 0; |
| 240 #endif |
| 241 |
229 size=sizeof(int); | 242 size=sizeof(int); |
230 /* Note: under Windows the third parameter is of type (char *) | 243 /* Note: under Windows the third parameter is of type (char *) |
231 * whereas under other systems it is (void *) if you don't have | 244 * whereas under other systems it is (void *) if you don't have |
232 * a cast it will choke the compiler: if you do have a cast then | 245 * a cast it will choke the compiler: if you do have a cast then |
233 * you can either go for (char *) or (void *). | 246 * you can either go for (char *) or (void *). |
234 */ | 247 */ |
235 i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); | 248 i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); |
236 if (i < 0) | 249 if (i < 0) |
237 return(1); | 250 return(1); |
238 else | 251 else |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 { | 472 { |
460 #ifdef OPENSSL_SYS_WINDOWS | 473 #ifdef OPENSSL_SYS_WINDOWS |
461 static struct WSAData wsa_state; | 474 static struct WSAData wsa_state; |
462 | 475 |
463 if (!wsa_init_done) | 476 if (!wsa_init_done) |
464 { | 477 { |
465 int err; | 478 int err; |
466 | 479 |
467 wsa_init_done=1; | 480 wsa_init_done=1; |
468 memset(&wsa_state,0,sizeof(wsa_state)); | 481 memset(&wsa_state,0,sizeof(wsa_state)); |
469 » » if (WSAStartup(0x0101,&wsa_state)!=0) | 482 » » /* Not making wsa_state available to the rest of the |
| 483 » » * code is formally wrong. But the structures we use |
| 484 » » * are [beleived to be] invariable among Winsock DLLs, |
| 485 » » * while API availability is [expected to be] probed |
| 486 » » * at run-time with DSO_global_lookup. */ |
| 487 » » if (WSAStartup(0x0202,&wsa_state)!=0) |
470 { | 488 { |
471 err=WSAGetLastError(); | 489 err=WSAGetLastError(); |
472 SYSerr(SYS_F_WSASTARTUP,err); | 490 SYSerr(SYS_F_WSASTARTUP,err); |
473 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP); | 491 BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP); |
474 return(-1); | 492 return(-1); |
475 } | 493 } |
476 } | 494 } |
477 #endif /* OPENSSL_SYS_WINDOWS */ | 495 #endif /* OPENSSL_SYS_WINDOWS */ |
478 #ifdef WATT32 | 496 #ifdef WATT32 |
479 extern int _watt_do_exit; | 497 extern int _watt_do_exit; |
(...skipping 23 matching lines...) Expand all Loading... |
503 | 521 |
504 return(1); | 522 return(1); |
505 } | 523 } |
506 | 524 |
507 void BIO_sock_cleanup(void) | 525 void BIO_sock_cleanup(void) |
508 { | 526 { |
509 #ifdef OPENSSL_SYS_WINDOWS | 527 #ifdef OPENSSL_SYS_WINDOWS |
510 if (wsa_init_done) | 528 if (wsa_init_done) |
511 { | 529 { |
512 wsa_init_done=0; | 530 wsa_init_done=0; |
513 #ifndef OPENSSL_SYS_WINCE | 531 #if 0» » /* this call is claimed to be non-present in Winsock2 */ |
514 » » WSACancelBlockingCall();» /* Winsock 1.1 specific */ | 532 » » WSACancelBlockingCall(); |
515 #endif | 533 #endif |
516 WSACleanup(); | 534 WSACleanup(); |
517 } | 535 } |
518 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) | 536 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) |
519 if (wsa_init_done) | 537 if (wsa_init_done) |
520 { | 538 { |
521 wsa_init_done=0; | 539 wsa_init_done=0; |
522 WSACleanup(); | 540 WSACleanup(); |
523 } | 541 } |
524 #endif | 542 #endif |
525 } | 543 } |
526 | 544 |
527 #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 | 545 #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 |
528 | 546 |
529 int BIO_socket_ioctl(int fd, long type, void *arg) | 547 int BIO_socket_ioctl(int fd, long type, void *arg) |
530 { | 548 { |
531 int i; | 549 int i; |
532 | 550 |
533 #ifdef __DJGPP__ | 551 #ifdef __DJGPP__ |
534 i=ioctlsocket(fd,type,(char *)arg); | 552 i=ioctlsocket(fd,type,(char *)arg); |
535 #else | 553 #else |
536 » i=ioctlsocket(fd,type,arg); | 554 # if defined(OPENSSL_SYS_VMS) |
| 555 » /* 2011-02-18 SMS. |
| 556 » * VMS ioctl() can't tolerate a 64-bit "void *arg", but we |
| 557 » * observe that all the consumers pass in an "unsigned long *", |
| 558 » * so we arrange a local copy with a short pointer, and use |
| 559 » * that, instead. |
| 560 » */ |
| 561 # if __INITIAL_POINTER_SIZE == 64 |
| 562 # define ARG arg_32p |
| 563 # pragma pointer_size save |
| 564 # pragma pointer_size 32 |
| 565 » unsigned long arg_32; |
| 566 » unsigned long *arg_32p; |
| 567 # pragma pointer_size restore |
| 568 » arg_32p = &arg_32; |
| 569 » arg_32 = *((unsigned long *) arg); |
| 570 # else /* __INITIAL_POINTER_SIZE == 64 */ |
| 571 # define ARG arg |
| 572 # endif /* __INITIAL_POINTER_SIZE == 64 [else] */ |
| 573 # else /* defined(OPENSSL_SYS_VMS) */ |
| 574 # define ARG arg |
| 575 # endif /* defined(OPENSSL_SYS_VMS) [else] */ |
| 576 |
| 577 » i=ioctlsocket(fd,type,ARG); |
537 #endif /* __DJGPP__ */ | 578 #endif /* __DJGPP__ */ |
538 if (i < 0) | 579 if (i < 0) |
539 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); | 580 SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); |
540 return(i); | 581 return(i); |
541 } | 582 } |
542 #endif /* __VMS_VER */ | 583 #endif /* __VMS_VER */ |
543 | 584 |
544 /* The reason I have implemented this instead of using sscanf is because | 585 /* The reason I have implemented this instead of using sscanf is because |
545 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ | 586 * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ |
546 static int get_ip(const char *str, unsigned char ip[4]) | 587 static int get_ip(const char *str, unsigned char ip[4]) |
(...skipping 27 matching lines...) Expand all Loading... |
574 ip[0]=tmp[0]; | 615 ip[0]=tmp[0]; |
575 ip[1]=tmp[1]; | 616 ip[1]=tmp[1]; |
576 ip[2]=tmp[2]; | 617 ip[2]=tmp[2]; |
577 ip[3]=tmp[3]; | 618 ip[3]=tmp[3]; |
578 return(1); | 619 return(1); |
579 } | 620 } |
580 | 621 |
581 int BIO_get_accept_socket(char *host, int bind_mode) | 622 int BIO_get_accept_socket(char *host, int bind_mode) |
582 { | 623 { |
583 int ret=0; | 624 int ret=0; |
584 » struct sockaddr_in server,client; | 625 » union { |
585 » int s=INVALID_SOCKET,cs; | 626 » » struct sockaddr sa; |
| 627 » » struct sockaddr_in sa_in; |
| 628 #if OPENSSL_USE_IPV6 |
| 629 » » struct sockaddr_in6 sa_in6; |
| 630 #endif |
| 631 » } server,client; |
| 632 » int s=INVALID_SOCKET,cs,addrlen; |
586 unsigned char ip[4]; | 633 unsigned char ip[4]; |
587 unsigned short port; | 634 unsigned short port; |
588 char *str=NULL,*e; | 635 char *str=NULL,*e; |
589 » const char *h,*p; | 636 » char *h,*p; |
590 unsigned long l; | 637 unsigned long l; |
591 int err_num; | 638 int err_num; |
592 | 639 |
593 if (BIO_sock_init() != 1) return(INVALID_SOCKET); | 640 if (BIO_sock_init() != 1) return(INVALID_SOCKET); |
594 | 641 |
595 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); | 642 if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); |
596 | 643 |
597 h=p=NULL; | 644 h=p=NULL; |
598 h=str; | 645 h=str; |
599 for (e=str; *e; e++) | 646 for (e=str; *e; e++) |
600 { | 647 { |
601 if (*e == ':') | 648 if (*e == ':') |
602 { | 649 { |
603 » » » p= &(e[1]); | 650 » » » p=e; |
604 » » » *e='\0'; | |
605 } | 651 } |
606 else if (*e == '/') | 652 else if (*e == '/') |
607 { | 653 { |
608 *e='\0'; | 654 *e='\0'; |
609 break; | 655 break; |
610 } | 656 } |
611 } | 657 } |
| 658 if (p) *p++='\0'; /* points at last ':', '::port' is special [see
below] */ |
| 659 else p=h,h=NULL; |
612 | 660 |
613 » if (p == NULL) | 661 #ifdef EAI_FAMILY |
| 662 » do { |
| 663 » static union {» void *p; |
| 664 » » » int (WSAAPI *f)(const char *,const char *, |
| 665 » » » » const struct addrinfo *, |
| 666 » » » » struct addrinfo **); |
| 667 » » » } p_getaddrinfo = {NULL}; |
| 668 » static union {» void *p; |
| 669 » » » void (WSAAPI *f)(struct addrinfo *); |
| 670 » » » } p_freeaddrinfo = {NULL}; |
| 671 » struct addrinfo *res,hint; |
| 672 |
| 673 » if (p_getaddrinfo.p==NULL) |
614 { | 674 { |
615 » » p=h; | 675 » » if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL || |
616 » » h="*"; | 676 » » (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL) |
| 677 » » » p_getaddrinfo.p=(void*)-1; |
617 } | 678 } |
| 679 if (p_getaddrinfo.p==(void *)-1) break; |
| 680 |
| 681 /* '::port' enforces IPv6 wildcard listener. Some OSes, |
| 682 * e.g. Solaris, default to IPv6 without any hint. Also |
| 683 * note that commonly IPv6 wildchard socket can service |
| 684 * IPv4 connections just as well... */ |
| 685 memset(&hint,0,sizeof(hint)); |
| 686 hint.ai_flags = AI_PASSIVE; |
| 687 if (h) |
| 688 { |
| 689 if (strchr(h,':')) |
| 690 { |
| 691 if (h[1]=='\0') h=NULL; |
| 692 #if OPENSSL_USE_IPV6 |
| 693 hint.ai_family = AF_INET6; |
| 694 #else |
| 695 h=NULL; |
| 696 #endif |
| 697 } |
| 698 else if (h[0]=='*' && h[1]=='\0') |
| 699 { |
| 700 hint.ai_family = AF_INET; |
| 701 h=NULL; |
| 702 } |
| 703 } |
| 704 |
| 705 if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break; |
| 706 |
| 707 addrlen = res->ai_addrlen<=sizeof(server) ? |
| 708 res->ai_addrlen : |
| 709 sizeof(server); |
| 710 memcpy(&server, res->ai_addr, addrlen); |
| 711 |
| 712 (*p_freeaddrinfo.f)(res); |
| 713 goto again; |
| 714 } while (0); |
| 715 #endif |
618 | 716 |
619 if (!BIO_get_port(p,&port)) goto err; | 717 if (!BIO_get_port(p,&port)) goto err; |
620 | 718 |
621 memset((char *)&server,0,sizeof(server)); | 719 memset((char *)&server,0,sizeof(server)); |
622 » server.sin_family=AF_INET; | 720 » server.sa_in.sin_family=AF_INET; |
623 » server.sin_port=htons(port); | 721 » server.sa_in.sin_port=htons(port); |
| 722 » addrlen = sizeof(server.sa_in); |
624 | 723 |
625 » if (strcmp(h,"*") == 0) | 724 » if (h == NULL || strcmp(h,"*") == 0) |
626 » » server.sin_addr.s_addr=INADDR_ANY; | 725 » » server.sa_in.sin_addr.s_addr=INADDR_ANY; |
627 else | 726 else |
628 { | 727 { |
629 if (!BIO_get_host_ip(h,&(ip[0]))) goto err; | 728 if (!BIO_get_host_ip(h,&(ip[0]))) goto err; |
630 l=(unsigned long) | 729 l=(unsigned long) |
631 ((unsigned long)ip[0]<<24L)| | 730 ((unsigned long)ip[0]<<24L)| |
632 ((unsigned long)ip[1]<<16L)| | 731 ((unsigned long)ip[1]<<16L)| |
633 ((unsigned long)ip[2]<< 8L)| | 732 ((unsigned long)ip[2]<< 8L)| |
634 ((unsigned long)ip[3]); | 733 ((unsigned long)ip[3]); |
635 » » server.sin_addr.s_addr=htonl(l); | 734 » » server.sa_in.sin_addr.s_addr=htonl(l); |
636 } | 735 } |
637 | 736 |
638 again: | 737 again: |
639 » s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | 738 » s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL); |
640 if (s == INVALID_SOCKET) | 739 if (s == INVALID_SOCKET) |
641 { | 740 { |
642 SYSerr(SYS_F_SOCKET,get_last_socket_error()); | 741 SYSerr(SYS_F_SOCKET,get_last_socket_error()); |
643 ERR_add_error_data(3,"port='",host,"'"); | 742 ERR_add_error_data(3,"port='",host,"'"); |
644 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET
); | 743 BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET
); |
645 goto err; | 744 goto err; |
646 } | 745 } |
647 | 746 |
648 #ifdef SO_REUSEADDR | 747 #ifdef SO_REUSEADDR |
649 if (bind_mode == BIO_BIND_REUSEADDR) | 748 if (bind_mode == BIO_BIND_REUSEADDR) |
650 { | 749 { |
651 int i=1; | 750 int i=1; |
652 | 751 |
653 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); | 752 ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); |
654 bind_mode=BIO_BIND_NORMAL; | 753 bind_mode=BIO_BIND_NORMAL; |
655 } | 754 } |
656 #endif | 755 #endif |
657 » if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) | 756 » if (bind(s,&server.sa,addrlen) == -1) |
658 { | 757 { |
659 #ifdef SO_REUSEADDR | 758 #ifdef SO_REUSEADDR |
660 err_num=get_last_socket_error(); | 759 err_num=get_last_socket_error(); |
661 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && | 760 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && |
662 #ifdef OPENSSL_SYS_WINDOWS | 761 #ifdef OPENSSL_SYS_WINDOWS |
663 /* Some versions of Windows define EADDRINUSE to | 762 /* Some versions of Windows define EADDRINUSE to |
664 * a dummy value. | 763 * a dummy value. |
665 */ | 764 */ |
666 (err_num == WSAEADDRINUSE)) | 765 (err_num == WSAEADDRINUSE)) |
667 #else | 766 #else |
668 (err_num == EADDRINUSE)) | 767 (err_num == EADDRINUSE)) |
669 #endif | 768 #endif |
670 { | 769 { |
671 » » » memcpy((char *)&client,(char *)&server,sizeof(server)); | 770 » » » client = server; |
672 » » » if (strcmp(h,"*") == 0) | 771 » » » if (h == NULL || strcmp(h,"*") == 0) |
673 » » » » client.sin_addr.s_addr=htonl(0x7F000001); | 772 » » » » { |
674 » » » cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | 773 #if OPENSSL_USE_IPV6 |
| 774 » » » » if (client.sa.sa_family == AF_INET6) |
| 775 » » » » » { |
| 776 » » » » » memset(&client.sa_in6.sin6_addr,0,sizeof
(client.sa_in6.sin6_addr)); |
| 777 » » » » » client.sa_in6.sin6_addr.s6_addr[15]=1; |
| 778 » » » » » } |
| 779 » » » » else |
| 780 #endif |
| 781 » » » » if (client.sa.sa_family == AF_INET) |
| 782 » » » » » { |
| 783 » » » » » client.sa_in.sin_addr.s_addr=htonl(0x7F0
00001); |
| 784 » » » » » } |
| 785 » » » » else» goto err; |
| 786 » » » » } |
| 787 » » » cs=socket(client.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCO
L); |
675 if (cs != INVALID_SOCKET) | 788 if (cs != INVALID_SOCKET) |
676 { | 789 { |
677 int ii; | 790 int ii; |
678 » » » » ii=connect(cs,(struct sockaddr *)&client, | 791 » » » » ii=connect(cs,&client.sa,addrlen); |
679 » » » » » sizeof(client)); | |
680 closesocket(cs); | 792 closesocket(cs); |
681 if (ii == INVALID_SOCKET) | 793 if (ii == INVALID_SOCKET) |
682 { | 794 { |
683 bind_mode=BIO_BIND_REUSEADDR; | 795 bind_mode=BIO_BIND_REUSEADDR; |
684 closesocket(s); | 796 closesocket(s); |
685 goto again; | 797 goto again; |
686 } | 798 } |
687 /* else error */ | 799 /* else error */ |
688 } | 800 } |
689 /* else error */ | 801 /* else error */ |
(...skipping 18 matching lines...) Expand all Loading... |
708 { | 820 { |
709 closesocket(s); | 821 closesocket(s); |
710 s= INVALID_SOCKET; | 822 s= INVALID_SOCKET; |
711 } | 823 } |
712 return(s); | 824 return(s); |
713 } | 825 } |
714 | 826 |
715 int BIO_accept(int sock, char **addr) | 827 int BIO_accept(int sock, char **addr) |
716 { | 828 { |
717 int ret=INVALID_SOCKET; | 829 int ret=INVALID_SOCKET; |
718 static struct sockaddr_in from; | |
719 unsigned long l; | 830 unsigned long l; |
720 unsigned short port; | 831 unsigned short port; |
721 int len; | |
722 char *p; | 832 char *p; |
723 | 833 |
724 » memset((char *)&from,0,sizeof(from)); | 834 » struct { |
725 » len=sizeof(from); | 835 » /* |
726 » /* Note: under VMS with SOCKETSHR the fourth parameter is currently | 836 » * As for following union. Trouble is that there are platforms |
727 » * of type (int *) whereas under other systems it is (void *) if | 837 » * that have socklen_t and there are platforms that don't, on |
728 » * you don't have a cast it will choke the compiler: if you do | 838 » * some platforms socklen_t is int and on some size_t. So what |
729 » * have a cast then you can either go for (int *) or (void *). | 839 » * one can do? One can cook #ifdef spaghetti, which is nothing |
| 840 » * but masochistic. Or one can do union between int and size_t. |
| 841 » * One naturally does it primarily for 64-bit platforms where |
| 842 » * sizeof(int) != sizeof(size_t). But would it work? Note that |
| 843 » * if size_t member is initialized to 0, then later int member |
| 844 » * assignment naturally does the job on little-endian platforms |
| 845 » * regardless accept's expectations! What about big-endians? |
| 846 » * If accept expects int*, then it works, and if size_t*, then |
| 847 » * length value would appear as unreasonably large. But this |
| 848 » * won't prevent it from filling in the address structure. The |
| 849 » * trouble of course would be if accept returns more data than |
| 850 » * actual buffer can accomodate and overwrite stack... That's |
| 851 » * where early OPENSSL_assert comes into picture. Besides, the |
| 852 » * only 64-bit big-endian platform found so far that expects |
| 853 » * size_t* is HP-UX, where stack grows towards higher address. |
| 854 » * <appro> |
730 */ | 855 */ |
731 » ret=accept(sock,(struct sockaddr *)&from,(void *)&len); | 856 » union { size_t s; int i; } len; |
| 857 » union { |
| 858 » » struct sockaddr sa; |
| 859 » » struct sockaddr_in sa_in; |
| 860 #if OPENSSL_USE_IPV6 |
| 861 » » struct sockaddr_in6 sa_in6; |
| 862 #endif |
| 863 » » } from; |
| 864 » } sa; |
| 865 |
| 866 » sa.len.s=0; |
| 867 » sa.len.i=sizeof(sa.from); |
| 868 » memset(&sa.from,0,sizeof(sa.from)); |
| 869 » ret=accept(sock,&sa.from.sa,(void *)&sa.len); |
| 870 » if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) |
| 871 » » { |
| 872 » » OPENSSL_assert(sa.len.s<=sizeof(sa.from)); |
| 873 » » sa.len.i = (int)sa.len.s; |
| 874 » » /* use sa.len.i from this point */ |
| 875 » » } |
732 if (ret == INVALID_SOCKET) | 876 if (ret == INVALID_SOCKET) |
733 { | 877 { |
734 if(BIO_sock_should_retry(ret)) return -2; | 878 if(BIO_sock_should_retry(ret)) return -2; |
735 SYSerr(SYS_F_ACCEPT,get_last_socket_error()); | 879 SYSerr(SYS_F_ACCEPT,get_last_socket_error()); |
736 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); | 880 BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); |
737 goto end; | 881 goto end; |
738 } | 882 } |
739 | 883 |
740 if (addr == NULL) goto end; | 884 if (addr == NULL) goto end; |
741 | 885 |
742 » l=ntohl(from.sin_addr.s_addr); | 886 #ifdef EAI_FAMILY |
743 » port=ntohs(from.sin_port); | 887 » do { |
| 888 » char h[NI_MAXHOST],s[NI_MAXSERV]; |
| 889 » size_t nl; |
| 890 » static union {» void *p; |
| 891 » » » int (WSAAPI *f)(const struct sockaddr *,size_t/*socklen_
t*/, |
| 892 » » » » char *,size_t,char *,size_t,int); |
| 893 » » » } p_getnameinfo = {NULL}; |
| 894 » » » /* 2nd argument to getnameinfo is specified to |
| 895 » » » * be socklen_t. Unfortunately there is a number |
| 896 » » » * of environments where socklen_t is not defined. |
| 897 » » » * As it's passed by value, it's safe to pass it |
| 898 » » » * as size_t... <appro> */ |
| 899 |
| 900 » if (p_getnameinfo.p==NULL) |
| 901 » » { |
| 902 » » if ((p_getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL) |
| 903 » » » p_getnameinfo.p=(void*)-1; |
| 904 » » } |
| 905 » if (p_getnameinfo.p==(void *)-1) break; |
| 906 |
| 907 » if ((*p_getnameinfo.f)(&sa.from.sa,sa.len.i,h,sizeof(h),s,sizeof(s), |
| 908 » NI_NUMERICHOST|NI_NUMERICSERV)) break; |
| 909 » nl = strlen(h)+strlen(s)+2; |
| 910 » p = *addr; |
| 911 » if (p)» { *p = '\0'; p = OPENSSL_realloc(p,nl);»} |
| 912 » else» { p = OPENSSL_malloc(nl);» » } |
| 913 » if (p==NULL) |
| 914 » » { |
| 915 » » BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); |
| 916 » » goto end; |
| 917 » » } |
| 918 » *addr = p; |
| 919 » BIO_snprintf(*addr,nl,"%s:%s",h,s); |
| 920 » goto end; |
| 921 » } while(0); |
| 922 #endif |
| 923 » if (sa.from.sa.sa_family != AF_INET) goto end; |
| 924 » l=ntohl(sa.from.sa_in.sin_addr.s_addr); |
| 925 » port=ntohs(sa.from.sa_in.sin_port); |
744 if (*addr == NULL) | 926 if (*addr == NULL) |
745 { | 927 { |
746 if ((p=OPENSSL_malloc(24)) == NULL) | 928 if ((p=OPENSSL_malloc(24)) == NULL) |
747 { | 929 { |
748 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); | 930 BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); |
749 goto end; | 931 goto end; |
750 } | 932 } |
751 *addr=p; | 933 *addr=p; |
752 } | 934 } |
753 BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d", | 935 BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d", |
(...skipping 30 matching lines...) Expand all Loading... |
784 { | 966 { |
785 int ret= -1; | 967 int ret= -1; |
786 int l; | 968 int l; |
787 | 969 |
788 l=mode; | 970 l=mode; |
789 #ifdef FIONBIO | 971 #ifdef FIONBIO |
790 ret=BIO_socket_ioctl(s,FIONBIO,&l); | 972 ret=BIO_socket_ioctl(s,FIONBIO,&l); |
791 #endif | 973 #endif |
792 return(ret == 0); | 974 return(ret == 0); |
793 } | 975 } |
OLD | NEW |