|
|
|
|
@ -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; |
|
|
|
|
|