From b0bb7bdb499367a5aebde7183e6e5d188280545a Mon Sep 17 00:00:00 2001 From: Heimdal Developers Date: Wed, 4 Jun 2014 16:04:19 -0400 Subject: [PATCH] Import of code from heimdal This commit updates the code imported from heimdal to 5dfaa0d10b8320293e85387778adcdd043dfc1fe (git2svn-syncpoint-master-311-g5dfaa0d) New files are: roken/freeaddrinfo.c roken/gai_strerror.c roken/getaddinfo.c roken/getnameinfo.c Change-Id: I4a80dfd0d95cfd252af5ce3228fb824b4aacb961 Reviewed-on: http://gerrit.openafs.org/11198 Tested-by: BuildBot Reviewed-by: D Brashear --- src/external/heimdal/roken/freeaddrinfo.c | 54 ++++ src/external/heimdal/roken/gai_strerror.c | 74 ++++++ src/external/heimdal/roken/getaddinfo.c | 414 ++++++++++++++++++++++++++++++ src/external/heimdal/roken/getnameinfo.c | 124 +++++++++ 4 files changed, 666 insertions(+) create mode 100644 src/external/heimdal/roken/freeaddrinfo.c create mode 100644 src/external/heimdal/roken/gai_strerror.c create mode 100644 src/external/heimdal/roken/getaddinfo.c create mode 100644 src/external/heimdal/roken/getnameinfo.c diff --git a/src/external/heimdal/roken/freeaddrinfo.c b/src/external/heimdal/roken/freeaddrinfo.c new file mode 100644 index 0000000..7132e95 --- /dev/null +++ b/src/external/heimdal/roken/freeaddrinfo.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS 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 INSTITUTE OR 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. + */ + +#include + +#include "roken.h" + +/* + * free the list of `struct addrinfo' starting at `ai' + */ + +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *tofree; + + while(ai != NULL) { + free (ai->ai_canonname); + free (ai->ai_addr); + tofree = ai; + ai = ai->ai_next; + free (tofree); + } +} diff --git a/src/external/heimdal/roken/gai_strerror.c b/src/external/heimdal/roken/gai_strerror.c new file mode 100644 index 0000000..1e326be --- /dev/null +++ b/src/external/heimdal/roken/gai_strerror.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS 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 INSTITUTE OR 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. + */ + +#include + +#include "roken.h" + +static struct gai_error { + int code; + const char *str; +} errors[] = { +{EAI_NOERROR, "no error"}, +#ifdef EAI_ADDRFAMILY +{EAI_ADDRFAMILY, "address family for nodename not supported"}, +#endif +{EAI_AGAIN, "temporary failure in name resolution"}, +{EAI_BADFLAGS, "invalid value for ai_flags"}, +{EAI_FAIL, "non-recoverable failure in name resolution"}, +{EAI_FAMILY, "ai_family not supported"}, +{EAI_MEMORY, "memory allocation failure"}, +#ifdef EAI_NODATA +{EAI_NODATA, "no address associated with nodename"}, +#endif +{EAI_NONAME, "nodename nor servname provided, or not known"}, +{EAI_SERVICE, "servname not supported for ai_socktype"}, +{EAI_SOCKTYPE, "ai_socktype not supported"}, +{EAI_SYSTEM, "system error returned in errno"}, +{0, NULL}, +}; + +/* + * + */ + +ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL +gai_strerror(int ecode) +{ + struct gai_error *g; + + for (g = errors; g->str != NULL; ++g) + if (g->code == ecode) + return g->str; + return "unknown error code in gai_strerror"; +} diff --git a/src/external/heimdal/roken/getaddinfo.c b/src/external/heimdal/roken/getaddinfo.c new file mode 100644 index 0000000..c8ed954 --- /dev/null +++ b/src/external/heimdal/roken/getaddinfo.c @@ -0,0 +1,414 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS 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 INSTITUTE OR 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. + */ + +#include + +#include "roken.h" + +/* + * uses hints->ai_socktype and hints->ai_protocol + */ + +static int +get_port_protocol_socktype (const char *servname, + const struct addrinfo *hints, + int *port, + int *protocol, + int *socktype) +{ + struct servent *se; + const char *proto_str = NULL; + + *socktype = 0; + + if (hints != NULL && hints->ai_protocol != 0) { + struct protoent *protoent = getprotobynumber (hints->ai_protocol); + + if (protoent == NULL) + return EAI_SOCKTYPE; /* XXX */ + + proto_str = protoent->p_name; + *protocol = protoent->p_proto; + } + + if (hints != NULL) + *socktype = hints->ai_socktype; + + if (*socktype == SOCK_STREAM) { + se = getservbyname (servname, proto_str ? proto_str : "tcp"); + if (proto_str == NULL) + *protocol = IPPROTO_TCP; + } else if (*socktype == SOCK_DGRAM) { + se = getservbyname (servname, proto_str ? proto_str : "udp"); + if (proto_str == NULL) + *protocol = IPPROTO_UDP; + } else if (*socktype == 0) { + if (proto_str != NULL) { + se = getservbyname (servname, proto_str); + } else { + se = getservbyname (servname, "tcp"); + *protocol = IPPROTO_TCP; + *socktype = SOCK_STREAM; + if (se == NULL) { + se = getservbyname (servname, "udp"); + *protocol = IPPROTO_UDP; + *socktype = SOCK_DGRAM; + } + } + } else + return EAI_SOCKTYPE; + + if (se == NULL) { + char *endstr; + + *port = htons(strtol (servname, &endstr, 10)); + if (servname == endstr) + return EAI_NONAME; + } else { + *port = se->s_port; + } + return 0; +} + +static int +add_one (int port, int protocol, int socktype, + struct addrinfo ***ptr, + int (*func)(struct addrinfo *, void *data, int port), + void *data, + char *canonname) +{ + struct addrinfo *a; + int ret; + + a = malloc (sizeof (*a)); + if (a == NULL) + return EAI_MEMORY; + memset (a, 0, sizeof(*a)); + a->ai_flags = 0; + a->ai_next = NULL; + a->ai_protocol = protocol; + a->ai_socktype = socktype; + a->ai_canonname = canonname; + ret = (*func)(a, data, port); + if (ret) { + free (a); + return ret; + } + **ptr = a; + *ptr = &a->ai_next; + return 0; +} + +static int +const_v4 (struct addrinfo *a, void *data, int port) +{ + struct sockaddr_in *sin4; + struct in_addr *addr = (struct in_addr *)data; + + a->ai_family = PF_INET; + a->ai_addrlen = sizeof(*sin4); + a->ai_addr = malloc (sizeof(*sin4)); + if (a->ai_addr == NULL) + return EAI_MEMORY; + sin4 = (struct sockaddr_in *)a->ai_addr; + memset (sin4, 0, sizeof(*sin4)); + sin4->sin_family = AF_INET; + sin4->sin_port = port; + sin4->sin_addr = *addr; + return 0; +} + +#ifdef HAVE_IPV6 +static int +const_v6 (struct addrinfo *a, void *data, int port) +{ + struct sockaddr_in6 *sin6; + struct in6_addr *addr = (struct in6_addr *)data; + + a->ai_family = PF_INET6; + a->ai_addrlen = sizeof(*sin6); + a->ai_addr = malloc (sizeof(*sin6)); + if (a->ai_addr == NULL) + return EAI_MEMORY; + sin6 = (struct sockaddr_in6 *)a->ai_addr; + memset (sin6, 0, sizeof(*sin6)); + sin6->sin6_family = AF_INET6; + sin6->sin6_port = port; + sin6->sin6_addr = *addr; + return 0; +} +#endif + +/* this is mostly a hack for some versions of AIX that has a prototype + for in6addr_loopback but no actual symbol in libc */ +#if defined(HAVE_IPV6) && !defined(HAVE_IN6ADDR_LOOPBACK) && defined(IN6ADDR_LOOPBACK_INIT) +#define in6addr_loopback _roken_in6addr_loopback +struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; +#endif + +static int +get_null (const struct addrinfo *hints, + int port, int protocol, int socktype, + struct addrinfo **res) +{ + struct in_addr v4_addr; +#ifdef HAVE_IPV6 + struct in6_addr v6_addr; +#endif + struct addrinfo *first = NULL; + struct addrinfo **current = &first; + int family = PF_UNSPEC; + int ret; + + if (hints != NULL) + family = hints->ai_family; + + if (hints && hints->ai_flags & AI_PASSIVE) { + v4_addr.s_addr = INADDR_ANY; +#ifdef HAVE_IPV6 + v6_addr = in6addr_any; +#endif + } else { + v4_addr.s_addr = htonl(INADDR_LOOPBACK); +#ifdef HAVE_IPV6 + v6_addr = in6addr_loopback; +#endif + } + +#ifdef HAVE_IPV6 + if (family == PF_INET6 || family == PF_UNSPEC) { + ret = add_one (port, protocol, socktype, + ¤t, const_v6, &v6_addr, NULL); + } +#endif + if (family == PF_INET || family == PF_UNSPEC) { + ret = add_one (port, protocol, socktype, + ¤t, const_v4, &v4_addr, NULL); + } + *res = first; + return 0; +} + +static int +add_hostent (int port, int protocol, int socktype, + struct addrinfo ***current, + int (*func)(struct addrinfo *, void *data, int port), + struct hostent *he, int *flags) +{ + int ret; + char *canonname = NULL; + char **h; + + if (*flags & AI_CANONNAME) { + struct hostent *he2 = NULL; + const char *tmp_canon; + + tmp_canon = hostent_find_fqdn (he); + if (strchr (tmp_canon, '.') == NULL) { + int error; + + he2 = getipnodebyaddr (he->h_addr_list[0], he->h_length, + he->h_addrtype, &error); + if (he2 != NULL) { + const char *tmp = hostent_find_fqdn (he2); + + if (strchr (tmp, '.') != NULL) + tmp_canon = tmp; + } + } + + canonname = strdup (tmp_canon); + if (he2 != NULL) + freehostent (he2); + if (canonname == NULL) + return EAI_MEMORY; + } + + for (h = he->h_addr_list; *h != NULL; ++h) { + ret = add_one (port, protocol, socktype, + current, func, *h, canonname); + if (ret) + return ret; + if (*flags & AI_CANONNAME) { + *flags &= ~AI_CANONNAME; + canonname = NULL; + } + } + return 0; +} + +static int +get_number (const char *nodename, + const struct addrinfo *hints, + int port, int protocol, int socktype, + struct addrinfo **res) +{ + struct addrinfo *first = NULL; + struct addrinfo **current = &first; + int family = PF_UNSPEC; + int ret; + + if (hints != NULL) { + family = hints->ai_family; + } + +#ifdef HAVE_IPV6 + if (family == PF_INET6 || family == PF_UNSPEC) { + struct in6_addr v6_addr; + + if (inet_pton (PF_INET6, nodename, &v6_addr) == 1) { + ret = add_one (port, protocol, socktype, + ¤t, const_v6, &v6_addr, NULL); + *res = first; + return ret; + } + } +#endif + if (family == PF_INET || family == PF_UNSPEC) { + struct in_addr v4_addr; + + if (inet_pton (PF_INET, nodename, &v4_addr) == 1) { + ret = add_one (port, protocol, socktype, + ¤t, const_v4, &v4_addr, NULL); + *res = first; + return ret; + } + } + return EAI_NONAME; +} + +static int +get_nodes (const char *nodename, + const struct addrinfo *hints, + int port, int protocol, int socktype, + struct addrinfo **res) +{ + struct addrinfo *first = NULL; + struct addrinfo **current = &first; + int family = PF_UNSPEC; + int flags = 0; + int ret = EAI_NONAME; + int error; + + if (hints != NULL) { + family = hints->ai_family; + flags = hints->ai_flags; + } + +#ifdef HAVE_IPV6 + if (family == PF_INET6 || family == PF_UNSPEC) { + struct hostent *he; + + he = getipnodebyname (nodename, PF_INET6, 0, &error); + + if (he != NULL) { + ret = add_hostent (port, protocol, socktype, + ¤t, const_v6, he, &flags); + freehostent (he); + } + } +#endif + if (family == PF_INET || family == PF_UNSPEC) { + struct hostent *he; + + he = getipnodebyname (nodename, PF_INET, 0, &error); + + if (he != NULL) { + ret = add_hostent (port, protocol, socktype, + ¤t, const_v4, he, &flags); + freehostent (he); + } + } + *res = first; + return ret; +} + +/* + * hints: + * + * struct addrinfo { + * int ai_flags; + * int ai_family; + * int ai_socktype; + * int ai_protocol; + * ... + * }; + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res) +{ + int ret; + int port = 0; + int protocol = 0; + int socktype = 0; + + *res = NULL; + + if (servname == NULL && nodename == NULL) + return EAI_NONAME; + + if (hints != NULL + && hints->ai_family != PF_UNSPEC + && hints->ai_family != PF_INET +#ifdef HAVE_IPV6 + && hints->ai_family != PF_INET6 +#endif + ) + return EAI_FAMILY; + + if (servname != NULL) { + ret = get_port_protocol_socktype (servname, hints, + &port, &protocol, &socktype); + if (ret) + return ret; + } + if (nodename != NULL) { + ret = get_number (nodename, hints, port, protocol, socktype, res); + if (ret) { + if(hints && hints->ai_flags & AI_NUMERICHOST) + ret = EAI_NONAME; + else + ret = get_nodes (nodename, hints, port, protocol, socktype, + res); + } + } else { + ret = get_null (hints, port, protocol, socktype, res); + } + if (ret) + freeaddrinfo (*res); + return ret; +} diff --git a/src/external/heimdal/roken/getnameinfo.c b/src/external/heimdal/roken/getnameinfo.c new file mode 100644 index 0000000..b23ad01 --- /dev/null +++ b/src/external/heimdal/roken/getnameinfo.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS 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 INSTITUTE OR 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. + */ + +#include + +#include "roken.h" + +static int +doit (int af, + const void *addr, + size_t addrlen, + int port, + char *host, size_t hostlen, + char *serv, size_t servlen, + int flags) +{ + if (host != NULL) { + if (flags & NI_NUMERICHOST) { + if (inet_ntop (af, addr, host, hostlen) == NULL) + return EAI_SYSTEM; + } else { + struct hostent *he = gethostbyaddr (addr, + addrlen, + af); + if (he != NULL) { + strlcpy (host, hostent_find_fqdn(he), hostlen); + if (flags & NI_NOFQDN) { + char *dot = strchr (host, '.'); + if (dot != NULL) + *dot = '\0'; + } + } else if (flags & NI_NAMEREQD) { + return EAI_NONAME; + } else if (inet_ntop (af, addr, host, hostlen) == NULL) + return EAI_SYSTEM; + } + } + + if (serv != NULL) { + if (flags & NI_NUMERICSERV) { + snprintf (serv, servlen, "%u", ntohs(port)); + } else { + const char *proto = "tcp"; + struct servent *se; + + if (flags & NI_DGRAM) + proto = "udp"; + + se = getservbyport (port, proto); + if (se == NULL) { + snprintf (serv, servlen, "%u", ntohs(port)); + } else { + strlcpy (serv, se->s_name, servlen); + } + } + } + return 0; +} + +/* + * + */ + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, + int flags) +{ + switch (sa->sa_family) { +#ifdef HAVE_IPV6 + case AF_INET6 : { + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + + return doit (AF_INET6, &sin6->sin6_addr, sizeof(sin6->sin6_addr), + sin6->sin6_port, + host, hostlen, + serv, servlen, + flags); + } +#endif + case AF_INET : { + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + return doit (AF_INET, &sin4->sin_addr, sizeof(sin4->sin_addr), + sin4->sin_port, + host, hostlen, + serv, servlen, + flags); + } + default : + return EAI_FAMILY; + } +} -- 1.9.4