# HG changeset patch # User Kai Engert # Date 1652465540 -7200 # Fri May 13 20:12:20 2022 +0200 # Node ID 2be45a781ba18e5904c1eed4dc0e1d66248d303c # Parent 005070e9849523de6c647dd15dd8a709db0f3b7d Bug 1769293 - Add API PR_GetPrefLoopbackAddrInfo. r=rrelyea Differential Revision: https://phabricator.services.mozilla.com/D146333 diff --git a/pr/include/prnetdb.h b/pr/include/prnetdb.h --- a/pr/include/prnetdb.h +++ b/pr/include/prnetdb.h @@ -426,10 +426,13 @@ NSPR_API(void) PR_FreeAddrInfo(PRAddrInf ** is ended if this value is NULL. ***********************************************************************/ NSPR_API(void *) PR_EnumerateAddrInfo( void *enumPtr, const PRAddrInfo *addrInfo, PRUint16 port, PRNetAddr *result); +NSPR_API(PRStatus) PR_GetPrefLoopbackAddrInfo(PRNetAddr *result, + PRUint16 port); + /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetCanonNameFromAddrInfo() ** Extracts the canonical name of the hostname passed to ** PR_GetAddrInfoByName(). diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c --- a/pr/src/misc/prnetdb.c +++ b/pr/src/misc/prnetdb.c @@ -2176,10 +2176,77 @@ PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInf } return NULL; #endif } +PR_IMPLEMENT(PRStatus) +PR_GetPrefLoopbackAddrInfo(PRNetAddr *result, + PRUint16 port) +{ + char tmpBuf[ 40 ]; + const int tmpBufSize = sizeof( tmpBuf ); + + if (!result) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return PR_FAILURE; + } + + if (!_pr_initialized) _PR_ImplicitInitialization(); + + PR_snprintf(tmpBuf, tmpBufSize, "%u", port ); + +#if !defined(_PR_HAVE_GETADDRINFO) || !defined(AI_PASSIVE) + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; +#else + + PRADDRINFO *res, hints; + PRStatus rv; + + memset(&hints, 0, sizeof(hints)); + + rv = GETADDRINFO(NULL, tmpBuf, &hints, &res); + if (rv == 0) { + PRBool result_still_empty = PR_TRUE; + PRADDRINFO *ai = res; + do { + PRNetAddr aNetAddr; + + while (ai && ai->ai_addrlen > sizeof(PRNetAddr)) + ai = ai->ai_next; + + if (ai) { + /* copy sockaddr to PRNetAddr */ + memcpy(&aNetAddr, ai->ai_addr, ai->ai_addrlen); + aNetAddr.raw.family = ai->ai_addr->sa_family; +#ifdef _PR_INET6 + if (AF_INET6 == aNetAddr.raw.family) + aNetAddr.raw.family = PR_AF_INET6; +#endif + if (ai->ai_addrlen < sizeof(PRNetAddr)) + memset(((char*)result)+ai->ai_addrlen, 0, + sizeof(PRNetAddr) - ai->ai_addrlen); + } + + /* If we obtain more than one result, prefer IPv6. */ + if (result_still_empty || aNetAddr.raw.family == PR_AF_INET6) { + memcpy(result, &aNetAddr, sizeof(PRNetAddr)); + } + result_still_empty = PR_FALSE; + ai = ai->ai_next; + } + while (ai); + + FREEADDRINFO(res); + return PR_SUCCESS; + } + + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv); + return PR_FAILURE; +#endif +} + PR_IMPLEMENT(void) PR_FreeAddrInfo(PRAddrInfo *ai) { #if defined(_PR_HAVE_GETADDRINFO) #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) { diff --git a/pr/src/nspr.def b/pr/src/nspr.def --- a/pr/src/nspr.def +++ b/pr/src/nspr.def @@ -460,5 +460,9 @@ EXPORTS ;- ;+NSPR_4.12 { ;+ global: PR_DuplicateEnvironment; PR_GetEnvSecure; ;+} NSPR_4.10.3; +;+NSPR_4.34 { +;+ global: + PR_GetPrefLoopbackAddrInfo; +;+} NSPR_4.12;