blob: b2edbd9f00283b750b1ea768848431594caab0a6 [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.
// Instantiations of filter tests with filter tree builder.
#include <zxtest/zxtest.h>
#include <type_traits>
#include <unordered_map>
#include "filter_builder_impl.h"
#include "filter_test.h"
namespace netdump::test {
static Tokenizer tkz{};
static parser::FilterTreeBuilder bld{tkz};
template <typename T>
class TokenMap;
template <>
class TokenMap<LengthComparator> {
public:
const std::unordered_map<LengthComparator, TokenPtr> map{{LEQ, tkz.LESS}, {GEQ, tkz.GREATER}};
};
template <>
class TokenMap<AddressFieldType> {
public:
const std::unordered_map<AddressFieldType, TokenPtr> map{
{SRC_ADDR, tkz.SRC}, {DST_ADDR, tkz.DST}, {EITHER_ADDR, tkz.HOST}};
};
template <>
class TokenMap<PortFieldType> {
public:
const std::unordered_map<PortFieldType, TokenPtr> map{
{SRC_PORT, tkz.SRC}, {DST_PORT, tkz.DST}, {EITHER_PORT, tkz.PORT}};
};
template <typename T>
static inline TokenPtr lookup_token(T key) {
TokenMap<T> tm{};
auto token = tm.map.find(key);
ZX_DEBUG_ASSERT(token != tm.map.end());
return token->second;
}
template <class Flt>
class CallFilterBuilder;
template <>
class CallFilterBuilder<FrameLengthFilter> {
public:
inline FilterPtr operator()(uint16_t length, LengthComparator comparator) {
return bld.frame_length(htons(length), lookup_token(comparator));
}
};
template <>
class CallFilterBuilder<EthFilter> {
public:
inline FilterPtr operator()(uint16_t ethtype) { return bld.ethertype(htons(ethtype)); }
inline FilterPtr operator()(EthFilter::MacAddress mac, AddressFieldType type) {
std::reverse(mac.begin(), mac.end());
return bld.mac(mac, lookup_token(type));
}
};
template <>
class CallFilterBuilder<IpFilter> {
public:
inline FilterPtr operator()(uint8_t version) { return bld.ip_version(version); }
inline FilterPtr operator()(uint8_t version, uint8_t protocol) {
return bld.ip_protocol(version, protocol);
}
inline FilterPtr operator()(uint8_t version, uint16_t length, LengthComparator comparator) {
return bld.ip_pkt_length(version, htons(length), lookup_token(comparator));
}
inline FilterPtr operator()(uint32_t ipv4_addr, AddressFieldType type) {
return bld.ipv4_address(htonl(ipv4_addr), lookup_token(type));
}
inline FilterPtr operator()(IpFilter::IPv6Address ipv6_addr, AddressFieldType type) {
std::reverse(ipv6_addr.begin(), ipv6_addr.end());
return bld.ipv6_address(ipv6_addr, lookup_token(type));
}
};
template <>
class CallFilterBuilder<PortFilter> {
public:
inline FilterPtr operator()(std::vector<PortRange> ranges, PortFieldType type) {
for (auto it = ranges.begin(); it < ranges.end(); ++it) {
it->first = htons(it->first);
it->second = htons(it->second);
}
return bld.ports(std::move(ranges), lookup_token(type));
}
};
template <>
class CallFilterBuilder<NegFilter> {
public:
inline FilterPtr operator()(FilterPtr filter) { return bld.negation(std::move(filter)); }
};
template <>
class CallFilterBuilder<ConjFilter> {
public:
inline FilterPtr operator()(FilterPtr left, FilterPtr right) {
return bld.conjunction(std::move(left), std::move(right));
}
};
template <>
class CallFilterBuilder<DisjFilter> {
public:
inline FilterPtr operator()(FilterPtr left, FilterPtr right) {
return bld.disjunction(std::move(left), std::move(right));
}
};
#define NETDUMP_TEST(test, flt) \
TEST(NetdumpFilterBuilderTest, test) { test(CallFilterBuilder<flt>()); }
NETDUMP_TEST(FrameLengthTest, FrameLengthFilter)
NETDUMP_TEST(EthtypeTest, EthFilter)
NETDUMP_TEST(MacTest, EthFilter)
NETDUMP_TEST(VersionTest, IpFilter)
NETDUMP_TEST(IPLengthTest, IpFilter)
NETDUMP_TEST(ProtocolTest, IpFilter)
NETDUMP_TEST(IPv4AddrTest, IpFilter)
NETDUMP_TEST(IPv6AddrTest, IpFilter)
NETDUMP_TEST(IPv4PortsTest, PortFilter)
NETDUMP_TEST(IPv6PortsTest, PortFilter)
#undef NETDUMP_TEST
TEST(NetdumpFilterBuilderTest, UnsupportedIpVersionAssertTest) {
UnsupportedIpVersionAssertTest(CallFilterBuilder<IpFilter>(), CallFilterBuilder<IpFilter>(),
CallFilterBuilder<IpFilter>());
}
TEST(NetdumpFilterBuilderTest, CompositionTest) {
CompositionTest(CallFilterBuilder<NegFilter>(), CallFilterBuilder<ConjFilter>(),
CallFilterBuilder<DisjFilter>());
}
} // namespace netdump::test