summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2016-08-30 00:57:57 +0000
committerache <ache@FreeBSD.org>2016-08-30 00:57:57 +0000
commitde43eec3e10416a7e9f3a7565f70e1ba2d265384 (patch)
treec470269a9d51d96ea14c5168d974b43b7747c6dc /lib
parent06b3d2ebf75f176db563f3fb963857dedd94c5eb (diff)
downloadFreeBSD-src-de43eec3e10416a7e9f3a7565f70e1ba2d265384.zip
FreeBSD-src-de43eec3e10416a7e9f3a7565f70e1ba2d265384.tar.gz
MFC r304911
The formal behavior of qsort is unstable with regard to objects that are equal. Unfortunately, RFC 3484 requires that otherwise equal objects remain in the order supplied by the DNS server. The present code attempts to deal with this by returning -1 for objects that are equal (i.e., returns that the first parameter is less then the second parameter). Unfortunately, the qsort API does not state that the first parameter passed in is in any particular position in the list. PR: 212122 Submitted by: Herbie.Robinson@stratus.com
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/net/getaddrinfo.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index d987a16..c5bfc5e 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -207,6 +207,7 @@ struct ai_order {
struct policyqueue *aio_dstpolicy;
struct addrinfo *aio_ai;
int aio_matchlen;
+ int aio_initial_sequence;
};
static const ns_src default_dns_files[] = {
@@ -690,6 +691,7 @@ reorder(struct addrinfo *sentinel)
aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
&policyhead);
set_source(&aio[i], &policyhead);
+ aio[i].aio_initial_sequence = i;
}
/* perform sorting. */
@@ -1048,6 +1050,23 @@ comp_dst(const void *arg1, const void *arg2)
}
/* Rule 10: Otherwise, leave the order unchanged. */
+
+ /*
+ * Note that qsort is unstable; so, we can't return zero and
+ * expect the order to be unchanged.
+ * That also means we can't depend on the current position of
+ * dst2 being after dst1. We must enforce the initial order
+ * with an explicit compare on the original position.
+ * The qsort specification requires that "When the same objects
+ * (consisting of width bytes, irrespective of their current
+ * positions in the array) are passed more than once to the
+ * comparison function, the results shall be consistent with one
+ * another."
+ * In other words, If A < B, then we must also return B > A.
+ */
+ if (dst2->aio_initial_sequence < dst1->aio_initial_sequence)
+ return(1);
+
return(-1);
}
OpenPOWER on IntegriCloud