+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * getaddrinfo.h
- * Support getaddrinfo() on platforms that don't have it.
- *
- * Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
- * whether or not the library routine getaddrinfo() can be found. This
- * policy is needed because on some platforms a manually installed libbind.a
- * may provide getaddrinfo(), yet the system headers may not provide the
- * struct definitions needed to call it. To avoid conflict with the libbind
- * definition in such cases, we rename our routines to pg_xxx() via macros.
- *
- * This code will also work on platforms where struct addrinfo is defined
- * in the system headers but no getaddrinfo() can be located.
- *
- * Copyright (c) 2003-2022, PostgreSQL Global Development Group
- *
- * src/include/getaddrinfo.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef GETADDRINFO_H
-#define GETADDRINFO_H
-
-#include <sys/socket.h>
-#include <netdb.h>
-
-
-/* Various macros that ought to be in <netdb.h>, but might not be */
-
-#ifndef EAI_FAIL
-#ifndef WIN32
-#define EAI_BADFLAGS (-1)
-#define EAI_NONAME (-2)
-#define EAI_AGAIN (-3)
-#define EAI_FAIL (-4)
-#define EAI_FAMILY (-6)
-#define EAI_SOCKTYPE (-7)
-#define EAI_SERVICE (-8)
-#define EAI_MEMORY (-10)
-#define EAI_SYSTEM (-11)
-#else /* WIN32 */
-#ifdef _MSC_VER
-#ifndef WSA_NOT_ENOUGH_MEMORY
-#define WSA_NOT_ENOUGH_MEMORY (WSAENOBUFS)
-#endif
-#define WSATYPE_NOT_FOUND (WSABASEERR+109)
-#endif
-#define EAI_AGAIN WSATRY_AGAIN
-#define EAI_BADFLAGS WSAEINVAL
-#define EAI_FAIL WSANO_RECOVERY
-#define EAI_FAMILY WSAEAFNOSUPPORT
-#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
-#define EAI_NODATA WSANO_DATA
-#define EAI_NONAME WSAHOST_NOT_FOUND
-#define EAI_SERVICE WSATYPE_NOT_FOUND
-#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
-#endif /* !WIN32 */
-#endif /* !EAI_FAIL */
-
-#ifndef AI_PASSIVE
-#define AI_PASSIVE 0x0001
-#endif
-
-#ifndef AI_NUMERICHOST
-/*
- * some platforms don't support AI_NUMERICHOST; define as zero if using
- * the system version of getaddrinfo...
- */
-#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
-#define AI_NUMERICHOST 0
-#else
-#define AI_NUMERICHOST 0x0004
-#endif
-#endif
-
-#ifndef NI_NUMERICHOST
-#define NI_NUMERICHOST 1
-#endif
-#ifndef NI_NUMERICSERV
-#define NI_NUMERICSERV 2
-#endif
-#ifndef NI_NAMEREQD
-#define NI_NAMEREQD 4
-#endif
-
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-
-#ifndef HAVE_STRUCT_ADDRINFO
-
-#ifndef WIN32
-struct addrinfo
-{
- int ai_flags;
- int ai_family;
- int ai_socktype;
- int ai_protocol;
- size_t ai_addrlen;
- struct sockaddr *ai_addr;
- char *ai_canonname;
- struct addrinfo *ai_next;
-};
-#else
-/*
- * The order of the structure elements on Win32 doesn't match the
- * order specified in the standard, but we have to match it for
- * IPv6 to work.
- */
-struct addrinfo
-{
- int ai_flags;
- int ai_family;
- int ai_socktype;
- int ai_protocol;
- size_t ai_addrlen;
- char *ai_canonname;
- struct sockaddr *ai_addr;
- struct addrinfo *ai_next;
-};
-#endif
-#endif /* HAVE_STRUCT_ADDRINFO */
-
-
-#ifndef HAVE_GETADDRINFO
-
-/* Rename private copies per comments above */
-#ifdef getaddrinfo
-#undef getaddrinfo
-#endif
-#define getaddrinfo pg_getaddrinfo
-
-#ifdef freeaddrinfo
-#undef freeaddrinfo
-#endif
-#define freeaddrinfo pg_freeaddrinfo
-
-#ifdef gai_strerror
-#undef gai_strerror
-#endif
-#define gai_strerror pg_gai_strerror
-
-#ifdef getnameinfo
-#undef getnameinfo
-#endif
-#define getnameinfo pg_getnameinfo
-
-extern int getaddrinfo(const char *node, const char *service,
- const struct addrinfo *hints, struct addrinfo **res);
-extern void freeaddrinfo(struct addrinfo *res);
-extern const char *gai_strerror(int errcode);
-extern int getnameinfo(const struct sockaddr *sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen, int flags);
-#endif /* HAVE_GETADDRINFO */
-
-#endif /* GETADDRINFO_H */
+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * getaddrinfo.c
- * Support getaddrinfo() on platforms that don't have it.
- *
- * We also supply getnameinfo() here, assuming that the platform will have
- * it if and only if it has getaddrinfo(). If this proves false on some
- * platform, we'll need to split this file and provide a separate configure
- * test for getnameinfo().
- *
- * Windows may or may not have these routines, so we handle Windows specially
- * by dynamically checking for their existence. If they already exist, we
- * use the Windows native routines, but if not, we use our own.
- *
- *
- * Copyright (c) 2003-2022, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * src/port/getaddrinfo.c
- *
- *-------------------------------------------------------------------------
- */
-
-/* This is intended to be used in both frontend and backend, so use c.h */
-#include "c.h"
-
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "getaddrinfo.h"
-#include "libpq/pqcomm.h" /* needed for struct sockaddr_storage */
-#include "port/pg_bswap.h"
-
-
-#ifdef FRONTEND
-static int pqGethostbyname(const char *name,
- struct hostent *resultbuf,
- char *buffer, size_t buflen,
- struct hostent **result,
- int *herrno);
-#endif
-
-#ifdef WIN32
-/*
- * The native routines may or may not exist on the Windows platform we are on,
- * so we dynamically look up the routines, and call them via function pointers.
- * Here we need to declare what the function pointers look like
- */
-typedef int (__stdcall * getaddrinfo_ptr_t) (const char *nodename,
- const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res);
-
-typedef void (__stdcall * freeaddrinfo_ptr_t) (struct addrinfo *ai);
-
-typedef int (__stdcall * getnameinfo_ptr_t) (const struct sockaddr *sa,
- int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags);
-
-/* static pointers to the native routines, so we only do the lookup once. */
-static getaddrinfo_ptr_t getaddrinfo_ptr = NULL;
-static freeaddrinfo_ptr_t freeaddrinfo_ptr = NULL;
-static getnameinfo_ptr_t getnameinfo_ptr = NULL;
-
-
-static bool
-haveNativeWindowsIPv6routines(void)
-{
- void *hLibrary = NULL;
- static bool alreadyLookedForIpv6routines = false;
-
- if (alreadyLookedForIpv6routines)
- return (getaddrinfo_ptr != NULL);
-
- /*
- * For Windows XP and later versions, the IPv6 routines are present in the
- * WinSock 2 library (ws2_32.dll).
- */
- hLibrary = LoadLibraryA("ws2_32");
-
- /* If hLibrary is null, we couldn't find a dll with functions */
- if (hLibrary != NULL)
- {
- /* We found a dll, so now get the addresses of the routines */
-
- getaddrinfo_ptr = (getaddrinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
- "getaddrinfo");
- freeaddrinfo_ptr = (freeaddrinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
- "freeaddrinfo");
- getnameinfo_ptr = (getnameinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
- "getnameinfo");
-
- /*
- * If any one of the routines is missing, let's play it safe and
- * ignore them all
- */
- if (getaddrinfo_ptr == NULL ||
- freeaddrinfo_ptr == NULL ||
- getnameinfo_ptr == NULL)
- {
- FreeLibrary(hLibrary);
- hLibrary = NULL;
- getaddrinfo_ptr = NULL;
- freeaddrinfo_ptr = NULL;
- getnameinfo_ptr = NULL;
- }
- }
-
- alreadyLookedForIpv6routines = true;
- return (getaddrinfo_ptr != NULL);
-}
-#endif
-
-
-/*
- * get address info for ipv4 sockets.
- *
- * Bugs: - only one addrinfo is set even though hintp is NULL or
- * ai_socktype is 0
- * - AI_CANONNAME is not supported.
- * - servname can only be a number, not text.
- */
-int
-getaddrinfo(const char *node, const char *service,
- const struct addrinfo *hintp,
- struct addrinfo **res)
-{
- struct addrinfo *ai;
- struct sockaddr_in sin,
- *psin;
- struct addrinfo hints;
-
-#ifdef WIN32
-
- /*
- * If Windows has native IPv6 support, use the native Windows routine.
- * Otherwise, fall through and use our own code.
- */
- if (haveNativeWindowsIPv6routines())
- return (*getaddrinfo_ptr) (node, service, hintp, res);
-#endif
-
- if (hintp == NULL)
- {
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- }
- else
- memcpy(&hints, hintp, sizeof(hints));
-
- if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC)
- return EAI_FAMILY;
-
- if (hints.ai_socktype == 0)
- hints.ai_socktype = SOCK_STREAM;
-
- if (!node && !service)
- return EAI_NONAME;
-
- memset(&sin, 0, sizeof(sin));
-
- sin.sin_family = AF_INET;
-
- if (node)
- {
- if (node[0] == '\0')
- sin.sin_addr.s_addr = pg_hton32(INADDR_ANY);
- else if (hints.ai_flags & AI_NUMERICHOST)
- {
- if (!inet_aton(node, &sin.sin_addr))
- return EAI_NONAME;
- }
- else
- {
- struct hostent *hp;
-
-#ifdef FRONTEND
- struct hostent hpstr;
- char buf[BUFSIZ];
- int herrno = 0;
-
- pqGethostbyname(node, &hpstr, buf, sizeof(buf),
- &hp, &herrno);
-#else
- hp = gethostbyname(node);
-#endif
- if (hp == NULL)
- {
- switch (h_errno)
- {
- case HOST_NOT_FOUND:
- case NO_DATA:
- return EAI_NONAME;
- case TRY_AGAIN:
- return EAI_AGAIN;
- case NO_RECOVERY:
- default:
- return EAI_FAIL;
- }
- }
- if (hp->h_addrtype != AF_INET)
- return EAI_FAIL;
-
- memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
- }
- }
- else
- {
- if (hints.ai_flags & AI_PASSIVE)
- sin.sin_addr.s_addr = pg_hton32(INADDR_ANY);
- else
- sin.sin_addr.s_addr = pg_hton32(INADDR_LOOPBACK);
- }
-
- if (service)
- sin.sin_port = pg_hton16((unsigned short) atoi(service));
-
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
- sin.sin_len = sizeof(sin);
-#endif
-
- ai = malloc(sizeof(*ai));
- if (!ai)
- return EAI_MEMORY;
-
- psin = malloc(sizeof(*psin));
- if (!psin)
- {
- free(ai);
- return EAI_MEMORY;
- }
-
- memcpy(psin, &sin, sizeof(*psin));
-
- ai->ai_flags = 0;
- ai->ai_family = AF_INET;
- ai->ai_socktype = hints.ai_socktype;
- ai->ai_protocol = hints.ai_protocol;
- ai->ai_addrlen = sizeof(*psin);
- ai->ai_addr = (struct sockaddr *) psin;
- ai->ai_canonname = NULL;
- ai->ai_next = NULL;
-
- *res = ai;
-
- return 0;
-}
-
-
-void
-freeaddrinfo(struct addrinfo *res)
-{
- if (res)
- {
-#ifdef WIN32
-
- /*
- * If Windows has native IPv6 support, use the native Windows routine.
- * Otherwise, fall through and use our own code.
- */
- if (haveNativeWindowsIPv6routines())
- {
- (*freeaddrinfo_ptr) (res);
- return;
- }
-#endif
-
- free(res->ai_addr);
- free(res);
- }
-}
-
-
-const char *
-gai_strerror(int errcode)
-{
-#ifdef HAVE_HSTRERROR
- int hcode;
-
- switch (errcode)
- {
- case EAI_NONAME:
- hcode = HOST_NOT_FOUND;
- break;
- case EAI_AGAIN:
- hcode = TRY_AGAIN;
- break;
- case EAI_FAIL:
- default:
- hcode = NO_RECOVERY;
- break;
- }
-
- return hstrerror(hcode);
-#else /* !HAVE_HSTRERROR */
-
- switch (errcode)
- {
- case EAI_NONAME:
- return "Unknown host";
- case EAI_AGAIN:
- return "Host name lookup failure";
- /* Errors below are probably WIN32 only */
-#ifdef EAI_BADFLAGS
- case EAI_BADFLAGS:
- return "Invalid argument";
-#endif
-#ifdef EAI_FAMILY
- case EAI_FAMILY:
- return "Address family not supported";
-#endif
-#ifdef EAI_MEMORY
- case EAI_MEMORY:
- return "Not enough memory";
-#endif
-#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME /* MSVC/WIN64 duplicate */
- case EAI_NODATA:
- return "No host data of that type was found";
-#endif
-#ifdef EAI_SERVICE
- case EAI_SERVICE:
- return "Class type not found";
-#endif
-#ifdef EAI_SOCKTYPE
- case EAI_SOCKTYPE:
- return "Socket type not supported";
-#endif
- default:
- return "Unknown server error";
- }
-#endif /* HAVE_HSTRERROR */
-}
-
-/*
- * Convert an ipv4 address to a hostname.
- *
- * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV behavior.
- * It will never resolve a hostname.
- * - No IPv6 support.
- */
-int
-getnameinfo(const struct sockaddr *sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen, int flags)
-{
-#ifdef WIN32
-
- /*
- * If Windows has native IPv6 support, use the native Windows routine.
- * Otherwise, fall through and use our own code.
- */
- if (haveNativeWindowsIPv6routines())
- return (*getnameinfo_ptr) (sa, salen, node, nodelen,
- service, servicelen, flags);
-#endif
-
- /* Invalid arguments. */
- if (sa == NULL || (node == NULL && service == NULL))
- return EAI_FAIL;
-
-#ifdef HAVE_IPV6
- if (sa->sa_family == AF_INET6)
- return EAI_FAMILY;
-#endif
-
- /* Unsupported flags. */
- if (flags & NI_NAMEREQD)
- return EAI_AGAIN;
-
- if (node)
- {
- if (sa->sa_family == AF_INET)
- {
- if (pg_inet_net_ntop(AF_INET,
- &((struct sockaddr_in *) sa)->sin_addr,
- sa->sa_family == AF_INET ? 32 : 128,
- node, nodelen) == NULL)
- return EAI_MEMORY;
- }
- else
- return EAI_MEMORY;
- }
-
- if (service)
- {
- int ret = -1;
-
- if (sa->sa_family == AF_INET)
- {
- ret = snprintf(service, servicelen, "%d",
- pg_ntoh16(((struct sockaddr_in *) sa)->sin_port));
- }
- if (ret < 0 || ret >= servicelen)
- return EAI_MEMORY;
- }
-
- return 0;
-}
-
-/*
- * Wrapper around gethostbyname() or gethostbyname_r() to mimic
- * POSIX gethostbyname_r() behaviour, if it is not available or required.
- */
-#ifdef FRONTEND
-static int
-pqGethostbyname(const char *name,
- struct hostent *resultbuf,
- char *buffer, size_t buflen,
- struct hostent **result,
- int *herrno)
-{
-#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
-
- /*
- * broken (well early POSIX draft) gethostbyname_r() which returns 'struct
- * hostent *'
- */
- *result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
- return (*result == NULL) ? -1 : 0;
-#else
-
- /* no gethostbyname_r(), just use gethostbyname() */
- *result = gethostbyname(name);
-
- if (*result != NULL)
- *herrno = h_errno;
-
- if (*result != NULL)
- return 0;
- else
- return -1;
-#endif
-}
-#endif /* FRONTEND */