| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-01-09 12:49:01 +08:00
										 |  |  |  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
											  
											
												Refactoring BIO: add wrappers around sockaddr et al
Because different platforms have different levels of support for IPv6,
different kinds of sockaddr variants, and some have getaddrinfo et al
while others don't, we could end up with a mess if ifdefs, duplicate
code and other maintainance nightmares.
Instead, we're introducing wrappers around the common form for socket
communication:
BIO_ADDR, closely related to struct sockaddr and some of its variants.
BIO_ADDRINFO, closely related to struct addrinfo.
With that comes support routines, both convenient creators and
accessors, plus a few utility functions:
BIO_parse_hostserv, takes a string of the form host:service and
splits it into host and service.  It checks for * in both parts, and
converts any [ipv6-address] syntax to ust the IPv6 address.
BIO_lookup, looks up information on a host.
All routines handle IPv4 (AF_INET) and IPv6 (AF_INET6) addresses, and
there is support for local sockets (AF_UNIX) as well.
Reviewed-by: Kurt Roeckx <kurt@openssl.org>
											
										 
											2016-02-02 22:54:57 +08:00
										 |  |  | #include "bio_lcl.h"
 | 
					
						
							| 
									
										
										
										
											2003-03-21 07:18:32 +08:00
										 |  |  | #ifndef OPENSSL_NO_SOCK
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # define SOCKET_PROTOCOL IPPROTO_TCP
 | 
					
						
							|  |  |  | # ifdef SO_MAXCONN
 | 
					
						
							|  |  |  | #  define MAX_LISTEN  SO_MAXCONN
 | 
					
						
							|  |  |  | # elif defined(SOMAXCONN)
 | 
					
						
							|  |  |  | #  define MAX_LISTEN  SOMAXCONN
 | 
					
						
							|  |  |  | # else
 | 
					
						
							|  |  |  | #  define MAX_LISTEN  32
 | 
					
						
							|  |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2016-03-18 00:53:11 +08:00
										 |  |  | # if defined(OPENSSL_SYS_WINDOWS)
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static int wsa_init_done = 0; | 
					
						
							|  |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-30 07:05:03 +08:00
										 |  |  | # if !OPENSSL_API_1_1_0
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int BIO_get_host_ip(const char *str, unsigned char *ip) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     BIO_ADDRINFO *res = NULL; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (BIO_sock_init() != 1) | 
					
						
							|  |  |  |         return 0;               /* don't generate another error code here */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { | 
					
						
							|  |  |  |         size_t l; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |         if (BIO_ADDRINFO_family(res) != AF_INET) { | 
					
						
							|  |  |  |             BIOerr(BIO_F_BIO_GET_HOST_IP, | 
					
						
							|  |  |  |                    BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); | 
					
						
							| 
									
										
										
										
											2017-06-21 22:52:11 +08:00
										 |  |  |         } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * Because only AF_INET addresses will reach this far, we can assert | 
					
						
							|  |  |  |              * that l should be 4 | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             if (ossl_assert(l == 4)) | 
					
						
							|  |  |  |                 ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         BIO_ADDRINFO_free(res); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ERR_add_error_data(2, "host=", str); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1999-06-08 06:50:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int BIO_get_port(const char *str, unsigned short *port_ptr) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     BIO_ADDRINFO *res = NULL; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (str == NULL) { | 
					
						
							|  |  |  |         BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (BIO_sock_init() != 1) | 
					
						
							|  |  |  |         return 0;               /* don't generate another error code here */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { | 
					
						
							|  |  |  |         if (BIO_ADDRINFO_family(res) != AF_INET) { | 
					
						
							|  |  |  |             BIOerr(BIO_F_BIO_GET_PORT, | 
					
						
							|  |  |  |                    BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); | 
					
						
							|  |  |  |             ret = 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |         BIO_ADDRINFO_free(res); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ERR_add_error_data(2, "host=", str); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-03 04:04:54 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int BIO_sock_error(int sock) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     int j = 0, i; | 
					
						
							| 
									
										
										
										
											2016-04-28 19:19:38 +08:00
										 |  |  |     socklen_t size = sizeof(j); | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Note: under Windows the third parameter is of type (char *) whereas | 
					
						
							|  |  |  |      * under other systems it is (void *) if you don't have a cast it will | 
					
						
							|  |  |  |      * choke the compiler: if you do have a cast then you can either go for | 
					
						
							|  |  |  |      * (char *) or (void *). | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (i < 0) | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return get_last_socket_error(); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return j; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-30 07:05:03 +08:00
										 |  |  | # if !OPENSSL_API_1_1_0
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | struct hostent *BIO_gethostbyname(const char *name) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Caching gethostbyname() results forever is wrong, so we have to let | 
					
						
							|  |  |  |      * the true gethostbyname() worry about this | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-01-30 10:38:57 +08:00
										 |  |  |     return gethostbyname(name); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-03 04:04:54 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2001-10-26 21:04:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int BIO_sock_init(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  | # ifdef OPENSSL_SYS_WINDOWS
 | 
					
						
							|  |  |  |     static struct WSAData wsa_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!wsa_init_done) { | 
					
						
							|  |  |  |         int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         wsa_init_done = 1; | 
					
						
							|  |  |  |         memset(&wsa_state, 0, sizeof(wsa_state)); | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Not making wsa_state available to the rest of the code is formally | 
					
						
							| 
									
										
										
										
											2016-02-06 04:23:54 +08:00
										 |  |  |          * wrong. But the structures we use are [believed to be] invariable | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |          * among Winsock DLLs, while API availability is [expected to be] | 
					
						
							|  |  |  |          * probed at run-time with DSO_global_lookup. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (WSAStartup(0x0202, &wsa_state) != 0) { | 
					
						
							|  |  |  |             err = WSAGetLastError(); | 
					
						
							|  |  |  |             SYSerr(SYS_F_WSASTARTUP, err); | 
					
						
							|  |  |  |             BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # endif                         /* OPENSSL_SYS_WINDOWS */
 | 
					
						
							|  |  |  | # ifdef WATT32
 | 
					
						
							|  |  |  |     extern int _watt_do_exit; | 
					
						
							|  |  |  |     _watt_do_exit = 0;          /* don't make sock_init() call exit() */ | 
					
						
							|  |  |  |     if (sock_init()) | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-09 19:05:58 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-12 19:20:16 +08:00
										 |  |  | void bio_sock_cleanup_int(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  | # ifdef OPENSSL_SYS_WINDOWS
 | 
					
						
							|  |  |  |     if (wsa_init_done) { | 
					
						
							|  |  |  |         wsa_init_done = 0; | 
					
						
							| 
									
										
										
										
											2003-11-28 21:10:58 +08:00
										 |  |  |         WSACleanup(); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-31 20:20:35 +08:00
										 |  |  | int BIO_socket_ioctl(int fd, long type, void *arg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  ifdef __DJGPP__
 | 
					
						
							|  |  |  |     i = ioctlsocket(fd, type, (char *)arg); | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | #   if defined(OPENSSL_SYS_VMS)
 | 
					
						
							| 
									
										
										
										
											2015-01-17 08:06:54 +08:00
										 |  |  |     /*-
 | 
					
						
							|  |  |  |      * 2011-02-18 SMS. | 
					
						
							|  |  |  |      * VMS ioctl() can't tolerate a 64-bit "void *arg", but we | 
					
						
							|  |  |  |      * observe that all the consumers pass in an "unsigned long *", | 
					
						
							|  |  |  |      * so we arrange a local copy with a short pointer, and use | 
					
						
							|  |  |  |      * that, instead. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #    if __INITIAL_POINTER_SIZE == 64
 | 
					
						
							|  |  |  | #     define ARG arg_32p
 | 
					
						
							|  |  |  | #     pragma pointer_size save
 | 
					
						
							|  |  |  | #     pragma pointer_size 32
 | 
					
						
							|  |  |  |     unsigned long arg_32; | 
					
						
							|  |  |  |     unsigned long *arg_32p; | 
					
						
							|  |  |  | #     pragma pointer_size restore
 | 
					
						
							|  |  |  |     arg_32p = &arg_32; | 
					
						
							|  |  |  |     arg_32 = *((unsigned long *)arg); | 
					
						
							|  |  |  | #    else                       /* __INITIAL_POINTER_SIZE == 64 */
 | 
					
						
							|  |  |  | #     define ARG arg
 | 
					
						
							|  |  |  | #    endif                      /* __INITIAL_POINTER_SIZE == 64 [else] */
 | 
					
						
							|  |  |  | #   else                        /* defined(OPENSSL_SYS_VMS) */
 | 
					
						
							|  |  |  | #    define ARG arg
 | 
					
						
							|  |  |  | #   endif                       /* defined(OPENSSL_SYS_VMS) [else] */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = ioctlsocket(fd, type, ARG); | 
					
						
							|  |  |  | #  endif                        /* __DJGPP__ */
 | 
					
						
							|  |  |  |     if (i < 0) | 
					
						
							|  |  |  |         SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return i; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-30 07:05:03 +08:00
										 |  |  | # if !OPENSSL_API_1_1_0
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int BIO_get_accept_socket(char *host, int bind_mode) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     int s = INVALID_SOCKET; | 
					
						
							|  |  |  |     char *h = NULL, *p = NULL; | 
					
						
							|  |  |  |     BIO_ADDRINFO *res = NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV)) | 
					
						
							|  |  |  |         return INVALID_SOCKET; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if (BIO_sock_init() != 1) | 
					
						
							|  |  |  |         return INVALID_SOCKET; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res), | 
					
						
							|  |  |  |                         BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) { | 
					
						
							|  |  |  |         s = INVALID_SOCKET; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if (!BIO_listen(s, BIO_ADDRINFO_address(res), | 
					
						
							|  |  |  |                     bind_mode ? BIO_SOCK_REUSEADDR : 0)) { | 
					
						
							|  |  |  |         BIO_closesocket(s); | 
					
						
							|  |  |  |         s = INVALID_SOCKET; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  err: | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     BIO_ADDRINFO_free(res); | 
					
						
							|  |  |  |     OPENSSL_free(h); | 
					
						
							|  |  |  |     OPENSSL_free(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return s; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  | int BIO_accept(int sock, char **ip_port) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-15 04:50:13 +08:00
										 |  |  |     BIO_ADDR res; | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     int ret = -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-15 04:50:13 +08:00
										 |  |  |     ret = BIO_accept_ex(sock, &res, 0); | 
					
						
							| 
									
										
										
										
											2015-09-30 16:15:03 +08:00
										 |  |  |     if (ret == (int)INVALID_SOCKET) { | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |         if (BIO_sock_should_retry(ret)) { | 
					
						
							|  |  |  |             ret = -2; | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         SYSerr(SYS_F_ACCEPT, get_last_socket_error()); | 
					
						
							|  |  |  |         BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     if (ip_port != NULL) { | 
					
						
							| 
									
										
										
										
											2016-02-15 04:50:13 +08:00
										 |  |  |         char *host = BIO_ADDR_hostname_string(&res, 1); | 
					
						
							|  |  |  |         char *port = BIO_ADDR_service_string(&res, 1); | 
					
						
							| 
									
										
										
										
											2016-05-04 17:38:02 +08:00
										 |  |  |         if (host != NULL && port != NULL) | 
					
						
							|  |  |  |             *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             *ip_port = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (*ip_port == NULL) { | 
					
						
							|  |  |  |             BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |             BIO_closesocket(ret); | 
					
						
							|  |  |  |             ret = (int)INVALID_SOCKET; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             strcpy(*ip_port, host); | 
					
						
							|  |  |  |             strcat(*ip_port, ":"); | 
					
						
							|  |  |  |             strcat(*ip_port, port); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |         OPENSSL_free(host); | 
					
						
							|  |  |  |         OPENSSL_free(port); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  end: | 
					
						
							| 
									
										
										
										
											2016-02-03 05:33:57 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-03 04:04:54 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int BIO_set_tcp_ndelay(int s, int on) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							|  |  |  | # if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
 | 
					
						
							|  |  |  |     int opt; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #  ifdef SOL_TCP
 | 
					
						
							|  |  |  |     opt = SOL_TCP; | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | #   ifdef IPPROTO_TCP
 | 
					
						
							|  |  |  |     opt = IPPROTO_TCP; | 
					
						
							|  |  |  | #   endif
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1998-12-21 19:00:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  |     return (ret == 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BIO_socket_nbio(int s, int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret = -1; | 
					
						
							|  |  |  |     int l; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     l = mode; | 
					
						
							|  |  |  | # ifdef FIONBIO
 | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:51 +08:00
										 |  |  |     l = mode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ret = BIO_socket_ioctl(s, FIONBIO, &l); | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:51 +08:00
										 |  |  | # elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
 | 
					
						
							|  |  |  |     /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     l = fcntl(s, F_GETFL, 0); | 
					
						
							|  |  |  |     if (l == -1) { | 
					
						
							| 
									
										
										
										
											2018-04-26 15:59:22 +08:00
										 |  |  |         SYSerr(SYS_F_FCNTL, get_last_sys_error()); | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:51 +08:00
										 |  |  |         ret = -1; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  | #  if defined(O_NONBLOCK)
 | 
					
						
							|  |  |  |         l &= ~O_NONBLOCK; | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  |         l &= ~FNDELAY; /* BSD4.x */ | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  |         if (mode) { | 
					
						
							|  |  |  | #  if defined(O_NONBLOCK)
 | 
					
						
							|  |  |  |             l |= O_NONBLOCK; | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  |             l |= FNDELAY; /* BSD4.x */ | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ret = fcntl(s, F_SETFL, l); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ret < 0) { | 
					
						
							| 
									
										
										
										
											2018-04-26 15:59:22 +08:00
										 |  |  |             SYSerr(SYS_F_FCNTL, get_last_sys_error()); | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:51 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # else
 | 
					
						
							|  |  |  |     /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ | 
					
						
							|  |  |  |     BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2016-02-11 22:33:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return (ret == 0); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-03 04:04:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int BIO_sock_info(int sock, | 
					
						
							|  |  |  |                   enum BIO_sock_info_type type, union BIO_sock_info_u *info) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							|  |  |  |     case BIO_SOCK_INFO_ADDRESS: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             socklen_t addr_len; | 
					
						
							|  |  |  |             int ret = 0; | 
					
						
							|  |  |  |             addr_len = sizeof(*info->addr); | 
					
						
							|  |  |  |             ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), | 
					
						
							|  |  |  |                               &addr_len); | 
					
						
							|  |  |  |             if (ret == -1) { | 
					
						
							|  |  |  |                 SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error()); | 
					
						
							|  |  |  |                 BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR); | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-02-14 18:16:37 +08:00
										 |  |  |             if ((size_t)addr_len > sizeof(*info->addr)) { | 
					
						
							| 
									
										
										
										
											2016-02-03 04:04:54 +08:00
										 |  |  |                 BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-17 01:42:36 +08:00
										 |  |  | #endif
 |