Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: net/base/net_util_posix.cc

Issue 670183003: Update from chromium 62675d9fb31fb8cedc40f68e78e8445a74f362e7 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/net_util_posix.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/net_util_posix.cc
diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc
index 73704cde69de5b5697acf1a5d621a5d880d5c1da..a2fa6cdf2ce7c1c871c4415911fe04c6b2d51602 100644
--- a/net/base/net_util_posix.cc
+++ b/net/base/net_util_posix.cc
@@ -19,11 +19,16 @@
#include "net/base/net_errors.h"
#include "url/gurl.h"
-#if !defined(OS_ANDROID) && !defined(OS_NACL)
+#if !defined(OS_NACL)
+#if defined(OS_MACOSX)
#include <ifaddrs.h>
+#else
+#include "net/base/address_tracker_linux.h"
+#include "net/base/net_util_posix.h"
+#endif // OS_MACOSX
#include <net/if.h>
#include <netinet/in.h>
-#endif
+#endif // !defined(OS_NACL)
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include <net/if_media.h>
@@ -31,15 +36,48 @@
#include <sys/ioctl.h>
#endif
-#if defined(OS_ANDROID)
-#include "net/android/network_library.h"
-#endif
-
namespace net {
namespace {
-#if !defined(OS_ANDROID)
+// The application layer can pass |policy| defined in net_util.h to
+// request filtering out certain type of interfaces.
+bool ShouldIgnoreInterface(const std::string& name, int policy) {
+ // Filter out VMware interfaces, typically named vmnet1 and vmnet8,
+ // which might not be useful for use cases like WebRTC.
+ if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) &&
+ ((name.find("vmnet") != std::string::npos) ||
+ (name.find("vnic") != std::string::npos))) {
+ return true;
+ }
+
+ return false;
+}
+
+// Check if the address is unspecified (i.e. made of zeroes) or loopback.
+bool IsLoopbackOrUnspecifiedAddress(const sockaddr* addr) {
+ if (addr->sa_family == AF_INET6) {
+ const struct sockaddr_in6* addr_in6 =
+ reinterpret_cast<const struct sockaddr_in6*>(addr);
+ const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
+ if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) {
+ return true;
+ }
+ } else if (addr->sa_family == AF_INET) {
+ const struct sockaddr_in* addr_in =
+ reinterpret_cast<const struct sockaddr_in*>(addr);
+ if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK ||
+ addr_in->sin_addr.s_addr == 0) {
+ return true;
+ }
+ } else {
+ // Skip non-IP addresses.
+ return true;
+ }
+ return false;
+}
+
+#if defined(OS_MACOSX)
struct NetworkInterfaceInfo {
NetworkInterfaceInfo() : permanent(true) { }
@@ -83,10 +121,7 @@ void RemovePermanentIPv6AddressesWhereTemporaryExists(
}
}
-#endif
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-
+#if !defined(OS_IOS)
NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(
int addr_family, const std::string& interface_name) {
NetworkChangeNotifier::ConnectionType type =
@@ -111,50 +146,151 @@ NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(
return type;
}
-#endif
+#endif // !defined(OS_IOS)
+#elif !defined(OS_NACL) // OS_MACOSX
+
+// Convert platform native IPv6 address attributes to net IP address
+// attributes and drop ones that can't be used by the application
+// layer.
+bool TryConvertNativeToNetIPAttributes(int native_attributes,
+ int* net_attributes) {
+ // For Linux/ChromeOS/Android, we disallow addresses with attributes
+ // IFA_F_OPTIMISTIC, IFA_F_DADFAILED, and IFA_F_TENTATIVE as these
+ // are still progressing through duplicated address detection (DAD)
+ // and shouldn't be used by the application layer until DAD process
+ // is completed.
+ if (native_attributes & (
+#if !defined(OS_ANDROID)
+ IFA_F_OPTIMISTIC | IFA_F_DADFAILED |
+#endif // !OS_ANDROID
+ IFA_F_TENTATIVE)) {
+ return false;
+ }
+ if (native_attributes & IFA_F_TEMPORARY) {
+ *net_attributes |= IP_ADDRESS_ATTRIBUTE_TEMPORARY;
+ }
+
+ if (native_attributes & IFA_F_DEPRECATED) {
+ *net_attributes |= IP_ADDRESS_ATTRIBUTE_DEPRECATED;
+ }
+
+ return true;
+}
+#endif // OS_MACOSX
} // namespace
-bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
-#if defined(OS_NACL)
- NOTIMPLEMENTED();
- return false;
-#elif defined(OS_ANDROID)
- std::string network_list = android::GetNetworkList();
- base::StringTokenizer network_interfaces(network_list, "\n");
- while (network_interfaces.GetNext()) {
- std::string network_item = network_interfaces.token();
- base::StringTokenizer network_tokenizer(network_item, "\t");
- CHECK(network_tokenizer.GetNext());
- std::string name = network_tokenizer.token();
-
- CHECK(network_tokenizer.GetNext());
- std::string interface_address = network_tokenizer.token();
- IPAddressNumber address;
- size_t network_prefix = 0;
- CHECK(ParseCIDRBlock(network_tokenizer.token(),
- &address,
- &network_prefix));
-
- CHECK(network_tokenizer.GetNext());
- uint32 index = 0;
- CHECK(base::StringToUint(network_tokenizer.token(), &index));
+namespace internal {
+
+#if !defined(OS_MACOSX) && !defined(OS_NACL)
+
+inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) {
+#if defined(OS_ANDROID)
+ return ip.begin();
+#else
+ return ip.data();
+#endif
+}
+
+bool GetNetworkListImpl(
+ NetworkInterfaceList* networks,
+ int policy,
+ const base::hash_set<int>& online_links,
+ const internal::AddressTrackerLinux::AddressMap& address_map,
+ GetInterfaceNameFunction get_interface_name) {
+ std::map<int, std::string> ifnames;
+
+ for (internal::AddressTrackerLinux::AddressMap::const_iterator it =
+ address_map.begin();
+ it != address_map.end();
+ ++it) {
+ // Ignore addresses whose links are not online.
+ if (online_links.find(it->second.ifa_index) == online_links.end())
+ continue;
+
+ sockaddr_storage sock_addr;
+ socklen_t sock_len = sizeof(sockaddr_storage);
+
+ // Convert to sockaddr for next check.
+ if (!IPEndPoint(it->first, 0)
+ .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addr), &sock_len)) {
+ continue;
+ }
+
+ // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses
+ if (IsLoopbackOrUnspecifiedAddress(reinterpret_cast<sockaddr*>(&sock_addr)))
+ continue;
+
+ int ip_attributes = IP_ADDRESS_ATTRIBUTE_NONE;
+
+ if (it->second.ifa_family == AF_INET6) {
+ // Ignore addresses whose attributes are not actionable by
+ // the application layer.
+ if (!TryConvertNativeToNetIPAttributes(it->second.ifa_flags,
+ &ip_attributes))
+ continue;
+ }
+
+ // Find the name of this link.
+ std::map<int, std::string>::const_iterator itname =
+ ifnames.find(it->second.ifa_index);
+ std::string ifname;
+ if (itname == ifnames.end()) {
+ char buffer[IF_NAMESIZE] = {0};
+ if (get_interface_name(it->second.ifa_index, buffer)) {
+ ifname = ifnames[it->second.ifa_index] = buffer;
+ } else {
+ // Ignore addresses whose interface name can't be retrieved.
+ continue;
+ }
+ } else {
+ ifname = itname->second;
+ }
+
+ // Based on the interface name and policy, determine whether we
+ // should ignore it.
+ if (ShouldIgnoreInterface(ifname, policy))
+ continue;
networks->push_back(
- NetworkInterface(name,
- name,
- index,
+ NetworkInterface(ifname,
+ ifname,
+ it->second.ifa_index,
NetworkChangeNotifier::CONNECTION_UNKNOWN,
- address,
- network_prefix,
- IP_ADDRESS_ATTRIBUTE_NONE));
+ it->first,
+ it->second.ifa_prefixlen,
+ ip_attributes));
}
+
return true;
-#else
+}
+#endif
+
+} // namespace internal
+
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
+ if (networks == NULL)
+ return false;
+#if defined(OS_NACL)
+ NOTIMPLEMENTED();
+ return false;
+#elif !defined(OS_MACOSX)
+
+ internal::AddressTrackerLinux tracker;
+ tracker.Init();
+
+ return internal::GetNetworkListImpl(networks,
+ policy,
+ tracker.GetOnlineLinks(),
+ tracker.GetAddressMap(),
+ &if_indextoname);
+
+#else // Only OS_MACOSX and OS_IOS will run the code below
+
// getifaddrs() may require IO operations.
base::ThreadRestrictions::AssertIOAllowed();
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if !defined(OS_IOS)
int ioctl_socket = -1;
if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) {
// we need a socket to query information about temporary address.
@@ -163,7 +299,7 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
}
#endif
- ifaddrs *interfaces;
+ ifaddrs* interfaces;
if (getifaddrs(&interfaces) < 0) {
PLOG(ERROR) << "getifaddrs";
return false;
@@ -187,41 +323,26 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
// Skip unspecified addresses (i.e. made of zeroes) and loopback addresses
// configured on non-loopback interfaces.
+ if (IsLoopbackOrUnspecifiedAddress(addr))
+ continue;
+
int addr_size = 0;
if (addr->sa_family == AF_INET6) {
- struct sockaddr_in6* addr_in6 =
- reinterpret_cast<struct sockaddr_in6*>(addr);
- struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
- addr_size = sizeof(*addr_in6);
- if (IN6_IS_ADDR_LOOPBACK(sin6_addr) ||
- IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) {
- continue;
- }
+ addr_size = sizeof(sockaddr_in6);
} else if (addr->sa_family == AF_INET) {
- struct sockaddr_in* addr_in =
- reinterpret_cast<struct sockaddr_in*>(addr);
- addr_size = sizeof(*addr_in);
- if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK ||
- addr_in->sin_addr.s_addr == 0) {
- continue;
- }
- } else {
- // Skip non-IP addresses.
- continue;
+ addr_size = sizeof(sockaddr_in);
}
const std::string& name = interface->ifa_name;
// Filter out VMware interfaces, typically named vmnet1 and vmnet8.
- if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) &&
- ((name.find("vmnet") != std::string::npos) ||
- (name.find("vnic") != std::string::npos))) {
+ if (ShouldIgnoreInterface(name, policy)) {
continue;
}
NetworkInterfaceInfo network_info;
NetworkChangeNotifier::ConnectionType connection_type =
NetworkChangeNotifier::CONNECTION_UNKNOWN;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if !defined(OS_IOS)
// Check if this is a temporary address. Currently this is only supported
// on Mac.
if ((policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) &&
@@ -264,7 +385,7 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
}
}
freeifaddrs(interfaces);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if !defined(OS_IOS)
if (ioctl_socket >= 0) {
close(ioctl_socket);
}
« no previous file with comments | « net/base/net_util_posix.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698