[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Wed Feb 3 18:37:18 UTC 2016


The branch master has been updated
       via  83be2778fe11ede4cd065a136c686fe664c212a2 (commit)
       via  a5cc75d6615227e5307a1f9f17f762a7e2d8d3fb (commit)
       via  28a0841bf58e3813b2e07ad22f19484308e2f70a (commit)
      from  ba2de73b185016e0a98e62f75b368ab6ae673919 (commit)


- Log -----------------------------------------------------------------
commit 83be2778fe11ede4cd065a136c686fe664c212a2
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Feb 2 16:25:42 2016 +0100

    Refactoring BIO: add error macros & text, and make update
    
    Reviewed-by: Kurt Roeckx <kurt at openssl.org>

commit a5cc75d6615227e5307a1f9f17f762a7e2d8d3fb
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Feb 2 16:23:26 2016 +0100

    Refactoring BIO: Small adjustments
    
    Because of the way bio_lcl.h is organised, we must not include
    internal/cryptlib.h before it.  As a matter of fact, bio_lcl.h
    includes internal/cryptlib.h on its own.
    
    Reviewed-by: Kurt Roeckx <kurt at openssl.org>

commit 28a0841bf58e3813b2e07ad22f19484308e2f70a
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Feb 2 15:54:57 2016 +0100

    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 at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 crypto/bio/Makefile.in            |   4 +-
 crypto/bio/b_addr.c               | 795 ++++++++++++++++++++++++++++++++++++++
 crypto/bio/b_dump.c               |   1 -
 crypto/bio/b_sock.c               |  11 +-
 crypto/bio/bio_err.c              |  10 +-
 crypto/bio/bio_lcl.h              |  78 ++++
 crypto/bio/bss_fd.c               |   6 +-
 crypto/bio/bss_file.c             |   1 -
 crypto/err/err.c                  |   2 +
 doc/crypto/BIO_ADDR.pod           | 109 ++++++
 doc/crypto/BIO_ADDRINFO.pod       |  82 ++++
 doc/crypto/BIO_parse_hostserv.pod |  62 +++
 e_os.h                            |   2 +
 include/openssl/bio.h             |  38 ++
 include/openssl/err.h             |   2 +
 util/libeay.num                   |  17 +
 16 files changed, 1203 insertions(+), 17 deletions(-)
 create mode 100644 crypto/bio/b_addr.c
 create mode 100644 doc/crypto/BIO_ADDR.pod
 create mode 100644 doc/crypto/BIO_ADDRINFO.pod
 create mode 100644 doc/crypto/BIO_parse_hostserv.pod

diff --git a/crypto/bio/Makefile.in b/crypto/bio/Makefile.in
index e4ba255..9bcc17e 100644
--- a/crypto/bio/Makefile.in
+++ b/crypto/bio/Makefile.in
@@ -18,14 +18,14 @@ LIB=$(TOP)/libcrypto.a
 LIBSRC= bio_lib.c bio_cb.c bio_err.c \
 	bss_mem.c bss_null.c bss_fd.c \
 	bss_file.c bss_sock.c bss_conn.c \
-	bf_null.c bf_buff.c b_print.c b_dump.c \
+	bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \
 	b_sock.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \
 	bss_dgram.c
 #	bf_lbuf.c
 LIBOBJ= bio_lib.o bio_cb.o bio_err.o \
 	bss_mem.o bss_null.o bss_fd.o \
 	bss_file.o bss_sock.o bss_conn.o \
-	bf_null.o bf_buff.o b_print.o b_dump.o \
+	bf_null.o bf_buff.o b_print.o b_dump.o b_addr.o \
 	b_sock.o bss_acpt.o bf_nbio.o bss_log.o bss_bio.o \
 	bss_dgram.o
 #	bf_lbuf.o
diff --git a/crypto/bio/b_addr.c b/crypto/bio/b_addr.c
new file mode 100644
index 0000000..ed267e9
--- /dev/null
+++ b/crypto/bio/b_addr.c
@@ -0,0 +1,795 @@
+/* ====================================================================
+ * 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include <string.h>
+
+#include "bio_lcl.h"
+
+#include <openssl/err.h>
+#include <openssl/buffer.h>
+
+/*
+ * Throughout this file and bio_lcl.h, the existence of the macro
+ * AI_PASSIVE is used to detect the availability of struct addrinfo,
+ * getnameinfo() and getaddrinfo().  If that macro doesn't exist,
+ * we use our own implementation instead, using gethostbyname,
+ * getservbyname and a few other.
+ */
+
+/**********************************************************************
+ *
+ * Address structure
+ *
+ */
+
+BIO_ADDR *BIO_ADDR_new(void)
+{
+    BIO_ADDR *ret = (BIO_ADDR *)OPENSSL_zalloc(sizeof(BIO_ADDR));
+    return ret;
+}
+
+void BIO_ADDR_free(BIO_ADDR *ap)
+{
+    OPENSSL_free(ap);
+}
+
+/*
+ * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
+ * of a struct sockaddr.
+ */
+int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
+{
+    if (sa->sa_family == AF_INET) {
+        ap->sin = *(const struct sockaddr_in *)sa;
+        return 1;
+    }
+#ifdef AF_INET6
+    if (sa->sa_family == AF_INET6) {
+        ap->sin6 = *(const struct sockaddr_in6 *)sa;
+        return 1;
+    }
+#endif
+#ifdef AF_UNIX
+    if (ap->sa.sa_family == AF_UNIX) {
+        ap->sun = *(const struct sockaddr_un *)sa;
+        return 1;
+    }
+#endif
+
+    return 0;
+}
+
+int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
+                     const void *where, size_t wherelen,
+                     unsigned short port)
+{
+#ifdef AF_UNIX
+    if (family == AF_UNIX) {
+        if (wherelen + 1 > sizeof(ap->sun.sun_path))
+            return 0;
+        memset(&ap->sun, 0, sizeof(ap->sun));
+        ap->sun.sun_family = family;
+        strncpy(ap->sun.sun_path, where, sizeof(ap->sun.sun_path) - 1);
+        return 1;
+    }
+#endif
+    if (family == AF_INET) {
+        if (wherelen != sizeof(struct in_addr))
+            return 0;
+        memset(&ap->sin, 0, sizeof(ap->sin));
+        ap->sin.sin_family = family;
+        ap->sin.sin_port = port;
+        ap->sin.sin_addr = *(struct in_addr *)where;
+        return 1;
+    }
+#ifdef AF_INET6
+    if (family == AF_INET6) {
+        if (wherelen != sizeof(struct in6_addr))
+            return 0;
+        memset(&ap->sin6, 0, sizeof(ap->sin6));
+        ap->sin6.sin6_family = family;
+        ap->sin6.sin6_port = port;
+        ap->sin6.sin6_addr = *(struct in6_addr *)where;
+        return 1;
+    }
+#endif
+
+    return 0;
+}
+
+int BIO_ADDR_family(const BIO_ADDR *ap)
+{
+    return ap->sa.sa_family;
+}
+
+int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
+{
+    size_t len = 0;
+    const void *addrptr = NULL;
+
+    if (ap->sa.sa_family == AF_INET) {
+        len = sizeof(ap->sin.sin_addr);
+        addrptr = &ap->sin.sin_addr;
+    }
+#ifdef AF_INET6
+    else if (ap->sa.sa_family == AF_INET6) {
+        len = sizeof(ap->sin6.sin6_addr);
+        addrptr = &ap->sin6.sin6_addr;
+    }
+#endif
+#ifdef AF_UNIX
+    else if (ap->sa.sa_family == AF_UNIX) {
+        len = strlen(ap->sun.sun_path);
+        addrptr = &ap->sun.sun_path;
+    }
+#endif
+
+    if (addrptr == NULL)
+        return 0;
+
+    if (p != NULL) {
+        memcpy(p, addrptr, len);
+    }
+    if (l != NULL)
+        *l = len;
+
+    return 1;
+}
+
+unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
+{
+    if (ap->sa.sa_family == AF_INET)
+        return ap->sin.sin_port;
+#ifdef AF_INET6
+    if (ap->sa.sa_family == AF_INET6)
+        return ap->sin6.sin6_port;
+#endif
+    return 0;
+}
+
+/*-
+ * addr_strings - helper function to get host and service names
+ * @ap: the BIO_ADDR that has the input info
+ * @numeric: 0 if actual names should be returned, 1 if the numeric
+ * representation should be returned.
+ * @hostname: a pointer to a pointer to a memory area to store the
+ * host name or numeric representation.  Unused if NULL.
+ * @service: a pointer to a pointer to a memory area to store the
+ * service name or numeric representation.  Unused if NULL.
+ *
+ * The return value is 0 on failure, with the error code in the error
+ * stack, and 1 on success.
+ */
+static int addr_strings(const BIO_ADDR *ap, int numeric,
+                        char **hostname, char **service)
+{
+    if (1) {
+#ifdef AI_PASSIVE
+        int ret = 0;
+        char host[NI_MAXHOST], serv[NI_MAXSERV];
+        int flags = 0;
+
+        if (numeric)
+            flags |= NI_NUMERICHOST | NI_NUMERICSERV;
+
+        if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
+                               BIO_ADDR_sockaddr_size(ap),
+                               host, sizeof(host), serv, sizeof(serv),
+                               flags)) != 0) {
+# ifdef EAI_SYSTEM
+            if (ret == EAI_SYSTEM) {
+                SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
+                BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
+            } else
+# endif
+            {
+                BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
+                ERR_add_error_data(1, gai_strerror(ret));
+            }
+            return 0;
+        }
+        if (hostname)
+            *hostname = OPENSSL_strdup(host);
+        if (service)
+            *service = OPENSSL_strdup(serv);
+    } else {
+#endif
+        if (hostname)
+            *hostname = OPENSSL_strdup(inet_ntoa(ap->sin.sin_addr));
+        if (service) {
+            char serv[6];        /* port is 16 bits => max 5 decimal digits */
+            BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->sin.sin_port));
+            *service = OPENSSL_strdup(serv);
+        }
+    }
+
+    return 1;
+}
+
+char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
+{
+    char *hostname = NULL;
+
+    if (addr_strings(ap, numeric, &hostname, NULL))
+        return hostname;
+
+    return NULL;
+}
+
+char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
+{
+    char *service = NULL;
+
+    if (addr_strings(ap, numeric, NULL, &service))
+        return service;
+
+    return NULL;
+}
+
+char *BIO_ADDR_path_string(const BIO_ADDR *ap)
+{
+#ifdef AF_UNIX
+    if (ap->sa.sa_family == AF_UNIX)
+        return OPENSSL_strdup(ap->sun.sun_path);
+#endif
+    return NULL;
+}
+
+/*
+ * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
+ * for a given BIO_ADDR.  In reality, this is simply a type safe cast.
+ * The returned struct sockaddr is const, so it can't be tampered with.
+ */
+const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
+{
+    return &(ap->sa);
+}
+
+/*
+ * BIO_ADDR_sockaddr_noconst - non-public function that does the same
+ * as BIO_ADDR_sockaddr, but returns a non-const.  USE WITH CARE, as
+ * it allows you to tamper with the data (and thereby the contents
+ * of the input BIO_ADDR).
+ */
+struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
+{
+    return &(ap->sa);
+}
+
+/*
+ * BIO_ADDR_sockaddr_size - non-public function that returns the size
+ * of the struct sockaddr the BIO_ADDR is using.  If the protocol family
+ * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
+ * the size of the BIO_ADDR type is returned.
+ */
+socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
+{
+    if (ap->sa.sa_family == AF_INET)
+        return sizeof(ap->sin);
+#ifdef AF_INET6
+    if (ap->sa.sa_family == AF_INET6)
+        return sizeof(ap->sin6);
+#endif
+#ifdef AF_UNIX
+    if (ap->sa.sa_family == AF_UNIX)
+        return sizeof(ap->sun);
+#endif
+    return sizeof(*ap);
+}
+
+/**********************************************************************
+ *
+ * Address into database
+ *
+ */
+
+const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return bai->bai_next;
+    return NULL;
+}
+
+int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return bai->bai_family;
+    return 0;
+}
+
+int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return bai->bai_socktype;
+    return 0;
+}
+
+int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return bai->bai_protocol;
+    return 0;
+}
+
+/*
+ * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
+ * of the struct sockaddr inside the BIO_ADDRINFO.
+ */
+socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return bai->bai_addrlen;
+    return 0;
+}
+
+/*
+ * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
+ * as the struct sockaddr it is.
+ */
+const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return bai->bai_addr;
+    return NULL;
+}
+
+const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
+{
+    if (bai != NULL)
+        return (BIO_ADDR *)bai->bai_addr;
+    return NULL;
+}
+
+void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
+{
+    if (bai == NULL)
+        return;
+
+#ifdef AI_PASSIVE
+# ifdef AF_UNIX
+#  define _cond bai->bai_family != AF_UNIX
+# else
+#  define _cond 1
+# endif
+    if (_cond) {
+        freeaddrinfo(bai);
+        return;
+    }
+#endif
+
+    /* Free manually when we know that addrinfo_wrap() was used.
+     * See further comment above addrinfo_wrap()
+     */
+    while (bai != NULL) {
+        BIO_ADDRINFO *next = bai->bai_next;
+        OPENSSL_free(bai->bai_addr);
+        OPENSSL_free(bai);
+        bai = next;
+    }
+}
+
+/**********************************************************************
+ *
+ * Service functions
+ *
+ */
+
+/*-
+ * The specs in hostserv can take these forms:
+ *
+ * host:service         => *host = "host", *service = "service"
+ * host:*               => *host = "host", *service = NULL
+ * host:                => *host = "host", *service = NULL
+ * :service             => *host = NULL, *service = "service"
+ * *:service            => *host = NULL, *service = "service"
+ *
+ * in case no : is present in the string, the result depends on
+ * hostserv_prio, as follows:
+ *
+ * when hostserv_prio == BIO_PARSE_PRIO_HOST
+ * host                 => *host = "host", *service untouched
+ *
+ * when hostserv_prio == BIO_PARSE_PRIO_SERV
+ * service              => *host untouched, *service = "service"
+ *
+ */
+int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
+                       enum BIO_hostserv_priorities hostserv_prio)
+{
+    const char *h = NULL; size_t hl = 0;
+    const char *p = NULL; size_t pl = 0;
+
+    if (*hostserv == '[') {
+        if ((p = strchr(hostserv, ']')) == NULL)
+            goto spec_err;
+        h = hostserv + 1;
+        hl = p - h;
+        p++;
+        if (*p == '\0')
+            p = NULL;
+        else if (*p != ':')
+            goto spec_err;
+        else {
+            p++;
+            pl = strlen(p);
+        }
+    } else {
+        const char *p2 = strrchr(hostserv, ':');
+        p = strchr(hostserv, ':');
+
+        /*-
+         * Check for more than one colon.  There are three possible
+         * interpretations:
+         * 1. IPv6 address with port number, last colon being separator.
+         * 2. IPv6 address only.
+         * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
+         *    IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
+         * Because of this ambiguity, we currently choose to make it an
+         * error.
+         */
+        if (p != p2)
+            goto amb_err;
+
+        if (p != NULL) {
+            h = hostserv;
+            hl = p - h;
+            p++;
+            pl = strlen(p);
+        } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
+            h = hostserv;
+            hl = strlen(h);
+        } else {
+            p = hostserv;
+            pl = strlen(p);
+        }
+    }
+
+    if (strchr(p, ':'))
+        goto spec_err;
+
+    if (h != NULL && host != NULL) {
+        if (hl == 0
+            || (hl == 1 && h[0] == '*')) {
+            *host = NULL;
+        } else {
+            *host = OPENSSL_strndup(h, hl);
+            if (*host == NULL)
+                goto memerr;
+        }
+    }
+    if (p != NULL && service != NULL) {
+        if (pl == 0
+            || (pl == 1 && p[0] == '*')) {
+            *service = NULL;
+        } else {
+            *service = OPENSSL_strndup(p, pl);
+            if (*service == NULL)
+                goto memerr;
+        }
+    }
+
+    return 1;
+ amb_err:
+    BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
+    return 0;
+ spec_err:
+    BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE);
+    return 0;
+ memerr:
+    BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE);
+    return 0;
+}
+
+/* addrinfo_wrap is used to build our own addrinfo "chain".
+ * (it has only one entry, so calling it a chain may be a stretch)
+ * It should ONLY be called when getaddrinfo() and friends
+ * aren't available, OR when dealing with a non IP protocol
+ * family, such as AF_UNIX
+ *
+ * the return value is 1 on success, or 0 on failure, which
+ * only happens if a memory allocation error occured.
+ */
+static int addrinfo_wrap(int family, int socktype,
+                         const void *where, size_t wherelen,
+                         unsigned short port,
+                         BIO_ADDRINFO **bai)
+{
+    OPENSSL_assert(bai != NULL);
+
+    *bai = (BIO_ADDRINFO *)OPENSSL_zalloc(sizeof(**bai));
+
+    if (*bai == NULL)
+        return 0;
+    (*bai)->bai_family = family;
+    (*bai)->bai_socktype = socktype;
+    if (socktype == SOCK_STREAM)
+        (*bai)->bai_protocol = IPPROTO_TCP;
+    if (socktype == SOCK_DGRAM)
+        (*bai)->bai_protocol = IPPROTO_UDP;
+#ifdef AF_UNIX
+    if (family == AF_UNIX)
+        (*bai)->bai_protocol = 0;
+#endif
+    {
+        /* Magic: We know that BIO_ADDR_sockaddr_noconst is really
+           just an advanced cast of BIO_ADDR* to struct sockaddr *
+           by the power of union, so while it may seem that we're
+           creating a memory leak here, we are not.  It will be
+           all right. */
+        BIO_ADDR *addr = BIO_ADDR_new();
+        if (addr != NULL) {
+            BIO_ADDR_rawmake(addr, family, where, wherelen, port);
+            (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
+        }
+    }
+    (*bai)->bai_next = NULL;
+    if ((*bai)->bai_addr == NULL) {
+        BIO_ADDRINFO_free(*bai);
+        *bai = NULL;
+        return 0;
+    }
+    return 1;
+}
+
+/*-
+ * BIO_lookup - look up the node and service you want to connect to.
+ * @node: the node you want to connect to.
+ * @service: the service you want to connect to.
+ * @lookup_type: declare intent with the result, client or server.
+ * @family: the address family you want to use.  Use AF_UNSPEC for any, or
+ *  AF_INET, AF_INET6 or AF_UNIX.
+ * @socktype: The socket type you want to use.  Can be SOCK_STREAM, SOCK_DGRAM
+ *  or 0 for all.
+ * @res: Storage place for the resulting list of returned addresses
+ *
+ * This will do a lookup of the node and service that you want to connect to.
+ * It returns a linked list of different addresses you can try to connect to.
+ *
+ * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
+ *
+ * The return value is 1 on success or 0 in case of error.
+ */
+int BIO_lookup(const char *host, const char *service,
+               enum BIO_lookup_type lookup_type,
+               int family, int socktype, BIO_ADDRINFO **res)
+{
+    int ret = 0;                 /* Assume failure */
+
+    switch(family) {
+    case AF_INET:
+#ifdef AF_INET6
+    case AF_INET6:
+#endif
+#ifdef AF_UNIX
+    case AF_UNIX:
+#endif
+#ifdef AF_UNSPEC
+    case AF_UNSPEC:
+#endif
+        break;
+    default:
+        BIOerr(BIO_F_BIO_LOOKUP, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
+        return 0;
+    }
+
+#ifdef AF_UNIX
+    if (family == AF_UNIX) {
+        if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
+            return 1;
+        else
+            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+#endif
+
+    if (1) {
+#ifdef AI_PASSIVE
+        struct addrinfo hints;
+
+        hints.ai_flags = 0;
+# ifdef AI_ADDRCONFIG
+        hints.ai_flags = AI_ADDRCONFIG;
+# endif
+        hints.ai_family = family;
+        hints.ai_socktype = socktype;
+        hints.ai_protocol = 0;
+        hints.ai_addrlen = 0;
+        hints.ai_addr = NULL;
+        hints.ai_canonname = NULL;
+        hints.ai_next = NULL;
+
+        if (lookup_type == BIO_LOOKUP_SERVER)
+            hints.ai_flags |= AI_PASSIVE;
+
+        /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
+         * macro magic in bio_lcl.h
+         */
+        switch (getaddrinfo(host, service, &hints, res)) {
+# ifdef EAI_SYSTEM
+        case EAI_SYSTEM:
+            SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
+            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
+            break;
+# endif
+        case 0:
+            ret = 1;             /* Success */
+            break;
+        default:
+            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
+            ERR_add_error_data(1, gai_strerror(ret));
+            break;
+        }
+    } else {
+#endif
+        struct hostent *he;
+        /* Windows doesn't seem to have in_addr_t */
+#ifdef OPENSSL_SYS_WINDOWS
+        uint32_t he_fallback_address = INADDR_ANY;
+        uint32_t *he_fallback_addresses[] = { &he_fallback_address, NULL };
+#else
+        in_addr_t he_fallback_address = INADDR_ANY;
+        in_addr_t *he_fallback_addresses[] = { &he_fallback_address, NULL };
+#endif
+        struct hostent he_fallback = { NULL, NULL, AF_INET,
+                                       sizeof(he_fallback_address),
+                                       (char **)&he_fallback_addresses };
+        struct servent *se;
+        /* Apprently, on WIN64, s_proto and s_port have traded places... */
+#ifdef _WIN64
+        struct servent se_fallback = { NULL, NULL, NULL, 0 };
+#else
+        struct servent se_fallback = { NULL, NULL, 0, NULL };
+#endif
+        char *proto = NULL;
+
+        CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
+        CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
+        if (host == NULL) {
+            he = &he_fallback;
+            switch(lookup_type) {
+            case BIO_LOOKUP_CLIENT:
+                he_fallback_address = INADDR_LOOPBACK;
+                break;
+            case BIO_LOOKUP_SERVER:
+                he_fallback_address = INADDR_ANY;
+                break;
+            default:
+                OPENSSL_assert(("We forgot to handle a lookup type!" == 0));
+                break;
+            }
+        } else {
+            he = gethostbyname(host);
+
+            if (he == NULL) {
+                BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
+                ERR_add_error_data(1, hstrerror(h_errno));
+                ret = 0;
+                goto err;
+            }
+        }
+
+        if (service == NULL) {
+            se_fallback.s_port = 0;
+            se_fallback.s_proto = proto;
+            se = &se_fallback;
+        } else {
+            char *endp = NULL;
+            long portnum = strtol(service, &endp, 10);
+
+            if (endp != service && *endp == '\0'
+                    && portnum > 0 && portnum < 65536) {
+                se_fallback.s_port = htons(portnum);
+                se_fallback.s_proto = proto;
+                se = &se_fallback;
+            } else if (endp == service) {
+                switch (socktype) {
+                case SOCK_STREAM:
+                    proto = "tcp";
+                    break;
+                case SOCK_DGRAM:
+                    proto = "udp";
+                    break;
+                }
+                se = getservbyname(service, proto);
+
+                if (se == NULL) {
+                    BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
+                    ERR_add_error_data(1, hstrerror(h_errno));
+                    goto err;
+                }
+            } else {
+                BIOerr(BIO_F_BIO_LOOKUP, BIO_R_MALFORMED_HOST_OR_SERVICE);
+                goto err;
+            }
+        }
+
+        *res = NULL;
+
+        {
+            char **addrlistp;
+            size_t addresses;
+            BIO_ADDRINFO *tmp_bai = NULL;
+
+            /* The easiest way to create a linked list from an
+               array is to start from the back */
+            for(addrlistp = he->h_addr_list; *addrlistp != NULL;
+                addrlistp++)
+                ;
+
+            for(addresses = addrlistp - he->h_addr_list;
+                addrlistp--, addresses-- > 0; ) {
+                if (!addrinfo_wrap(he->h_addrtype, socktype,
+                                   *addrlistp, he->h_length,
+                                   se->s_port, &tmp_bai))
+                    goto addrinfo_malloc_err;
+                tmp_bai->bai_next = *res;
+                *res = tmp_bai;
+                continue;
+             addrinfo_malloc_err:
+                BIO_ADDRINFO_free(*res);
+                *res = NULL;
+                BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
+                ret = 0;
+                goto err;
+            }
+
+            ret = 1;
+        }
+     err:
+        CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
+        CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
+    }
+
+    return ret;
+}
diff --git a/crypto/bio/b_dump.c b/crypto/bio/b_dump.c
index 77d8c3d..c586b76 100644
--- a/crypto/bio/b_dump.c
+++ b/crypto/bio/b_dump.c
@@ -60,7 +60,6 @@
  */
 
 #include <stdio.h>
-#include "internal/cryptlib.h"
 #include "bio_lcl.h"
 
 #define TRUNCATE
diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c
index a7a6aab..5a50251 100644
--- a/crypto/bio/b_sock.c
+++ b/crypto/bio/b_sock.c
@@ -58,15 +58,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#define USE_SOCKETS
-#include "internal/cryptlib.h"
-#include <openssl/bio.h>
-#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
-# include <netdb.h>
-# if defined(NETWARE_CLIB)
-#  include <sys/ioctl.h>
+#include "bio_lcl.h"
+#if defined(NETWARE_CLIB)
+# include <sys/ioctl.h>
 NETDB_DEFINE_CONTEXT
-# endif
 #endif
 #ifndef OPENSSL_NO_SOCK
 # include <openssl/dso.h>
diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c
index 308bc3b..e30c96a 100644
--- a/crypto/bio/bio_err.c
+++ b/crypto/bio/bio_err.c
@@ -1,5 +1,6 @@
+/* crypto/bio/bio_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2015 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2016 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
@@ -70,6 +71,7 @@
 
 static ERR_STRING_DATA BIO_str_functs[] = {
     {ERR_FUNC(BIO_F_ACPT_STATE), "acpt_state"},
+    {ERR_FUNC(BIO_F_ADDR_STRINGS), "addr_strings"},
     {ERR_FUNC(BIO_F_BIO_ACCEPT), "BIO_accept"},
     {ERR_FUNC(BIO_F_BIO_BER_GET_HEADER), "BIO_BER_GET_HEADER"},
     {ERR_FUNC(BIO_F_BIO_CALLBACK_CTRL), "BIO_callback_ctrl"},
@@ -79,6 +81,7 @@ static ERR_STRING_DATA BIO_str_functs[] = {
     {ERR_FUNC(BIO_F_BIO_GET_ACCEPT_SOCKET), "BIO_get_accept_socket"},
     {ERR_FUNC(BIO_F_BIO_GET_HOST_IP), "BIO_get_host_ip"},
     {ERR_FUNC(BIO_F_BIO_GET_PORT), "BIO_get_port"},
+    {ERR_FUNC(BIO_F_BIO_LOOKUP), "BIO_lookup"},
     {ERR_FUNC(BIO_F_BIO_MAKE_PAIR), "bio_make_pair"},
     {ERR_FUNC(BIO_F_BIO_NEW), "BIO_new"},
     {ERR_FUNC(BIO_F_BIO_NEW_FILE), "BIO_new_file"},
@@ -87,6 +90,7 @@ static ERR_STRING_DATA BIO_str_functs[] = {
     {ERR_FUNC(BIO_F_BIO_NREAD0), "BIO_nread0"},
     {ERR_FUNC(BIO_F_BIO_NWRITE), "BIO_nwrite"},
     {ERR_FUNC(BIO_F_BIO_NWRITE0), "BIO_nwrite0"},
+    {ERR_FUNC(BIO_F_BIO_PARSE_HOSTSERV), "BIO_parse_hostserv"},
     {ERR_FUNC(BIO_F_BIO_PUTS), "BIO_puts"},
     {ERR_FUNC(BIO_F_BIO_READ), "BIO_read"},
     {ERR_FUNC(BIO_F_BIO_SOCK_INIT), "BIO_sock_init"},
@@ -108,6 +112,7 @@ static ERR_STRING_DATA BIO_str_functs[] = {
 
 static ERR_STRING_DATA BIO_str_reasons[] = {
     {ERR_REASON(BIO_R_ACCEPT_ERROR), "accept error"},
+    {ERR_REASON(BIO_R_AMBIGUOUS_HOST_OR_SERVICE), "ambiguous host or service"},
     {ERR_REASON(BIO_R_BAD_FOPEN_MODE), "bad fopen mode"},
     {ERR_REASON(BIO_R_BAD_HOSTNAME_LOOKUP), "bad hostname lookup"},
     {ERR_REASON(BIO_R_BROKEN_PIPE), "broken pipe"},
@@ -124,6 +129,7 @@ static ERR_STRING_DATA BIO_str_reasons[] = {
     {ERR_REASON(BIO_R_INVALID_IP_ADDRESS), "invalid ip address"},
     {ERR_REASON(BIO_R_IN_USE), "in use"},
     {ERR_REASON(BIO_R_KEEPALIVE), "keepalive"},
+    {ERR_REASON(BIO_R_MALFORMED_HOST_OR_SERVICE), "malformed host or service"},
     {ERR_REASON(BIO_R_NBIO_CONNECT_ERROR), "nbio connect error"},
     {ERR_REASON(BIO_R_NO_ACCEPT_PORT_SPECIFIED), "no accept port specified"},
     {ERR_REASON(BIO_R_NO_HOSTNAME_SPECIFIED), "no hostname specified"},
@@ -137,6 +143,8 @@ static ERR_STRING_DATA BIO_str_reasons[] = {
     {ERR_REASON(BIO_R_UNABLE_TO_LISTEN_SOCKET), "unable to listen socket"},
     {ERR_REASON(BIO_R_UNINITIALIZED), "uninitialized"},
     {ERR_REASON(BIO_R_UNSUPPORTED_METHOD), "unsupported method"},
+    {ERR_REASON(BIO_R_UNSUPPORTED_PROTOCOL_FAMILY),
+     "unsupported protocol family"},
     {ERR_REASON(BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"},
     {ERR_REASON(BIO_R_WSASTARTUP), "WSAStartup"},
     {0, NULL}
diff --git a/crypto/bio/bio_lcl.h b/crypto/bio/bio_lcl.h
index 741884d..19bfe53 100644
--- a/crypto/bio/bio_lcl.h
+++ b/crypto/bio/bio_lcl.h
@@ -1,5 +1,81 @@
+#define USE_SOCKETS
+#include "e_os.h"
+
+/* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */
+
+#ifndef OPENSSL_NO_SOCK
+/*
+ * Throughout this file and b_addr.c, the existence of the macro
+ * AI_PASSIVE is used to detect the availability of struct addrinfo,
+ * getnameinfo() and getaddrinfo().  If that macro doesn't exist,
+ * we use our own implementation instead.
+ */
+
+/*
+ * It's imperative that these macros get defined before openssl/bio.h gets
+ * included.  Otherwise, the AI_PASSIVE hack will not work properly.
+ * For clarity, we check for internal/cryptlib.h since it's a common header
+ * that also includes bio.h.
+ */
+# ifdef HEADER_CRYPTLIB_H
+#  error internal/cryptlib.h included before bio_lcl.h
+# endif
+# ifdef HEADER_BIO_H
+#  error openssl/bio.h included before bio_lcl.h
+# endif
+
+/*
+ * Undefine AF_UNIX on systems that define it but don't support it.
+ */
+# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VMS)
+#  undef AF_UNIX
+# endif
+
+# ifdef AI_PASSIVE
+#  define bio_addrinfo_st addrinfo
+#  define bai_family      ai_family
+#  define bai_socktype    ai_socktype
+#  define bai_protocol    ai_protocol
+#  define bai_addrlen     ai_addrlen
+#  define bai_addr        ai_addr
+#  define bai_next        ai_next
+# else
+struct bio_addrinfo_st {
+    int bai_family;
+    int bai_socktype;
+    int bai_protocol;
+    size_t bai_addrlen;
+    struct sockaddr *bai_addr;
+    struct bio_addrinfo_st *bai_next;
+};
+# endif
+
+union bio_addr_st {
+    struct sockaddr sa;
+# ifdef AF_INET6
+    struct sockaddr_in6 sin6;
+# endif
+    struct sockaddr_in sin;
+# ifdef AF_UNIX
+    struct sockaddr_un sun;
+# endif
+};
+#endif
+
+/* END BIO_ADDRINFO/BIO_ADDR stuff. */
+
+#include "internal/cryptlib.h"
 #include <openssl/bio.h>
 
+#ifndef OPENSSL_NO_SOCK
+int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa);
+const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap);
+struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap);
+socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap);
+socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai);
+const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai);
+#endif
+
 #if BIO_FLAGS_UPLINK==0
 /* Shortcut UPLINK calls on most platforms... */
 # define UP_stdin        stdin
@@ -33,4 +109,6 @@
 #  define UP_lseek        lseek
 #  define UP_close        close
 # endif
+
 #endif
+
diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c
index 12306c2..d00c5ce 100644
--- a/crypto/bio/bss_fd.c
+++ b/crypto/bio/bss_fd.c
@@ -57,8 +57,8 @@
 
 #include <stdio.h>
 #include <errno.h>
-#define USE_SOCKETS
-#include "internal/cryptlib.h"
+
+#include "bio_lcl.h"
 
 #if defined(OPENSSL_NO_POSIX_IO)
 /*
@@ -96,8 +96,6 @@ BIO_METHOD *BIO_s_fd(void)
  * file descriptors can only be provided by application. Therefore
  * "UPLINK" calls are due...
  */
-# include "bio_lcl.h"
-
 static int fd_write(BIO *h, const char *buf, int num);
 static int fd_read(BIO *h, char *buf, int size);
 static int fd_puts(BIO *h, const char *str);
diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c
index 1e3f463..334eca0 100644
--- a/crypto/bio/bss_file.c
+++ b/crypto/bio/bss_file.c
@@ -84,7 +84,6 @@
 
 # include <stdio.h>
 # include <errno.h>
-# include "internal/cryptlib.h"
 # include "bio_lcl.h"
 # include <openssl/err.h>
 
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 2b2ecf4..13757c2 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -173,6 +173,8 @@ static ERR_STRING_DATA ERR_str_functs[] = {
 # endif
     {ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"},
     {ERR_PACK(0, SYS_F_FREAD, 0), "fread"},
+    {ERR_PACK(0, SYS_F_GETADDRINFO, 0), "getaddrinfo"},
+    {ERR_PACK(0, SYS_F_GETNAMEINFO, 0), "getnameinfo"},
     {0, NULL},
 };
 
diff --git a/doc/crypto/BIO_ADDR.pod b/doc/crypto/BIO_ADDR.pod
new file mode 100644
index 0000000..cec7ddd
--- /dev/null
+++ b/doc/crypto/BIO_ADDR.pod
@@ -0,0 +1,109 @@
+=pod
+
+=head1 NAME
+
+BIO_ADDR, BIO_ADDR_new, BIO_ADDR_free, BIO_ADDR_rawmake,
+BIO_ADDR_family, BIO_ADDR_rawaddress, BIO_ADDR_rawport,
+BIO_ADDR_hostname_string, BIO_ADDR_service_string,
+BIO_ADDR_path_string - BIO_ADDR routines
+
+=head1 SYNOPSIS
+
+ #include <sys/types.h>
+ #include <openssl/bio.h>
+
+ typedef union bio_addr_st BIO_ADDR;
+
+ BIO_ADDR *BIO_ADDR_new(void);
+ void BIO_ADDR_free(BIO_ADDR *);
+ int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
+                      const void *where, size_t wherelen, unsigned short port);
+ int BIO_ADDR_family(const BIO_ADDR *ap);
+ int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l);
+ unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap);
+ char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric);
+ char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric);
+ char *BIO_ADDR_path_string(const BIO_ADDR *ap);
+
+=head1 DESCRIPTION
+
+The B<BIO_ADDR> type is a wrapper around all types of socket
+addresses that OpenSSL deals with, currently transparently
+supporting AF_INET, AF_INET6 and AF_UNIX according to what's
+available on the platform at hand.
+
+BIO_ADDR_new() creates a new unfilled B<BIO_ADDR>, to be used
+with routines that will fill it with information, such as
+BIO_accept_ex().
+
+BIO_ADDR_free() frees a B<BIO_ADDR> created with BIO_ADDR_new().
+
+BIO_ADDR_rawmake() takes a protocol B<family>, an byte array of
+size B<wherelen> with an address in network byte order pointed at
+by B<where> and a port number in network byte order in B<port> (except
+for the B<AF_UNIX> protocol family, where B<port> is meaningless and
+therefore ignored) and populates the given B<BIO_ADDR> with them.
+In case this creates a B<AF_UNIX> B<BIO_ADDR>, B<wherelen> is expected
+to be the length of the path string (not including the terminating
+NUL, such as the result of a call to strlen()).
+I<Read on about the addresses in L</RAW ADDRESSES> below>.
+
+BIO_ADDR_family() returns the protocol family of the given
+B<BIO_ADDR>.  The possible non-error results are one of the
+constants AF_INET, AF_INET6 and AF_UNIX.
+
+BIO_ADDR_rawaddress() will write the raw address of the given
+B<BIO_ADDR> in the area pointed at by B<p> if B<p> is non-NULL,
+and will set B<*l> to be the amount of bytes the raw address
+takes up if B<l> is non-NULL.
+A technique to only find out the size of the address is a call
+with B<p> set to B<NULL>.  The raw address will be in network byte
+order, most significant byte first.
+In case this is a B<AF_UNIX> B<BIO_ADDR>, B<l> gets the length of the
+path string (not including the terminating NUL, such as the result of
+a call to strlen()).
+I<Read on about the addresses in L</RAW ADDRESSES> below>.
+
+BIO_ADDR_rawport() returns the raw port of the given B<BIO_ADDR>.
+The raw port will be in network byte order.
+
+BIO_ADDR_hostname_string() returns a character string with the
+hostname of the given B<BIO_ADDR>.  If B<numeric> is 1, the string
+will contain the numerical form of the address.  This only works for
+B<BIO_ADDR> of the protocol families AF_INET and AF_INET6.  The
+returned string has been allocated on the heap and must be freed
+with OPENSSL_free().
+
+BIO_ADDR_service_string() returns a character string with the
+service name of the port of the given B<BIO_ADDR>.  If B<numeric>
+is 1, the string will contain the port number.  This only works
+for B<BIO_ADDR> of the protocol families AF_INET and AF_INET6.  The
+returned string has been allocated on the heap and must be freed
+with OPENSSL_free().
+
+BIO_ADDR_path_string() returns a character string with the path
+of the given B<BIO_ADDR>.  This only works for B<BIO_ADDR> of the
+protocol family AF_UNIX.  The returned string has been allocated
+on the heap and must be freed with OPENSSL_free().
+
+=head1 RAW ADDRESSES
+
+Both BIO_ADDR_rawmake() and BIO_ADDR_rawaddress() take a pointer to a
+network byte order address of a specific site.  Internally, those are
+treated as a pointer to B<struct in_addr> (for B<AF_INET>), B<struct
+in6_addr> (for B<AF_INET6>) or B<char *> (for B<AF_UNIX>), all
+depending on the protocol family the address is for.
+
+=head1 RETURN VALUES
+
+The string producing functions BIO_ADDR_hostname_string(),
+BIO_ADDR_service_string() and BIO_ADDR_path_string() will
+return B<NULL> on error and leave an error indication on the
+OpenSSL error stack.
+
+All other functions described here return 0 or B<NULL> when the
+information they should return isn't available.
+
+=head1 SEE ALSO
+
+L<BIO_connect(3)>, L<BIO_s_connect(3)>
diff --git a/doc/crypto/BIO_ADDRINFO.pod b/doc/crypto/BIO_ADDRINFO.pod
new file mode 100644
index 0000000..85652ad
--- /dev/null
+++ b/doc/crypto/BIO_ADDRINFO.pod
@@ -0,0 +1,82 @@
+=pod
+
+=head1 NAME
+
+BIO_ADDRINFO, BIO_ADDRINFO_lookup, BIO_ADDRINFO_next, BIO_ADDRINFO_free,
+BIO_ADDRINFO_family, BIO_ADDRINFO_socktype, BIO_ADDRINFO_protocol,
+BIO_ADDRINFO_sockaddr, BIO_ADDRINFO_sockaddr_size, BIO_ADDRINFO_address
+- BIO_ADDRINFO type and routines
+
+=head1 SYNOPSIS
+
+ #include <sys/types.h>
+ #include <openssl/bio.h>
+
+ typedef union bio_addrinfo_st BIO_ADDRINFO;
+
+ enum BIO_lookup_type {
+     BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER
+ };
+ int BIO_lookup(const char *node, const char *service,
+                enum BIO_lookup_type lookup_type,
+                int family, int socktype, BIO_ADDRINFO **res);
+
+ const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai);
+ int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai);
+ int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai);
+ int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai);
+ const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai);
+ void BIO_ADDRINFO_free(BIO_ADDRINFO *bai);
+
+=head1 DESCRIPTION
+
+The B<BIO_ADDRINFO> type is a wrapper for address information
+types provided on your platform.
+
+B<BIO_ADDRINFO> normally forms a chain of several that can be
+picked at one by one.
+
+BIO_lookup() looks up a specified B<host> and B<service>, and
+uses B<lookup_type> to determine what the default address should
+be if B<host> is B<NULL>.  B<family>, B<socktype> are used to
+determine what protocol family and protocol should be used for
+the lookup.  B<family> can be any of AF_INET, AF_INET6, AF_UNIX and
+AF_UNSPEC, and B<socktype> can be SOCK_STREAM or SOCK_DGRAM.
+B<res> points at a pointer to hold the start of a B<BIO_ADDRINFO>
+chain.
+For the family B<AF_UNIX>, BIO_lookup() will ignore the B<service>
+parameter and expects the B<node> parameter to hold the path to the
+socket file.
+
+BIO_ADDRINFO_family() returns the family of the given
+B<BIO_ADDRINFO>.  The result will be one of the constants
+AF_INET, AF_INET6 and AF_UNIX.
+
+BIO_ADDRINFO_socktype() returns the socket type of the given
+B<BIO_ADDRINFO>.  The result will be one of the constants
+SOCK_STREAM and SOCK_DGRAM.
+
+BIO_ADDRINFO_protocol() returns the protocol id of the given
+B<BIO_ADDRINFO>.  The result will be one of the constants
+IPPROTO_TCP and IPPROTO_UDP.
+
+BIO_ADDRINFO_address() returns the underlying B<BIO_ADDR>
+of the given B<BIO_ADDRINFO>.
+
+BIO_ADDRINFO_next() returns the next B<BIO_ADDRINFO> in the chain
+from the given one.
+
+BIO_ADDRINFO_free() frees the chain of B<BIO_ADDRINFO> starting
+with the given one.
+
+=head1 RETURN VALUES
+
+BIO_lookup() returns 1 on success and 0 when an error occured, and
+will leave an error indicaton on the OpenSSL error stack in that case.
+
+All other functions described here return 0 or B<NULL> when the
+information they should return isn't available.
+
+=head1 SEE ALSO
+
+L<BIO_lookup(3)>
diff --git a/doc/crypto/BIO_parse_hostserv.pod b/doc/crypto/BIO_parse_hostserv.pod
new file mode 100644
index 0000000..0c9cfbe
--- /dev/null
+++ b/doc/crypto/BIO_parse_hostserv.pod
@@ -0,0 +1,62 @@
+=pod
+
+=head1 NAME
+
+BIO_parse_hostserv - utility routines to parse a standard host and service
+string
+
+=head1 SYNOPSIS
+
+ #include <openssl/bio.h>
+
+ enum BIO_hostserv_priorities {
+     BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV
+ };
+ int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
+                        enum BIO_hostserv_priorities hostserv_prio);
+
+=head1 DESCRIPTION
+
+BIO_parse_hostserv() will parse the information given in B<hostserv>,
+create strings with the host name and service name and give those
+back via B<host> and B<service>.  Those will need to be freed after
+they are used.  B<hostserv_prio> helps determine if B<hostserv> shall
+be interpreted primarly as a host name or a service name in ambiguous
+cases.
+
+The syntax the BIO_parse_hostserv() recognises is:
+
+ host + ':' + service
+ host + ':' + '*'
+ host + ':'
+        ':' + service
+ '*'  + ':' + service
+ host
+ service
+
+The host part can be a name or an IP address.  If it's a IPv6
+address, it MUST be enclosed in brackets, such as '[::1]'.
+
+The service part can  be a service name or its port number.
+
+The returned values will depend on the given B<hostserv> string
+and B<hostserv_prio>, as follows:
+
+ host + ':' + service  => *host = "host", *service = "service"
+ host + ':' + '*'      => *host = "host", *service = NULL
+ host + ':'            => *host = "host", *service = NULL
+        ':' + service  => *host = NULL, *service = "service"
+  '*' + ':' + service  => *host = NULL, *service = "service"
+ 
+ in case no ':' is present in the string, the result depends on
+ hostserv_prio, as follows:
+ 
+ when hostserv_prio == BIO_PARSE_PRIO_HOST
+ host                 => *host = "host", *service untouched
+ 
+ when hostserv_prio == BIO_PARSE_PRIO_SERV
+ service              => *host untouched, *service = "service"
+
+=head1 SEE ALSO
+
+L<BIO_ADDRINFO(3)>
diff --git a/e_os.h b/e_os.h
index 9b9bb4f..4456b7e 100644
--- a/e_os.h
+++ b/e_os.h
@@ -497,6 +497,7 @@ struct servent *PASCAL getservbyname(const char *, const char *);
           * configured for BSD
           */
 #   if defined(NETWARE_BSDSOCK)
+#    include <netdb.h>
 #    include <sys/socket.h>
 #    include <netinet/in.h>
 #    include <sys/time.h>
@@ -545,6 +546,7 @@ struct servent *PASCAL getservbyname(const char *, const char *);
 #    endif
 #    include <netinet/in.h>
 #    include <arpa/inet.h>
+#    include <netinet/tcp.h>
 #   endif
 
 #   ifdef OPENSSL_SYS_AIX
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index 9b398ee..82d4845 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -221,6 +221,9 @@ extern "C" {
  */
 # define BIO_FLAGS_MEM_RDONLY    0x200
 
+typedef union bio_addr_st BIO_ADDR;
+typedef struct bio_addrinfo_st BIO_ADDRINFO;
+
 void BIO_set_flags(BIO *b, int flags);
 int BIO_test_flags(const BIO *b, int flags);
 void BIO_clear_flags(BIO *b, int flags);
@@ -699,6 +702,35 @@ int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
 int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
                    int datalen);
 
+BIO_ADDR *BIO_ADDR_new(void);
+int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
+                     const void *where, size_t wherelen, unsigned short port);
+void BIO_ADDR_free(BIO_ADDR *);
+int BIO_ADDR_family(const BIO_ADDR *ap);
+int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l);
+unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap);
+char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric);
+char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric);
+char *BIO_ADDR_path_string(const BIO_ADDR *ap);
+
+const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai);
+int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai);
+int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai);
+int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai);
+const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai);
+void BIO_ADDRINFO_free(BIO_ADDRINFO *bai);
+
+enum BIO_hostserv_priorities {
+    BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV
+};
+int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
+                       enum BIO_hostserv_priorities hostserv_prio);
+enum BIO_lookup_type {
+    BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER
+};
+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:
@@ -778,6 +810,7 @@ void ERR_load_BIO_strings(void);
 
 /* Function codes. */
 # define BIO_F_ACPT_STATE                                 100
+# define BIO_F_ADDR_STRINGS                               134
 # define BIO_F_BIO_ACCEPT                                 101
 # define BIO_F_BIO_BER_GET_HEADER                         102
 # define BIO_F_BIO_CALLBACK_CTRL                          131
@@ -787,6 +820,7 @@ void ERR_load_BIO_strings(void);
 # define BIO_F_BIO_GET_ACCEPT_SOCKET                      105
 # define BIO_F_BIO_GET_HOST_IP                            106
 # define BIO_F_BIO_GET_PORT                               107
+# define BIO_F_BIO_LOOKUP                                 135
 # define BIO_F_BIO_MAKE_PAIR                              121
 # define BIO_F_BIO_NEW                                    108
 # define BIO_F_BIO_NEW_FILE                               109
@@ -795,6 +829,7 @@ void ERR_load_BIO_strings(void);
 # define BIO_F_BIO_NREAD0                                 124
 # define BIO_F_BIO_NWRITE                                 125
 # define BIO_F_BIO_NWRITE0                                122
+# define BIO_F_BIO_PARSE_HOSTSERV                         136
 # define BIO_F_BIO_PUTS                                   110
 # define BIO_F_BIO_READ                                   111
 # define BIO_F_BIO_SOCK_INIT                              112
@@ -814,6 +849,7 @@ void ERR_load_BIO_strings(void);
 
 /* Reason codes. */
 # define BIO_R_ACCEPT_ERROR                               100
+# define BIO_R_AMBIGUOUS_HOST_OR_SERVICE                  129
 # define BIO_R_BAD_FOPEN_MODE                             101
 # define BIO_R_BAD_HOSTNAME_LOOKUP                        102
 # define BIO_R_BROKEN_PIPE                                124
@@ -827,6 +863,7 @@ void ERR_load_BIO_strings(void);
 # define BIO_R_INVALID_IP_ADDRESS                         108
 # define BIO_R_IN_USE                                     123
 # define BIO_R_KEEPALIVE                                  109
+# define BIO_R_MALFORMED_HOST_OR_SERVICE                  130
 # define BIO_R_NBIO_CONNECT_ERROR                         110
 # define BIO_R_NO_ACCEPT_PORT_SPECIFIED                   111
 # define BIO_R_NO_HOSTNAME_SPECIFIED                      112
@@ -840,6 +877,7 @@ void ERR_load_BIO_strings(void);
 # define BIO_R_UNABLE_TO_LISTEN_SOCKET                    119
 # define BIO_R_UNINITIALIZED                              120
 # define BIO_R_UNSUPPORTED_METHOD                         121
+# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY                131
 # define BIO_R_WRITE_TO_READ_ONLY_BIO                     126
 # define BIO_R_WSASTARTUP                                 122
 
diff --git a/include/openssl/err.h b/include/openssl/err.h
index dd6f125..0214e68 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -257,6 +257,8 @@ typedef struct err_state_st {
 # define SYS_F_WSASTARTUP        9/* Winsock stuff */
 # define SYS_F_OPENDIR           10
 # define SYS_F_FREAD             11
+# define SYS_F_GETADDRINFO       12
+# define SYS_F_GETNAMEINFO       13
 
 /* reasons */
 # define ERR_R_SYS_LIB   ERR_LIB_SYS/* 2 */
diff --git a/util/libeay.num b/util/libeay.num
index f8ecea8..e2e0564 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -4772,3 +4772,20 @@ EC_GROUP_get0_cofactor                  5166	1_1_0	EXIST::FUNCTION:EC
 BN_bn2lebinpad                          5167	1_1_0	EXIST::FUNCTION:
 BN_lebin2bn                             5168	1_1_0	EXIST::FUNCTION:
 BN_bn2binpad                            5169	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_service_string                 5170	1_1_0	EXIST::FUNCTION:
+BIO_ADDRINFO_family                     5171	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_family                         5172	1_1_0	EXIST::FUNCTION:
+BIO_lookup                              5173	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_path_string                    5174	1_1_0	EXIST::FUNCTION:
+BIO_ADDRINFO_protocol                   5175	1_1_0	EXIST::FUNCTION:
+BIO_ADDRINFO_socktype                   5176	1_1_0	EXIST::FUNCTION:
+BIO_ADDRINFO_next                       5177	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_rawaddress                     5178	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_hostname_string                5179	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_free                           5180	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_rawport                        5181	1_1_0	EXIST::FUNCTION:
+BIO_ADDRINFO_address                    5182	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_new                            5183	1_1_0	EXIST::FUNCTION:
+BIO_ADDR_rawmake                        5184	1_1_0	EXIST::FUNCTION:
+BIO_ADDRINFO_free                       5185	1_1_0	EXIST::FUNCTION:
+BIO_parse_hostserv                      5186	1_1_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list