summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordarin%meer.net <devnull@localhost>2003-09-11 17:25:05 +0000
committerdarin%meer.net <devnull@localhost>2003-09-11 17:25:05 +0000
commit51009cbb96b7ba1589793aec86feca1b2e4f18a5 (patch)
tree9aea8e0086acf98e17c0dfeab0c08e450fd3c9b0
parent20e7115a85d8f4f30be1001ff28a2184785dd03f (diff)
downloadnspr-hg-51009cbb96b7ba1589793aec86feca1b2e4f18a5.tar.gz
patch for bug 211501 "NSPR should provide getaddrinfo" r=wtc
-rw-r--r--pr/include/md/_aix.h1
-rw-r--r--pr/include/md/_bsdi.h1
-rw-r--r--pr/include/md/_darwin.h1
-rw-r--r--pr/include/md/_freebsd.h1
-rw-r--r--pr/include/md/_hpux.h1
-rw-r--r--pr/include/md/_irix.h1
-rw-r--r--pr/include/md/_linux.h1
-rw-r--r--pr/include/md/_netbsd.h1
-rw-r--r--pr/include/md/_openvms.h12
-rw-r--r--pr/include/md/_osf1.h12
-rw-r--r--pr/include/md/_solaris.h12
-rw-r--r--pr/include/md/_win95.h17
-rw-r--r--pr/include/md/_winnt.h17
-rw-r--r--pr/include/prio.h4
-rw-r--r--pr/include/prnetdb.h82
-rw-r--r--pr/src/io/pripv6.c64
-rw-r--r--pr/src/misc/prnetdb.c297
-rw-r--r--pr/src/nspr.def8
-rw-r--r--pr/src/nspr_symvec.opt23
-rw-r--r--pr/tests/Makefile.in1
-rw-r--r--pr/tests/getai.c60
21 files changed, 569 insertions, 48 deletions
diff --git a/pr/include/md/_aix.h b/pr/include/md/_aix.h
index 2ef0fc1d..6e89d52d 100644
--- a/pr/include/md/_aix.h
+++ b/pr/include/md/_aix.h
@@ -74,6 +74,7 @@
#ifdef _PR_INET6
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
#endif
#define _PR_HAVE_SYSV_SEMAPHORES
#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
diff --git a/pr/include/md/_bsdi.h b/pr/include/md/_bsdi.h
index 346f1049..14eca99e 100644
--- a/pr/include/md/_bsdi.h
+++ b/pr/include/md/_bsdi.h
@@ -69,6 +69,7 @@
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETIPNODEBYNAME
#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#endif
diff --git a/pr/include/md/_darwin.h b/pr/include/md/_darwin.h
index bad90a65..d8487441 100644
--- a/pr/include/md/_darwin.h
+++ b/pr/include/md/_darwin.h
@@ -68,6 +68,7 @@
* thread-safe. AI_V4MAPPED|AI_ADDRCONFIG doesn't work either.
*/
#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
/*
* On Mac OS X 10.2, gethostbyaddr fails with h_errno=NO_RECOVERY
* if you pass an IPv4-mapped IPv6 address to it.
diff --git a/pr/include/md/_freebsd.h b/pr/include/md/_freebsd.h
index 68542336..c6f47f9f 100644
--- a/pr/include/md/_freebsd.h
+++ b/pr/include/md/_freebsd.h
@@ -92,6 +92,7 @@
#define _PR_INET6
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#endif
diff --git a/pr/include/md/_hpux.h b/pr/include/md/_hpux.h
index 2341d973..bf8569b3 100644
--- a/pr/include/md/_hpux.h
+++ b/pr/include/md/_hpux.h
@@ -83,6 +83,7 @@
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETIPNODEBYNAME
#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#endif
diff --git a/pr/include/md/_irix.h b/pr/include/md/_irix.h
index 5e7b624c..e09b2638 100644
--- a/pr/include/md/_irix.h
+++ b/pr/include/md/_irix.h
@@ -82,6 +82,7 @@
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETIPNODEBYNAME
#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
#endif
/* Initialization entry points */
diff --git a/pr/include/md/_linux.h b/pr/include/md/_linux.h
index df2cfd40..159b8a65 100644
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -124,6 +124,7 @@ extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval);
#define _PR_INET6
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#endif
#define _PR_HAVE_SYSV_SEMAPHORES
diff --git a/pr/include/md/_netbsd.h b/pr/include/md/_netbsd.h
index 0ccc2399..cd829df3 100644
--- a/pr/include/md/_netbsd.h
+++ b/pr/include/md/_netbsd.h
@@ -82,6 +82,7 @@
#define _PR_INET6
#define _PR_HAVE_INET_NTOP
#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#endif
diff --git a/pr/include/md/_openvms.h b/pr/include/md/_openvms.h
index 4b3fb92a..735c3f2c 100644
--- a/pr/include/md/_openvms.h
+++ b/pr/include/md/_openvms.h
@@ -105,11 +105,23 @@ struct ip_mreq {
#endif
#define _PR_HAVE_GETIPNODEBYNAME
#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#ifdef _PR_INET6
#define _PR_HAVE_INET_NTOP
#else
#define AF_INET6 26
+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;
+};
+#define AI_CANONNAME 0x00000002
#define AI_V4MAPPED 0x00000010
#define AI_ALL 0x00000008
#define AI_ADDRCONFIG 0x00000020
diff --git a/pr/include/md/_osf1.h b/pr/include/md/_osf1.h
index a098a0db..df6359a1 100644
--- a/pr/include/md/_osf1.h
+++ b/pr/include/md/_osf1.h
@@ -64,11 +64,23 @@
#define _PR_HAVE_LARGE_OFF_T
#define _PR_HAVE_GETIPNODEBYNAME
#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#ifdef _PR_INET6
#define _PR_HAVE_INET_NTOP
#else
#define AF_INET6 26
+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;
+};
+#define AI_CANONNAME 0x00000002
#define AI_V4MAPPED 0x00000010
#define AI_ALL 0x00000008
#define AI_ADDRCONFIG 0x00000020
diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h
index 01b5fed4..9c2ebffe 100644
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -109,12 +109,24 @@
#endif
#define _PR_HAVE_GETIPNODEBYNAME
#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
#define _PR_INET6_PROBE
#define _PR_ACCEPT_INHERIT_NONBLOCK
#ifdef _PR_INET6
#define _PR_HAVE_INET_NTOP
#else
#define AF_INET6 26
+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;
+};
+#define AI_CANONNAME 0x0010
#define AI_V4MAPPED 0x0001
#define AI_ALL 0x0002
#define AI_ADDRCONFIG 0x0004
diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h
index 5307a881..a7f39b71 100644
--- a/pr/include/md/_win95.h
+++ b/pr/include/md/_win95.h
@@ -51,6 +51,23 @@
#define HAVE_DLL
#undef HAVE_THREAD_AFFINITY
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#ifndef _PR_INET6
+#define AF_INET6 23
+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;
+};
+#define AI_CANONNAME 0x2
+#endif
+#define _PR_HAVE_THREADSAFE_GETHOST
#define _PR_HAVE_ATOMIC_OPS
#define PR_HAVE_WIN32_NAMED_SHARED_MEMORY
diff --git a/pr/include/md/_winnt.h b/pr/include/md/_winnt.h
index efc60edd..d630f63c 100644
--- a/pr/include/md/_winnt.h
+++ b/pr/include/md/_winnt.h
@@ -66,6 +66,23 @@
#define HAVE_DLL
#define HAVE_CUSTOM_USER_THREADS
#define HAVE_THREAD_AFFINITY
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#ifndef _PR_INET6
+#define AF_INET6 23
+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;
+};
+#define AI_CANONNAME 0x2
+#endif
+#define _PR_HAVE_THREADSAFE_GETHOST
#define _PR_HAVE_ATOMIC_OPS
#define _PR_HAVE_ATOMIC_CAS
#define PR_HAVE_WIN32_NAMED_SHARED_MEMORY
diff --git a/pr/include/prio.h b/pr/include/prio.h
index 42beca33..bb96c296 100644
--- a/pr/include/prio.h
+++ b/pr/include/prio.h
@@ -139,6 +139,10 @@ typedef enum PRTransmitFileFlags {
#define PR_AF_INET6 100
#endif
+#ifndef PR_AF_UNSPEC
+#define PR_AF_UNSPEC 0
+#endif
+
/*
**************************************************************************
** A network address
diff --git a/pr/include/prnetdb.h b/pr/include/prnetdb.h
index 1eb23dbe..a2456137 100644
--- a/pr/include/prnetdb.h
+++ b/pr/include/prnetdb.h
@@ -386,6 +386,88 @@ NSPR_API(PRStatus) PR_GetProtoByNumber(
PRInt32 protocolnumber, char* buffer, PRInt32 bufsize, PRProtoEnt* result);
/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetAddrInfoByName()
+** Lookup a host by name. Equivalent to getaddrinfo(host, NULL, ...) of
+** RFC 3493.
+**
+** INPUTS:
+** char *hostname Character string defining the host name of interest
+** PRUint16 af Must be PR_AF_UNSPEC
+** PRIntn flags Must be PR_AI_ADDRCONFIG
+** RETURN:
+** PRAddrInfo* Handle to a data structure containing the results
+** of the host lookup. Use PR_EnumerateAddrInfo to
+** inspect the PRNetAddr values stored in this object.
+** When no longer needed, this handle must be destroyed
+** with a call to PR_FreeAddrInfo. If a lookup error
+** occurs, then NULL will be returned.
+***********************************************************************/
+typedef struct PRAddrInfo PRAddrInfo;
+
+NSPR_API(PRAddrInfo*) PR_GetAddrInfoByName(
+ const char *hostname, PRUint16 af, PRIntn flags);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_FreeAddrInfo()
+** Destroy the PRAddrInfo handle allocated by PR_GetAddrInfoByName().
+**
+** INPUTS:
+** PRAddrInfo *addrInfo
+** The handle resulting from a successful call to
+** PR_GetAddrInfoByName().
+** RETURN:
+** void
+***********************************************************************/
+NSPR_API(void) PR_FreeAddrInfo(PRAddrInfo *addrInfo);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_EnumerateAddrInfo()
+** A stateless enumerator over a PRAddrInfo handle acquired from
+** PR_GetAddrInfoByName() to inspect the possible network addresses.
+**
+** INPUTS:
+** void *enumPtr Index pointer of the enumeration. The enumeration
+** starts and ends with a value of NULL.
+** PRAddrInfo *addrInfo
+** The PRAddrInfo handle returned by a successful
+** call to PR_GetAddrInfoByName().
+** PRUint16 port The port number to be assigned as part of the
+** PRNetAddr.
+** OUTPUTS:
+** PRNetAddr *result A pointer to an address structure that will be
+** filled in by the call to the enumeration if the
+** result of the call is greater than zero.
+** RETURN:
+** void* The value that should be used for the next call
+** of the enumerator ('enumPtr'). The enumeration
+** is ended if this value is returned NULL.
+***********************************************************************/
+NSPR_API(void *) PR_EnumerateAddrInfo(
+ void *enumPtr, const PRAddrInfo *addrInfo, PRUint16 port, PRNetAddr *result);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetCanonNameFromAddrInfo()
+** Extracts the canonical name of the hostname passed to
+** PR_GetAddrInfoByName().
+**
+** INPUTS:
+** PRAddrInfo *addrInfo
+** The PRAddrInfo handle returned by a successful
+** call to PR_GetAddrInfoByName().
+** RETURN:
+** const char * A const pointer to the canonical hostname stored
+** in the given PRAddrInfo handle. This pointer is
+** invalidated once the PRAddrInfo handle is destroyed
+** by a call to PR_FreeAddrInfo().
+***********************************************************************/
+NSPR_API(const char *) PR_GetCanonNameFromAddrInfo(
+ const PRAddrInfo *addrInfo);
+
+/***********************************************************************
** FUNCTIONS: PR_ntohs, PR_ntohl, PR_ntohll, PR_htons, PR_htonl, PR_htonll
**
** DESCRIPTION: API entries for the common byte ordering routines.
diff --git a/pr/src/io/pripv6.c b/pr/src/io/pripv6.c
index fd104677..a5c2360f 100644
--- a/pr/src/io/pripv6.c
+++ b/pr/src/io/pripv6.c
@@ -276,51 +276,41 @@ static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf,
#if defined(_PR_INET6_PROBE)
PRBool _pr_ipv6_is_present;
-PR_EXTERN(PRBool) _pr_test_ipv6_socket();
-#if defined(_PR_HAVE_GETIPNODEBYNAME)
-void *_pr_getipnodebyname_fp;
-void *_pr_getipnodebyaddr_fp;
-void *_pr_freehostent_fp;
+extern PRBool _pr_test_ipv6_socket(void);
+
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
+extern PRStatus _pr_find_getipnodebyname(void);
+#endif
+
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO)
+extern PRStatus _pr_find_getaddrinfo(void);
#endif
+
+static PRBool
+_pr_probe_ipv6_presence(void)
+{
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ if (_pr_find_getipnodebyname() != PR_SUCCESS)
+ return PR_FALSE;
#endif
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO)
+ if (_pr_find_getaddrinfo() != PR_SUCCESS)
+ return PR_FALSE;
+#endif
+
+ return _pr_test_ipv6_socket();
+}
+#endif /* _PR_INET6_PROBE */
+
PRStatus _pr_init_ipv6()
{
const PRIOMethods *stubMethods;
#if defined(_PR_INET6_PROBE)
-
-#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
- PRLibrary *lib;
-#if defined(VMS)
-#define GETIPNODEBYNAME getenv("GETIPNODEBYNAME")
-#define GETIPNODEBYADDR getenv("GETIPNODEBYADDR")
-#define FREEHOSTENT getenv("FREEHOSTENT")
-#else
-#define GETIPNODEBYNAME "getipnodebyname"
-#define GETIPNODEBYADDR "getipnodebyaddr"
-#define FREEHOSTENT "freehostent"
-#endif
- _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib);
- if (NULL != _pr_getipnodebyname_fp) {
- _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT);
- if (NULL != _pr_freehostent_fp) {
- _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR);
- if (NULL != _pr_getipnodebyaddr_fp)
- _pr_ipv6_is_present = PR_TRUE;
- else
- _pr_ipv6_is_present = PR_FALSE;
- } else
- _pr_ipv6_is_present = PR_FALSE;
- (void)PR_UnloadLibrary(lib);
- } else
- _pr_ipv6_is_present = PR_FALSE;
- if (PR_TRUE == _pr_ipv6_is_present)
-#endif
-
- _pr_ipv6_is_present = _pr_test_ipv6_socket();
- if (PR_TRUE == _pr_ipv6_is_present)
- return PR_SUCCESS;
+ _pr_ipv6_is_present = _pr_probe_ipv6_presence();
+ if (PR_TRUE == _pr_ipv6_is_present)
+ return PR_SUCCESS;
#endif
_pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer");
diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c
index dc89b891..99e6ccd6 100644
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -715,15 +715,51 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName(
return rv;
}
-#if defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
+#if !defined(_PR_INET6) && \
+ defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
typedef struct hostent * (*_pr_getipnodebyname_t)(const char *, int,
int, int *);
typedef struct hostent * (*_pr_getipnodebyaddr_t)(const void *, size_t,
int, int *);
typedef void (*_pr_freehostent_t)(struct hostent *);
-extern void * _pr_getipnodebyname_fp;
-extern void * _pr_getipnodebyaddr_fp;
-extern void * _pr_freehostent_fp;
+static void * _pr_getipnodebyname_fp;
+static void * _pr_getipnodebyaddr_fp;
+static void * _pr_freehostent_fp;
+
+/*
+ * Look up the addresses of getipnodebyname, getipnodebyaddr,
+ * and freehostent.
+ */
+PRStatus
+_pr_find_getipnodebyname(void)
+{
+ PRLibrary *lib;
+ PRStatus rv;
+#if defined(VMS)
+#define GETIPNODEBYNAME getenv("GETIPNODEBYNAME")
+#define GETIPNODEBYADDR getenv("GETIPNODEBYADDR")
+#define FREEHOSTENT getenv("FREEHOSTENT")
+#else
+#define GETIPNODEBYNAME "getipnodebyname"
+#define GETIPNODEBYADDR "getipnodebyaddr"
+#define FREEHOSTENT "freehostent"
+#endif
+ _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib);
+ if (NULL != _pr_getipnodebyname_fp) {
+ _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT);
+ if (NULL != _pr_freehostent_fp) {
+ _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR);
+ if (NULL != _pr_getipnodebyaddr_fp)
+ rv = PR_SUCCESS;
+ else
+ rv = PR_FAILURE;
+ } else
+ rv = PR_FAILURE;
+ (void)PR_UnloadLibrary(lib);
+ } else
+ rv = PR_FAILURE;
+ return rv;
+}
#endif
#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
@@ -1876,3 +1912,256 @@ PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n)
return n;
#endif
} /* htonll */
+
+
+/*
+ * Implementation of PR_GetAddrInfoByName and friends
+ *
+ * Compile-time options:
+ *
+ * _PR_HAVE_GETADDRINFO Define this macro if the target system provides
+ * getaddrinfo. With this defined, NSPR will require
+ * getaddrinfo at run time. If this if not defined,
+ * then NSPR will attempt to dynamically resolve
+ * getaddrinfo, falling back to PR_GetHostByName if
+ * getaddrinfo does not exist on the target system.
+ *
+ * Since getaddrinfo is a relatively new system call on many systems,
+ * we are forced to dynamically resolve it at run time in most cases.
+ * The exception includes any system (such as Mac OS X) that is known to
+ * provide getaddrinfo in all versions that NSPR cares to support.
+ */
+
+#if defined(_PR_HAVE_GETADDRINFO)
+
+#if defined(_PR_INET6)
+
+typedef struct addrinfo PRADDRINFO;
+#define GETADDRINFO getaddrinfo
+#define FREEADDRINFO freeaddrinfo
+
+#elif defined(_PR_INET6_PROBE)
+
+typedef struct addrinfo PRADDRINFO;
+
+/* getaddrinfo/freeaddrinfo prototypes */
+#if defined(WIN32)
+#define FUNC_MODIFIER __stdcall
+#else
+#define FUNC_MODIFIER
+#endif
+typedef int (FUNC_MODIFIER * FN_GETADDRINFO)
+ (const char *nodename,
+ const char *servname,
+ const PRADDRINFO *hints,
+ PRADDRINFO **res);
+typedef int (FUNC_MODIFIER * FN_FREEADDRINFO)
+ (PRADDRINFO *ai);
+
+/* global state */
+static FN_GETADDRINFO _pr_getaddrinfo = NULL;
+static FN_FREEADDRINFO _pr_freeaddrinfo = NULL;
+
+#if defined(VMS)
+#define GETADDRINFO_SYMBOL getenv("GETADDRINFO")
+#define FREEADDRINFO_SYMBOL getenv("FREEADDRINFO")
+#else
+#define GETADDRINFO_SYMBOL "getaddrinfo"
+#define FREEADDRINFO_SYMBOL "freeaddrinfo"
+#endif
+
+PRStatus
+_pr_find_getaddrinfo(void)
+{
+ PRLibrary *lib;
+#ifdef WIN32
+ /*
+ * On windows, we need to search ws2_32.dll for getaddrinfo and
+ * freeaddrinfo. This library might not be loaded yet.
+ */
+ lib = PR_LoadLibrary("ws2_32.dll");
+ if (!lib) {
+ return PR_FAILURE;
+ }
+ _pr_getaddrinfo = (FN_GETADDRINFO)
+ PR_FindFunctionSymbol(lib, GETADDRINFO_SYMBOL);
+ _pr_freeaddrinfo = (FN_FREEADDRINFO)
+ PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL);
+ if (!_pr_getaddrinfo || !_pr_freeaddrinfo) {
+ PR_UnloadLibrary(lib);
+ return PR_FAILURE;
+ }
+ /* Keep ws2_32.dll loaded. */
+ return PR_SUCCESS;
+#else
+ /*
+ * Resolve getaddrinfo by searching all loaded libraries. Then
+ * search library containing getaddrinfo for freeaddrinfo.
+ */
+ _pr_getaddrinfo = (FN_GETADDRINFO)
+ PR_FindFunctionSymbolAndLibrary(GETADDRINFO_SYMBOL, &lib);
+ if (!_pr_getaddrinfo) {
+ return PR_FAILURE;
+ }
+ _pr_freeaddrinfo = (FN_FREEADDRINFO)
+ PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL);
+ PR_UnloadLibrary(lib);
+ if (!_pr_freeaddrinfo) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+#endif
+}
+
+#define GETADDRINFO (*_pr_getaddrinfo)
+#define FREEADDRINFO (*_pr_freeaddrinfo)
+
+#endif /* _PR_INET6 */
+
+#endif /* _PR_HAVE_GETADDRINFO */
+
+/*
+ * If getaddrinfo does not exist, then we will fall back on
+ * PR_GetHostByName, which requires that we allocate a buffer for the
+ * PRHostEnt data structure and its members.
+ */
+typedef struct PRAddrInfoFB {
+ char buf[PR_NETDB_BUF_SIZE];
+ PRHostEnt hostent;
+} PRAddrInfoFB;
+
+static PRAddrInfo *
+pr_GetAddrInfoByNameFB(const char *hostname,
+ PRUint16 af,
+ PRIntn flags)
+{
+ PRStatus rv;
+ PRAddrInfoFB *ai;
+ /* fallback on PR_GetHostByName */
+ ai = PR_NEW(PRAddrInfoFB);
+ if (!ai) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ rv = PR_GetHostByName(hostname, ai->buf, sizeof ai->buf, &ai->hostent);
+ if (rv == PR_FAILURE) {
+ PR_Free(ai);
+ return NULL;
+ }
+ return (PRAddrInfo *) ai;
+}
+
+PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByName(const char *hostname,
+ PRUint16 af,
+ PRIntn flags)
+{
+ /* restrict input to supported values */
+ if (af != PR_AF_UNSPEC || flags != PR_AI_ADDRCONFIG) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#if !defined(_PR_HAVE_GETADDRINFO)
+ return pr_GetAddrInfoByNameFB(hostname, af, flags);
+#else
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present) {
+ return pr_GetAddrInfoByNameFB(hostname, af, flags);
+ }
+#endif
+ {
+ PRADDRINFO *res, hints;
+ PRStatus rv;
+
+ /*
+ * we assume a RFC 2553 compliant getaddrinfo. this may at some
+ * point need to be customized as platforms begin to adopt the
+ * RFC 3493.
+ */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+
+ rv = GETADDRINFO(hostname, NULL, &hints, &res);
+ if (rv == 0)
+ return (PRAddrInfo *) res;
+
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv);
+ }
+ return NULL;
+#endif
+}
+
+PR_IMPLEMENT(void) PR_FreeAddrInfo(PRAddrInfo *ai)
+{
+#if defined(_PR_HAVE_GETADDRINFO)
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present)
+ PR_Free((PRAddrInfoFB *) ai);
+ else
+#endif
+ FREEADDRINFO((PRADDRINFO *) ai);
+#else
+ PR_Free((PRAddrInfoFB *) ai);
+#endif
+}
+
+PR_IMPLEMENT(void *) PR_EnumerateAddrInfo(void *iterPtr,
+ const PRAddrInfo *base,
+ PRUint16 port,
+ PRNetAddr *result)
+{
+#if defined(_PR_HAVE_GETADDRINFO)
+ PRADDRINFO *ai;
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present) {
+ /* using PRAddrInfoFB */
+ PRIntn iter = (PRIntn) iterPtr;
+ iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result);
+ if (iter < 0)
+ iter = 0;
+ return (void *) iter;
+ }
+#endif
+
+ if (iterPtr)
+ ai = ((PRADDRINFO *) iterPtr)->ai_next;
+ else
+ ai = (PRADDRINFO *) base;
+
+ if (ai) {
+ /* copy sockaddr to PRNetAddr */
+ memcpy(result, ai->ai_addr, ai->ai_addrlen);
+ if (ai->ai_addrlen < sizeof(PRNetAddr))
+ memset(((char*)result)+ai->ai_addrlen, 0, sizeof(PRNetAddr) - ai->ai_addrlen);
+
+ if (port != 0)
+ result->inet.port = PR_htons(port);
+ }
+
+ return ai;
+#else
+ /* using PRAddrInfoFB */
+ PRIntn iter = (PRIntn) iterPtr;
+ iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result);
+ if (iter < 0)
+ iter = 0;
+ return (void *) iter;
+#endif
+}
+
+PR_IMPLEMENT(const char *) PR_GetCanonNameFromAddrInfo(const PRAddrInfo *ai)
+{
+#if defined(_PR_HAVE_GETADDRINFO)
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present)
+ return ((const PRAddrInfoFB *) ai)->hostent.h_name;
+#endif
+ return ((const PRADDRINFO *) ai)->ai_canonname;
+#else
+ return ((const PRAddrInfoFB *) ai)->hostent.h_name;
+#endif
+}
diff --git a/pr/src/nspr.def b/pr/src/nspr.def
index 676bd21d..144df2ca 100644
--- a/pr/src/nspr.def
+++ b/pr/src/nspr.def
@@ -447,3 +447,11 @@ EXPORTS ;-
;+ global:
PR_GetPathSeparator;
;+} NSPR_4.3;
+;+
+;+NSPR_4.5 {
+;+ global:
+ PR_EnumerateAddrInfo;
+ PR_FreeAddrInfo;
+ PR_GetAddrInfoByName;
+ PR_GetCanonNameFromAddrInfo;
+;+} NSPR_4.4;
diff --git a/pr/src/nspr_symvec.opt b/pr/src/nspr_symvec.opt
index 68e78bdb..b6441372 100644
--- a/pr/src/nspr_symvec.opt
+++ b/pr/src/nspr_symvec.opt
@@ -1,6 +1,6 @@
! Fixed section of symbol vector for LIBNSPR4 (non-debug)
!
-GSMATCH=LEQUAL,2,5
+GSMATCH=LEQUAL,2,7
case_sensitive=YES
!
! --------------------------------------------------------------------------
@@ -31,6 +31,15 @@ case_sensitive=YES
! Ident 2,5 introduced for post Mozilla 1.3.
! LL_MaxUint introduced. Replaces Stub54.
! --------------------------------------------------------------------------
+! Ident 2,6 introduced for post Mozilla 1.4.
+! PR_GetPathSeparator introduced in NSPR 4.4.
+! This replaces stub 53
+! --------------------------------------------------------------------------
+! Ident 2,7 introduced for post Mozilla 1.4.
+! PR_GetAddrInfoByName, PR_FreeAddrInfo, PR_EnumerateAddrInfo and
+! PR_GetCanonNameFromAddrInfo introduced in NSPR 4.5.
+! These replace stubs 49-52
+! --------------------------------------------------------------------------
!
SYMBOL_VECTOR=(PR_Accept=PROCEDURE)
SYMBOL_VECTOR=(PR_AcceptRead=PROCEDURE)
@@ -473,12 +482,12 @@ SYMBOL_VECTOR=(PR_VMS_Stub45=PROCEDURE)
SYMBOL_VECTOR=(PR_VMS_Stub46=PROCEDURE)
SYMBOL_VECTOR=(PR_VMS_Stub47=PROCEDURE)
SYMBOL_VECTOR=(PR_VMS_Stub48=PROCEDURE)
-SYMBOL_VECTOR=(PR_VMS_Stub49=PROCEDURE)
-SYMBOL_VECTOR=(PR_VMS_Stub50=PROCEDURE)
-SYMBOL_VECTOR=(PR_VMS_Stub51=PROCEDURE)
-SYMBOL_VECTOR=(PR_VMS_Stub52=PROCEDURE)
-SYMBOL_VECTOR=(PR_VMS_Stub53=PROCEDURE)
-SYMBOL_VECTOR=(LL_MaxUint=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetAddrInfoByName=PROCEDURE) ! was Stub49
+SYMBOL_VECTOR=(PR_FreeAddrInfo=PROCEDURE) ! was Stub50
+SYMBOL_VECTOR=(PR_EnumerateAddrInfo=PROCEDURE) ! was Stub51
+SYMBOL_VECTOR=(PR_GetCanonNameFromAddrInfo=PROCEDURE) ! was Stub52
+SYMBOL_VECTOR=(PR_GetPathSeparator=PROCEDURE) ! was Stub53
+SYMBOL_VECTOR=(LL_MaxUint=PROCEDURE) ! was Stub54
!
SYMBOL_VECTOR=(PR_CallOnceWithArg=PROCEDURE)
SYMBOL_VECTOR=(PR_GetLibraryFilePathname=PROCEDURE)
diff --git a/pr/tests/Makefile.in b/pr/tests/Makefile.in
index 17105b4e..d765b256 100644
--- a/pr/tests/Makefile.in
+++ b/pr/tests/Makefile.in
@@ -76,6 +76,7 @@ CSRCS = \
foreign.c \
forktest.c \
fsync.c \
+ getai.c \
gethost.c \
getproto.c \
i2l.c \
diff --git a/pr/tests/getai.c b/pr/tests/getai.c
new file mode 100644
index 00000000..11094bce
--- /dev/null
+++ b/pr/tests/getai.c
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2003 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ PRAddrInfo *ai;
+ void *iter;
+ PRNetAddr addr;
+
+ if (PR_GetAddrInfoByName(argv[1], 0, 0, &ai) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetAddrInfoByName failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("%s\n", PR_GetCanonNameFromAddrInfo(ai));
+ iter = NULL;
+ while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) {
+ char buf[128];
+ PR_NetAddrToString(&addr, buf, sizeof buf);
+ printf("%s\n", buf);
+ }
+ PR_FreeAddrInfo(ai);
+ return 0;
+}