Lines
96.4 %
Functions
92.5 %
#pragma once
#include "envoy/extensions/matching/common_inputs/network/v3/network_inputs.pb.h"
#include "envoy/extensions/matching/common_inputs/network/v3/network_inputs.pb.validate.h"
#include "envoy/matcher/matcher.h"
#include "envoy/network/filter.h"
#include "envoy/registry/registry.h"
#include "source/common/common/logger.h"
#include "source/common/network/utility.h"
namespace Envoy {
namespace Network {
namespace Matching {
template <class InputType, class ProtoType, class MatchingDataType>
class BaseFactory : public Matcher::DataInputFactory<MatchingDataType> {
protected:
explicit BaseFactory(const std::string& name) : name_(name) {}
public:
std::string name() const override { return "envoy.matching.inputs." + name_; }
Matcher::DataInputFactoryCb<MatchingDataType>
createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override {
return []() { return std::make_unique<InputType>(); };
};
ProtobufTypes::MessagePtr createEmptyConfigProto() override {
return std::make_unique<ProtoType>();
}
private:
const std::string name_;
template <class MatchingDataType>
class DestinationIPInput : public Matcher::DataInput<MatchingDataType> {
Matcher::DataInputGetResult get(const MatchingDataType& data) const override {
const auto& address = data.localAddress();
if (address.type() != Network::Address::Type::Ip) {
return Matcher::DataInputGetResult::NoData();
const std::string& address_string = address.ip()->addressAsString();
return Matcher::DataInputGetResult::CreateStringView(absl::string_view(address_string));
class DestinationIPInputBaseFactory
: public BaseFactory<
DestinationIPInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::DestinationIPInput,
MatchingDataType> {
DestinationIPInputBaseFactory()
: BaseFactory<DestinationIPInput<MatchingDataType>,
MatchingDataType>("destination_ip") {}
DECLARE_FACTORY(DestinationIPInputFactory);
DECLARE_FACTORY(UdpDestinationIPInputFactory);
DECLARE_FACTORY(HttpDestinationIPInputFactory);
// With the support of generic matching API, integer is allowed in inputs such as
// `DestinationPortInput` and `SourcePortInput`. As a result, there is no longer a need for the
// redundant conversion of int-to-string. We can change them here once IntInputMatcher (for integer
// type input) is implemented.
class DestinationPortInput : public Matcher::DataInput<MatchingDataType> {
return Matcher::DataInputGetResult::CreateString(absl::StrCat(address.ip()->port()));
class DestinationPortInputBaseFactory
DestinationPortInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::DestinationPortInput,
DestinationPortInputBaseFactory()
: BaseFactory<DestinationPortInput<MatchingDataType>,
MatchingDataType>("destination_port") {}
DECLARE_FACTORY(DestinationPortInputFactory);
DECLARE_FACTORY(UdpDestinationPortInputFactory);
DECLARE_FACTORY(HttpDestinationPortInputFactory);
class SourceIPInput : public Matcher::DataInput<MatchingDataType> {
const auto& address = data.remoteAddress();
class SourceIPInputBaseFactory
: public BaseFactory<SourceIPInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::SourceIPInput,
SourceIPInputBaseFactory()
: BaseFactory<SourceIPInput<MatchingDataType>,
MatchingDataType>("source_ip") {}
DECLARE_FACTORY(SourceIPInputFactory);
DECLARE_FACTORY(UdpSourceIPInputFactory);
DECLARE_FACTORY(HttpSourceIPInputFactory);
class SourcePortInput : public Matcher::DataInput<MatchingDataType> {
class SourcePortInputBaseFactory
: public BaseFactory<SourcePortInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::SourcePortInput,
SourcePortInputBaseFactory()
: BaseFactory<SourcePortInput<MatchingDataType>,
MatchingDataType>("source_port") {}
DECLARE_FACTORY(SourcePortInputFactory);
DECLARE_FACTORY(UdpSourcePortInputFactory);
DECLARE_FACTORY(HttpSourcePortInputFactory);
class DirectSourceIPInput : public Matcher::DataInput<MatchingDataType> {
const auto& address = data.connectionInfoProvider().directRemoteAddress();
if (address->type() != Network::Address::Type::Ip) {
const std::string& address_string = address->ip()->addressAsString();
class DirectSourceIPInputBaseFactory
DirectSourceIPInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::DirectSourceIPInput,
DirectSourceIPInputBaseFactory()
: BaseFactory<DirectSourceIPInput<MatchingDataType>,
MatchingDataType>("direct_source_ip") {}
DECLARE_FACTORY(DirectSourceIPInputFactory);
DECLARE_FACTORY(HttpDirectSourceIPInputFactory);
inline constexpr absl::string_view Local = "local";
class SourceTypeInput : public Matcher::DataInput<MatchingDataType> {
const bool is_local_connection =
Network::Utility::isSameIpOrLoopback(data.connectionInfoProvider());
if (is_local_connection) {
return Matcher::DataInputGetResult::CreateStringView(Local);
class SourceTypeInputBaseFactory
: public BaseFactory<SourceTypeInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::SourceTypeInput,
SourceTypeInputBaseFactory()
: BaseFactory<SourceTypeInput<MatchingDataType>,
MatchingDataType>("source_type") {}
DECLARE_FACTORY(SourceTypeInputFactory);
DECLARE_FACTORY(HttpSourceTypeInputFactory);
class ServerNameInput : public Matcher::DataInput<MatchingDataType> {
absl::string_view server_name = data.connectionInfoProvider().requestedServerName();
if (!server_name.empty()) {
return Matcher::DataInputGetResult::CreateStringView(server_name);
class ServerNameInputBaseFactory
: public BaseFactory<ServerNameInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::ServerNameInput,
ServerNameInputBaseFactory()
: BaseFactory<ServerNameInput<MatchingDataType>,
MatchingDataType>("server_name") {}
DECLARE_FACTORY(ServerNameInputFactory);
DECLARE_FACTORY(HttpServerNameInputFactory);
class TransportProtocolInput : public Matcher::DataInput<MatchingData> {
Matcher::DataInputGetResult get(const MatchingData& data) const override;
class TransportProtocolInputFactory
TransportProtocolInput,
envoy::extensions::matching::common_inputs::network::v3::TransportProtocolInput,
MatchingData> {
TransportProtocolInputFactory() : BaseFactory("transport_protocol") {}
DECLARE_FACTORY(TransportProtocolInputFactory);
class FilterStateInput : public Matcher::DataInput<MatchingDataType> {
FilterStateInput(const std::string& filter_state_key, const std::string& field = "")
: filter_state_key_(filter_state_key), field_(field) {}
const auto* filter_state_object =
data.filterState().template getDataReadOnly<StreamInfo::FilterState::Object>(
filter_state_key_);
if (filter_state_object != nullptr) {
// If a field is specified and the object supports field access, use getField().
if (!field_.empty() && filter_state_object->hasFieldSupport()) {
const auto field_value = filter_state_object->getField(field_);
if (absl::holds_alternative<absl::string_view>(field_value)) {
return Matcher::DataInputGetResult::CreateStringView(
absl::get<absl::string_view>(field_value));
} else if (absl::holds_alternative<int64_t>(field_value)) {
return Matcher::DataInputGetResult::CreateString(
absl::StrCat(absl::get<int64_t>(field_value)));
// Default: return the serialized string representation of the whole object.
auto str = filter_state_object->serializeAsString();
if (str.has_value()) {
return Matcher::DataInputGetResult::CreateString(std::move(str).value());
} else {
const std::string filter_state_key_;
const std::string field_;
class FilterStateInputBaseFactory : public Matcher::DataInputFactory<MatchingDataType> {
std::string name() const override { return "envoy.matching.inputs.filter_state"; }
createDataInputFactoryCb(const Protobuf::Message& message,
ProtobufMessage::ValidationVisitor& validation_visitor) override {
const auto& typed_config = MessageUtil::downcastAndValidate<
const envoy::extensions::matching::common_inputs::network::v3::FilterStateInput&>(
message, validation_visitor);
return [filter_state_key = typed_config.key(), field = typed_config.field()] {
return std::make_unique<FilterStateInput<MatchingDataType>>(filter_state_key, field);
return std::make_unique<
envoy::extensions::matching::common_inputs::network::v3::FilterStateInput>();
DECLARE_FACTORY(FilterStateInputFactory);
DECLARE_FACTORY(HttpFilterStateInputFactory);
class NetworkNamespaceInput : public Matcher::DataInput<MatchingDataType>,
public Logger::Loggable<Logger::Id::matcher> {
auto network_namespace = address.networkNamespace();
if (network_namespace.has_value() && !network_namespace->empty()) {
ENVOY_LOG(debug, "NetworkNamespaceInput: local_address={} network_namespace='{}'",
address.asString(), network_namespace.value());
return Matcher::DataInputGetResult::CreateString(std::move(network_namespace).value());
ENVOY_LOG(debug, "NetworkNamespaceInput: no network namespace for local_address={}",
address.asString());
class NetworkNamespaceInputBaseFactory
NetworkNamespaceInput<MatchingDataType>,
envoy::extensions::matching::common_inputs::network::v3::NetworkNamespaceInput,
NetworkNamespaceInputBaseFactory()
: BaseFactory<NetworkNamespaceInput<MatchingDataType>,
MatchingDataType>("network_namespace") {}
// Provide a literal factory name for static discovery by the extensions checker.
std::string name() const override { return "envoy.matching.inputs.network_namespace"; }
DECLARE_FACTORY(NetworkNamespaceInputFactory);
DECLARE_FACTORY(UdpNetworkNamespaceInputFactory);
DECLARE_FACTORY(HttpNetworkNamespaceInputFactory);
} // namespace Matching
} // namespace Network
} // namespace Envoy