15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/address_sorter_posix.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) || defined(OS_BSD)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>  // Must be included before ifaddrs.h.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ifaddrs.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <net/if.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in_var.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ioctl.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/datagram_client_socket.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_tracker_linux.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Address sorting is performed according to RFC3484 with revisions.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://tools.ietf.org/html/draft-ietf-6man-rfc3484bis-06
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Precedence and label are separate to support override through /etc/gai.conf.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |p1| should precede |p2| in the table.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sorts table by decreasing prefix size to allow longest prefix matching.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ComparePolicy(const AddressSorterPosix::PolicyEntry& p1,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const AddressSorterPosix::PolicyEntry& p2) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p1.prefix_length > p2.prefix_length;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates sorted PolicyTable from |table| with |size| entries.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::PolicyTable LoadPolicy(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddressSorterPosix::PolicyEntry* table,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressSorterPosix::PolicyTable result(table, table + size);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(result.begin(), result.end(), ComparePolicy);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Search |table| for matching prefix of |address|. |table| must be sorted by
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descending prefix (prefix of another prefix must be later in table).
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned GetPolicyValue(const AddressSorterPosix::PolicyTable& table,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const IPAddressNumber& address) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.size() == kIPv4AddressSize)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetPolicyValue(table, ConvertIPv4NumberToIPv6Number(address));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < table.size(); ++i) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AddressSorterPosix::PolicyEntry& entry = table[i];
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressNumber prefix(entry.prefix, entry.prefix + kIPv6AddressSize);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IPNumberMatchesPrefix(address, prefix, entry.prefix_length))
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return entry.value;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last entry is the least restrictive, so assume it's default.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return table.back().value;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIPv6Multicast(const IPAddressNumber& address) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kIPv6AddressSize, address.size());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address[0] == 0xFF;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::AddressScope GetIPv6MulticastScope(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& address) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kIPv6AddressSize, address.size());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<AddressSorterPosix::AddressScope>(address[1] & 0x0F);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIPv6Loopback(const IPAddressNumber& address) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kIPv6AddressSize, address.size());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IN6_IS_ADDR_LOOPBACK
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char kLoopback[kIPv6AddressSize] = {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 0, 0, 0, 0, 0, 0, 0,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 0, 0, 0, 0, 0, 0, 1,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address == IPAddressNumber(kLoopback, kLoopback + kIPv6AddressSize);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIPv6LinkLocal(const IPAddressNumber& address) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kIPv6AddressSize, address.size());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IN6_IS_ADDR_LINKLOCAL
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (address[0] == 0xFE) && ((address[1] & 0xC0) == 0x80);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIPv6SiteLocal(const IPAddressNumber& address) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kIPv6AddressSize, address.size());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IN6_IS_ADDR_SITELOCAL
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (address[0] == 0xFE) && ((address[1] & 0xC0) == 0xC0);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::AddressScope GetScope(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AddressSorterPosix::PolicyTable& ipv4_scope_table,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& address) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.size() == kIPv6AddressSize) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsIPv6Multicast(address)) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetIPv6MulticastScope(address);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (IsIPv6Loopback(address) || IsIPv6LinkLocal(address)) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddressSorterPosix::SCOPE_LINKLOCAL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (IsIPv6SiteLocal(address)) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddressSorterPosix::SCOPE_SITELOCAL;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AddressSorterPosix::SCOPE_GLOBAL;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (address.size() == kIPv4AddressSize) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<AddressSorterPosix::AddressScope>(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetPolicyValue(ipv4_scope_table, address));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AddressSorterPosix::SCOPE_NODELOCAL;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default policy table. RFC 3484, Section 2.1.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::PolicyEntry kDefaultPrecedenceTable[] = {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::1/128 -- loopback
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 128, 50 },
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::/0 -- any
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { }, 0, 40 },
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::ffff:0:0/96 -- IPv4 mapped
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF }, 96, 35 },
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2002::/16 -- 6to4
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0x20, 0x02, }, 16, 30 },
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2001::/32 -- Teredo
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0x20, 0x01, 0, 0 }, 32, 5 },
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fc00::/7 -- unique local address
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0xFC }, 7, 3 },
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::/96 -- IPv4 compatible
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 1 },
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fec0::/10 -- site-local expanded scope
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0xFE, 0xC0 }, 10, 1 },
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3ffe::/16 -- 6bone
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0x3F, 0xFE }, 16, 1 },
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::PolicyEntry kDefaultLabelTable[] = {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::1/128 -- loopback
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 128, 0 },
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::/0 -- any
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { }, 0, 1 },
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::ffff:0:0/96 -- IPv4 mapped
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF }, 96, 4 },
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2002::/16 -- 6to4
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0x20, 0x02, }, 16, 2 },
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2001::/32 -- Teredo
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0x20, 0x01, 0, 0 }, 32, 5 },
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fc00::/7 -- unique local address
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0xFC }, 7, 13 },
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::/96 -- IPv4 compatible
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 3 },
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fec0::/10 -- site-local expanded scope
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0xFE, 0xC0 }, 10, 11 },
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3ffe::/16 -- 6bone
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0x3F, 0xFE }, 16, 12 },
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default mapping of IPv4 addresses to scope.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::PolicyEntry kDefaultIPv4ScopeTable[] = {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0x7F }, 104,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddressSorterPosix::SCOPE_LINKLOCAL },
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0xA9, 0xFE }, 112,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddressSorterPosix::SCOPE_LINKLOCAL },
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { { }, 0, AddressSorterPosix::SCOPE_GLOBAL },
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns number of matching initial bits between the addresses |a1| and |a2|.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned CommonPrefixLength(const IPAddressNumber& a1,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const IPAddressNumber& a2) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(a1.size(), a2.size());
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < a1.size(); ++i) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned diff = a1[i] ^ a2[i];
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!diff)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned j = 0; j < CHAR_BIT; ++j) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (diff & (1 << (CHAR_BIT - 1)))
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return i * CHAR_BIT + j;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      diff <<= 1;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return a1.size() * CHAR_BIT;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Computes the number of leading 1-bits in |mask|.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned MaskPrefixLength(const IPAddressNumber& mask) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber all_ones(mask.size(), 0xFF);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CommonPrefixLength(mask, all_ones);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DestinationInfo {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber address;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressSorterPosix::AddressScope scope;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned precedence;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned label;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AddressSorterPosix::SourceAddressInfo* src;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned common_prefix_length;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true iff |dst_a| should precede |dst_b| in the address list.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RFC 3484, section 6.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CompareDestinations(const DestinationInfo* dst_a,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const DestinationInfo* dst_b) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 1: Avoid unusable destinations.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unusable destinations are already filtered out.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dst_a->src);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dst_b->src);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 2: Prefer matching scope.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool scope_match1 = (dst_a->src->scope == dst_a->scope);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool scope_match2 = (dst_b->src->scope == dst_b->scope);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scope_match1 != scope_match2)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scope_match1;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 3: Avoid deprecated addresses.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dst_a->src->deprecated != dst_b->src->deprecated)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !dst_a->src->deprecated;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 4: Prefer home addresses.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dst_a->src->home != dst_b->src->home)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dst_a->src->home;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 5: Prefer matching label.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool label_match1 = (dst_a->src->label == dst_a->label);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool label_match2 = (dst_b->src->label == dst_b->label);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (label_match1 != label_match2)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return label_match1;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 6: Prefer higher precedence.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dst_a->precedence != dst_b->precedence)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dst_a->precedence > dst_b->precedence;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 7: Prefer native transport.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dst_a->src->native != dst_b->src->native)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dst_a->src->native;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 8: Prefer smaller scope.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dst_a->scope != dst_b->scope)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dst_a->scope < dst_b->scope;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 9: Use longest matching prefix. Only for matching address families.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dst_a->address.size() == dst_b->address.size()) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dst_a->common_prefix_length != dst_b->common_prefix_length)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dst_a->common_prefix_length > dst_b->common_prefix_length;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rule 10: Leave the order unchanged.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stable_sort takes care of that.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::AddressSorterPosix(ClientSocketFactory* socket_factory)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : socket_factory_(socket_factory),
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      precedence_table_(LoadPolicy(kDefaultPrecedenceTable,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   arraysize(kDefaultPrecedenceTable))),
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label_table_(LoadPolicy(kDefaultLabelTable,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              arraysize(kDefaultLabelTable))),
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipv4_scope_table_(LoadPolicy(kDefaultIPv4ScopeTable,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              arraysize(kDefaultIPv4ScopeTable))) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::AddIPAddressObserver(this);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnIPAddressChanged();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AddressSorterPosix::~AddressSorterPosix() {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::RemoveIPAddressObserver(this);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddressSorterPosix::Sort(const AddressList& list,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const CallbackType& callback) const {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<DestinationInfo> sort_list;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < list.size(); ++i) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DestinationInfo> info(new DestinationInfo());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->address = list[i].address();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->scope = GetScope(ipv4_scope_table_, info->address);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->precedence = GetPolicyValue(precedence_table_, info->address);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->label = GetPolicyValue(label_table_, info->address);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Each socket can only be bound once.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DatagramClientSocket> socket(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        socket_factory_->CreateDatagramClientSocket(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DatagramSocket::DEFAULT_BIND,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            RandIntCallback(),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL /* NetLog */,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog::Source()));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Even though no packets are sent, cannot use port 0 in Connect.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPEndPoint dest(info->address, 80 /* port */);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = socket->Connect(dest);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != OK) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Could not connect to " << dest.ToStringWithoutPort()
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " reason " << rv;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Filter out unusable destinations.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPEndPoint src;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = socket->GetLocalAddress(&src);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != OK) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Could not get local address for "
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << src.ToStringWithoutPort() << " reason " << rv;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SourceAddressInfo& src_info = source_map_[src.address()];
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (src_info.scope == SCOPE_UNDEFINED) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If |source_info_| is out of date, |src| might be missing, but we still
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // want to sort, even though the HostCache will be cleared soon.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FillPolicy(src.address(), &src_info);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->src = &src_info;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (info->address.size() == src.address().size()) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info->common_prefix_length = std::min(
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CommonPrefixLength(info->address, src.address()),
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info->src->prefix_length);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sort_list.push_back(info.release());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stable_sort(sort_list.begin(), sort_list.end(), CompareDestinations);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressList result;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < sort_list.size(); ++i)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.push_back(IPEndPoint(sort_list[i]->address, 0 /* port */));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(true, result);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddressSorterPosix::OnIPAddressChanged() {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_map_.clear();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const internal::AddressTrackerLinux* tracker =
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetworkChangeNotifier::GetAddressTracker();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tracker)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef internal::AddressTrackerLinux::AddressMap AddressMap;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressMap map = tracker->GetAddressMap();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (AddressMap::const_iterator it = map.begin(); it != map.end(); ++it) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& address = it->first;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct ifaddrmsg& msg = it->second;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SourceAddressInfo& info = source_map_[address];
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.native = false;  // TODO(szym): obtain this via netlink.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.deprecated = msg.ifa_flags & IFA_F_DEPRECATED;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.home = msg.ifa_flags & IFA_F_HOMEADDRESS;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.prefix_length = msg.ifa_prefixlen;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillPolicy(address, &info);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX) || defined(OS_BSD)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's not clear we will receive notification when deprecated flag changes.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Socket for ioctl.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ioctl_socket = socket(AF_INET6, SOCK_DGRAM, 0);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ioctl_socket < 0)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ifaddrs* addrs;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = getifaddrs(&addrs);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv < 0) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "getifaddrs failed " << rv;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    close(ioctl_socket);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPEndPoint src;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!src.FromSockAddr(ifa->ifa_addr, ifa->ifa_addr->sa_len))
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SourceAddressInfo& info = source_map_[src.address()];
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note: no known way to fill in |native| and |home|.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.native = info.home = info.deprecated = false;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ifa->ifa_addr->sa_family == AF_INET6) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct in6_ifreq ifr = {};
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name) - 1);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_LE(ifa->ifa_addr->sa_len, sizeof(ifr.ifr_ifru.ifru_addr));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(&ifr.ifr_ifru.ifru_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rv = ioctl(ioctl_socket, SIOCGIFAFLAG_IN6, &ifr);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv >= 0) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        info.deprecated = ifr.ifr_ifru.ifru_flags & IN6_IFF_DEPRECATED;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "SIOCGIFAFLAG_IN6 failed " << rv;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ifa->ifa_netmask) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPEndPoint netmask;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (netmask.FromSockAddr(ifa->ifa_netmask, ifa->ifa_addr->sa_len)) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        info.prefix_length = MaskPrefixLength(netmask.address());
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "FromSockAddr failed on netmask";
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillPolicy(src.address(), &info);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  freeifaddrs(addrs);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close(ioctl_socket);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddressSorterPosix::FillPolicy(const IPAddressNumber& address,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    SourceAddressInfo* info) const {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->scope = GetScope(ipv4_scope_table_, address);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->label = GetPolicyValue(label_table_, address);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<AddressSorter> AddressSorter::CreateAddressSorter() {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_ptr<AddressSorter>(
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new AddressSorterPosix(ClientSocketFactory::GetDefaultFactory()));
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
427