address_sorting.c
Go to the documentation of this file.
1 /* $NetBSD: getaddrinfo.c,v 1.82 2006/03/25 12:09:40 rpaulo Exp $ */
2 /* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */
3 /*
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  */
32 
33 /*
34  * This is an adaptation of Android's implementation of RFC 6724
35  * (in Android's getaddrinfo.c). It has some cosmetic differences
36  * from Android's getaddrinfo.c, but Android's getaddrinfo.c was
37  * used as a guide or example of a way to implement the RFC 6724 spec when
38  * this was written.
39  */
40 
42 
43 #include <errno.h>
44 #include <inttypes.h>
45 #include <limits.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sys/types.h>
49 
50 // Scope values increase with increase in scope.
51 static const int kIPv6AddrScopeLinkLocal = 1;
52 static const int kIPv6AddrScopeSiteLocal = 2;
53 static const int kIPv6AddrScopeGlobal = 3;
54 
56  NULL;
57 
59  address_sorting_address* source) {
62 }
63 
66  return address_sorting_get_source_addr(dest, source);
67 }
68 
69 static int ipv6_prefix_match_length(const struct sockaddr_in6* sa,
70  const struct sockaddr_in6* sb) {
71  unsigned char* a = (unsigned char*)&sa->sin6_addr;
72  unsigned char* b = (unsigned char*)&sb->sin6_addr;
73  int cur_bit = 0;
74  while (cur_bit < 128) {
75  int high_bit = 1 << (CHAR_BIT - 1);
76  int a_val = a[cur_bit / CHAR_BIT] & (high_bit >> (cur_bit % CHAR_BIT));
77  int b_val = b[cur_bit / CHAR_BIT] & (high_bit >> (cur_bit % CHAR_BIT));
78  if (a_val == b_val) {
79  cur_bit++;
80  } else {
81  break;
82  }
83  }
84  return cur_bit;
85 }
86 
87 static int in6_is_addr_loopback(const struct in6_addr* ipv6_address) {
88  uint32_t* bits32 = (uint32_t*)ipv6_address;
89  return bits32[0] == 0 && bits32[1] == 0 && bits32[2] == 0 &&
90  bits32[3] == htonl(1);
91 }
92 
93 static int in6_is_addr_v4mapped(const struct in6_addr* ipv6_address) {
94  uint32_t* bits32 = (uint32_t*)ipv6_address;
95  return bits32[0] == 0 && bits32[1] == 0 && bits32[2] == htonl(0x0000ffff);
96 }
97 
98 static int in6_is_addr_v4compat(const struct in6_addr* ipv6_address) {
99  uint32_t* bits32 = (uint32_t*)ipv6_address;
100  return bits32[0] == 0 && bits32[1] == 0 && bits32[2] == 0 && bits32[3] != 0 &&
101  bits32[3] != htonl(1);
102 }
103 
104 static int in6_is_addr_sitelocal(const struct in6_addr* ipv6_address) {
105  uint8_t* bytes = (uint8_t*)ipv6_address;
106  return bytes[0] == 0xfe && (bytes[1] & 0xc0) == 0xc0;
107 }
108 
109 static int in6_is_addr_linklocal(const struct in6_addr* ipv6_address) {
110  uint8_t* bytes = (uint8_t*)ipv6_address;
111  return bytes[0] == 0xfe && (bytes[1] & 0xc0) == 0x80;
112 }
113 
114 static int in6_is_addr_6to4(const struct in6_addr* ipv6_address) {
115  uint8_t* bytes = (uint8_t*)ipv6_address;
116  return bytes[0] == 0x20 && bytes[1] == 0x02;
117 }
118 
119 static int in6_is_addr_ula(const struct in6_addr* ipv6_address) {
120  uint8_t* bytes = (uint8_t*)ipv6_address;
121  return (bytes[0] & 0xfe) == 0xfc;
122 }
123 
124 static int in6_is_addr_teredo(const struct in6_addr* ipv6_address) {
125  uint8_t* bytes = (uint8_t*)ipv6_address;
126  return bytes[0] == 0x20 && bytes[1] == 0x01 && bytes[2] == 0x00 &&
127  bytes[3] == 0x00;
128 }
129 
130 static int in6_is_addr_6bone(const struct in6_addr* ipv6_address) {
131  uint8_t* bytes = (uint8_t*)ipv6_address;
132  return bytes[0] == 0x3f && bytes[1] == 0xfe;
133 }
134 
136  const address_sorting_address* address) {
137  switch (((struct sockaddr*)address)->sa_family) {
138  case AF_INET:
140  case AF_INET6:
142  default:
144  }
145 }
146 
147 static int get_label_value(const address_sorting_address* resolved_addr) {
148  if (address_sorting_abstract_get_family(resolved_addr) ==
150  return 4;
151  } else if (address_sorting_abstract_get_family(resolved_addr) !=
153  return 1;
154  }
155  struct sockaddr_in6* ipv6_addr = (struct sockaddr_in6*)&resolved_addr->addr;
156  if (in6_is_addr_loopback(&ipv6_addr->sin6_addr)) {
157  return 0;
158  } else if (in6_is_addr_v4mapped(&ipv6_addr->sin6_addr)) {
159  return 4;
160  } else if (in6_is_addr_6to4(&ipv6_addr->sin6_addr)) {
161  return 2;
162  } else if (in6_is_addr_teredo(&ipv6_addr->sin6_addr)) {
163  return 5;
164  } else if (in6_is_addr_ula(&ipv6_addr->sin6_addr)) {
165  return 13;
166  } else if (in6_is_addr_v4compat(&ipv6_addr->sin6_addr)) {
167  return 3;
168  } else if (in6_is_addr_sitelocal(&ipv6_addr->sin6_addr)) {
169  return 11;
170  } else if (in6_is_addr_6bone(&ipv6_addr->sin6_addr)) {
171  return 12;
172  }
173  return 1;
174 }
175 
176 static int get_precedence_value(const address_sorting_address* resolved_addr) {
177  if (address_sorting_abstract_get_family(resolved_addr) ==
179  return 35;
180  } else if (address_sorting_abstract_get_family(resolved_addr) !=
182  return 1;
183  }
184  struct sockaddr_in6* ipv6_addr = (struct sockaddr_in6*)&resolved_addr->addr;
185  if (in6_is_addr_loopback(&ipv6_addr->sin6_addr)) {
186  return 50;
187  } else if (in6_is_addr_v4mapped(&ipv6_addr->sin6_addr)) {
188  return 35;
189  } else if (in6_is_addr_6to4(&ipv6_addr->sin6_addr)) {
190  return 30;
191  } else if (in6_is_addr_teredo(&ipv6_addr->sin6_addr)) {
192  return 5;
193  } else if (in6_is_addr_ula(&ipv6_addr->sin6_addr)) {
194  return 3;
195  } else if (in6_is_addr_v4compat(&ipv6_addr->sin6_addr) ||
196  in6_is_addr_sitelocal(&ipv6_addr->sin6_addr) ||
197  in6_is_addr_6bone(&ipv6_addr->sin6_addr)) {
198  return 1;
199  }
200  return 40;
201 }
202 
203 static int sockaddr_get_scope(const address_sorting_address* resolved_addr) {
204  if (address_sorting_abstract_get_family(resolved_addr) ==
206  return kIPv6AddrScopeGlobal;
207  } else if (address_sorting_abstract_get_family(resolved_addr) ==
209  struct sockaddr_in6* ipv6_addr = (struct sockaddr_in6*)&resolved_addr->addr;
210  if (in6_is_addr_loopback(&ipv6_addr->sin6_addr) ||
211  in6_is_addr_linklocal(&ipv6_addr->sin6_addr)) {
213  }
214  if (in6_is_addr_sitelocal(&ipv6_addr->sin6_addr)) {
216  }
217  return kIPv6AddrScopeGlobal;
218  }
219  return 0;
220 }
221 
224  if (first->source_addr_exists != second->source_addr_exists) {
225  return first->source_addr_exists ? -1 : 1;
226  }
227  return 0;
228 }
229 
233  bool first_src_dst_scope_matches = false;
234  if (sockaddr_get_scope(&first->dest_addr) ==
235  sockaddr_get_scope(&first->source_addr)) {
236  first_src_dst_scope_matches = true;
237  }
238  bool second_src_dst_scope_matches = false;
239  if (sockaddr_get_scope(&second->dest_addr) ==
240  sockaddr_get_scope(&second->source_addr)) {
241  second_src_dst_scope_matches = true;
242  }
243  if (first_src_dst_scope_matches != second_src_dst_scope_matches) {
244  return first_src_dst_scope_matches ? -1 : 1;
245  }
246  return 0;
247 }
248 
252  bool first_label_matches = false;
253  if (get_label_value(&first->dest_addr) ==
254  get_label_value(&first->source_addr)) {
255  first_label_matches = true;
256  }
257  bool second_label_matches = false;
258  if (get_label_value(&second->dest_addr) ==
259  get_label_value(&second->source_addr)) {
260  second_label_matches = true;
261  }
262  if (first_label_matches != second_label_matches) {
263  return first_label_matches ? -1 : 1;
264  }
265  return 0;
266 }
267 
270  return get_precedence_value(&second->dest_addr) -
271  get_precedence_value(&first->dest_addr);
272 }
273 
276  return sockaddr_get_scope(&first->dest_addr) -
277  sockaddr_get_scope(&second->dest_addr);
278 }
279 
283  if (first->source_addr_exists &&
286  second->source_addr_exists &&
289  int first_match_length =
290  ipv6_prefix_match_length((struct sockaddr_in6*)&first->source_addr.addr,
291  (struct sockaddr_in6*)&first->dest_addr.addr);
292  int second_match_length = ipv6_prefix_match_length(
293  (struct sockaddr_in6*)&second->source_addr.addr,
294  (struct sockaddr_in6*)&second->dest_addr.addr);
295  return second_match_length - first_match_length;
296  }
297  return 0;
298 }
299 
300 static int rfc_6724_compare(const void* a, const void* b) {
303  int out = 0;
305  return out;
306  }
308  return out;
309  }
311  return out;
312  }
313  // TODO: Implement rule 3; avoid deprecated addresses.
314  // TODO: Implement rule 4; avoid temporary addresses.
316  return out;
317  }
318  // TODO: Implement rule 7; prefer native transports.
319  if ((out = compare_dest_scope(first, second))) {
320  return out;
321  }
323  return out;
324  }
325  // Prefer that the sort be stable otherwise
326  return (int)(first->original_index - second->original_index);
327 }
328 
331  if (g_current_source_addr_factory == NULL) {
332  abort();
333  }
336 }
337 
339  const address_sorting_sortable* sortable) {
340  address_sorting_address expected_source_addr;
341  memset(&expected_source_addr, 0, sizeof(expected_source_addr));
342  if (memcmp(&expected_source_addr, &sortable->source_addr,
343  sizeof(address_sorting_address)) ||
344  sortable->original_index || sortable->source_addr_exists) {
345  abort();
346  }
347 }
348 
350  size_t sortables_len) {
351  for (size_t i = 0; i < sortables_len; i++) {
353  sortables[i].original_index = i;
355  &sortables[i].dest_addr, &sortables[i].source_addr);
356  }
357  qsort(sortables, sortables_len, sizeof(address_sorting_sortable),
359 }
360 
362  if (g_current_source_addr_factory != NULL) {
363  abort();
364  }
367 }
368 
370  if (g_current_source_addr_factory == NULL) {
371  abort();
372  }
375 }
address_sorting_sortable
Definition: address_sorting.h:58
address_sorting_get_source_addr_for_testing
bool address_sorting_get_source_addr_for_testing(const address_sorting_address *dest, address_sorting_address *source)
Definition: address_sorting.c:64
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
rfc_6724_compare
static int rfc_6724_compare(const void *a, const void *b)
Definition: address_sorting.c:300
address_sorting_sortable::source_addr
address_sorting_address source_addr
Definition: address_sorting.h:64
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
address_sorting_source_addr_factory::vtable
const address_sorting_source_addr_factory_vtable * vtable
Definition: address_sorting.h:90
memset
return memset(p, 0, total)
g_current_source_addr_factory
static address_sorting_source_addr_factory * g_current_source_addr_factory
Definition: address_sorting.c:55
in6_is_addr_ula
static int in6_is_addr_ula(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:119
in6_is_addr_v4compat
static int in6_is_addr_v4compat(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:98
string.h
address_sorting_get_source_addr
static bool address_sorting_get_source_addr(const address_sorting_address *dest, address_sorting_address *source)
Definition: address_sorting.c:58
address_sorting_shutdown
void address_sorting_shutdown()
Definition: address_sorting.c:369
address_sorting_sortable::source_addr_exists
bool source_addr_exists
Definition: address_sorting.h:65
in6_is_addr_linklocal
static int in6_is_addr_linklocal(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:109
compare_source_dest_labels_match
static int compare_source_dest_labels_match(const address_sorting_sortable *first, const address_sorting_sortable *second)
Definition: address_sorting.c:249
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
second
StrT second
Definition: cxa_demangle.cpp:4885
in6_is_addr_loopback
static int in6_is_addr_loopback(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:87
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
in6_is_addr_teredo
static int in6_is_addr_teredo(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:124
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
ADDRESS_SORTING_AF_INET
@ ADDRESS_SORTING_AF_INET
Definition: address_sorting.h:95
address_sorting_address::addr
char addr[128]
Definition: address_sorting.h:51
sanity_check_private_fields_are_unused
static void sanity_check_private_fields_are_unused(const address_sorting_sortable *sortable)
Definition: address_sorting.c:338
sockaddr_in6
Definition: ares_ipv6.h:25
get_label_value
static int get_label_value(const address_sorting_address *resolved_addr)
Definition: address_sorting.c:147
compare_source_dest_scope_matches
static int compare_source_dest_scope_matches(const address_sorting_sortable *first, const address_sorting_sortable *second)
Definition: address_sorting.c:230
compare_dest_scope
static int compare_dest_scope(const address_sorting_sortable *first, const address_sorting_sortable *second)
Definition: address_sorting.c:274
address_sorting_abstract_get_family
address_sorting_family address_sorting_abstract_get_family(const address_sorting_address *address)
Definition: address_sorting.c:135
in6_is_addr_6bone
static int in6_is_addr_6bone(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:130
address_sorting_create_source_addr_factory_for_current_platform
address_sorting_source_addr_factory * address_sorting_create_source_addr_factory_for_current_platform()
Definition: address_sorting_posix.c:90
address_sorting_address
Definition: address_sorting.h:50
address_sorting_init
void address_sorting_init()
Definition: address_sorting.c:361
address_sorting_source_addr_factory_vtable::get_source_addr
bool(* get_source_addr)(struct address_sorting_source_addr_factory *factory, const address_sorting_address *dest_addr, address_sorting_address *source_addr)
Definition: address_sorting.h:83
get_precedence_value
static int get_precedence_value(const address_sorting_address *resolved_addr)
Definition: address_sorting.c:176
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
qsort
void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *))
Definition: qsort.h:130
tests.qps.qps_worker.dest
dest
Definition: qps_worker.py:45
sockaddr_get_scope
static int sockaddr_get_scope(const address_sorting_address *resolved_addr)
Definition: address_sorting.c:203
ADDRESS_SORTING_UNKNOWN_FAMILY
@ ADDRESS_SORTING_UNKNOWN_FAMILY
Definition: address_sorting.h:97
address_sorting_sortable::original_index
size_t original_index
Definition: address_sorting.h:66
address_sorting_rfc_6724_sort
void address_sorting_rfc_6724_sort(address_sorting_sortable *sortables, size_t sortables_len)
Definition: address_sorting.c:349
bytes
uint8 bytes[10]
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:153
compare_source_addr_exists
static int compare_source_addr_exists(const address_sorting_sortable *first, const address_sorting_sortable *second)
Definition: address_sorting.c:222
address_sorting_override_source_addr_factory_for_testing
void address_sorting_override_source_addr_factory_for_testing(address_sorting_source_addr_factory *factory)
Definition: address_sorting.c:329
first
StrT first
Definition: cxa_demangle.cpp:4884
compare_dest_precedence
static int compare_dest_precedence(const address_sorting_sortable *first, const address_sorting_sortable *second)
Definition: address_sorting.c:268
in6_is_addr_sitelocal
static int in6_is_addr_sitelocal(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:104
kIPv6AddrScopeLinkLocal
static const int kIPv6AddrScopeLinkLocal
Definition: address_sorting.c:51
ADDRESS_SORTING_AF_INET6
@ ADDRESS_SORTING_AF_INET6
Definition: address_sorting.h:96
in6_is_addr_6to4
static int in6_is_addr_6to4(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:114
ipv6_prefix_match_length
static int ipv6_prefix_match_length(const struct sockaddr_in6 *sa, const struct sockaddr_in6 *sb)
Definition: address_sorting.c:69
sockaddr_in6::sin6_addr
struct ares_in6_addr sin6_addr
Definition: ares_ipv6.h:30
in6_is_addr_v4mapped
static int in6_is_addr_v4mapped(const struct in6_addr *ipv6_address)
Definition: address_sorting.c:93
address_sorting_source_addr_factory_vtable::destroy
void(* destroy)(struct address_sorting_source_addr_factory *factory)
Definition: address_sorting.h:86
kIPv6AddrScopeSiteLocal
static const int kIPv6AddrScopeSiteLocal
Definition: address_sorting.c:52
kIPv6AddrScopeGlobal
static const int kIPv6AddrScopeGlobal
Definition: address_sorting.c:53
address_sorting_source_addr_factory
Definition: address_sorting.h:89
compare_source_dest_prefix_match_lengths
static int compare_source_dest_prefix_match_lengths(const address_sorting_sortable *first, const address_sorting_sortable *second)
Definition: address_sorting.c:280
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
errno.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
address_sorting_internal.h
address_sorting_family
address_sorting_family
Definition: address_sorting.h:94


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:40