diff options
-rw-r--r-- | net/base/ip_endpoint.cc | 3 | ||||
-rw-r--r-- | net/base/net_util.cc | 13 | ||||
-rw-r--r-- | net/base/net_util.h | 25 | ||||
-rw-r--r-- | net/base/net_util_posix.cc | 38 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 27 | ||||
-rw-r--r-- | net/base/net_util_win.cc | 60 |
6 files changed, 156 insertions, 10 deletions
diff --git a/net/base/ip_endpoint.cc b/net/base/ip_endpoint.cc index df90f1a..3d776b1 100644 --- a/net/base/ip_endpoint.cc +++ b/net/base/ip_endpoint.cc @@ -14,9 +14,6 @@ namespace net { -const size_t kIPv4AddressSize = 4; -const size_t kIPv6AddressSize = 16; - IPEndPoint::IPEndPoint() : port_(0) {} IPEndPoint::~IPEndPoint() {} diff --git a/net/base/net_util.cc b/net/base/net_util.cc index f3b0127..1a8aa89 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -2111,4 +2111,15 @@ int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) { return ntohs(*port_field); } +NetworkInterface::NetworkInterface() { +} + +NetworkInterface::NetworkInterface(const std::string& name, + const IPAddressNumber& address) + : name(name), address(address) { +} + +NetworkInterface::~NetworkInterface() { +} + } // namespace net diff --git a/net/base/net_util.h b/net/base/net_util.h index 935eab6..9e30d2b 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -15,6 +15,7 @@ #include <sys/socket.h> #endif +#include <list> #include <string> #include <set> #include <vector> @@ -372,6 +373,9 @@ bool HaveOnlyLoopbackAddresses(); // IPv4 addresses will have length 4, whereas IPv6 address will have length 16. typedef std::vector<unsigned char> IPAddressNumber; +static const size_t kIPv4AddressSize = 4; +static const size_t kIPv6AddressSize = 16; + // Parses an IP address literal (either IPv4 or IPv6) to its numeric value. // Returns true on success and fills |ip_number| with the numeric value. bool ParseIPLiteralToNumber(const std::string& ip_literal, @@ -423,6 +427,25 @@ const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address, int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len); +// struct that is used by GetNetworkList() to represent a network +// interface. +struct NetworkInterface { + NetworkInterface(); + NetworkInterface(const std::string& name, const IPAddressNumber& address); + ~NetworkInterface(); + + std::string name; + IPAddressNumber address; +}; + +typedef std::list<NetworkInterface> NetworkInterfaceList; + +// Returns list of network interfaces except loopback interface. If an +// interface has more than one address, a separate entry is added to +// the list for each address. +// Can be called only on a thread that allows IO. +bool GetNetworkList(NetworkInterfaceList* networks); + } // namespace net #endif // NET_BASE_NET_UTIL_H_ diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc index 651be1b..af3d5d1 100644 --- a/net/base/net_util_posix.cc +++ b/net/base/net_util_posix.cc @@ -1,13 +1,21 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/base/net_util.h" +#include <ifaddrs.h> +#include <sys/types.h> + +#include "base/eintr_wrapper.h" #include "base/file_path.h" +#include "base/logging.h" #include "base/string_util.h" +#include "base/threading/thread_restrictions.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" namespace net { @@ -45,4 +53,32 @@ bool FileURLToFilePath(const GURL& url, FilePath* path) { return !file_path_str.empty(); } +bool GetNetworkList(NetworkInterfaceList* networks) { + // getifaddrs() may require IO operations. + base::ThreadRestrictions::AssertIOAllowed(); + + ifaddrs *ifaddr; + if (getifaddrs(&ifaddr) < 0) { + PLOG(ERROR) << "getifaddrs"; + return false; + } + + for (ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + int family = ifa->ifa_addr->sa_family; + if (family == AF_INET || family == AF_INET6) { + IPEndPoint address; + std::string name = ifa->ifa_name; + if (address.FromSockAddr(ifa->ifa_addr, + sizeof(ifa->ifa_addr)) && + name.substr(0, 2) != "lo") { + networks->push_back(NetworkInterface(name, address.address())); + } + } + } + + freeifaddrs(ifaddr); + + return true; +} + } // namespace net diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 46293a3..8f05c20 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -2166,3 +2166,28 @@ TEST(NetUtilTest, IPNumberMatchesPrefix) { prefix_length_in_bits)); } } + +// Verify GetNetworkList(). +TEST(NetUtilTest, GetNetworkList) { + net::NetworkInterfaceList list; + ASSERT_TRUE(net::GetNetworkList(&list)); + + for (net::NetworkInterfaceList::iterator it = list.begin(); + it != list.end(); ++it) { + // Verify that the name is not empty. + EXPECT_FALSE(it->name.empty()); + + // Verify that the address is correct. + EXPECT_TRUE(it->address.size() == net::kIPv4AddressSize || + it->address.size() == net::kIPv6AddressSize) + << "Invalid address of size " << it->address.size(); + bool all_zeroes = true; + for (size_t i = 0; i < it->address.size(); ++i) { + if (it->address[i] != 0) { + all_zeroes = false; + break; + } + } + EXPECT_FALSE(all_zeroes); + } +} diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc index dac93a9..ee6a5af 100644 --- a/net/base/net_util_win.cc +++ b/net/base/net_util_win.cc @@ -1,18 +1,24 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <algorithm> - #include "net/base/net_util.h" +#include <iphlpapi.h> + +#include <algorithm> + #include "base/file_path.h" +#include "base/scoped_ptr.h" #include "base/string_piece.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" +#include "base/threading/thread_restrictions.h" #include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" namespace net { @@ -69,4 +75,52 @@ bool FileURLToFilePath(const GURL& url, FilePath* file_path) { return true; } +bool GetNetworkList(NetworkInterfaceList* networks) { + // GetAdaptersAddresses() may require IO operations. + base::ThreadRestrictions::AssertIOAllowed(); + + IP_ADAPTER_ADDRESSES info_temp; + ULONG len = 0; + + // First get number of networks. + ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len); + if (result != ERROR_BUFFER_OVERFLOW) { + // There are 0 networks. + return true; + } + + scoped_array<char> buf(new char[len]); + IP_ADAPTER_ADDRESSES *adapters = + reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get()); + result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len); + if (result != NO_ERROR) { + LOG(ERROR) << "GetAdaptersAddresses failed: " << result; + return false; + } + + for (IP_ADAPTER_ADDRESSES *adapter = adapters; adapter != NULL; + adapter = adapter->Next) { + // Ignore the loopback device. + if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { + continue; + } + + IP_ADAPTER_UNICAST_ADDRESS* address; + for (address = adapter->FirstUnicastAddress; address != NULL; + address = address->Next) { + int family = address->Address.lpSockaddr->sa_family; + if (family == AF_INET || family == AF_INET6) { + IPEndPoint endpoint; + if (endpoint.FromSockAddr(address->Address.lpSockaddr, + address->Address.iSockaddrLength)) { + std::string name = adapter->AdapterName; + networks->push_back(NetworkInterface(name, endpoint.address())); + } + } + } + } + + return true; +} + } // namespace net |