diff options
Diffstat (limited to 'missing/getaddrinfo.c')
-rw-r--r-- | missing/getaddrinfo.c | 605 |
1 files changed, 0 insertions, 605 deletions
diff --git a/missing/getaddrinfo.c b/missing/getaddrinfo.c deleted file mode 100644 index f6f2916..0000000 --- a/missing/getaddrinfo.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (c) 2001, 02 Motoyuki Kasahara - * - * 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 project 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 PROJECT 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 PROJECT 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. - */ - -/* - * This program provides getaddrinfo() and getnameinfo() described in - * RFC2133, 2553 and 3493. These functions are mainly used for IPv6 - * application to resolve hostname or address. - * - * This program is designed to be working on traditional IPv4 systems - * which don't have those functions. Therefore, this implementation - * supports IPv4 only. - * - * This program is useful for application which should support both IPv6 - * and traditional IPv4 systems. Use genuine getaddrinfo() and getnameinfo() - * provided by system if the system supports IPv6. Otherwise, use this - * implementation. - * - * This program is intended to be used in combination with GNU Autoconf. - * - * This program also provides freeaddrinfo() and gai_strerror(). - * - * To use this program in your application, insert the following lines to - * C source files after including `sys/types.h', `sys/socket.h' and - * `netdb.h'. `getaddrinfo.h' defines `struct addrinfo' and AI_, NI_, - * EAI_ macros. - * - * #ifndef HAVE_GETADDRINFO - * #include "getaddrinfo.h" - * #endif - * - * Restriction: - * getaddrinfo() and getnameinfo() of this program are NOT thread - * safe, unless the cpp macro ENABLE_PTHREAD is defined. - */ - -/* - * Add the following code to your configure.ac (or configure.in). - * AC_C_CONST - * AC_HEADER_STDC - * AC_CHECK_HEADERS(string.h memory.h stdlib.h) - * AC_CHECK_FUNCS(memcpy) - * AC_REPLACE_FUNCS(memset) - * AC_TYPE_SOCKLEN_T - * AC_TYPE_IN_PORT_T - * AC_DECL_H_ERRNO - * - * AC_CHECK_FUNCS(getaddrinfo getnameinfo) - * if test "$ac_cv_func_getaddrinfo$ac_cv_func_getnameinfo" != yesyes ; then - * LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext" - * fi - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <stdio.h> - -#ifdef WIN32 -#include <time.h> -#include <winsock2.h> -#ifdef DO_IPV6 -#include <ws2tcpip.h> -#endif /* DO_IPV6 */ -#include <windows.h> -#else -#include <sys/socket.h> -#endif - - -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> - -#if defined(STDC_HEADERS) || defined(HAVE_STRING_H) -#include <string.h> -#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H) -#include <memory.h> -#endif /* not STDC_HEADERS and HAVE_MEMORY_H */ -#else /* not STDC_HEADERS and not HAVE_STRING_H */ -#include <strings.h> -#endif /* not STDC_HEADERS and not HAVE_STRING_H */ - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#ifdef ENABLE_PTHREAD -#include <pthread.h> -#endif - -#ifdef ENABLE_NLS -#include <libintl.h> -#endif - -#ifndef HAVE_MEMCPY -#define memcpy(d, s, n) bcopy((s), (d), (n)) -#ifdef __STDC__ -void *memchr(const void *, int, size_t); -int memcmp(const void *, const void *, size_t); -void *memmove(void *, const void *, size_t); -void *memset(void *, int, size_t); -#else /* not __STDC__ */ -char *memchr(); -int memcmp(); -char *memmove(); -char *memset(); -#endif /* not __STDC__ */ -#endif /* not HAVE_MEMCPY */ - -#ifndef H_ERRNO_DECLARED -extern int h_errno; -#endif - -#include "getaddrinfo.h" - -#ifdef ENABLE_NLS -#define _(string) gettext(string) -#ifdef gettext_noop -#define N_(string) gettext_noop(string) -#else -#define N_(string) (string) -#endif -#else -#define gettext(string) (string) -#define _(string) (string) -#define N_(string) (string) -#endif - -/* - * Error messages for gai_strerror(). - */ -static char *eai_errlist[] = { - N_("Success"), - - /* EAI_ADDRFAMILY */ - N_("Address family for hostname not supported"), - - /* EAI_AGAIN */ - N_("Temporary failure in name resolution"), - - /* EAI_BADFLAGS */ - N_("Invalid value for ai_flags"), - - /* EAI_FAIL */ - N_("Non-recoverable failure in name resolution"), - - /* EAI_FAMILY */ - N_("ai_family not supported"), - - /* EAI_MEMORY */ - N_("Memory allocation failure"), - - /* EAI_NONAME */ - N_("hostname nor servname provided, or not known"), - - /* EAI_OVERFLOW */ - N_("An argument buffer overflowed"), - - /* EAI_SERVICE */ - N_("servname not supported for ai_socktype"), - - /* EAI_SOCKTYPE */ - N_("ai_socktype not supported"), - - /* EAI_SYSTEM */ - N_("System error returned in errno") -}; - -/* - * Default hints for getaddrinfo(). - */ -static struct addrinfo default_hints = { - 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL -}; - -/* - * Mutex. - */ -#ifdef ENABLE_PTHREAD -static pthread_mutex_t gai_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif - -/* - * Declaration of static functions. - */ -#ifdef __STDC__ -static int is_integer(const char *); -static int is_address(const char *); -static int itoa_length(int); -#else -static int is_integer(); -static int is_address(); -static int itoa_length(); -#endif - -/* - * gai_strerror(). - */ -const char * -gai_strerror(ecode) - int ecode; -{ - if (ecode < 0 || ecode > EAI_SYSTEM) - return _("Unknown error"); - - return gettext(eai_errlist[ecode]); -} - -/* - * freeaddrinfo(). - */ -void -freeaddrinfo(ai) - struct addrinfo *ai; -{ - struct addrinfo *next_ai; - - while (ai != NULL) { - if (ai->ai_canonname != NULL) - free(ai->ai_canonname); - if (ai->ai_addr != NULL) - free(ai->ai_addr); - next_ai = ai->ai_next; - free(ai); - ai = next_ai; - } -} - -/* - * Return 1 if the string `s' represents an integer. - */ -static int -is_integer(s) - const char *s; -{ - if (*s == '-' || *s == '+') - s++; - if (*s < '0' || '9' < *s) - return 0; - - s++; - while ('0' <= *s && *s <= '9') - s++; - - return (*s == '\0'); -} - -/* - * Return 1 if the string `s' represents an IPv4 address. - * Unlike inet_addr(), it doesn't permit malformed nortation such - * as "192.168". - */ -static int -is_address(s) - const char *s; -{ - const static char delimiters[] = {'.', '.', '.', '\0'}; - int i, j; - int octet; - - for (i = 0; i < 4; i++) { - if (*s == '0' && *(s + 1) != delimiters[i]) - return 0; - for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++) - octet = octet * 10 + (*s - '0'); - if (j == 0 || octet > 255 || *s != delimiters[i]) - return 0; - s++; - } - - return 1; -} - -/* - * Calcurate length of the string `s', where `s' is set by - * sprintf(s, "%d", n). - */ -static int -itoa_length(n) - int n; -{ - int result = 1; - - if (n < 0) { - n = -n; - result++; - } - - while (n >= 10) { - result++; - n /= 10; - } - - return result; -} - -/* - * getaddrinfo(). - */ -int -getaddrinfo(nodename, servname, hints, res) - const char *nodename; - const char *servname; - const struct addrinfo *hints; - struct addrinfo **res; -{ - struct addrinfo *head_res = NULL; - struct addrinfo *tail_res = NULL; - struct addrinfo *new_res; - struct sockaddr_in *sa_in; - struct in_addr **addr_list; - struct in_addr *addr_list_buf[2]; - struct in_addr addr_buf; - struct in_addr **ap; - struct servent *servent; - struct hostent *hostent; - const char *canonname = NULL; - in_port_t port; - int saved_h_errno; - int result = 0; - -#ifdef ENABLE_PTHREAD - pthread_mutex_lock(&gai_mutex); -#endif - - saved_h_errno = h_errno; - - if (nodename == NULL && servname == NULL) { - result = EAI_NONAME; - goto end; - } - - if (hints != NULL) { - if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) { - result = EAI_FAMILY; - goto end; - } - if (hints->ai_socktype != SOCK_DGRAM - && hints->ai_socktype != SOCK_STREAM - && hints->ai_socktype != 0) { - result = EAI_SOCKTYPE; - goto end; - } - } else { - hints = &default_hints; - } - - if (servname != NULL) { - if (is_integer(servname)) - port = htons(atoi(servname)); - else { - if (hints->ai_flags & AI_NUMERICSERV) { - result = EAI_NONAME; - goto end; - } - - if (hints->ai_socktype == SOCK_DGRAM) - servent = getservbyname(servname, "udp"); - else if (hints->ai_socktype == SOCK_STREAM) - servent = getservbyname(servname, "tcp"); - else if (hints->ai_socktype == 0) - servent = getservbyname(servname, "tcp"); - else { - result = EAI_SOCKTYPE; - goto end; - } - - if (servent == NULL) { - result = EAI_SERVICE; - goto end; - } - port = servent->s_port; - } - } else { - port = htons(0); - } - - if (nodename != NULL) { - if (is_address(nodename)) { - addr_buf.s_addr = inet_addr(nodename); - addr_list_buf[0] = &addr_buf; - addr_list_buf[1] = NULL; - addr_list = addr_list_buf; - - if (hints->ai_flags & AI_CANONNAME - && !(hints->ai_flags & AI_NUMERICHOST)) { - hostent = gethostbyaddr((char *)&addr_buf, - sizeof(struct in_addr), AF_INET); - if (hostent != NULL) - canonname = hostent->h_name; - else - canonname = nodename; - } - } else { - if (hints->ai_flags & AI_NUMERICHOST) { - result = EAI_NONAME; - goto end; - } - - hostent = gethostbyname(nodename); - if (hostent == NULL) { - switch (h_errno) { - case HOST_NOT_FOUND: - case NO_DATA: - result = EAI_NONAME; - goto end; - case TRY_AGAIN: - result = EAI_AGAIN; - goto end; - default: - result = EAI_FAIL; - goto end; - } - } - addr_list = (struct in_addr **)hostent->h_addr_list; - - if (hints->ai_flags & AI_CANONNAME) - canonname = hostent->h_name; - } - } else { - if (hints->ai_flags & AI_PASSIVE) - addr_buf.s_addr = htonl(INADDR_ANY); - else - addr_buf.s_addr = htonl(0x7F000001); - addr_list_buf[0] = &addr_buf; - addr_list_buf[1] = NULL; - addr_list = addr_list_buf; - } - - for (ap = addr_list; *ap != NULL; ap++) { - new_res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); - if (new_res == NULL) { - if (head_res != NULL) - freeaddrinfo(head_res); - result = EAI_MEMORY; - goto end; - } - - new_res->ai_family = PF_INET; - new_res->ai_socktype = hints->ai_socktype; - new_res->ai_protocol = hints->ai_protocol; - new_res->ai_addr = NULL; - new_res->ai_addrlen = sizeof(struct sockaddr_in); - new_res->ai_canonname = NULL; - new_res->ai_next = NULL; - - new_res->ai_addr = (struct sockaddr *) - malloc(sizeof(struct sockaddr_in)); - if (new_res->ai_addr == NULL) { - free(new_res); - if (head_res != NULL) - freeaddrinfo(head_res); - result = EAI_MEMORY; - goto end; - } - - sa_in = (struct sockaddr_in *)new_res->ai_addr; - memset(sa_in, 0, sizeof(struct sockaddr_in)); - sa_in->sin_family = PF_INET; - sa_in->sin_port = port; - memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr)); - - if (head_res == NULL) - head_res = new_res; - else - tail_res->ai_next = new_res; - tail_res = new_res; - } - - if (canonname != NULL && head_res != NULL) { - head_res->ai_canonname = (char *)malloc(strlen(canonname) + 1); - if (head_res->ai_canonname != NULL) - strcpy(head_res->ai_canonname, canonname); - } - - *res = head_res; - - end: - h_errno = saved_h_errno; -#ifdef ENABLE_PTHREAD - pthread_mutex_unlock(&gai_mutex); -#endif - return result; -} - -/* - * getnameinfo(). - */ -int -getnameinfo(sa, salen, node, nodelen, serv, servlen, flags) - const struct sockaddr *sa; - socklen_t salen; - char *node; - socklen_t nodelen; - char *serv; - socklen_t servlen; - int flags; -{ - const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa; - struct hostent *hostent; - struct servent *servent; - char *ntoa_address; - int saved_h_errno; - int result = 0; - -#ifdef ENABLE_PTHREAD - pthread_mutex_lock(&gai_mutex); -#endif - - saved_h_errno = h_errno; - - if (sa_in->sin_family != PF_INET) { - result = EAI_FAMILY; - goto end; - } else if (node == NULL && serv == NULL) { - result = EAI_NONAME; - goto end; - } - - if (serv != NULL && servlen > 0) { - if (flags & NI_NUMERICSERV) - servent = NULL; - else if (flags & NI_DGRAM) - servent = getservbyport(sa_in->sin_port, "udp"); - else - servent = getservbyport(sa_in->sin_port, "tcp"); - - if (servent != NULL) { - if (servlen <= strlen(servent->s_name)) { - result = EAI_OVERFLOW; - goto end; - } - strcpy(serv, servent->s_name); - } else { - if (servlen <= itoa_length(ntohs(sa_in->sin_port))) { - result = EAI_OVERFLOW; - goto end; - } - sprintf(serv, "%d", ntohs(sa_in->sin_port)); - } - } - - if (node != NULL && nodelen > 0) { - if (flags & NI_NUMERICHOST) - hostent = NULL; - else { - hostent = gethostbyaddr((char *)&sa_in->sin_addr, - sizeof(struct in_addr), AF_INET); - } - if (hostent != NULL) { - if (nodelen <= strlen(hostent->h_name)) { - result = EAI_OVERFLOW; - goto end; - } - strcpy(node, hostent->h_name); - } else { - if (flags & NI_NAMEREQD) { - result = EAI_NONAME; - goto end; - } - ntoa_address = inet_ntoa(sa_in->sin_addr); - if (nodelen <= strlen(ntoa_address)) { - result = EAI_OVERFLOW; - goto end; - } - strcpy(node, ntoa_address); - } - - } - - end: - h_errno = saved_h_errno; -#ifdef ENABLE_PTHREAD - pthread_mutex_unlock(&gai_mutex); -#endif - return result; -} - |