From 0efd19566da2186c571dae4807afbd4db3356e0a Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 10 Jan 2008 20:00:52 +0000 Subject: [PATCH] * sysdeps/posix/getaddrinfo.c (sort_results): Remove service_order field. Use sockaddr_in6 for source_addr. (get_scope): Change type of parameter to sockaddr_in6. Adjust. (match_prefix): Likewise. (get_label): Likewise. (get_precedence): Likewise. (rfc3484_sort): Change to use indirect access to results array. Adjust to use of sockaddr_in6. Replace service_order test with simple index comparison. (getaddrinfo): Define order array. Initialize it. Don't initialize service_order field. Adjust qsort_t calls. Access sorted result array indirectly through order array. * posix/tst-rfc3484.c: Adjust for change of rfc3484_sort. * posix/tst-rfc3484-2.c: Likewise. * posix/tst-rfc3484-3.c: Likewise. --- ChangeLog | 18 +++++++++ posix/tst-rfc3484-2.c | 17 +++++---- posix/tst-rfc3484-3.c | 8 ++-- posix/tst-rfc3484.c | 8 ++-- sysdeps/posix/getaddrinfo.c | 74 ++++++++++++++++++------------------- 5 files changed, 74 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index d70e40a72d..5f8f1d3b61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-01-10 Ulrich Drepper + + * sysdeps/posix/getaddrinfo.c (sort_results): Remove service_order + field. Use sockaddr_in6 for source_addr. + (get_scope): Change type of parameter to sockaddr_in6. Adjust. + (match_prefix): Likewise. + (get_label): Likewise. + (get_precedence): Likewise. + (rfc3484_sort): Change to use indirect access to results array. + Adjust to use of sockaddr_in6. Replace service_order test with + simple index comparison. + (getaddrinfo): Define order array. Initialize it. Don't initialize + service_order field. Adjust qsort_t calls. Access sorted result + array indirectly through order array. + * posix/tst-rfc3484.c: Adjust for change of rfc3484_sort. + * posix/tst-rfc3484-2.c: Likewise. + * posix/tst-rfc3484-3.c: Likewise. + 2008-01-09 Ulrich Drepper [BZ #5541] diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c index d29f0725cc..56c0277b17 100644 --- a/posix/tst-rfc3484-2.c +++ b/posix/tst-rfc3484-2.c @@ -100,31 +100,32 @@ do_test (void) struct sort_result results[2]; + size_t order[2]; results[0].dest_addr = &ai1; results[0].got_source_addr = true; results[0].source_addr_len = sizeof (so1); results[0].source_addr_flags = 0; - results[0].service_order = 0; results[0].prefixlen = 16; results[0].index = 0; memcpy (&results[0].source_addr, &so1, sizeof (so1)); + order[0] = 0; results[1].dest_addr = &ai2; results[1].got_source_addr = true; results[1].source_addr_len = sizeof (so2); results[1].source_addr_flags = 0; - results[1].service_order = 1; results[1].prefixlen = 16; results[1].index = 0; memcpy (&results[1].source_addr, &so2, sizeof (so2)); + order[1] = 1; struct sort_result_combo combo = { .results = results, .nresults = 2 }; - qsort_r (results, 2, sizeof (results[0]), rfc3484_sort, &combo); + qsort_r (order, 2, sizeof (order[0]), rfc3484_sort, &combo); int result = 0; - if (results[0].dest_addr->ai_family == AF_INET6) + if (results[order[0]].dest_addr->ai_family == AF_INET6) { puts ("wrong order in first test"); result |= 1; @@ -136,24 +137,24 @@ do_test (void) results[1].got_source_addr = true; results[1].source_addr_len = sizeof (so1); results[1].source_addr_flags = 0; - results[1].service_order = 1; results[1].prefixlen = 16; results[1].index = 0; memcpy (&results[1].source_addr, &so1, sizeof (so1)); + order[1] = 1; results[0].dest_addr = &ai2; results[0].got_source_addr = true; results[0].source_addr_len = sizeof (so2); results[0].source_addr_flags = 0; - results[0].service_order = 0; results[0].prefixlen = 16; results[0].index = 0; memcpy (&results[0].source_addr, &so2, sizeof (so2)); + order[0] = 0; - qsort_r (results, 2, sizeof (results[0]), rfc3484_sort, &combo); + qsort_r (order, 2, sizeof (order[0]), rfc3484_sort, &combo); - if (results[0].dest_addr->ai_family == AF_INET6) + if (results[order[0]].dest_addr->ai_family == AF_INET6) { puts ("wrong order in second test"); result |= 1; diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c index 4aede81ee3..616722eb1c 100644 --- a/posix/tst-rfc3484-3.c +++ b/posix/tst-rfc3484-3.c @@ -66,6 +66,7 @@ struct sockaddr_in addrs[] = #define naddrs (sizeof (addrs) / sizeof (addrs[0])) static struct addrinfo ais[naddrs]; static struct sort_result results[naddrs]; +static size_t order[naddrs]; static const int expected[naddrs] = { @@ -111,18 +112,19 @@ do_test (void) memcpy(&results[i].source_addr, &so, sizeof (so)); results[i].source_addr_len = sizeof (so); results[i].source_addr_flags = 0; - results[i].service_order = i; results[i].prefixlen = 8; results[i].index = 0; + + order[i] = i; } struct sort_result_combo combo = { .results = results, .nresults = naddrs }; - qsort_r (results, naddrs, sizeof (results[0]), rfc3484_sort, &combo); + qsort_r (order, naddrs, sizeof (order[0]), rfc3484_sort, &combo); int result = 0; for (int i = 0; i < naddrs; ++i) { - struct in_addr addr = ((struct sockaddr_in *) (results[i].dest_addr->ai_addr))->sin_addr; + struct in_addr addr = ((struct sockaddr_in *) (results[order[i]].dest_addr->ai_addr))->sin_addr; int here = memcmp (&addr, &addrs[expected[i]].sin_addr, sizeof (struct in_addr)); diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c index fe06255759..4df5b2951b 100644 --- a/posix/tst-rfc3484.c +++ b/posix/tst-rfc3484.c @@ -64,6 +64,7 @@ struct sockaddr_in addrs[] = #define naddrs (sizeof (addrs) / sizeof (addrs[0])) static struct addrinfo ais[naddrs]; static struct sort_result results[naddrs]; +static size_t order[naddrs]; static int expected[naddrs] = { @@ -100,18 +101,19 @@ do_test (void) memcpy(&results[i].source_addr, &so, sizeof (so)); results[i].source_addr_len = sizeof (so); results[i].source_addr_flags = 0; - results[i].service_order = i; results[i].prefixlen = 8; results[i].index = 0; + + order[i] = i; } struct sort_result_combo combo = { .results = results, .nresults = naddrs }; - qsort_r (results, naddrs, sizeof (results[0]), rfc3484_sort, &combo); + qsort_r (order, naddrs, sizeof (order[0]), rfc3484_sort, &combo); int result = 0; for (int i = 0; i < naddrs; ++i) { - struct in_addr addr = ((struct sockaddr_in *) (results[i].dest_addr->ai_addr))->sin_addr; + struct in_addr addr = ((struct sockaddr_in *) (results[order[i]].dest_addr->ai_addr))->sin_addr; int here = memcmp (&addr, &addrs[expected[i]].sin_addr, sizeof (struct in_addr)); diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index e8f4099b7f..23d463d188 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -997,8 +997,10 @@ gaih_inet (const char *name, const struct gaih_service *service, struct sort_result { struct addrinfo *dest_addr; - struct sockaddr_storage source_addr; - size_t service_order; + /* Using sockaddr_storage is for now overkill. We only support IPv4 + and IPv6 so far. If this changes at some point we can adjust the + type here. */ + struct sockaddr_in6 source_addr; uint8_t source_addr_len; bool got_source_addr; uint8_t source_addr_flags; @@ -1047,13 +1049,11 @@ static const struct scopeentry *scopes; static int -get_scope (const struct sockaddr_storage *ss) +get_scope (const struct sockaddr_in6 *in6) { int scope; - if (ss->ss_family == PF_INET6) + if (in6->sin6_family == PF_INET6) { - const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss; - if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr)) { if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)) @@ -1067,9 +1067,9 @@ get_scope (const struct sockaddr_storage *ss) else scope = in6->sin6_addr.s6_addr[1] & 0xf; } - else if (ss->ss_family == PF_INET) + else if (in6->sin6_family == PF_INET) { - const struct sockaddr_in *in = (const struct sockaddr_in *) ss; + const struct sockaddr_in *in = (const struct sockaddr_in *) in6; size_t cnt = 0; while (1) @@ -1179,18 +1179,15 @@ static const struct prefixentry default_precedence[] = static int -match_prefix (const struct sockaddr_storage *ss, +match_prefix (const struct sockaddr_in6 *in6, const struct prefixentry *list, int default_val) { int idx; struct sockaddr_in6 in6_mem; - const struct sockaddr_in6 *in6; - if (ss->ss_family == PF_INET6) - in6 = (const struct sockaddr_in6 *) ss; - else if (ss->ss_family == PF_INET) + if (in6->sin6_family == PF_INET) { - const struct sockaddr_in *in = (const struct sockaddr_in *) ss; + const struct sockaddr_in *in = (const struct sockaddr_in *) in6; /* Convert to IPv6 address. */ in6_mem.sin6_family = PF_INET6; @@ -1209,7 +1206,7 @@ match_prefix (const struct sockaddr_storage *ss, in6 = &in6_mem; } - else + else if (in6->sin6_family != PF_INET6) return default_val; for (idx = 0; ; ++idx) @@ -1241,18 +1238,18 @@ match_prefix (const struct sockaddr_storage *ss, static int -get_label (const struct sockaddr_storage *ss) +get_label (const struct sockaddr_in6 *in6) { /* XXX What is a good default value? */ - return match_prefix (ss, labels, INT_MAX); + return match_prefix (in6, labels, INT_MAX); } static int -get_precedence (const struct sockaddr_storage *ss) +get_precedence (const struct sockaddr_in6 *in6) { /* XXX What is a good default value? */ - return match_prefix (ss, precedence, 0); + return match_prefix (in6, precedence, 0); } @@ -1272,9 +1269,11 @@ fls (uint32_t a) static int rfc3484_sort (const void *p1, const void *p2, void *arg) { - const struct sort_result *a1 = (const struct sort_result *) p1; - const struct sort_result *a2 = (const struct sort_result *) p2; + const size_t idx1 = *(const size_t *) p1; + const size_t idx2 = *(const size_t *) p2; struct sort_result_combo *src = (struct sort_result_combo *) arg; + struct sort_result *a1 = &src->results[idx1]; + struct sort_result *a2 = &src->results[idx2]; /* Rule 1: Avoid unusable destinations. We have the got_source_addr flag set if the destination is reachable. */ @@ -1287,10 +1286,10 @@ rfc3484_sort (const void *p1, const void *p2, void *arg) /* Rule 2: Prefer matching scope. Only interesting if both destination addresses are IPv6. */ int a1_dst_scope - = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr); + = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr); int a2_dst_scope - = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr); + = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr); if (a1->got_source_addr) { @@ -1330,11 +1329,11 @@ rfc3484_sort (const void *p1, const void *p2, void *arg) if (a1->got_source_addr) { int a1_dst_label - = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr); + = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr); int a1_src_label = get_label (&a1->source_addr); int a2_dst_label - = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr); + = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr); int a2_src_label = get_label (&a2->source_addr); if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label) @@ -1346,9 +1345,9 @@ rfc3484_sort (const void *p1, const void *p2, void *arg) /* Rule 6: Prefer higher precedence. */ int a1_prec - = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr); + = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr); int a2_prec - = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr); + = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr); if (a1_prec > a2_prec) return -1; @@ -1406,8 +1405,8 @@ rfc3484_sort (const void *p1, const void *p2, void *arg) if (a1->dest_addr->ai_family == PF_INET) { - assert (a1->source_addr.ss_family == PF_INET); - assert (a2->source_addr.ss_family == PF_INET); + assert (a1->source_addr.sin6_family == PF_INET); + assert (a2->source_addr.sin6_family == PF_INET); /* Outside of subnets, as defined by the network masks, common address prefixes for IPv4 addresses make no sense. @@ -1437,8 +1436,8 @@ rfc3484_sort (const void *p1, const void *p2, void *arg) } else if (a1->dest_addr->ai_family == PF_INET6) { - assert (a1->source_addr.ss_family == PF_INET6); - assert (a2->source_addr.ss_family == PF_INET6); + assert (a1->source_addr.sin6_family == PF_INET6); + assert (a2->source_addr.sin6_family == PF_INET6); struct sockaddr_in6 *in1_dst; struct sockaddr_in6 *in1_src; @@ -1478,7 +1477,7 @@ rfc3484_sort (const void *p1, const void *p2, void *arg) compare with the value indicating the order in which the entries have been received from the services. NB: no two entries can have the same order so the test will never return zero. */ - return a1->service_order < a2->service_order ? -1 : 1; + return idx1 < idx2 ? -1 : 1; } @@ -2100,6 +2099,7 @@ getaddrinfo (const char *name, const char *service, __libc_once (once, gaiconf_init); /* Sort results according to RFC 3484. */ struct sort_result results[nresults]; + size_t order[nresults]; struct addrinfo *q; struct addrinfo *last = NULL; char *canonname = NULL; @@ -2115,8 +2115,8 @@ getaddrinfo (const char *name, const char *service, for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next) { results[i].dest_addr = q; - results[i].service_order = i; results[i].native = -1; + order[i] = i; /* If we just looked up the address for a different protocol, reuse the result. */ @@ -2255,16 +2255,16 @@ getaddrinfo (const char *name, const char *service, __libc_lock_lock (lock); if (old_once && gaiconf_reload_flag) gaiconf_reload (); - qsort_r (results, nresults, sizeof (results[0]), rfc3484_sort, &src); + qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src); __libc_lock_unlock (lock); } else - qsort_r (results, nresults, sizeof (results[0]), rfc3484_sort, &src); + qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src); /* Queue the results up as they come out of sorting. */ - q = p = results[0].dest_addr; + q = p = results[order[0]].dest_addr; for (i = 1; i < nresults; ++i) - q = q->ai_next = results[i].dest_addr; + q = q->ai_next = results[order[i]].dest_addr; q->ai_next = NULL; /* Fill in the canonical name into the new first entry. */