17cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
27cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Copyright (c) 2001, 02  Motoyuki Kasahara
37cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
47cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Redistribution and use in source and binary forms, with or without
57cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * modification, are permitted provided that the following conditions
67cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * are met:
77cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * 1. Redistributions of source code must retain the above copyright
87cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    notice, this list of conditions and the following disclaimer.
97cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright
107cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    notice, this list of conditions and the following disclaimer in the
117cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    documentation and/or other materials provided with the distribution.
127cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * 3. Neither the name of the project nor the names of its contributors
137cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    may be used to endorse or promote products derived from this software
147cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    without specific prior written permission.
157cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
167cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
177cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
187cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
197cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
207cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
217cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
227cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
237cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
247cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * SUCH DAMAGE.
277cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
287cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
297cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
307cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * This program provides getaddrinfo() and getnameinfo() described in
317cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * RFC2133, 2553 and 3493.  These functions are mainly used for IPv6
327cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * application to resolve hostname or address.
337cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
347cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * This program is designed to be working on traditional IPv4 systems
357cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * which don't have those functions.  Therefore, this implementation
367cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * supports IPv4 only.
377cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
387cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * This program is useful for application which should support both IPv6
397cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * and traditional IPv4 systems.  Use genuine getaddrinfo() and getnameinfo()
407cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * provided by system if the system supports IPv6.  Otherwise, use this
417cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * implementation.
427cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
437cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * This program is intended to be used in combination with GNU Autoconf.
447cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
457cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * This program also provides freeaddrinfo() and gai_strerror().
467cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
477cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * To use this program in your application, insert the following lines to
487cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * C source files after including `sys/types.h', `sys/socket.h' and
497cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * `netdb.h'.  `getaddrinfo.h' defines `struct addrinfo' and AI_, NI_,
507cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * EAI_ macros.
517cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
527cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    #ifndef HAVE_GETADDRINFO
537cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    #include "getaddrinfo.h"
547cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *    #endif
557cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
567cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Restriction:
577cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   getaddrinfo() and getnameinfo() of this program are NOT thread
587cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   safe, unless the cpp macro ENABLE_PTHREAD is defined.
597cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
607cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
617cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
627cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Add the following code to your configure.ac (or configure.in).
637cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_C_CONST
647cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_HEADER_STDC
657cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_CHECK_HEADERS(string.h memory.h stdlib.h)
667cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_CHECK_FUNCS(memcpy)
677cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_REPLACE_FUNCS(memset)
687cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_TYPE_SOCKLEN_T
697cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_TYPE_IN_PORT_T
707cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_DECL_H_ERRNO
717cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *
727cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   AC_CHECK_FUNCS(getaddrinfo getnameinfo)
737cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   if test "$ac_cv_func_getaddrinfo$ac_cv_func_getnameinfo" != yesyes ; then
747cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *       LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext"
757cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes *   fi
767cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
777cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
787cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef HAVE_CONFIG_H
797cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include "config.h"
807cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
817cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
827cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <sys/types.h>
837cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <stdio.h>
847cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
857cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef WIN32
867cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <time.h>
877cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <winsock2.h>
887cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef DO_IPV6
897cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <ws2tcpip.h>
907cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif  /* DO_IPV6 */
917cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <windows.h>
927cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#else
937cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <sys/socket.h>
947cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
957cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
967cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
977cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <netinet/in.h>
987cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <arpa/inet.h>
997cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <netdb.h>
1007cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1017cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
1027cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <string.h>
1037cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
1047cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <memory.h>
1057cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
1067cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#else /* not STDC_HEADERS and not HAVE_STRING_H */
1077cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <strings.h>
1087cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif /* not STDC_HEADERS and not HAVE_STRING_H */
1097cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1107cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef HAVE_STDLIB_H
1117cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <stdlib.h>
1127cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
1137cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1147cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_PTHREAD
1157cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <pthread.h>
1167cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
1177cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1187cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_NLS
1197cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include <libintl.h>
1207cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
1217cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1227cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifndef HAVE_MEMCPY
1237cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define memcpy(d, s, n) bcopy((s), (d), (n))
1247cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef __STDC__
1257cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesvoid *memchr(const void *, int, size_t);
1267cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesint memcmp(const void *, const void *, size_t);
1277cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesvoid *memmove(void *, const void *, size_t);
1287cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesvoid *memset(void *, int, size_t);
1297cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#else /* not __STDC__ */
1307cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hugheschar *memchr();
1317cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesint memcmp();
1327cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hugheschar *memmove();
1337cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hugheschar *memset();
1347cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif /* not __STDC__ */
1357cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif /* not HAVE_MEMCPY */
1367cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1377cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifndef H_ERRNO_DECLARED
1387cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesextern int h_errno;
1397cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
1407cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1417cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#include "getaddrinfo.h"
1427cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1437cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_NLS
1447cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define _(string) gettext(string)
1457cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef gettext_noop
1467cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define N_(string) gettext_noop(string)
1477cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#else
1487cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define N_(string) (string)
1497cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
1507cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#else
1517cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define gettext(string) (string)
1527cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define _(string) (string)
1537cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#define N_(string) (string)
1547cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
1557cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1567cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
1577cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Error messages for gai_strerror().
1587cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
1597cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic char *eai_errlist[] = {
1607cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("Success"),
1617cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1627cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_ADDRFAMILY */
1637cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("Address family for hostname not supported"),
1647cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1657cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_AGAIN */
1667cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("Temporary failure in name resolution"),
1677cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1687cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_BADFLAGS */
1697cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("Invalid value for ai_flags"),
1707cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1717cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_FAIL */
1727cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("Non-recoverable failure in name resolution"),
1737cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1747cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_FAMILY */
1757cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("ai_family not supported"),
1767cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1777cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_MEMORY */
1787cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("Memory allocation failure"),
1797cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1807cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_NONAME */
1817cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("hostname nor servname provided, or not known"),
1827cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1837cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_OVERFLOW */
1847cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("An argument buffer overflowed"),
1857cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1867cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_SERVICE */
1877cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("servname not supported for ai_socktype"),
1887cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1897cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_SOCKTYPE */
1907cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("ai_socktype not supported"),
1917cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1927cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    /* EAI_SYSTEM */
1937cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    N_("System error returned in errno")
1947cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes};
1957cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
1967cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
1977cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Default hints for getaddrinfo().
1987cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
1997cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic struct addrinfo default_hints = {
2007cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL
2017cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes};
2027cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2037cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
2047cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Mutex.
2057cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
2067cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_PTHREAD
2077cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic pthread_mutex_t gai_mutex = PTHREAD_MUTEX_INITIALIZER;
2087cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
2097cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2107cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
2117cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Declaration of static functions.
2127cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
2137cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef __STDC__
2147cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int is_integer(const char *);
2157cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int is_address(const char *);
2167cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int itoa_length(int);
2177cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#else
2187cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int is_integer();
2197cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int is_address();
2207cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int itoa_length();
2217cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
2227cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2237cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
2247cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * gai_strerror().
2257cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
2267cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesconst char *
2277cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesgai_strerror(ecode)
2287cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int ecode;
2297cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
2307cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (ecode < 0 || ecode > EAI_SYSTEM)
2317cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	return _("Unknown error");
2327cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2337cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    return gettext(eai_errlist[ecode]);
2347cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
2357cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2367cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
2377cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * freeaddrinfo().
2387cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
2397cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesvoid
2407cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesfreeaddrinfo(ai)
2417cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct addrinfo *ai;
2427cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
2437cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct addrinfo *next_ai;
2447cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2457cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    while (ai != NULL) {
2467cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (ai->ai_canonname != NULL)
2477cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    free(ai->ai_canonname);
2487cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (ai->ai_addr != NULL)
2497cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    free(ai->ai_addr);
2507cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	next_ai = ai->ai_next;
2517cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	free(ai);
2527cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	ai = next_ai;
2537cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
2547cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
2557cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2567cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
2577cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Return 1 if the string `s' represents an integer.
2587cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
2597cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int
2607cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesis_integer(s)
2617cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const char *s;
2627cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
2637cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (*s == '-' || *s == '+')
2647cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	s++;
2657cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (*s < '0' || '9' < *s)
2667cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	return 0;
2677cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2687cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    s++;
2697cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    while ('0' <= *s && *s <= '9')
2707cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	s++;
2717cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2727cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    return (*s == '\0');
2737cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
2747cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2757cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
2767cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Return 1 if the string `s' represents an IPv4 address.
2777cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Unlike inet_addr(), it doesn't permit malformed nortation such
2787cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * as "192.168".
2797cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
2807cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int
2817cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesis_address(s)
2827cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const char *s;
2837cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
2847cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const static char delimiters[] = {'.', '.', '.', '\0'};
2857cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int i, j;
2867cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int octet;
2877cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2887cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    for (i = 0; i < 4; i++) {
2897cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (*s == '0' && *(s + 1) != delimiters[i])
2907cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    return 0;
2917cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++)
2927cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    octet = octet * 10 + (*s - '0');
2937cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (j == 0 || octet > 255 || *s != delimiters[i])
2947cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    return 0;
2957cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	s++;
2967cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
2977cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
2987cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    return 1;
2997cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
3007cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3017cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
3027cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * Calcurate length of the string `s', where `s' is set by
3037cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * sprintf(s, "%d", n).
3047cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
3057cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesstatic int
3067cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesitoa_length(n)
3077cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int n;
3087cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
3097cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int result = 1;
3107cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3117cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (n < 0) {
3127cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	n = -n;
3137cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	result++;
3147cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
3157cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3167cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    while (n >= 10) {
3177cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	result++;
3187cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	n /= 10;
3197cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
3207cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3217cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    return result;
3227cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
3237cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3247cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
3257cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * getaddrinfo().
3267cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
3277cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesint
3287cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesgetaddrinfo(nodename, servname, hints, res)
3297cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const char *nodename;
3307cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const char *servname;
3317cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const struct addrinfo *hints;
3327cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct addrinfo **res;
3337cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
3347cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct addrinfo *head_res = NULL;
3357cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct addrinfo *tail_res = NULL;
3367cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct addrinfo *new_res;
3377cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct sockaddr_in *sa_in;
3387cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct in_addr **addr_list;
3397cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct in_addr *addr_list_buf[2];
3407cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct in_addr addr_buf;
3417cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct in_addr **ap;
3427cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct servent *servent;
3437cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct hostent *hostent;
3447cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const char *canonname = NULL;
3457cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    in_port_t port;
3467cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int saved_h_errno;
3477cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int result = 0;
3487cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3497cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_PTHREAD
3507cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    pthread_mutex_lock(&gai_mutex);
3517cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
3527cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3537cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    saved_h_errno = h_errno;
3547cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3557cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (nodename == NULL && servname == NULL) {
3567cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	result = EAI_NONAME;
3577cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	goto end;
3587cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
3597cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3607cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (hints != NULL) {
3617cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) {
3627cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    result = EAI_FAMILY;
3637cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    goto end;
3647cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
3657cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (hints->ai_socktype != SOCK_DGRAM
3667cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    && hints->ai_socktype != SOCK_STREAM
3677cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    && hints->ai_socktype != 0) {
3687cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    result = EAI_SOCKTYPE;
3697cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    goto end;
3707cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
3717cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    } else {
3727cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	hints = &default_hints;
3737cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
3747cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3757cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (servname != NULL) {
3767cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (is_integer(servname))
3777cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    port = htons(atoi(servname));
3787cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	else  {
3797cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (hints->ai_flags & AI_NUMERICSERV) {
3807cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_NONAME;
3817cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
3827cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
3837cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3847cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (hints->ai_socktype == SOCK_DGRAM)
3857cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		servent = getservbyname(servname, "udp");
3867cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    else if (hints->ai_socktype == SOCK_STREAM)
3877cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		servent = getservbyname(servname, "tcp");
3887cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    else if (hints->ai_socktype == 0)
3897cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		servent = getservbyname(servname, "tcp");
3907cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    else {
3917cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_SOCKTYPE;
3927cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
3937cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
3947cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
3957cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (servent == NULL) {
3967cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_SERVICE;
3977cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
3987cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
3997cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    port = servent->s_port;
4007cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
4017cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    } else {
4027cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	port = htons(0);
4037cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
4047cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4057cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (nodename != NULL) {
4067cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (is_address(nodename)) {
4077cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_buf.s_addr = inet_addr(nodename);
4087cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_list_buf[0] = &addr_buf;
4097cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_list_buf[1] = NULL;
4107cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_list = addr_list_buf;
4117cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4127cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (hints->ai_flags & AI_CANONNAME
4137cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		&& !(hints->ai_flags & AI_NUMERICHOST)) {
4147cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		hostent = gethostbyaddr((char *)&addr_buf,
4157cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    sizeof(struct in_addr), AF_INET);
4167cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		if (hostent != NULL)
4177cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    canonname = hostent->h_name;
4187cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		else
4197cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    canonname = nodename;
4207cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
4217cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	} else {
4227cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (hints->ai_flags & AI_NUMERICHOST) {
4237cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_NONAME;
4247cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
4257cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
4267cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4277cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    hostent = gethostbyname(nodename);
4287cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (hostent == NULL) {
4297cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		switch (h_errno) {
4307cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		case HOST_NOT_FOUND:
4317cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		case NO_DATA:
4327cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    result = EAI_NONAME;
4337cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    goto end;
4347cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		case TRY_AGAIN:
4357cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    result = EAI_AGAIN;
4367cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    goto end;
4377cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		default:
4387cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    result = EAI_FAIL;
4397cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		    goto end;
4407cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes                }
4417cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
4427cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_list = (struct in_addr **)hostent->h_addr_list;
4437cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4447cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (hints->ai_flags & AI_CANONNAME)
4457cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		canonname = hostent->h_name;
4467cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
4477cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    } else {
4487cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (hints->ai_flags & AI_PASSIVE)
4497cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_buf.s_addr = htonl(INADDR_ANY);
4507cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	else
4517cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    addr_buf.s_addr = htonl(0x7F000001);
4527cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	addr_list_buf[0] = &addr_buf;
4537cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	addr_list_buf[1] = NULL;
4547cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	addr_list = addr_list_buf;
4557cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
4567cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4577cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    for (ap = addr_list; *ap != NULL; ap++) {
4587cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res = (struct addrinfo *)malloc(sizeof(struct addrinfo));
4597cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (new_res == NULL) {
4607cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (head_res != NULL)
4617cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		freeaddrinfo(head_res);
4627cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    result = EAI_MEMORY;
4637cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    goto end;
4647cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
4657cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4667cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_family = PF_INET;
4677cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_socktype = hints->ai_socktype;
4687cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_protocol = hints->ai_protocol;
4697cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_addr = NULL;
4707cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_addrlen = sizeof(struct sockaddr_in);
4717cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_canonname = NULL;
4727cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_next = NULL;
4737cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4747cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	new_res->ai_addr = (struct sockaddr *)
4757cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    malloc(sizeof(struct sockaddr_in));
4767cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (new_res->ai_addr == NULL) {
4777cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    free(new_res);
4787cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (head_res != NULL)
4797cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		freeaddrinfo(head_res);
4807cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    result = EAI_MEMORY;
4817cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    goto end;
4827cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
4837cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4847cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	sa_in = (struct sockaddr_in *)new_res->ai_addr;
4857cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	memset(sa_in, 0, sizeof(struct sockaddr_in));
4867cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	sa_in->sin_family = PF_INET;
4877cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	sa_in->sin_port = port;
4887cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr));
4897cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4907cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (head_res == NULL)
4917cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    head_res = new_res;
4927cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	else
4937cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    tail_res->ai_next = new_res;
4947cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	tail_res = new_res;
4957cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
4967cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
4977cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (canonname != NULL && head_res != NULL) {
4987cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	head_res->ai_canonname = (char *)malloc(strlen(canonname) + 1);
4997cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (head_res->ai_canonname != NULL)
5007cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    strcpy(head_res->ai_canonname, canonname);
5017cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
5027cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5037cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    *res = head_res;
5047cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5057cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes  end:
5067cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    h_errno = saved_h_errno;
5077cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_PTHREAD
5087cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    pthread_mutex_unlock(&gai_mutex);
5097cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
5107cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    return result;
5117cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
5127cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5137cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes/*
5147cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes * getnameinfo().
5157cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes */
5167cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesint
5177cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughesgetnameinfo(sa, salen, node, nodelen, serv, servlen, flags)
5187cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const struct sockaddr *sa;
5197cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    socklen_t salen;
5207cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    char *node;
5217cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    socklen_t nodelen;
5227cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    char *serv;
5237cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    socklen_t servlen;
5247cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int flags;
5257cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes{
5267cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa;
5277cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct hostent *hostent;
5287cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    struct servent *servent;
5297cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    char *ntoa_address;
5307cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int saved_h_errno;
5317cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    int result = 0;
5327cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5337cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_PTHREAD
5347cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    pthread_mutex_lock(&gai_mutex);
5357cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
5367cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5377cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    saved_h_errno = h_errno;
5387cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5397cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (sa_in->sin_family != PF_INET) {
5407cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	result = EAI_FAMILY;
5417cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	goto end;
5427cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    } else if (node == NULL && serv == NULL) {
5437cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	result = EAI_NONAME;
5447cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	goto end;
5457cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
5467cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5477cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (serv != NULL && servlen > 0) {
5487cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (flags & NI_NUMERICSERV)
5497cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    servent = NULL;
5507cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	else if (flags & NI_DGRAM)
5517cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    servent = getservbyport(sa_in->sin_port, "udp");
5527cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	else
5537cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    servent = getservbyport(sa_in->sin_port, "tcp");
5547cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5557cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (servent != NULL) {
5567cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (servlen <= strlen(servent->s_name)) {
5577cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_OVERFLOW;
5587cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
5597cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
5607cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    strcpy(serv, servent->s_name);
5617cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	} else {
5627cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (servlen <= itoa_length(ntohs(sa_in->sin_port))) {
5637cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_OVERFLOW;
5647cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
5657cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
5667cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    sprintf(serv, "%d", ntohs(sa_in->sin_port));
5677cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
5687cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
5697cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5707cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    if (node != NULL && nodelen > 0) {
5717cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (flags & NI_NUMERICHOST)
5727cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    hostent = NULL;
5737cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	else {
5747cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    hostent = gethostbyaddr((char *)&sa_in->sin_addr,
5757cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		sizeof(struct in_addr), AF_INET);
5767cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
5777cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	if (hostent != NULL) {
5787cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (nodelen <= strlen(hostent->h_name)) {
5797cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_OVERFLOW;
5807cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
5817cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
5827cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    strcpy(node, hostent->h_name);
5837cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	} else {
5847cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (flags & NI_NAMEREQD) {
5857cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_NONAME;
5867cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
5877cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
5887cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    ntoa_address = inet_ntoa(sa_in->sin_addr);
5897cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    if (nodelen <= strlen(ntoa_address)) {
5907cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		result = EAI_OVERFLOW;
5917cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes		goto end;
5927cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    }
5937cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	    strcpy(node, ntoa_address);
5947cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes	}
5957cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5967cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    }
5977cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
5987cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes  end:
5997cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    h_errno = saved_h_errno;
6007cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#ifdef ENABLE_PTHREAD
6017cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    pthread_mutex_unlock(&gai_mutex);
6027cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes#endif
6037cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes    return result;
6047cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes}
6057cb62816f02cc6abb1fe88b94808fc412e0b29d0Elliott Hughes
606