summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Engert <kaie@kuix.de>2022-05-13 20:12:57 +0200
committerKai Engert <kaie@kuix.de>2022-05-13 20:12:57 +0200
commit0b6e72ef03a3562d843a88adcd53c1abdb1ef13d (patch)
tree86d05096785a42f1b76056b414d623158b6f8639
parentac4fbec717b61d6bcafdc1f25839276b5f6a99f3 (diff)
downloadnss-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.txt5
-rw-r--r--cmd/selfserv/selfserv.c23
-rw-r--r--cmd/tstclnt/tstclnt.c63
-rw-r--r--nspr.patch121
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;