Add code to use Windows getaddrinfo and friends if they exist. This

has to be tested dynamically if we want to make portable executables.
Chuck McDevitt and Andrew Dunstan.
REL8_1_STABLE
Tom Lane 21 years ago
parent bd19ee3457
commit c3bf8dee0e
  1. 135
      src/port/getaddrinfo.c

@ -8,11 +8,15 @@
* 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 special
* 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-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/port/getaddrinfo.c,v 1.17 2005/07/28 04:03:14 tgl Exp $
* $PostgreSQL: pgsql/src/port/getaddrinfo.c,v 1.18 2005/08/24 22:13:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -29,6 +33,103 @@
#include "getaddrinfo.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/*
* 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 *host, int hostlen,
char *serv, int servlen,
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 Windows 2003 (and longhorn/vista), the IPv6
* routines are present in the WinSock 2 library (ws2_32.dll).
* Try that first
*/
hLibrary = LoadLibraryA("ws2_32");
if (hLibrary == NULL || GetProcAddress(hLibrary, "getaddrinfo") == NULL)
{
/*
* Well, ws2_32 doesn't exist, or more likely doesn't have
* getaddrinfo.
*/
if (hLibrary != NULL)
FreeLibrary(hLibrary);
/*
* In Windows 2000, there was only the IPv6 Technology Preview look in
* the IPv6 WinSock library (wship6.dll).
*/
hLibrary = LoadLibraryA("wship6");
}
/* 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 = GetProcAddress(hLibrary, "getaddrinfo");
freeaddrinfo_ptr = GetProcAddress(hLibrary, "freeaddrinfo");
getnameinfo_ptr = 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.
*
@ -47,6 +148,15 @@ getaddrinfo(const char *node, const char *service,
*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));
@ -160,6 +270,18 @@ 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) (node, service, hintp, res);
return;
}
#endif
if (res->ai_addr)
free(res->ai_addr);
free(res);
@ -188,7 +310,6 @@ gai_strerror(int errcode)
}
return hstrerror(hcode);
#else /* !HAVE_HSTRERROR */
switch (errcode)
@ -216,6 +337,16 @@ 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;

Loading…
Cancel
Save