blob: 0e06a1b2b60999d1e6aa465a23c0c9668e38d8f8 [file] [log] [blame]
// Copyright 2018 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/filter/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 NetstackFilterTest : public sys::testing::TestWithEnvironment {};
const zx::duration kTimeout = zx::sec(10);
const char kNetstackUrl[] =
"fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cmx";
const char kTopoPath[] = "/fake/topo/path";
const char kInterfaceName[] = "en0";
const char kFilterClientUrl[] =
"fuchsia-pkg://fuchsia.com/test_filter_client#meta/test_filter_client.cmx";
TEST_F(NetstackFilterTest, TestRuleset) {
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 filter_launch_info;
filter_launch_info.url = kNetstackUrl;
filter_launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
filter_launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
services->AddServiceWithLaunchInfo(std::move(filter_launch_info),
fuchsia::net::filter::Filter::Name_);
auto env = CreateNewEnclosingEnvironment("NetstackFilterTest_TestRules",
std::move(services));
ASSERT_TRUE(WaitForEnclosingEnvToStart(env.get()));
auto eth_config = netemul::EthertapConfig("TestRuleset");
auto tap = netemul::EthertapClient::Create(eth_config);
ASSERT_TRUE(tap) << "failed to create ethertap device";
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());
inet::IpAddress test_static_ip = inet::IpAddress(192, 168, 250, 1);
ASSERT_NE(test_static_ip, inet::IpAddress::kInvalid)
<< "Failed to create static IP address: "
<< test_static_ip.ToString().c_str();
fprintf(stderr, "created static ip address: %s\n",
test_static_ip.ToString().c_str());
fuchsia::net::Subnet subnet;
fuchsia::net::Ipv4Address ipv4;
memcpy(ipv4.addr.data(), test_static_ip.as_bytes(), 4);
subnet.addr.set_ipv4(ipv4);
subnet.prefix_len = 24;
fuchsia::netstack::InterfaceConfig config;
config.name = kInterfaceName;
config.ip_address_config.set_static_ip(std::move(subnet));
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; }));
// Launch the test program.
std::vector<std::string> args = {test_static_ip.ToString()};
fuchsia::sys::LaunchInfo client_launch_info;
client_launch_info.url = kFilterClientUrl;
client_launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
client_launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
for (const auto& a : args) {
client_launch_info.arguments.push_back(a);
}
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(RunLoopWithTimeoutOrUntil([&wait] { return wait; }, kTimeout));
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