Alien-cares
view release on metacpan or search on metacpan
libcares/ares_getaddrinfo.c view on Meta::CPAN
const struct sockaddr_in6 *a1_dst =
(const struct sockaddr_in6 *)a1->ai->ai_addr;
const struct sockaddr_in6 *a2_src = &a2->src_addr.sa6;
const struct sockaddr_in6 *a2_dst =
(const struct sockaddr_in6 *)a2->ai->ai_addr;
prefixlen1 = common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr);
prefixlen2 = common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr);
if (prefixlen1 != prefixlen2)
{
return prefixlen2 - prefixlen1;
}
}
/*
* Rule 10: Leave the order unchanged.
* We need this since qsort() is not necessarily stable.
*/
return a1->original_order - a2->original_order;
}
static int get_scope(const struct sockaddr *addr)
{
if (addr->sa_family == AF_INET6)
{
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr))
{
return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr);
}
else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) ||
IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr))
{
/*
* RFC 4291 section 2.5.3 says loopback is to be treated as having
* link-local scope.
*/
return IPV6_ADDR_SCOPE_LINKLOCAL;
}
else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr))
{
return IPV6_ADDR_SCOPE_SITELOCAL;
}
else
{
return IPV6_ADDR_SCOPE_GLOBAL;
}
}
else if (addr->sa_family == AF_INET)
{
const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
unsigned long int na = ntohl(addr4->sin_addr.s_addr);
if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */
(na & 0xffff0000) == 0xa9fe0000)
{ /* 169.254.0.0/16 */
return IPV6_ADDR_SCOPE_LINKLOCAL;
}
else
{
/*
* RFC 6724 section 3.2. Other IPv4 addresses, including private
* addresses and shared addresses (100.64.0.0/10), are assigned global
* scope.
*/
return IPV6_ADDR_SCOPE_GLOBAL;
}
}
else
{
/*
* This should never happen.
* Return a scope with low priority as a last resort.
*/
return IPV6_ADDR_SCOPE_NODELOCAL;
}
}
static int get_label(const struct sockaddr *addr)
{
if (addr->sa_family == AF_INET)
{
return 4;
}
else if (addr->sa_family == AF_INET6)
{
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr))
{
return 0;
}
else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr))
{
return 4;
}
else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr))
{
return 2;
}
else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr))
{
return 5;
}
else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr))
{
return 13;
}
else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr))
{
return 3;
}
else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr))
{
return 11;
}
else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr))
{
return 12;
}
else
{
/* All other IPv6 addresses, including global unicast addresses. */
return 1;
}
}
else
{
/*
* This should never happen.
* Return a semi-random label as a last resort.
*/
return 1;
}
}
/*
* Get the precedence for a given IPv4/IPv6 address.
* RFC 6724, section 2.1.
*/
static int get_precedence(const struct sockaddr *addr)
{
if (addr->sa_family == AF_INET)
{
return 35;
}
else if (addr->sa_family == AF_INET6)
{
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr))
{
return 50;
}
else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr))
{
return 35;
}
else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr))
{
return 30;
}
else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr))
{
return 5;
}
else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr))
{
return 3;
}
else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
IN6_IS_ADDR_6BONE(&addr6->sin6_addr))
{
return 1;
}
else
{
/* All other IPv6 addresses, including global unicast addresses. */
return 40;
}
}
else
{
return 1;
}
}
static int common_prefix_len(const struct in6_addr *a1,
const struct in6_addr *a2)
{
const char *p1 = (const char *)a1;
const char *p2 = (const char *)a2;
unsigned i;
for (i = 0; i < sizeof(*a1); ++i)
{
int x, j;
if (p1[i] == p2[i])
{
continue;
}
x = p1[i] ^ p2[i];
for (j = 0; j < CHAR_BIT; ++j)
{
if (x & (1 << (CHAR_BIT - 1)))
{
return i * CHAR_BIT + j;
}
x <<= 1;
}
}
return sizeof(*a1) * CHAR_BIT;
}
( run in 0.482 second using v1.01-cache-2.11-cpan-e1769b4cff6 )