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