blob: 5bc9bd4d6ded4c2affeb2c0103ff9cda1d4abb82 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "routing-simulator/routing_policy_entry.h"
#include <chromeos/net-base/ip_address.h>
#include <gtest/gtest.h>
#include "routing-simulator/packet.h"
namespace routing_simulator {
namespace {
constexpr auto kIPv4DefaultPrefix = net_base::IPCIDR(net_base::IPFamily::kIPv4);
constexpr auto kIPv6DefaultPrefix = net_base::IPCIDR(net_base::IPFamily::kIPv6);
constexpr auto kFwmarkDefault = RoutingPolicyEntry::Fwmark();
TEST(RoutingPolicyEntryTest, CreateFromPolicyStringIPv4Success) {
// Policy with fwmark.
const auto policy_1 = RoutingPolicyEntry::CreateFromPolicyString(
"1020: from all fwmark 0x3eb0000/0xffff0000 lookup 1003",
net_base::IPFamily::kIPv4);
RoutingPolicyEntry::Fwmark fwmark;
fwmark.mark = 0x3eb0000;
fwmark.mask = 0xffff0000;
ASSERT_TRUE(policy_1.has_value());
EXPECT_EQ(policy_1->priority(), 1020);
EXPECT_EQ(policy_1->source_prefix(), kIPv4DefaultPrefix);
EXPECT_EQ(policy_1->table_id(), "1003");
EXPECT_EQ(policy_1->output_interface(), "");
EXPECT_EQ(policy_1->input_interface(), "");
EXPECT_EQ(policy_1->fwmark(), fwmark);
// Policy with input interface.
const auto policy_2 = RoutingPolicyEntry::CreateFromPolicyString(
"1020: from all iif wlan0 lookup 1003", net_base::IPFamily::kIPv4);
ASSERT_TRUE(policy_2.has_value());
EXPECT_EQ(policy_2->priority(), 1020);
EXPECT_EQ(policy_2->source_prefix(), kIPv4DefaultPrefix);
EXPECT_EQ(policy_2->table_id(), "1003");
EXPECT_EQ(policy_2->output_interface(), "");
EXPECT_EQ(policy_2->input_interface(), "wlan0");
EXPECT_EQ(policy_2->fwmark(), kFwmarkDefault);
// Policy with output interface.
const auto policy_3 = RoutingPolicyEntry::CreateFromPolicyString(
"1020: from all oif wlan0 lookup main", net_base::IPFamily::kIPv4);
ASSERT_TRUE(policy_3.has_value());
EXPECT_EQ(policy_3->priority(), 1020);
EXPECT_EQ(policy_3->source_prefix(), kIPv4DefaultPrefix);
EXPECT_EQ(policy_3->table_id(), "main");
EXPECT_EQ(policy_3->output_interface(), "wlan0");
EXPECT_EQ(policy_3->input_interface(), "");
EXPECT_EQ(policy_3->fwmark(), kFwmarkDefault);
// Policy with a certain destination prefix.
const auto policy_4 = RoutingPolicyEntry::CreateFromPolicyString(
"1020: from 100.86.210.153/22 lookup 1003", net_base::IPFamily::kIPv4);
ASSERT_TRUE(policy_4.has_value());
EXPECT_EQ(policy_4->priority(), 1020);
EXPECT_EQ(policy_4->source_prefix(),
net_base::IPCIDR::CreateFromCIDRString("100.86.210.153/22"));
EXPECT_EQ(policy_4->table_id(), "1003");
EXPECT_EQ(policy_4->output_interface(), "");
EXPECT_EQ(policy_4->input_interface(), "");
EXPECT_EQ(policy_4->fwmark(), kFwmarkDefault);
// Test the special case (e.g. no prefix length in route strings).
const auto route_with_no_prefix_length =
RoutingPolicyEntry::CreateFromPolicyString(
"1020: from 100.86.210.153 lookup 1003", net_base::IPFamily::kIPv4);
const auto prefix =
net_base::IPCIDR::CreateFromCIDRString("100.86.210.153").value();
ASSERT_TRUE(route_with_no_prefix_length.has_value());
EXPECT_EQ(route_with_no_prefix_length->source_prefix(), prefix);
}
TEST(RoutingPolicyEntryTest, CreateFromPolicyStringIPv6Success) {
// Policy with fwmark.
const auto policy_1 = RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all fwmark 0x3ea0000/0xffff0000 lookup 1002",
net_base::IPFamily::kIPv6);
RoutingPolicyEntry::Fwmark fwmark;
fwmark.mark = 0x3ea0000;
fwmark.mask = 0xffff0000;
ASSERT_TRUE(policy_1.has_value());
EXPECT_EQ(policy_1->priority(), 1010);
EXPECT_EQ(policy_1->source_prefix(), kIPv6DefaultPrefix);
EXPECT_EQ(policy_1->table_id(), "1002");
EXPECT_EQ(policy_1->output_interface(), "");
EXPECT_EQ(policy_1->input_interface(), "");
EXPECT_EQ(policy_1->fwmark(), fwmark);
// Policy with a output interface.
const auto policy_2 = RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all oif eth0 lookup 1002", net_base::IPFamily::kIPv6);
RoutingPolicyEntry::Fwmark kFwmarkDefault;
ASSERT_TRUE(policy_2.has_value());
EXPECT_EQ(policy_2->priority(), 1010);
EXPECT_EQ(policy_2->source_prefix(), kIPv6DefaultPrefix);
EXPECT_EQ(policy_2->table_id(), "1002");
EXPECT_EQ(policy_2->output_interface(), "eth0");
EXPECT_EQ(policy_2->input_interface(), "");
EXPECT_EQ(policy_2->fwmark(), kFwmarkDefault);
// Policy with a certain destination prefix.
const auto policy_3 = RoutingPolicyEntry::CreateFromPolicyString(
"1010: from 2401:fa00:480:ee08:7022:5d3a:3805:7110/64 lookup main",
net_base::IPFamily::kIPv6);
ASSERT_TRUE(policy_3.has_value());
EXPECT_EQ(policy_3->priority(), 1010);
EXPECT_EQ(policy_3->source_prefix(),
net_base::IPCIDR::CreateFromCIDRString(
"2401:fa00:480:ee08:7022:5d3a:3805:7110/64"));
EXPECT_EQ(policy_3->table_id(), "main");
EXPECT_EQ(policy_3->output_interface(), "");
EXPECT_EQ(policy_3->input_interface(), "");
EXPECT_EQ(policy_3->fwmark(), kFwmarkDefault);
// Policy with input interface.
const auto policy_4 = RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all iif eth0 lookup 1002", net_base::IPFamily::kIPv6);
ASSERT_TRUE(policy_4.has_value());
EXPECT_EQ(policy_4->priority(), 1010);
EXPECT_EQ(policy_4->source_prefix(), kIPv6DefaultPrefix);
EXPECT_EQ(policy_4->table_id(), "1002");
EXPECT_EQ(policy_4->output_interface(), "");
EXPECT_EQ(policy_4->input_interface(), "eth0");
EXPECT_EQ(policy_4->fwmark(), kFwmarkDefault);
// Test the special case (e.g. no prefix length in route strings).
// Test the special case (e.g. no prefix length in route strings).
const auto route_with_no_prefix_length =
RoutingPolicyEntry::CreateFromPolicyString(
"1020: from 2401:fa00:480:ee08:7022:5d3a:3805:7110 lookup 1003",
net_base::IPFamily::kIPv6);
const auto prefix = net_base::IPCIDR::CreateFromCIDRString(
"2401:fa00:480:ee08:7022:5d3a:3805:7110")
.value();
ASSERT_TRUE(route_with_no_prefix_length.has_value());
EXPECT_EQ(route_with_no_prefix_length->source_prefix(), prefix);
}
TEST(RoutingPolicyEntryTest, CreateFromPolicyStringFail) {
// Priority is out of the valid range(0~32767).
EXPECT_EQ(RoutingPolicyEntry::CreateFromPolicyString(
"32800: from all fwmark 0x3eb0000/0xffff0000 lookup 1003",
net_base::IPFamily::kIPv4),
std::nullopt);
// No source prefix identifier.
EXPECT_EQ(RoutingPolicyEntry::CreateFromPolicyString(
"1002: fwmark 0x3eb0000/0xffff0000 lookup 1003",
net_base::IPFamily::kIPv4),
std::nullopt);
// No table id identifier.
EXPECT_EQ(RoutingPolicyEntry::CreateFromPolicyString(
"1002: from all fwmark 0x3eb0000/0xffff0000 1003",
net_base::IPFamily::kIPv4),
std::nullopt);
// Identifiers next to each other.
EXPECT_EQ(RoutingPolicyEntry::CreateFromPolicyString(
"1002: from all fwmark 0x3eb0000/0xffff0000 table lookup 1003",
net_base::IPFamily::kIPv4),
std::nullopt);
// Invalid prefix.
EXPECT_EQ(RoutingPolicyEntry::CreateFromPolicyString(
"1020: from default lookup 1003", net_base::IPFamily::kIPv4),
std::nullopt);
}
TEST(RoutingPolicyEntryTest, MatchesIPv4) {
const auto ip_family = net_base::IPFamily::kIPv4;
const auto destination_ip =
net_base::IPAddress::CreateFromString("168.87.84.90").value();
const auto source_ip_eth0 =
net_base::IPAddress::CreateFromString("100.87.84.90").value();
const auto source_ip_eth1 =
net_base::IPAddress::CreateFromString("160.87.84.90").value();
auto packet_eth0 = Packet::CreatePacketForTesting(
ip_family, Packet::Protocol::kIcmp, destination_ip,
source_ip_eth0, 0, 0, "eth0")
.value();
packet_eth0.set_fwmark(0x3eb0000);
packet_eth0.set_output_interface("eth0");
auto packet_eth1 = Packet::CreatePacketForTesting(
ip_family, Packet::Protocol::kIcmp, destination_ip,
source_ip_eth1, 0, 0, "eth1")
.value();
packet_eth1.set_output_interface("wlan0");
// No condition. Matcheses any packet.
const auto policy_with_no_condition =
RoutingPolicyEntry::CreateFromPolicyString("1000: from all lookup main",
ip_family)
.value();
EXPECT_TRUE(policy_with_no_condition.Matches(packet_eth0));
EXPECT_TRUE(policy_with_no_condition.Matches(packet_eth1));
// Only source prefix specified.
const auto policy_with_prefix =
RoutingPolicyEntry::CreateFromPolicyString(
"1010: from 100.87.84.132/24 lookup 1002", ip_family)
.value();
EXPECT_TRUE(policy_with_prefix.Matches(packet_eth0));
EXPECT_FALSE(policy_with_prefix.Matches(packet_eth1));
// Only input interface specified.
const auto policy_with_iif =
RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all iif eth0 lookup 1002", ip_family)
.value();
EXPECT_TRUE(policy_with_iif.Matches(packet_eth0));
EXPECT_FALSE(policy_with_iif.Matches(packet_eth1));
// Only output interface specified.
const auto policy_with_oif =
RoutingPolicyEntry::CreateFromPolicyString(
"1020: from all oif wlan0 lookup 1003", ip_family)
.value();
EXPECT_FALSE(policy_with_oif.Matches(packet_eth0));
EXPECT_TRUE(policy_with_oif.Matches(packet_eth1));
// Only fwmark specified.
const auto policy_with_fwmark =
RoutingPolicyEntry::CreateFromPolicyString(
"1020: from all fwmark 0x3eb0000/0xffff0000 lookup 1003", ip_family)
.value();
EXPECT_TRUE(policy_with_fwmark.Matches(packet_eth0));
EXPECT_FALSE(policy_with_fwmark.Matches(packet_eth1));
// All condition specified (source prefix, input interface, output interface
// and fwmark)
const auto policy_with_all_condition =
RoutingPolicyEntry::CreateFromPolicyString(
"1020: from 100.86.210.153/22 fwmark 0x3ea0000/0xffff0000 oif eth0 "
"iif eth0 lookup 249",
ip_family);
EXPECT_TRUE(policy_with_fwmark.Matches(packet_eth0));
EXPECT_FALSE(policy_with_fwmark.Matches(packet_eth1));
}
TEST(RoutingPolicyEntryTest, MatchesIPv6) {
const auto ip_family = net_base::IPFamily::kIPv6;
const auto destination_ip = net_base::IPAddress::CreateFromString(
"2008:fa00:480:ee08:aa23:5cbe:8db7:4c51")
.value();
const auto source_ip_eth0 = net_base::IPAddress::CreateFromString(
"2401:fa00:480:ee08:aa23:5cbe:8db7:4c51")
.value();
const auto source_ip_eth1 = net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:abb3:65ff:fe56:100d")
.value();
auto packet_eth0 = Packet::CreatePacketForTesting(
ip_family, Packet::Protocol::kIcmp, destination_ip,
source_ip_eth0, 0, 0, "eth0")
.value();
packet_eth0.set_fwmark(0x3ea0000);
auto packet_eth1 = Packet::CreatePacketForTesting(
ip_family, Packet::Protocol::kIcmp, destination_ip,
source_ip_eth1, 0, 0, "eth1")
.value();
packet_eth1.set_output_interface("wlan0");
packet_eth1.set_fwmark(0x3eb0000);
// No condition. Matcheses any packet.
const auto policy_with_no_condition =
RoutingPolicyEntry::CreateFromPolicyString("1000: from all lookup main",
ip_family)
.value();
EXPECT_TRUE(policy_with_no_condition.Matches(packet_eth0));
EXPECT_TRUE(policy_with_no_condition.Matches(packet_eth1));
// Only source prefix specified.
const auto policy_with_prefix =
RoutingPolicyEntry::CreateFromPolicyString(
"1010: from 2401:fa00:480:ee08:a44b:5cbe:8db7:4c51/64 lookup 1002",
ip_family)
.value();
EXPECT_TRUE(policy_with_prefix.Matches(packet_eth0));
EXPECT_FALSE(policy_with_prefix.Matches(packet_eth1));
// Only input interface specified.
const auto policy_with_iif =
RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all iif eth0 lookup 1002", ip_family)
.value();
EXPECT_TRUE(policy_with_iif.Matches(packet_eth0));
EXPECT_FALSE(policy_with_iif.Matches(packet_eth1));
// Only output interface specified.
const auto policy_with_oif =
RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all oif wlan0 lookup 1002", ip_family)
.value();
EXPECT_FALSE(policy_with_oif.Matches(packet_eth0));
EXPECT_TRUE(policy_with_oif.Matches(packet_eth1));
// Only fwmark specified.
const auto policy_with_fwmark =
RoutingPolicyEntry::CreateFromPolicyString(
"1010: from all fwmark 0x3ea0000/0xffff0000 lookup 1002", ip_family)
.value();
EXPECT_TRUE(policy_with_fwmark.Matches(packet_eth0));
EXPECT_FALSE(policy_with_fwmark.Matches(packet_eth1));
// All condition specified (source prefix, input interface, output interface
// and fwmark)
const auto policy_with_all_condition =
RoutingPolicyEntry::CreateFromPolicyString(
"11020: from 2a00:79e1:abc:f604:faac:65ff:fe56:100d/64 fwmark "
"0x3eb0000/0xffff0000 iif eth1 oif wlan0 lookup 1003",
ip_family)
.value();
EXPECT_FALSE(policy_with_all_condition.Matches(packet_eth0));
EXPECT_TRUE(policy_with_all_condition.Matches(packet_eth1));
}
} // namespace
} // namespace routing_simulator