--- /dev/null
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "bio_lcl.h"
+
+#include <openssl/err.h>
+
+#ifndef OPENSSL_NO_SOCK
+# ifdef SO_MAXCONN
+# define MAX_LISTEN SO_MAXCONN
+# elif defined(SOMAXCONN)
+# define MAX_LISTEN SOMAXCONN
+# else
+# define MAX_LISTEN 32
+# endif
+
+/*-
+ * BIO_socket - create a socket
+ * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
+ * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
+ * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
+ * @options: BIO socket options (currently unused)
+ *
+ * Creates a socket. This should be called before calling any
+ * of BIO_connect and BIO_listen.
+ *
+ * Returns the file descriptor on success or INVALID_SOCKET on failure. On
+ * failure errno is set, and a status is added to the OpenSSL error stack.
+ */
+int BIO_socket(int domain, int socktype, int protocol, int options)
+{
+ int sock = -1;
+
+ if (BIO_sock_init() != 1)
+ return INVALID_SOCKET;
+
+ sock = socket(domain, socktype, protocol);
+ if (sock == -1) {
+ SYSerr(SYS_F_SOCKET, get_last_socket_error());
+ BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
+ return INVALID_SOCKET;
+ }
+
+ return sock;
+}
+
+/*-
+ * BIO_connect - connect to an address
+ * @sock: the socket to connect with
+ * @addr: the address to connect to
+ * @options: BIO socket options
+ *
+ * Connects to the address using the given socket and options.
+ *
+ * Options can be a combination of the following:
+ * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
+ * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
+ * - BIO_SOCK_NODELAY: don't delay small messages.
+ *
+ * options holds BIO socket options that can be used
+ * You should call this for every address returned by BIO_lookup
+ * until the connection is succesful.
+ *
+ * Returns 1 on success or 0 on failure. On failure errno is set
+ * and an error status is added to the OpenSSL error stack.
+ */
+int BIO_connect(int sock, const BIO_ADDR *addr, int options)
+{
+ int on = 1;
+
+ if (sock == -1) {
+ BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
+ return 0;
+ }
+
+ if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
+ return 0;
+
+ if (options & BIO_SOCK_KEEPALIVE) {
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) != 0) {
+ SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
+ return 0;
+ }
+ }
+
+ if (options & BIO_SOCK_NODELAY) {
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) != 0) {
+ SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
+ return 0;
+ }
+ }
+
+ if (connect(sock, BIO_ADDR_sockaddr(addr),
+ BIO_ADDR_sockaddr_size(addr)) == -1) {
+ SYSerr(SYS_F_CONNECT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * BIO_listen - Creates a listen socket
+ * @sock: the socket to listen with
+ * @addr: local address to bind to
+ * @options: BIO socket options
+ *
+ * Binds to the address using the given socket and options, then
+ * starts listening for incoming connections.
+ *
+ * Options can be a combination of the following:
+ * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
+ * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
+ * - BIO_SOCK_NODELAY: don't delay small messages.
+ * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
+ * for a recently closed port.
+ * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
+ * for IPv6 addresses and not IPv4 addresses mapped to IPv6.
+ *
+ * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
+ * then check both for new clients that connect to it. You want to set up
+ * the socket as non-blocking in that case since else it could hang.
+ *
+ * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
+ * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to
+ * create the IPv6 sockets to only listen for IPv6 connection.
+ *
+ * It could be that the first BIO_listen() call will listen to all the IPv6
+ * and IPv4 addresses and that then trying to bind to the IPv4 address will
+ * fail. We can't tell the difference between already listening ourself to
+ * it and someone else listening to it when failing and errno is EADDRINUSE, so
+ * it's recommended to not give an error in that case if the first call was
+ * succesful.
+ *
+ * When restarting the program it could be that the port is still in use. If
+ * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
+ * It's recommended that you use this.
+ */
+int BIO_listen(int sock, const BIO_ADDR *addr, int options)
+{
+ int on = 1;
+ int socktype;
+ socklen_t socktype_len = sizeof(socktype);
+
+ if (sock == -1) {
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
+ return 0;
+ }
+
+ if (getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &socktype_len) != 0
+ || socktype_len != sizeof(socktype)) {
+ SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
+ return 0;
+ }
+
+ if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
+ return 0;
+
+# ifndef OPENSSL_SYS_WINDOWS
+ /* SO_REUSEADDR has different behavior on Windows than on
+ * other operating systems, don't set it there. */
+ if (options & BIO_SOCK_REUSEADDR) {
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
+ SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_REUSEADDR);
+ return 0;
+ }
+ }
+# endif
+
+ if (options & BIO_SOCK_KEEPALIVE) {
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) != 0) {
+ SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE);
+ return 0;
+ }
+ }
+
+ if (options & BIO_SOCK_NODELAY) {
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) != 0) {
+ SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY);
+ return 0;
+ }
+ }
+
+# ifdef IPV6_V6ONLY
+ if ((options & BIO_SOCK_V6_ONLY) && BIO_ADDR_family(addr) == AF_INET6) {
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) != 0) {
+ SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY);
+ return 0;
+ }
+ }
+# endif
+
+ if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
+ SYSerr(SYS_F_BIND, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_BIND_SOCKET);
+ return 0;
+ }
+
+ if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
+ SYSerr(SYS_F_LISTEN, get_last_socket_error());
+ BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*-
+ * BIO_accept_ex - Accept new incoming connections
+ * @sock: the listening socket
+ * @addr: the BIO_ADDR to store the peer address in
+ * @options: BIO socket options, applied on the accepted socket.
+ *
+ */
+int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options)
+{
+ socklen_t len;
+ int accepted_sock;
+
+ len = sizeof(*addr);
+ accepted_sock = accept(accept_sock,
+ BIO_ADDR_sockaddr_noconst(addr), &len);
+ if (accepted_sock == -1) {
+ SYSerr(SYS_F_ACCEPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
+ return INVALID_SOCKET;
+ }
+
+ if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0))
+ return INVALID_SOCKET;
+
+ return accepted_sock;
+}
+
+/*-
+ * BIO_closesocket - Close a socket
+ * @sock: the socket to close
+ */
+int BIO_closesocket(int sock)
+{
+ if (closesocket(sock) < 0)
+ return 0;
+ return 1;
+}
+#endif
--- /dev/null
+=pod
+
+=head1 NAME
+
+BIO_socket, BIO_connect, BIO_listen, BIO_accept_ex, BIO_closesocket - BIO
+socket communication setup routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ int BIO_socket(int domain, int socktype, int protocol, int options);
+ int BIO_connect(int sock, const BIO_ADDR *addr, int options);
+ int BIO_listen(int sock, const BIO_ADDR *addr, int options);
+ int BIO_accept_ex(int accept_sock, BIO_ADDR *peer, int options);
+ int BIO_closesocket(int sock);
+
+=head1 DESCRIPTION
+
+BIO_socket() creates a socket in the domain B<domain>, of type
+B<socktype> and B<protocol>. Socket B<options> are currently unused,
+but is present for future use.
+
+BIO_connect() connects B<sock> to the address and service given by
+B<addr>. Connection B<options> may be zero or any combination of
+B<BIO_SOCK_KEEPALIVE>, B<BIO_SOCK_NONBLOCK> and B<BIO_SOCK_NODELAY>.
+The flags are described in L</FLAGS> below.
+
+BIO_listen() has B<sock> start listening on the address and service
+given by B<addr>. Connection B<options> may be zero or any
+combination of B<BIO_SOCK_KEEPALIVE>, B<BIO_SOCK_NONBLOCK>,
+B<BIO_SOCK_NODELAY>, B<BIO_SOCK_REUSEADDR> and B<BIO_SOCK_V6_ONLY>.
+The flags are described in L</FLAGS> below.
+
+BIO_accept_ex() waits for an incoming connections on the given
+socket B<accept_sock>. When it gets a connection, the address and
+port of the peer gets stored in B<peer> if that one is non-NULL.
+Accept B<options> may be zero or B<BIO_SOCK_NONBLOCK>, and is applied
+on the accepted socket. The flags are described in L</FLAGS> below.
+
+BIO_closesocket() closes B<sock>.
+
+=head1 FLAGS
+
+=over 4
+
+=item BIO_SOCK_KEEPALIVE
+
+Enables regular sending of keep-alive messages.
+
+=item BIO_SOCK_NONBLOCK
+
+Sets the socket to non-blocking mode.
+
+=item BIO_SOCK_NODELAY
+
+Corresponds to B<TCP_NODELAY>, and disables the Nagle algorithm. With
+this set, any data will be sent as soon as possible instead of being
+buffered until there's enough for the socket to send out in one go.
+
+=item BIO_SOCK_REUSEADDR
+
+Try to reuse the address and port combination for a recently closed
+port.
+
+=item BIO_SOCK_V6_ONLY
+
+When creating an IPv6 socket, make it only listen for IPv6 addresses
+and not IPv4 addresses mapped to IPv6.
+
+=back
+
+These flags are bit flags, so they are to be combined with the
+C<|> operator, for example:
+
+ BIO_connect(sock, addr, BIO_SOCK_KEEPALIVE | BIO_SOCK_NONBLOCK);
+
+=head1 RETURN VALUES
+
+BIO_socket() returns the socket number on success or B<INVALID_SOCKET>
+(-1) on error. When an error has occured, the OpenSSL error stack
+will hold the error data and errno has the system error.
+
+BIO_connect() and BIO_listen() return 1 on success or 0 on error.
+When an error has occured, the OpenSSL error stack will hold the error
+data and errno has the system error.
+
+BIO_accept_ex() returns the accepted socket on success or
+B<INVALID_SOCKET> (-1) on error. When an error has occured, the
+OpenSSL error stack will hold the error data and errno has the system
+error.
+
+=head1 HISTORY
+
+BIO_gethostname(), BIO_get_port(), BIO_get_host_ip(),
+BIO_get_accept_socket() and BIO_accept() are deprecated since OpenSSL
+1.1. Use the functions described above instead.
+
+=head1 SEE ALSO
+
+L<BIO_ADDR(3)>
int BIO_lookup(const char *host, const char *service,
enum BIO_lookup_type lookup_type,
int family, int socktype, BIO_ADDRINFO **res);
-struct hostent *BIO_gethostbyname(const char *name);
-/*-
- * We might want a thread-safe interface too:
- * struct hostent *BIO_gethostbyname_r(const char *name,
- * struct hostent *result, void *buffer, size_t buflen);
- * or something similar (caller allocates a struct hostent,
- * pointed to by "result", and additional buffer space for the various
- * substructures; if the buffer does not suffice, NULL is returned
- * and an appropriate error code is set).
- */
int BIO_sock_error(int sock);
int BIO_socket_ioctl(int fd, long type, void *arg);
int BIO_socket_nbio(int fd, int mode);
-int BIO_get_port(const char *str, unsigned short *port_ptr);
-int BIO_get_host_ip(const char *str, unsigned char *ip);
-int BIO_get_accept_socket(char *host_port, int mode);
-int BIO_accept(int sock, char **ip_port);
int BIO_sock_init(void);
void BIO_sock_cleanup(void);
int BIO_set_tcp_ndelay(int sock, int turn_on);
+DEPRECATEDIN_1_1_0(struct hostent *BIO_gethostbyname(const char *name))
+DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr))
+DEPRECATEDIN_1_1_0(int BIO_get_host_ip(const char *str, unsigned char *ip))
+DEPRECATEDIN_1_1_0(int BIO_get_accept_socket(char *host_port, int mode))
+DEPRECATEDIN_1_1_0(int BIO_accept(int sock, char **ip_port))
+
+union BIO_sock_info_u {
+ BIO_ADDR *addr;
+};
+enum BIO_sock_info_type {
+ BIO_SOCK_INFO_ADDRESS
+};
+int BIO_sock_info(int sock,
+ enum BIO_sock_info_type type, union BIO_sock_info_u *info);
+
+# define BIO_SOCK_REUSEADDR 0x01
+# define BIO_SOCK_V6_ONLY 0x02
+# define BIO_SOCK_KEEPALIVE 0x04
+# define BIO_SOCK_NONBLOCK 0x08
+# define BIO_SOCK_NODELAY 0x10
+
+int BIO_socket(int domain, int socktype, int protocol, int options);
+int BIO_connect(int sock, const BIO_ADDR *addr, int options);
+int BIO_listen(int sock, const BIO_ADDR *addr, int options);
+int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options);
+# if OPENSSL_API_COMPAT >= 0x10100000L
+# define BIO_accept(as,s,a) BIO_accept_ex((as),(s),(a))
+# endif
+int BIO_closesocket(int sock);
+
BIO *BIO_new_socket(int sock, int close_flag);
BIO *BIO_new_dgram(int fd, int close_flag);
# ifndef OPENSSL_NO_SCTP