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

Unified Diff: net/base/net_util_posix.cc

Issue 213423004: Detect IPv6 interface is temporary or not. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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
Index: net/base/net_util_posix.cc
diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc
index 8b9e067f4faad7972a84f222795607086f43f99a..36c7c1e1cd8b68eb3e77143b17e8cd07211d6657 100644
--- a/net/base/net_util_posix.cc
+++ b/net/base/net_util_posix.cc
@@ -23,12 +23,73 @@
#include <net/if.h>
#include <netinet/in.h>
+#if defined(OS_MACOSX) || defined(OS_BSD)
+#include <netinet/in_var.h>
+#include <sys/ioctl.h>
+#endif
+
#if defined(OS_ANDROID)
#include "net/android/network_library.h"
#endif
namespace net {
+namespace {
+
+#if !defined(OS_ANDROID)
+
+struct NET_EXPORT NetworkInterfaceInfo {
+ NetworkInterfaceInfo() : permanent(true) {}
+
+ bool permanent; // IPv6 has notion of temporary address. If the address is
+ // IPv6 and it's temporary this field will be set to false.
agl 2014/03/27 14:52:53 remove "set to"
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+ NetworkInterface interface;
+};
+
+// This method will remove permanent IPv6 address, if a temporary address
agl 2014/03/27 14:52:53 remove comma
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+// is available for same network interface.
+void PruneIPv6Addresses(std::vector<NetworkInterfaceInfo>* infos) {
agl 2014/03/27 14:52:53 I would go nuts with the name in order to make thi
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 I Agree. On 2014/03/27 14:52:53, agl wrote:
+ // First find a temporary address. If available find permanent address
+ // belonging to same interface. If available remove it.
+
+ // Pushing all IPv6 temp addresses to a different list.
+ std::vector<NetworkInterfaceInfo> temp_ipv6_list;
+ std::vector<NetworkInterfaceInfo>::iterator iter = infos->begin();
agl 2014/03/27 14:52:53 If you just just |i| for iter then you can use |j|
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+ for (; iter != infos->end(); ++iter) {
agl 2014/03/27 14:52:53 do the assignment of iter in the first for clause.
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+ if (iter->permanent && iter->interface.address.size() == kIPv6AddressSize) {
agl 2014/03/27 14:52:53 This is pushing permanent addresses into a list ca
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Yea, I discovered that later. On 2014/03/27 14:52:
+ temp_ipv6_list.push_back(*iter);
+ iter = infos->erase(iter);
+ }
+ }
+
+ // Search for permenent address belonging to same network interface.
+ iter = temp_ipv6_list.begin();
agl 2014/03/27 14:52:53 move into the for loop.
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+ for (; iter != temp_ipv6_list.end(); ++iter) {
+ std::string name = iter->interface.name;
agl 2014/03/27 14:52:53 const &?
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 not needed. On 2014/03/27 14:52:53, agl wrote:
+ std::vector<NetworkInterfaceInfo>::iterator piter = infos->begin();
+ for (; piter != infos->end(); ++piter) {
+ if (piter->interface.address.size() == kIPv4AddressSize)
+ continue;
+ if (piter->interface.name != iter->interface.name)
agl 2014/03/27 14:52:53 RHS should be |name|?
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 removed now. On 2014/03/27 14:52:53, agl wrote:
+ continue;
+ DCHECK_EQ(piter->interface.address.size(), kIPv6AddressSize);
+ piter = infos->erase(piter);
+ }
+ }
agl 2014/03/27 14:52:53 Isn't it easier to do one pass building a set?: s
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Cool, that makes life bit easy. On 2014/03/27 14:5
+
+ // Push temp addresses back to original list.
+ iter = temp_ipv6_list.begin();
+ for (; iter != temp_ipv6_list.end(); ++iter) {
+ infos->push_back(*iter);
+ }
+
+ // TODO(mallinath) Above logic seems to be it "quirky", find better solution.
+}
+
+#endif
+
+} // namespace
+
bool FileURLToFilePath(const GURL& url, base::FilePath* path) {
*path = base::FilePath();
std::string& file_path_str = const_cast<std::string&>(path->value());
@@ -63,8 +124,7 @@ bool FileURLToFilePath(const GURL& url, base::FilePath* path) {
return !file_path_str.empty();
}
-bool GetNetworkList(NetworkInterfaceList* networks,
- HostScopeVirtualInterfacePolicy policy) {
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
#if defined(OS_ANDROID)
std::string network_list = android::GetNetworkList();
base::StringTokenizer network_interfaces(network_list, "\n");
@@ -94,12 +154,21 @@ bool GetNetworkList(NetworkInterfaceList* networks,
// getifaddrs() may require IO operations.
base::ThreadRestrictions::AssertIOAllowed();
+ int ioctl_socket = -1;
+ if (policy & INCLUDE_IPV6_TEMP_ADDRESS_IF_AVAILABLE) {
+ // we need a socket to query information about temporary address.
+ ioctl_socket = socket(AF_INET6, SOCK_DGRAM, 0);
+ DCHECK_GT(ioctl_socket, 0);
+ }
+
ifaddrs *interfaces;
if (getifaddrs(&interfaces) < 0) {
PLOG(ERROR) << "getifaddrs";
return false;
}
+ std::vector<NetworkInterfaceInfo> network_infos;
+
// Enumerate the addresses assigned to network interfaces which are up.
for (ifaddrs *interface = interfaces;
interface != NULL;
@@ -141,11 +210,29 @@ bool GetNetworkList(NetworkInterfaceList* networks,
const std::string& name = interface->ifa_name;
// Filter out VMware interfaces, typically named vmnet1 and vmnet8.
- if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES &&
+ if (policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES &&
((name.find("vmnet") != std::string::npos) ||
(name.find("vnic") != std::string::npos))) {
continue;
}
+
+ NetworkInterfaceInfo network_info;
+#if defined(OS_MACOSX) || defined(OS_BSD)
+ // Check if this is a temporary address. Currently this is only supported
+ // on Mac.
+ if (policy & INCLUDE_IPV6_TEMP_ADDRESS_IF_AVAILABLE &&
+ ioctl_socket > 0 && addr->sa_family == AF_INET6) {
agl 2014/03/27 14:52:53 ioctl_socket >= 0
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+ struct in6_ifreq ifr = {};
+ strncpy(ifr.ifr_name, interface->ifa_name, sizeof(ifr.ifr_name) - 1);
+ memcpy(&ifr.ifr_ifru.ifru_addr, interface->ifa_addr,
+ interface->ifa_addr->sa_len);
+ int rv = ioctl(ioctl_socket, SIOCGIFAFLAG_IN6, &ifr);
+ if (rv >= 0) {
+ network_info.permanent = !(ifr.ifr_ifru.ifru_flags & IN6_IFF_TEMPORARY);
+ }
+ }
+#endif
+
IPEndPoint address;
if (address.FromSockAddr(addr, addr_size)) {
uint8 net_mask = 0;
@@ -159,15 +246,23 @@ bool GetNetworkList(NetworkInterfaceList* networks,
net_mask = MaskPrefixLength(netmask.address());
}
}
+ network_info.interface = NetworkInterface(
+ name, name, if_nametoindex(name.c_str()),
+ address.address(), net_mask);
- networks->push_back(
- NetworkInterface(name, name, if_nametoindex(name.c_str()),
- address.address(), net_mask));
+ network_infos.push_back(network_info);
}
}
-
freeifaddrs(interfaces);
+ close(ioctl_socket);
agl 2014/03/27 14:52:53 guard this by an if - we shouldn't call close(-1)
Mallinath (Gone from Chromium) 2014/03/27 19:04:18 Done.
+
+ if (policy & INCLUDE_IPV6_TEMP_ADDRESS_IF_AVAILABLE) {
+ PruneIPv6Addresses(&network_infos);
+ }
+ for (size_t i = 0; i < network_infos.size(); ++i) {
+ networks->push_back(network_infos[i].interface);
+ }
return true;
#endif
}
« net/base/net_util.h ('K') | « net/base/net_util.h ('k') | net/base/net_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698