diff options
-rw-r--r-- | pr/include/md/_aix.h | 1 | ||||
-rw-r--r-- | pr/include/md/_bsdi.h | 1 | ||||
-rw-r--r-- | pr/include/md/_darwin.h | 1 | ||||
-rw-r--r-- | pr/include/md/_freebsd.h | 1 | ||||
-rw-r--r-- | pr/include/md/_hpux.h | 1 | ||||
-rw-r--r-- | pr/include/md/_irix.h | 1 | ||||
-rw-r--r-- | pr/include/md/_linux.h | 1 | ||||
-rw-r--r-- | pr/include/md/_netbsd.h | 1 | ||||
-rw-r--r-- | pr/include/md/_openvms.h | 12 | ||||
-rw-r--r-- | pr/include/md/_osf1.h | 12 | ||||
-rw-r--r-- | pr/include/md/_solaris.h | 12 | ||||
-rw-r--r-- | pr/include/md/_win95.h | 17 | ||||
-rw-r--r-- | pr/include/md/_winnt.h | 17 | ||||
-rw-r--r-- | pr/include/prio.h | 4 | ||||
-rw-r--r-- | pr/include/prnetdb.h | 82 | ||||
-rw-r--r-- | pr/src/io/pripv6.c | 64 | ||||
-rw-r--r-- | pr/src/misc/prnetdb.c | 297 | ||||
-rw-r--r-- | pr/src/nspr.def | 8 | ||||
-rw-r--r-- | pr/src/nspr_symvec.opt | 23 | ||||
-rw-r--r-- | pr/tests/Makefile.in | 1 | ||||
-rw-r--r-- | pr/tests/getai.c | 60 |
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; +} |