blob: c070321fda24559788439c50f1108fc048465d3b [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 <fuchsia/net/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <lib/sys/cpp/file_descriptor.h>
#include <lib/sys/cpp/termination_reason.h>
#include <lib/sys/cpp/testing/test_with_environment.h>
#include <src/connectivity/network/testing/netemul/lib/network/ethernet_client.h>
#include <src/connectivity/network/testing/netemul/lib/network/ethertap_client.h>
#include "garnet/lib/inet/ip_address.h"
#include "gtest/gtest.h"
namespace {
class NetstackNoNetworkTest : public sys::testing::TestWithEnvironment {};
const char kNetstackUrl[] =
"fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cmx";
const char kTopoPath[] = "/fake/topo/path";
const char kInterfaceName[] = "en0";
const char kTestNoNetworkClientUrl[] =
"fuchsia-pkg://fuchsia.com/test_no_network_client#meta/"
"test_no_network_client.cmx";
TEST_F(NetstackNoNetworkTest, DisableEthernetInterface) {
auto services = CreateServices();
fuchsia::sys::LaunchInfo netstack_launch_info;
netstack_launch_info.url = kNetstackUrl;
netstack_launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
netstack_launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
services->AddServiceWithLaunchInfo(std::move(netstack_launch_info),
fuchsia::netstack::Netstack::Name_);
fuchsia::sys::LaunchInfo socket_provider_launch_info;
socket_provider_launch_info.url = kNetstackUrl;
socket_provider_launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
socket_provider_launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
services->AddServiceWithLaunchInfo(std::move(socket_provider_launch_info),
fuchsia::net::SocketProvider::Name_);
auto env = CreateNewEnclosingEnvironment(
"NetstackNoNetworkTest_DisableEthernetInterface", std::move(services));
ASSERT_TRUE(WaitForEnclosingEnvToStart(env.get()));
auto eth_config = netemul::EthertapConfig("DisableEthernetInterface");
auto tap = netemul::EthertapClient::Create(eth_config);
ASSERT_TRUE(tap) << "failed to create ethertap device";
tap->SetLinkUp(true);
netemul::EthernetClientFactory eth_factory;
auto eth = eth_factory.RetrieveWithMAC(eth_config.tap_cfg.mac);
ASSERT_TRUE(eth) << "failed to retrieve ethernet client";
fuchsia::netstack::NetstackPtr netstack;
env->ConnectToService(netstack.NewRequest());
fuchsia::netstack::InterfaceConfig config;
config.name = kInterfaceName;
config.ip_address_config.set_dhcp(false);
uint32_t eth_id = 0;
netstack->AddEthernetDevice(std::move(kTopoPath), std::move(config),
std::move(eth->device()),
[&eth_id](uint32_t id) { eth_id = id; });
ASSERT_TRUE(RunLoopUntil([&eth_id] { return eth_id != 0; }));
inet::IpAddress ip = inet::IpAddress(192, 168, 0, 2);
fuchsia::net::IpAddress addr;
fuchsia::net::Ipv4Address ipv4;
memcpy(ipv4.addr.data(), ip.as_bytes(), 4);
addr.set_ipv4(ipv4);
fuchsia::netstack::Status net_status =
fuchsia::netstack::Status::UNKNOWN_ERROR;
netstack->SetInterfaceAddress(
eth_id, std::move(addr), 32,
[&net_status](fuchsia::netstack::NetErr result) {
net_status = result.status;
});
ASSERT_TRUE(RunLoopWithTimeoutOrUntil(
[&net_status] { return net_status == fuchsia::netstack::Status::OK; },
zx::sec(10)));
// Run the client without enabling the interface.
fuchsia::sys::LaunchInfo client_launch_info;
client_launch_info.url = kTestNoNetworkClientUrl;
client_launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
client_launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
auto controller = env.get()->CreateComponent(std::move(client_launch_info));
bool wait = false;
int64_t exit_code;
fuchsia::sys::TerminationReason term_reason;
controller.events().OnTerminated =
[&wait, &exit_code, &term_reason](
int64_t retcode, fuchsia::sys::TerminationReason reason) {
wait = true;
exit_code = retcode;
term_reason = reason;
};
EXPECT_TRUE(RunLoopUntil([&wait] { return wait; }));
EXPECT_EQ(exit_code, 0) << "Exit code was non-zero, got: " << exit_code;
EXPECT_EQ(term_reason, fuchsia::sys::TerminationReason::EXITED)
<< "TerminationReason was not 'EXITED' as expected, got: "
<< sys::TerminationReasonToString(term_reason);
}
} // namespace