blob: fe1984b22c86162794c5760eaa4e2ee0e4790c9b [file] [log] [blame]
// Copyright 2017 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/network_interfaces_linux.h"
#include <net/if.h>
#include <netinet/in.h>
#include <ostream>
#include <string>
#include <unordered_set>
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "net/base/address_tracker_linux.h"
#include "net/base/ip_endpoint.h"
#include "net/base/network_interfaces_posix.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
static const char kIfnameEm1[] = "em1";
static const char kIfnameVmnet[] = "vmnet";
static const unsigned char kIPv6LocalAddr[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};
static const unsigned char kIPv6Addr[] = {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04,
0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
0xfe, 0xe5, 0x00, 0xc3};
char* GetInterfaceName(int interface_index, char* ifname) {
static_assert(base::size(kIfnameEm1) < IF_NAMESIZE, "Invalid interface name");
memcpy(ifname, kIfnameEm1, base::size(kIfnameEm1));
return ifname;
}
char* GetInterfaceNameVM(int interface_index, char* ifname) {
static_assert(base::size(kIfnameVmnet) < IF_NAMESIZE,
"Invalid interface name");
memcpy(ifname, kIfnameVmnet, base::size(kIfnameVmnet));
return ifname;
}
TEST(NetworkInterfacesTest, NetworkListTrimmingLinux) {
IPAddress ipv6_local_address(kIPv6LocalAddr);
IPAddress ipv6_address(kIPv6Addr);
NetworkInterfaceList results;
std::unordered_set<int> online_links;
internal::AddressTrackerLinux::AddressMap address_map;
// Interface 1 is offline.
struct ifaddrmsg msg = {
AF_INET6, // Address type
1, // Prefix length
IFA_F_TEMPORARY, // Address flags
0, // Link scope
1 // Link index
};
// Address of offline links should be ignored.
ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceName));
EXPECT_EQ(results.size(), 0ul);
// Mark interface 1 online.
online_links.insert(1);
// Local address should be trimmed out.
address_map.clear();
ASSERT_TRUE(
address_map.insert(std::make_pair(ipv6_local_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceName));
EXPECT_EQ(results.size(), 0ul);
// vmware address should return by default.
address_map.clear();
ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceNameVM));
EXPECT_EQ(results.size(), 1ul);
EXPECT_EQ(results[0].name, kIfnameVmnet);
EXPECT_EQ(results[0].prefix_length, 1ul);
EXPECT_EQ(results[0].address, ipv6_address);
results.clear();
// vmware address should be trimmed out if policy specified so.
address_map.clear();
ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceNameVM));
EXPECT_EQ(results.size(), 0ul);
results.clear();
// Addresses with banned attributes should be ignored.
address_map.clear();
msg.ifa_flags = IFA_F_TENTATIVE;
ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceName));
EXPECT_EQ(results.size(), 0ul);
results.clear();
// Addresses with allowed attribute IFA_F_TEMPORARY should be returned and
// attributes should be translated correctly.
address_map.clear();
msg.ifa_flags = IFA_F_TEMPORARY;
ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceName));
EXPECT_EQ(results.size(), 1ul);
EXPECT_EQ(results[0].name, kIfnameEm1);
EXPECT_EQ(results[0].prefix_length, 1ul);
EXPECT_EQ(results[0].address, ipv6_address);
EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
results.clear();
// Addresses with allowed attribute IFA_F_DEPRECATED should be returned and
// attributes should be translated correctly.
address_map.clear();
msg.ifa_flags = IFA_F_DEPRECATED;
ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second);
EXPECT_TRUE(internal::GetNetworkListImpl(
&results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links,
address_map, GetInterfaceName));
EXPECT_EQ(results.size(), 1ul);
EXPECT_EQ(results[0].name, kIfnameEm1);
EXPECT_EQ(results[0].prefix_length, 1ul);
EXPECT_EQ(results[0].address, ipv6_address);
EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
results.clear();
}
const char kWiFiSSID[] = "TestWiFi";
const char kInterfaceWithDifferentSSID[] = "wlan999";
std::string TestGetInterfaceSSID(const std::string& ifname) {
return (ifname == kInterfaceWithDifferentSSID) ? "AnotherSSID" : kWiFiSSID;
}
TEST(NetworkInterfacesTest, GetWifiSSIDFromInterfaceList) {
NetworkInterfaceList list;
EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal(
list, TestGetInterfaceSSID));
NetworkInterface interface1;
interface1.name = "wlan0";
interface1.type = NetworkChangeNotifier::CONNECTION_WIFI;
list.push_back(interface1);
ASSERT_EQ(1u, list.size());
EXPECT_EQ(std::string(kWiFiSSID),
internal::GetWifiSSIDFromInterfaceListInternal(
list, TestGetInterfaceSSID));
NetworkInterface interface2;
interface2.name = "wlan1";
interface2.type = NetworkChangeNotifier::CONNECTION_WIFI;
list.push_back(interface2);
ASSERT_EQ(2u, list.size());
EXPECT_EQ(std::string(kWiFiSSID),
internal::GetWifiSSIDFromInterfaceListInternal(
list, TestGetInterfaceSSID));
NetworkInterface interface3;
interface3.name = kInterfaceWithDifferentSSID;
interface3.type = NetworkChangeNotifier::CONNECTION_WIFI;
list.push_back(interface3);
ASSERT_EQ(3u, list.size());
EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal(
list, TestGetInterfaceSSID));
list.pop_back();
NetworkInterface interface4;
interface4.name = "eth0";
interface4.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
list.push_back(interface4);
ASSERT_EQ(3u, list.size());
EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal(
list, TestGetInterfaceSSID));
}
} // namespace
} // namespace net