Skip to content

Commit

Permalink
Added NetworkInterface::network_prefix.
Browse files Browse the repository at this point in the history
BUG=295997
NOTRY=true

Review URL: https://codereview.chromium.org/23726043

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225303 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
vitalybuka@chromium.org committed Sep 26, 2013
1 parent 65bc0bf commit 9f9a7b7
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 49 deletions.
13 changes: 8 additions & 5 deletions net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URLConnection;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.List;

/**
* This class implements net utilities required by the net component.
Expand Down Expand Up @@ -165,24 +167,25 @@ static public String getNetworkList() {
// Skip loopback interfaces, and ones which are down.
if (!netIf.isUp() || netIf.isLoopback())
continue;
Enumeration<InetAddress> addressList = netIf.getInetAddresses();
while (addressList.hasMoreElements()) {
InetAddress address = addressList.nextElement();
for (InterfaceAddress interfaceAddress : netIf.getInterfaceAddresses()) {
InetAddress address = interfaceAddress.getAddress();
// Skip loopback addresses configured on non-loopback interfaces.
if (address.isLoopbackAddress())
continue;
StringBuilder addressString = new StringBuilder();
addressString.append(netIf.getName());
addressString.append(",");
addressString.append("\t");

String ipAddress = address.getHostAddress();
if (address instanceof Inet6Address && ipAddress.contains("%")) {
ipAddress = ipAddress.substring(0, ipAddress.lastIndexOf("%"));
}
addressString.append(ipAddress);
addressString.append("/");
addressString.append(interfaceAddress.getNetworkPrefixLength());

if (result.length() != 0)
result.append(";");
result.append("\n");
result.append(addressString.toString());
}
} catch (SocketException e) {
Expand Down
29 changes: 26 additions & 3 deletions net/base/net_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2142,15 +2142,38 @@ bool IsLocalhost(const std::string& host) {
return false;
}

NetworkInterface::NetworkInterface() {
NetworkInterface::NetworkInterface() : network_prefix(0) {
}

NetworkInterface::NetworkInterface(const std::string& name,
const IPAddressNumber& address)
: name(name), address(address) {
const IPAddressNumber& address,
uint8 network_prefix)
: name(name), address(address), network_prefix(network_prefix) {
}

NetworkInterface::~NetworkInterface() {
}

unsigned CommonPrefixLength(const IPAddressNumber& a1,
const IPAddressNumber& a2) {
DCHECK_EQ(a1.size(), a2.size());
for (size_t i = 0; i < a1.size(); ++i) {
unsigned diff = a1[i] ^ a2[i];
if (!diff)
continue;
for (unsigned j = 0; j < CHAR_BIT; ++j) {
if (diff & (1 << (CHAR_BIT - 1)))
return i * CHAR_BIT + j;
diff <<= 1;
}
NOTREACHED();
}
return a1.size() * CHAR_BIT;
}

unsigned MaskPrefixLength(const IPAddressNumber& mask) {
IPAddressNumber all_ones(mask.size(), 0xFF);
return CommonPrefixLength(mask, all_ones);
}

} // namespace net
12 changes: 11 additions & 1 deletion net/base/net_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,11 +516,14 @@ NET_EXPORT_PRIVATE bool IsLocalhost(const std::string& host);
// interface.
struct NET_EXPORT NetworkInterface {
NetworkInterface();
NetworkInterface(const std::string& name, const IPAddressNumber& address);
NetworkInterface(const std::string& name,
const IPAddressNumber& address,
uint8 network_prefix);
~NetworkInterface();

std::string name;
IPAddressNumber address;
uint8 network_prefix;
};

typedef std::vector<NetworkInterface> NetworkInterfaceList;
Expand Down Expand Up @@ -553,6 +556,13 @@ enum WifiPHYLayerProtocol {
// Currently only available on OS_WIN.
NET_EXPORT WifiPHYLayerProtocol GetWifiPHYLayerProtocol();

// Returns number of matching initial bits between the addresses |a1| and |a2|.
unsigned CommonPrefixLength(const IPAddressNumber& a1,
const IPAddressNumber& a2);

// Computes the number of leading 1-bits in |mask|.
unsigned MaskPrefixLength(const IPAddressNumber& mask);

} // namespace net

#endif // NET_BASE_NET_UTIL_H_
47 changes: 33 additions & 14 deletions net/base/net_util_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
Expand Down Expand Up @@ -66,24 +67,33 @@ bool FileURLToFilePath(const GURL& url, base::FilePath* path) {
bool GetNetworkList(NetworkInterfaceList* networks) {
#if defined(OS_ANDROID)
std::string network_list = android::GetNetworkList();
base::StringTokenizer network_interfaces(network_list, ";");
base::StringTokenizer network_interfaces(network_list, "\n");
while (network_interfaces.GetNext()) {
std::string network_item = network_interfaces.token();
base::StringTokenizer network_tokenizer(network_item, ",");
std::string name;
if (!network_tokenizer.GetNext())
continue;
name = network_tokenizer.token();
base::StringTokenizer network_tokenizer(network_item, "\t");
CHECK(network_tokenizer.GetNext());
std::string name = network_tokenizer.token();

std::string literal_address;
if (!network_tokenizer.GetNext())
continue;
literal_address = network_tokenizer.token();
CHECK(network_tokenizer.GetNext());
std::string interface_address = network_tokenizer.token();

base::StringTokenizer address_tokenizer(interface_address, "/");

CHECK(address_tokenizer.GetNext());
std::string literal_address = address_tokenizer.token();

CHECK(address_tokenizer.GetNext());
std::string network_prefix = address_tokenizer.token();

IPAddressNumber address;
if (!ParseIPLiteralToNumber(literal_address, &address))
continue;
networks->push_back(NetworkInterface(name, address));
CHECK(ParseIPLiteralToNumber(literal_address, &address));

unsigned net_mask = 0;
CHECK(base::StringToUint(network_prefix, &net_mask));
CHECK_LE(net_mask, address.size() * 8);

networks->push_back(
NetworkInterface(name, address, static_cast<uint8>(net_mask)));
}
return true;
#else
Expand Down Expand Up @@ -133,10 +143,19 @@ bool GetNetworkList(NetworkInterfaceList* networks) {
// Skip non-IP addresses.
continue;
}

IPEndPoint address;
std::string name = interface->ifa_name;
if (address.FromSockAddr(addr, addr_size)) {
networks->push_back(NetworkInterface(name, address.address()));
uint8 net_mask = 0;
if (interface->ifa_netmask) {
IPEndPoint netmask;
if (netmask.FromSockAddr(interface->ifa_netmask, addr_size)) {
net_mask = MaskPrefixLength(netmask.address());
}
}

networks->push_back(NetworkInterface(name, address.address(), net_mask));
}
}

Expand Down
3 changes: 2 additions & 1 deletion net/base/net_util_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3291,7 +3291,6 @@ TEST(NetUtilTest, IsLocalhost) {
TEST(NetUtilTest, GetNetworkList) {
NetworkInterfaceList list;
ASSERT_TRUE(GetNetworkList(&list));

for (NetworkInterfaceList::iterator it = list.begin();
it != list.end(); ++it) {
// Verify that the name is not empty.
Expand All @@ -3309,6 +3308,8 @@ TEST(NetUtilTest, GetNetworkList) {
}
}
EXPECT_FALSE(all_zeroes);
EXPECT_GE(it->network_prefix, 1u);
EXPECT_LE(it->network_prefix, it->address.size() * 8);
}
}

Expand Down
3 changes: 2 additions & 1 deletion net/base/net_util_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ bool GetNetworkList(NetworkInterfaceList* networks) {
if (endpoint.FromSockAddr(address->Address.lpSockaddr,
address->Address.iSockaddrLength)) {
std::string name = adapter->AdapterName;
networks->push_back(NetworkInterface(name, endpoint.address()));
networks->push_back(NetworkInterface(name, endpoint.address(),
address->OnLinkPrefixLength));
}
}
}
Expand Down
24 changes: 0 additions & 24 deletions net/dns/address_sorter_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,30 +175,6 @@ AddressSorterPosix::PolicyEntry kDefaultIPv4ScopeTable[] = {
{ { }, 0, AddressSorterPosix::SCOPE_GLOBAL },
};

// Returns number of matching initial bits between the addresses |a1| and |a2|.
unsigned CommonPrefixLength(const IPAddressNumber& a1,
const IPAddressNumber& a2) {
DCHECK_EQ(a1.size(), a2.size());
for (size_t i = 0; i < a1.size(); ++i) {
unsigned diff = a1[i] ^ a2[i];
if (!diff)
continue;
for (unsigned j = 0; j < CHAR_BIT; ++j) {
if (diff & (1 << (CHAR_BIT - 1)))
return i * CHAR_BIT + j;
diff <<= 1;
}
NOTREACHED();
}
return a1.size() * CHAR_BIT;
}

// Computes the number of leading 1-bits in |mask|.
unsigned MaskPrefixLength(const IPAddressNumber& mask) {
IPAddressNumber all_ones(mask.size(), 0xFF);
return CommonPrefixLength(mask, all_ones);
}

struct DestinationInfo {
IPAddressNumber address;
AddressSorterPosix::AddressScope scope;
Expand Down

0 comments on commit 9f9a7b7

Please sign in to comment.