Index: net/base/net_util_win.cc |
diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc |
index 7d146b91e511f2f3ba1c8f213ea90eb2652b3e4b..ec4023384c4c48699195cd51b3be7ed0506995e4 100644 |
--- a/net/base/net_util_win.cc |
+++ b/net/base/net_util_win.cc |
@@ -85,35 +85,11 @@ WlanApi::WlanApi() : initialized(false) { |
free_memory_func && close_handle_func; |
} |
-} // namespace internal |
- |
-bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
- // GetAdaptersAddresses() may require IO operations. |
- base::ThreadRestrictions::AssertIOAllowed(); |
- bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA; |
- ULONG len = 0; |
- ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0; |
- // First get number of networks. |
- ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len); |
- if (result != ERROR_BUFFER_OVERFLOW) { |
- // There are 0 networks. |
- return true; |
- } |
- scoped_ptr<char[]> buf(new char[len]); |
- IP_ADAPTER_ADDRESSES *adapters = |
- reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get()); |
- result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len); |
- if (result != NO_ERROR) { |
- LOG(ERROR) << "GetAdaptersAddresses failed: " << result; |
- return false; |
- } |
- |
- // These two variables are used below when this method is asked to pick a |
- // IPv6 address which has the shortest lifetime. |
- ULONG ipv6_valid_lifetime = 0; |
- scoped_ptr<NetworkInterface> ipv6_address; |
- |
- for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL; |
+bool GetNetworkListImpl(NetworkInterfaceList* networks, |
+ int policy, |
+ bool is_xp, |
+ const IP_ADAPTER_ADDRESSES* adapters) { |
+ for (const IP_ADAPTER_ADDRESSES* adapter = adapters; adapter != NULL; |
adapter = adapter->Next) { |
// Ignore the loopback device. |
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { |
@@ -128,7 +104,7 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
// VMware Virtual Ethernet Adapter for VMnet1 |
// but don't ignore any GUEST side adapters with a description like: |
// VMware Accelerated AMD PCNet Adapter #2 |
- if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES && |
+ if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) && |
strstr(adapter->AdapterName, "VMnet") != NULL) { |
continue; |
} |
@@ -141,7 +117,7 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
if (endpoint.FromSockAddr(address->Address.lpSockaddr, |
address->Address.iSockaddrLength)) { |
// XP has no OnLinkPrefixLength field. |
- size_t net_prefix = is_xp ? 0 : address->OnLinkPrefixLength; |
+ size_t prefix_length = is_xp ? 0 : address->OnLinkPrefixLength; |
if (is_xp) { |
// Prior to Windows Vista the FirstPrefix pointed to the list with |
// single prefix for each IP address assigned to the adapter. |
@@ -157,50 +133,70 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
IPNumberMatchesPrefix(endpoint.address(), |
network_endpoint.address(), |
prefix->PrefixLength)) { |
- net_prefix = std::max<size_t>(net_prefix, prefix->PrefixLength); |
+ prefix_length = |
+ std::max<size_t>(prefix_length, prefix->PrefixLength); |
} |
} |
} |
+ |
+ // If the duplicate address detection (DAD) state is not changed to |
+ // Preferred, skip this address. |
+ if (address->DadState != IpDadStatePreferred) { |
+ continue; |
+ } |
+ |
uint32 index = |
(family == AF_INET) ? adapter->IfIndex : adapter->Ipv6IfIndex; |
- // Pick one IPv6 address with least valid lifetime. |
- // The reason we are checking |ValidLifeftime| as there is no other |
- // way identifying the interface type. Usually (and most likely) temp |
- // IPv6 will have a shorter ValidLifetime value then the permanent |
- // interface. |
- if (family == AF_INET6 && |
- (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE)) { |
- if (ipv6_valid_lifetime == 0 || |
- ipv6_valid_lifetime > address->ValidLifetime) { |
- ipv6_valid_lifetime = address->ValidLifetime; |
- ipv6_address.reset(new NetworkInterface( |
- adapter->AdapterName, |
- base::SysWideToNativeMB(adapter->FriendlyName), |
- index, |
- GetNetworkInterfaceType(adapter->IfType), |
- endpoint.address(), |
- net_prefix, |
- IP_ADDRESS_ATTRIBUTE_NONE)); |
- continue; |
+ |
+ // From http://technet.microsoft.com/en-us/ff568768(v=vs.60).aspx, the |
+ // way to identify a temporary IPv6 Address is to check if |
+ // PrefixOrigin is equal to IpPrefixOriginRouterAdvertisement and |
+ // SuffixOrigin equal to IpSuffixOriginRandom. |
+ int ip_address_attributes = IP_ADDRESS_ATTRIBUTE_NONE; |
+ if (family == AF_INET6) { |
+ if (address->PrefixOrigin == IpPrefixOriginRouterAdvertisement && |
+ address->SuffixOrigin == IpSuffixOriginRandom) { |
+ ip_address_attributes |= IP_ADDRESS_ATTRIBUTE_TEMPORARY; |
+ } |
+ if (address->PreferredLifetime == 0) { |
+ ip_address_attributes |= IP_ADDRESS_ATTRIBUTE_DEPRECATED; |
} |
} |
- networks->push_back( |
- NetworkInterface(adapter->AdapterName, |
- base::SysWideToNativeMB(adapter->FriendlyName), |
- index, |
- GetNetworkInterfaceType(adapter->IfType), |
- endpoint.address(), |
- net_prefix, |
- IP_ADDRESS_ATTRIBUTE_NONE)); |
+ networks->push_back(NetworkInterface( |
+ adapter->AdapterName, |
+ base::SysWideToNativeMB(adapter->FriendlyName), index, |
+ GetNetworkInterfaceType(adapter->IfType), endpoint.address(), |
+ prefix_length, ip_address_attributes)); |
} |
} |
} |
} |
+ return true; |
+} |
+ |
+} // namespace internal |
- if (ipv6_address.get()) { |
- networks->push_back(*(ipv6_address.get())); |
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
+ bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA; |
+ ULONG len = 0; |
+ ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0; |
+ // GetAdaptersAddresses() may require IO operations. |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len); |
+ if (result != ERROR_BUFFER_OVERFLOW) { |
+ // There are 0 networks. |
+ return true; |
} |
- return true; |
+ scoped_ptr<char[]> buf(new char[len]); |
+ IP_ADAPTER_ADDRESSES* adapters = |
+ reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get()); |
+ result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len); |
+ if (result != NO_ERROR) { |
+ LOG(ERROR) << "GetAdaptersAddresses failed: " << result; |
+ return false; |
+ } |
+ |
+ return internal::GetNetworkListImpl(networks, policy, is_xp, adapters); |
} |
WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { |