diff options
author | Kai Engert <kaie@kuix.de> | 2022-05-13 20:12:57 +0200 |
---|---|---|
committer | Kai Engert <kaie@kuix.de> | 2022-05-13 20:12:57 +0200 |
commit | 0b6e72ef03a3562d843a88adcd53c1abdb1ef13d (patch) | |
tree | 86d05096785a42f1b76056b414d623158b6f8639 | |
parent | ac4fbec717b61d6bcafdc1f25839276b5f6a99f3 (diff) | |
download | nss-hg-0b6e72ef03a3562d843a88adcd53c1abdb1ef13d.tar.gz |
Bug 1769295 - selfserv and tstclnt should use PR_GetPrefLoopbackAddrInfo. r=rrelyea
Differential Revision: https://phabricator.services.mozilla.com/D146334
-rw-r--r-- | automation/abi-check/expected-report-libnspr4.so.txt | 5 | ||||
-rw-r--r-- | cmd/selfserv/selfserv.c | 23 | ||||
-rw-r--r-- | cmd/tstclnt/tstclnt.c | 63 | ||||
-rw-r--r-- | nspr.patch | 121 |
4 files changed, 181 insertions, 31 deletions
diff --git a/automation/abi-check/expected-report-libnspr4.so.txt b/automation/abi-check/expected-report-libnspr4.so.txt index e69de29bb..b8b5c57b2 100644 --- a/automation/abi-check/expected-report-libnspr4.so.txt +++ b/automation/abi-check/expected-report-libnspr4.so.txt @@ -0,0 +1,5 @@ + +1 Added function: + + 'function PRStatus PR_GetPrefLoopbackAddrInfo(PRNetAddr*, PRUint16)' {PR_GetPrefLoopbackAddrInfo} + diff --git a/cmd/selfserv/selfserv.c b/cmd/selfserv/selfserv.c index 5094cc7bf..d26851d98 100644 --- a/cmd/selfserv/selfserv.c +++ b/cmd/selfserv/selfserv.c @@ -1711,19 +1711,30 @@ do_accepts( PRFileDesc * getBoundListenSocket(unsigned short port) { - PRFileDesc *listen_sock; + PRFileDesc *listen_sock = NULL; int listenQueueDepth = 5 + (2 * maxThreads); PRStatus prStatus; PRNetAddr addr; PRSocketOptionData opt; - addr.inet.family = PR_AF_INET; - addr.inet.ip = PR_INADDR_ANY; - addr.inet.port = PR_htons(port); + // We want to listen on the IP family that tstclnt will use. + // tstclnt uses PR_GetPrefLoopbackAddrInfo to decide, if it's + // asked to connect to localhost. + + prStatus = PR_GetPrefLoopbackAddrInfo(&addr, port); + if (prStatus == PR_FAILURE) { + addr.inet.family = PR_AF_INET; + addr.inet.ip = PR_INADDR_ANY; + addr.inet.port = PR_htons(port); + } - listen_sock = PR_NewTCPSocket(); + if (addr.inet.family == PR_AF_INET6) { + listen_sock = PR_OpenTCPSocket(PR_AF_INET6); + } else if (addr.inet.family == PR_AF_INET) { + listen_sock = PR_NewTCPSocket(); + } if (listen_sock == NULL) { - errExit("PR_NewTCPSocket"); + errExit("Couldn't create socket"); } opt.option = PR_SockOpt_Nonblocking; diff --git a/cmd/tstclnt/tstclnt.c b/cmd/tstclnt/tstclnt.c index 6d3359c03..453842b16 100644 --- a/cmd/tstclnt/tstclnt.c +++ b/cmd/tstclnt/tstclnt.c @@ -2190,32 +2190,45 @@ main(int argc, char **argv) if (status == PR_SUCCESS) { addr.inet.port = PR_htons(portno); } else { - /* Lookup host */ - PRAddrInfo *addrInfo; - void *enumPtr = NULL; - - addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC, - PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME); - if (!addrInfo) { - fprintf(stderr, "HOSTNAME=%s\n", host); - SECU_PrintError(progName, "error looking up host"); - error = 1; - goto done; - } - for (;;) { - enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr); - if (enumPtr == NULL) - break; - if (addr.raw.family == PR_AF_INET && allowIPv4) - break; - if (addr.raw.family == PR_AF_INET6 && allowIPv6) - break; + PRBool gotLoopbackIP = PR_FALSE; + if ((!strcmp(host, "localhost") || !strcmp(host, "localhost.localdomain")) + /* only check for preference if both types are allowed */ + && allowIPv4 && allowIPv6) { + /* make a decision which IP to prefer */ + status = PR_GetPrefLoopbackAddrInfo(&addr, portno); + if (status != PR_FAILURE) { + gotLoopbackIP = PR_TRUE; + } } - PR_FreeAddrInfo(addrInfo); - if (enumPtr == NULL) { - SECU_PrintError(progName, "error looking up host address"); - error = 1; - goto done; + + if (!gotLoopbackIP) { + /* Lookup host */ + PRAddrInfo *addrInfo; + void *enumPtr = NULL; + + addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC, + PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME); + if (!addrInfo) { + fprintf(stderr, "HOSTNAME=%s\n", host); + SECU_PrintError(progName, "error looking up host"); + error = 1; + goto done; + } + for (;;) { + enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr); + if (enumPtr == NULL) + break; + if (addr.raw.family == PR_AF_INET && allowIPv4) + break; + if (addr.raw.family == PR_AF_INET6 && allowIPv6) + break; + } + PR_FreeAddrInfo(addrInfo); + if (enumPtr == NULL) { + SECU_PrintError(progName, "error looking up host address"); + error = 1; + goto done; + } } } diff --git a/nspr.patch b/nspr.patch new file mode 100644 index 000000000..4300489e1 --- /dev/null +++ b/nspr.patch @@ -0,0 +1,121 @@ +# HG changeset patch +# User Kai Engert <kaie@kuix.de> +# 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; |