This is an automated email from the ASF dual-hosted git repository.

maskit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c47100354 Cleanup P_SNIActionPerformer (#10727)
0c47100354 is described below

commit 0c471003541e0835a6f190104e5214da4ca9a026
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Tue Nov 7 08:21:36 2023 +0900

    Cleanup P_SNIActionPerformer (#10727)
    
    Move function definitions into the .cc file so the hedaer file doesn't 
bring unrelated dependencies.
---
 .../net/{SNIActionPerformer.h => SNIActionItem.h}  |   3 +-
 include/iocore/net/SSLSNIConfig.h                  |   2 +-
 include/iocore/net/YamlSNIConfig.h                 |   3 +-
 src/iocore/net/P_Connection.h                      |   1 +
 src/iocore/net/P_SNIActionPerformer.h              | 582 ---------------------
 src/iocore/net/SNIActionPerformer.cc               | 321 +++++++++++-
 src/iocore/net/SNIActionPerformer.h                | 304 +++++++++++
 src/iocore/net/SSLSNIConfig.cc                     |   5 +-
 src/iocore/net/YamlSNIConfig.cc                    |   4 +-
 src/proxy/http/HttpSM.cc                           |   1 +
 src/proxy/http3/Http3SessionAccept.cc              |   1 +
 11 files changed, 639 insertions(+), 588 deletions(-)

diff --git a/include/iocore/net/SNIActionPerformer.h 
b/include/iocore/net/SNIActionItem.h
similarity index 98%
rename from include/iocore/net/SNIActionPerformer.h
rename to include/iocore/net/SNIActionItem.h
index 5e49822857..11902f3481 100644
--- a/include/iocore/net/SNIActionPerformer.h
+++ b/include/iocore/net/SNIActionItem.h
@@ -32,7 +32,8 @@
 
 #include <vector>
 #include <optional>
-#include "iocore/net/TLSSNISupport.h"
+#include <openssl/ssl.h>
+
 #include "tscore/ink_inet.h"
 #include "ts/DbgCtl.h"
 
diff --git a/include/iocore/net/SSLSNIConfig.h 
b/include/iocore/net/SSLSNIConfig.h
index 434d43d202..856c1b9f30 100644
--- a/include/iocore/net/SSLSNIConfig.h
+++ b/include/iocore/net/SSLSNIConfig.h
@@ -40,7 +40,7 @@
 #include "tscpp/util/ts_ip.h"
 
 #include "iocore/eventsystem/ConfigProcessor.h"
-#include "iocore/net/SNIActionPerformer.h"
+#include "iocore/net/SNIActionItem.h"
 #include "iocore/net/YamlSNIConfig.h"
 
 #include <functional>
diff --git a/include/iocore/net/YamlSNIConfig.h 
b/include/iocore/net/YamlSNIConfig.h
index eed19f56be..ce57136e79 100644
--- a/include/iocore/net/YamlSNIConfig.h
+++ b/include/iocore/net/YamlSNIConfig.h
@@ -29,7 +29,6 @@
 #include <memory>
 #include <cstdint>
 
-#include "iocore/net/SNIActionPerformer.h"
 #include "iocore/net/SSLTypes.h"
 
 #include "tscpp/util/ts_ip.h"
@@ -74,6 +73,8 @@ TSDECL(http2_initial_window_size_in);
 TSDECL(server_max_early_data);
 #undef TSDECL
 
+class ActionItem;
+
 struct YamlSNIConfig {
   enum class Policy : uint8_t { DISABLED = 0, PERMISSIVE, ENFORCED, UNSET };
   enum class Property : uint8_t { NONE = 0, SIGNATURE_MASK = 0x1, NAME_MASK = 
0x2, ALL_MASK = 0x3, UNSET };
diff --git a/src/iocore/net/P_Connection.h b/src/iocore/net/P_Connection.h
index dd1a95c051..ffbe51d9b9 100644
--- a/src/iocore/net/P_Connection.h
+++ b/src/iocore/net/P_Connection.h
@@ -50,6 +50,7 @@
 #pragma once
 
 #include "tscore/ink_platform.h"
+#include "iocore/net/NetProcessor.h"
 
 struct NetVCOptions;
 
diff --git a/src/iocore/net/P_SNIActionPerformer.h 
b/src/iocore/net/P_SNIActionPerformer.h
deleted file mode 100644
index 9f5fc67871..0000000000
--- a/src/iocore/net/P_SNIActionPerformer.h
+++ /dev/null
@@ -1,582 +0,0 @@
-/** @file
-
-  A brief file description
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- */
-
-/*************************** -*- Mod: C++ -*- ******************************
-  P_ActionProcessor.h
-   Created On      : 05/02/2017
-
-   Description:
-   SNI based Configuration in ATS
- ****************************************************************************/
-#pragma once
-
-#include "swoc/TextView.h"
-#include "swoc/swoc_ip.h"
-
-#include "iocore/eventsystem/EventSystem.h"
-#include "P_SSLNextProtocolAccept.h"
-#include "P_SSLNetVConnection.h"
-#include "iocore/net/SNIActionPerformer.h"
-#include "iocore/net/SSLTypes.h"
-
-#include "tscore/ink_inet.h"
-
-#include <vector>
-
-class ControlQUIC : public ActionItem
-{
-public:
-#if TS_USE_QUIC == 1
-  ControlQUIC(bool turn_on) : enable_quic(turn_on) {}
-#else
-  ControlQUIC(bool turn_on) {}
-#endif
-  ~ControlQUIC() override {}
-
-  int SNIAction(SSL &ssl, const Context &ctx) const override;
-
-private:
-#if TS_USE_QUIC == 1
-  bool enable_quic = false;
-#endif
-};
-
-class ControlH2 : public ActionItem
-{
-public:
-  ControlH2(bool turn_on) : enable_h2(turn_on) {}
-  ~ControlH2() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    auto snis  = TLSSNISupport::getInstance(&ssl);
-    auto alpns = ALPNSupport::getInstance(&ssl);
-
-    if (snis == nullptr || alpns == nullptr) {
-      return SSL_TLSEXT_ERR_OK;
-    }
-
-    const char *servername = snis->get_sni_server_name();
-    if (!enable_h2) {
-      alpns->disableProtocol(TS_ALPN_PROTOCOL_INDEX_HTTP_2_0);
-      Dbg(dbg_ctl_ssl_sni, "H2 disabled, fqdn [%s]", servername);
-    } else {
-      alpns->enableProtocol(TS_ALPN_PROTOCOL_INDEX_HTTP_2_0);
-      Dbg(dbg_ctl_ssl_sni, "H2 enabled, fqdn [%s]", servername);
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  bool enable_h2 = false;
-};
-
-class HTTP2BufferWaterMark : public ActionItem
-{
-public:
-  HTTP2BufferWaterMark(int value) : value(value) {}
-  ~HTTP2BufferWaterMark() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-      snis->hints_from_sni.http2_buffer_water_mark = value;
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  int value = -1;
-};
-
-class HTTP2InitialWindowSizeIn : public ActionItem
-{
-public:
-  HTTP2InitialWindowSizeIn(int value) : value(value) {}
-  ~HTTP2InitialWindowSizeIn() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-      snis->hints_from_sni.http2_initial_window_size_in = value;
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  int value = -1;
-};
-
-class HTTP2MaxSettingsFramesPerMinute : public ActionItem
-{
-public:
-  HTTP2MaxSettingsFramesPerMinute(int value) : value(value) {}
-  ~HTTP2MaxSettingsFramesPerMinute() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-      snis->hints_from_sni.http2_max_settings_frames_per_minute = value;
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  int value = -1;
-};
-
-class HTTP2MaxPingFramesPerMinute : public ActionItem
-{
-public:
-  HTTP2MaxPingFramesPerMinute(int value) : value(value) {}
-  ~HTTP2MaxPingFramesPerMinute() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-      snis->hints_from_sni.http2_max_ping_frames_per_minute = value;
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  int value = -1;
-};
-
-class HTTP2MaxPriorityFramesPerMinute : public ActionItem
-{
-public:
-  HTTP2MaxPriorityFramesPerMinute(int value) : value(value) {}
-  ~HTTP2MaxPriorityFramesPerMinute() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-      snis->hints_from_sni.http2_max_priority_frames_per_minute = value;
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  int value = -1;
-};
-
-class HTTP2MaxRstStreamFramesPerMinute : public ActionItem
-{
-public:
-  HTTP2MaxRstStreamFramesPerMinute(int value) : value(value) {}
-  ~HTTP2MaxRstStreamFramesPerMinute() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-      snis->hints_from_sni.http2_max_rst_stream_frames_per_minute = value;
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  int value = -1;
-};
-
-class TunnelDestination : public ActionItem
-{
-  // ID of the configured variable. This will be used to know which function
-  // should be called when processing the tunnel destination.
-  enum OpId : int32_t {
-    MATCH_GROUPS,                 // Deal with configured groups.
-    MAP_WITH_RECV_PORT,           // Use port from inbound local
-    MAP_WITH_PROXY_PROTOCOL_PORT, // Use port from the proxy protocol
-    MAX                           // Always at the end and do not change the 
value of the above items.
-  };
-  static constexpr std::string_view MAP_WITH_RECV_PORT_STR           = 
"{inbound_local_port}";
-  static constexpr std::string_view MAP_WITH_PROXY_PROTOCOL_PORT_STR = 
"{proxy_protocol_port}";
-
-public:
-  TunnelDestination(const std::string_view &dest, SNIRoutingType type, 
YamlSNIConfig::TunnelPreWarm prewarm,
-                    const std::vector<int> &alpn)
-    : destination(dest), type(type), tunnel_prewarm(prewarm), alpn_ids(alpn)
-  {
-    // Check for port variable specification. Note that this is checked before
-    // the match group so that the corresponding function can be applied before
-    // the match group expansion(when the var_start_pos is still accurate).
-    auto recv_port_start_pos = destination.find(MAP_WITH_RECV_PORT_STR);
-    auto pp_port_start_pos   = 
destination.find(MAP_WITH_PROXY_PROTOCOL_PORT_STR);
-    bool has_recv_port_var   = recv_port_start_pos != std::string::npos;
-    bool has_pp_port_var     = pp_port_start_pos != std::string::npos;
-    if (has_recv_port_var && has_pp_port_var) {
-      Error("Invalid destination \"%.*s\" in SNI configuration - Only one port 
variable can be specified.",
-            static_cast<int>(destination.size()), destination.data());
-    } else if (has_recv_port_var) {
-      fnArrIndexes.push_back(OpId::MAP_WITH_RECV_PORT);
-      var_start_pos = recv_port_start_pos;
-    } else if (has_pp_port_var) {
-      fnArrIndexes.push_back(OpId::MAP_WITH_PROXY_PROTOCOL_PORT);
-      var_start_pos = pp_port_start_pos;
-    }
-    // Check for match groups as well.
-    if (destination.find_first_of('$') != std::string::npos) {
-      fnArrIndexes.push_back(OpId::MATCH_GROUPS);
-    }
-  }
-  ~TunnelDestination() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    auto snis      = TLSSNISupport::getInstance(&ssl);
-    auto tuns      = TLSTunnelSupport::getInstance(&ssl);
-    auto alpns     = ALPNSupport::getInstance(&ssl);
-    auto ssl_netvc = SSLNetVCAccess(&ssl);
-
-    if (snis == nullptr || tuns == nullptr || alpns == nullptr || ssl_netvc == 
nullptr) {
-      return SSL_TLSEXT_ERR_OK;
-    }
-
-    const char *servername = snis->get_sni_server_name();
-    if (fnArrIndexes.empty()) {
-      tuns->set_tunnel_destination(destination, type, 
!TLSTunnelSupport::PORT_IS_DYNAMIC, tunnel_prewarm);
-      Debug("ssl_sni", "Destination now is [%s], fqdn [%s]", 
destination.c_str(), servername);
-    } else {
-      bool port_is_dynamic = false;
-      auto fixed_dst{destination};
-      // Apply mapping functions to get the final destination.
-      for (auto fnArrIndex : fnArrIndexes) {
-        // Dispatch to the correct tunnel destination port function.
-        fixed_dst = fix_destination[fnArrIndex](fixed_dst, var_start_pos, ctx, 
ssl_netvc, port_is_dynamic);
-      }
-      tuns->set_tunnel_destination(fixed_dst, type, port_is_dynamic, 
tunnel_prewarm);
-      Debug("ssl_sni", "Destination now is [%s], configured [%s], fqdn [%s]", 
fixed_dst.c_str(), destination.c_str(), servername);
-    }
-
-    if (type == SNIRoutingType::BLIND) {
-      ssl_netvc->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
-    }
-
-    // ALPN
-    for (int id : alpn_ids) {
-      alpns->enableProtocol(id);
-    }
-
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  static bool
-  is_number(std::string_view s)
-  {
-    return !s.empty() &&
-           std::find_if(std::begin(s), std::end(s), 
[](std::string_view::value_type c) { return !std::isdigit(c); }) == std::end(s);
-  }
-
-  /**
-   * `tunnel_route` may contain matching groups ie: `$1` which needs to be 
replaced by the corresponding
-   * captured group from the `fqdn`, this function will replace them using 
proper group string. Matching
-   * groups could be at any order.
-   */
-  static std::string
-  replace_match_groups(std::string_view dst, const 
ActionItem::Context::CapturedGroupViewVec &groups, bool &port_is_dynamic)
-  {
-    port_is_dynamic = false;
-    if (dst.empty() || groups.empty()) {
-      return std::string{dst};
-    }
-    std::string real_dst;
-    std::string::size_type pos{0};
-
-    const auto end = std::end(dst);
-    // We need to split the tunnel string and place each corresponding match 
on the
-    // configured one, so we need to first, get the match, then get the match 
number
-    // making sure that it does exist in the captured group.
-    bool is_writing_port = false;
-    for (auto c = std::begin(dst); c != end; c++, pos++) {
-      if (*c == ':') {
-        is_writing_port = true;
-      }
-      if (*c == '$') {
-        // find the next '.' so we can get the group number.
-        const auto dot            = dst.find('.', pos);
-        std::string::size_type to = std::string::npos;
-        if (dot != std::string::npos) {
-          to = dot - (pos + 1);
-        } else {
-          // It may not have a dot, which could be because it's the last part. 
In that case
-          // we should check for the port separator.
-          if (const auto port = dst.find(':', pos); port != std::string::npos) 
{
-            to = (port - pos) - 1;
-          }
-        }
-        std::string_view number_str{dst.substr(pos + 1, to)};
-        if (!is_number(number_str)) {
-          // it may be some issue on the configured string, place the char and 
keep going.
-          real_dst += *c;
-          continue;
-        }
-        const std::size_t group_index = swoc::svtoi(number_str);
-        if ((group_index - 1) < groups.size()) {
-          // place the captured group.
-          real_dst += groups[group_index - 1];
-          if (is_writing_port) {
-            port_is_dynamic = true;
-          }
-          // if it was the last match, then ...
-          if (dot == std::string::npos && to == std::string::npos) {
-            // that's it.
-            break;
-          }
-          pos += number_str.size() + 1;
-          std::advance(c, number_str.size() + 1);
-        }
-        // If there is no match for a specific group, then we keep the `$#` as 
defined in the string.
-      }
-      real_dst += *c;
-    }
-
-    return real_dst;
-  }
-
-  std::string destination;
-
-  /// The start position of a tunnel destination variable, such as 
'{proxy_protocol_port}'.
-  size_t var_start_pos{0};
-  SNIRoutingType type                         = SNIRoutingType::NONE;
-  YamlSNIConfig::TunnelPreWarm tunnel_prewarm = 
YamlSNIConfig::TunnelPreWarm::UNSET;
-  const std::vector<int> &alpn_ids;
-
-  /** The indexes of the mapping functions that need to be called. On
-  creation, we decide which functions need to be called, add the coressponding
-  indexes and then we call those functions with the relevant data.
-  */
-  std::vector<OpId> fnArrIndexes;
-
-  /// tunnel_route destination callback array.
-  static std::array<std::function<std::string(std::string_view,    // 
destination view
-                                              size_t,              // The 
start position for any relevant tunnel_route variable.
-                                              const Context &,     // Context
-                                              SSLNetVConnection *, // Net vc 
to get the port.
-                                              bool &               // Whether 
the port is derived from information on the wire.
-                                              )>,
-                    OpId::MAX>
-    fix_destination;
-};
-
-class VerifyClient : public ActionItem
-{
-  uint8_t mode;
-  std::string ca_file;
-  std::string ca_dir;
-
-public:
-  VerifyClient(uint8_t param, std::string_view file, std::string_view dir) : 
mode(param), ca_file(file), ca_dir(dir) {}
-  VerifyClient(const char *param, std::string_view file, std::string_view dir) 
: VerifyClient(atoi(param), file, dir) {}
-  ~VerifyClient() override;
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    auto snis   = TLSSNISupport::getInstance(&ssl);
-    auto ssl_vc = SSLNetVCAccess(&ssl);
-
-    if (snis == nullptr || ssl_vc == nullptr) {
-      return SSL_TLSEXT_ERR_OK;
-    }
-
-    const char *servername = snis->get_sni_server_name();
-    Dbg(dbg_ctl_ssl_sni, "action verify param %d, fqdn [%s]", this->mode, 
servername);
-    setClientCertLevel(ssl_vc->ssl, this->mode);
-    ssl_vc->set_ca_cert_file(ca_file, ca_dir);
-    setClientCertCACerts(ssl_vc->ssl, ssl_vc->get_ca_cert_file(), 
ssl_vc->get_ca_cert_dir());
-
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-  bool
-  TestClientSNIAction(const char *servername, const IpEndpoint &ep, int 
&policy) const override
-  {
-    // This action is triggered by a SNI if it was set
-    return true;
-  }
-
-  // No copying or moving.
-  VerifyClient(VerifyClient const &)            = delete;
-  VerifyClient &operator=(VerifyClient const &) = delete;
-};
-
-class HostSniPolicy : public ActionItem
-{
-  uint8_t policy;
-
-public:
-  HostSniPolicy(const char *param) : policy(atoi(param)) {}
-  HostSniPolicy(uint8_t param) : policy(param) {}
-  ~HostSniPolicy() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    // On action this doesn't do anything
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-  bool
-  TestClientSNIAction(const char *servername, const IpEndpoint &ep, int 
&in_policy) const override
-  {
-    // Update the policy when testing
-    in_policy = this->policy;
-    // But this action didn't really trigger during the action phase
-    return false;
-  }
-};
-
-class TLSValidProtocols : public ActionItem
-{
-  bool unset = true;
-  unsigned long protocol_mask;
-  int min_ver = -1;
-  int max_ver = -1;
-
-public:
-#ifdef SSL_OP_NO_TLSv1_3
-  static const unsigned long max_mask = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | 
SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3;
-#else
-  static const unsigned long max_mask = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | 
SSL_OP_NO_TLSv1_2;
-#endif
-  TLSValidProtocols() : protocol_mask(max_mask) {}
-  TLSValidProtocols(unsigned long protocols) : unset(false), 
protocol_mask(protocols) {}
-  TLSValidProtocols(int min_ver, int max_ver) : unset(false), 
protocol_mask(0), min_ver(min_ver), max_ver(max_ver) {}
-
-  int
-  SNIAction(SSL &ssl, const Context & /* ctx */) const override
-  {
-    auto snis = TLSSNISupport::getInstance(&ssl);
-    auto tbs  = TLSBasicSupport::getInstance(&ssl);
-
-    if (snis == nullptr || tbs == nullptr) {
-      return SSL_TLSEXT_ERR_OK;
-    }
-
-    if (this->min_ver >= 0 || this->max_ver >= 0) {
-      const char *servername = snis->get_sni_server_name();
-      Dbg(dbg_ctl_ssl_sni, "TLSValidProtocol min=%d, max=%d, fqdn [%s]", 
this->min_ver, this->max_ver, servername);
-      tbs->set_valid_tls_version_min(this->min_ver);
-      tbs->set_valid_tls_version_max(this->max_ver);
-    } else {
-      if (!unset) {
-        const char *servername = snis->get_sni_server_name();
-        Dbg(dbg_ctl_ssl_sni, "TLSValidProtocol param 0%x, fqdn [%s]", 
static_cast<unsigned int>(this->protocol_mask), servername);
-        tbs->set_valid_tls_protocols(protocol_mask, 
TLSValidProtocols::max_mask);
-        Warning("valid_tls_versions_in is deprecated. Use 
valid_tls_version_min_in and ivalid_tls_version_max_in instead.");
-      }
-    }
-
-    return SSL_TLSEXT_ERR_OK;
-  }
-};
-
-class SNI_IpAllow : public ActionItem
-{
-  swoc::IPRangeSet ip_addrs;
-
-public:
-  SNI_IpAllow(std::string &ip_allow_list, const std::string &servername);
-
-  int SNIAction(SSL &ssl, const Context &ctx) const override;
-
-  bool TestClientSNIAction(const char *servrername, const IpEndpoint &ep, int 
&policy) const override;
-
-protected:
-  /** Load the map from @a text.
-   *
-   * @param content A list of IP addresses in text form, separated by commas 
or newlines.
-   * @param server_name Server named, used only for debugging messages.
-   */
-  void load(swoc::TextView content, swoc::TextView server_name);
-};
-
-/**
-   Override proxy.config.ssl.client.sni_policy by client_sni_policy in sni.yaml
- */
-class OutboundSNIPolicy : public ActionItem
-{
-public:
-  OutboundSNIPolicy(const std::string_view &p) : policy(p) {}
-  ~OutboundSNIPolicy() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-    if (!policy.empty()) {
-      if (auto snis = TLSSNISupport::getInstance(&ssl)) {
-        snis->hints_from_sni.outbound_sni_policy = policy;
-      }
-    }
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-private:
-  std::string_view policy{};
-};
-
-class ServerMaxEarlyData : public ActionItem
-{
-public:
-  ServerMaxEarlyData(uint32_t value)
-#if TS_HAS_TLS_EARLY_DATA
-    : server_max_early_data(value)
-#endif
-  {
-  }
-  ~ServerMaxEarlyData() override {}
-
-  int
-  SNIAction(SSL &ssl, const Context &ctx) const override
-  {
-#if TS_HAS_TLS_EARLY_DATA
-    auto snis = TLSSNISupport::getInstance(&ssl);
-    auto eds  = TLSEarlyDataSupport::getInstance(&ssl);
-
-    if (snis == nullptr || eds == nullptr) {
-      return SSL_TLSEXT_ERR_OK;
-    }
-
-    snis->hints_from_sni.server_max_early_data = server_max_early_data;
-    const uint32_t EARLY_DATA_DEFAULT_SIZE     = 16384;
-    const uint32_t server_recv_max_early_data =
-      server_max_early_data > 0 ? std::max(server_max_early_data, 
EARLY_DATA_DEFAULT_SIZE) : 0;
-    eds->update_early_data_config(&ssl, server_max_early_data, 
server_recv_max_early_data);
-#endif
-    return SSL_TLSEXT_ERR_OK;
-  }
-
-#if TS_HAS_TLS_EARLY_DATA
-private:
-  uint32_t server_max_early_data = 0;
-#endif
-};
diff --git a/src/iocore/net/SNIActionPerformer.cc 
b/src/iocore/net/SNIActionPerformer.cc
index c1f8169fcf..e4caa2ae91 100644
--- a/src/iocore/net/SNIActionPerformer.cc
+++ b/src/iocore/net/SNIActionPerformer.cc
@@ -26,7 +26,10 @@
 #include "swoc/bwf_std.h"
 #include "swoc/bwf_ip.h"
 
-#include "P_SNIActionPerformer.h"
+#include "SNIActionPerformer.h"
+
+#include "P_SSLNextProtocolAccept.h"
+#include "P_SSLNetVConnection.h"
 
 #if TS_USE_QUIC == 1
 #include "P_QUICNetVConnection.h"
@@ -58,6 +61,291 @@ ControlQUIC::SNIAction(SSL &ssl, const Context &ctx) const
 #endif
 }
 
+int
+ControlH2::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  auto snis  = TLSSNISupport::getInstance(&ssl);
+  auto alpns = ALPNSupport::getInstance(&ssl);
+
+  if (snis == nullptr || alpns == nullptr) {
+    return SSL_TLSEXT_ERR_OK;
+  }
+
+  const char *servername = snis->get_sni_server_name();
+  if (!enable_h2) {
+    alpns->disableProtocol(TS_ALPN_PROTOCOL_INDEX_HTTP_2_0);
+    Dbg(dbg_ctl_ssl_sni, "H2 disabled, fqdn [%s]", servername);
+  } else {
+    alpns->enableProtocol(TS_ALPN_PROTOCOL_INDEX_HTTP_2_0);
+    Dbg(dbg_ctl_ssl_sni, "H2 enabled, fqdn [%s]", servername);
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+HTTP2BufferWaterMark::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+    snis->hints_from_sni.http2_buffer_water_mark = value;
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+HTTP2InitialWindowSizeIn::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+    snis->hints_from_sni.http2_initial_window_size_in = value;
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+HTTP2MaxSettingsFramesPerMinute::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+    snis->hints_from_sni.http2_max_settings_frames_per_minute = value;
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+HTTP2MaxPingFramesPerMinute::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+    snis->hints_from_sni.http2_max_ping_frames_per_minute = value;
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+HTTP2MaxPriorityFramesPerMinute::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+    snis->hints_from_sni.http2_max_priority_frames_per_minute = value;
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+HTTP2MaxRstStreamFramesPerMinute::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+    snis->hints_from_sni.http2_max_rst_stream_frames_per_minute = value;
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+TunnelDestination::TunnelDestination(const std::string_view &dest, 
SNIRoutingType type, YamlSNIConfig::TunnelPreWarm prewarm,
+                                     const std::vector<int> &alpn)
+  : destination(dest), type(type), tunnel_prewarm(prewarm), alpn_ids(alpn)
+{
+  // Check for port variable specification. Note that this is checked before
+  // the match group so that the corresponding function can be applied before
+  // the match group expansion(when the var_start_pos is still accurate).
+  auto recv_port_start_pos = destination.find(MAP_WITH_RECV_PORT_STR);
+  auto pp_port_start_pos   = 
destination.find(MAP_WITH_PROXY_PROTOCOL_PORT_STR);
+  bool has_recv_port_var   = recv_port_start_pos != std::string::npos;
+  bool has_pp_port_var     = pp_port_start_pos != std::string::npos;
+  if (has_recv_port_var && has_pp_port_var) {
+    Error("Invalid destination \"%.*s\" in SNI configuration - Only one port 
variable can be specified.",
+          static_cast<int>(destination.size()), destination.data());
+  } else if (has_recv_port_var) {
+    fnArrIndexes.push_back(OpId::MAP_WITH_RECV_PORT);
+    var_start_pos = recv_port_start_pos;
+  } else if (has_pp_port_var) {
+    fnArrIndexes.push_back(OpId::MAP_WITH_PROXY_PROTOCOL_PORT);
+    var_start_pos = pp_port_start_pos;
+  }
+  // Check for match groups as well.
+  if (destination.find_first_of('$') != std::string::npos) {
+    fnArrIndexes.push_back(OpId::MATCH_GROUPS);
+  }
+}
+
+int
+TunnelDestination::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  auto snis      = TLSSNISupport::getInstance(&ssl);
+  auto tuns      = TLSTunnelSupport::getInstance(&ssl);
+  auto alpns     = ALPNSupport::getInstance(&ssl);
+  auto ssl_netvc = SSLNetVCAccess(&ssl);
+
+  if (snis == nullptr || tuns == nullptr || alpns == nullptr || ssl_netvc == 
nullptr) {
+    return SSL_TLSEXT_ERR_OK;
+  }
+
+  const char *servername = snis->get_sni_server_name();
+  if (fnArrIndexes.empty()) {
+    tuns->set_tunnel_destination(destination, type, 
!TLSTunnelSupport::PORT_IS_DYNAMIC, tunnel_prewarm);
+    Debug("ssl_sni", "Destination now is [%s], fqdn [%s]", 
destination.c_str(), servername);
+  } else {
+    bool port_is_dynamic = false;
+    auto fixed_dst{destination};
+    // Apply mapping functions to get the final destination.
+    for (auto fnArrIndex : fnArrIndexes) {
+      // Dispatch to the correct tunnel destination port function.
+      fixed_dst = fix_destination[fnArrIndex](fixed_dst, var_start_pos, ctx, 
ssl_netvc, port_is_dynamic);
+    }
+    tuns->set_tunnel_destination(fixed_dst, type, port_is_dynamic, 
tunnel_prewarm);
+    Debug("ssl_sni", "Destination now is [%s], configured [%s], fqdn [%s]", 
fixed_dst.c_str(), destination.c_str(), servername);
+  }
+
+  if (type == SNIRoutingType::BLIND) {
+    ssl_netvc->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
+  }
+
+  // ALPN
+  for (int id : alpn_ids) {
+    alpns->enableProtocol(id);
+  }
+
+  return SSL_TLSEXT_ERR_OK;
+}
+
+bool
+TunnelDestination::is_number(std::string_view s)
+{
+  return !s.empty() &&
+         std::find_if(std::begin(s), std::end(s), 
[](std::string_view::value_type c) { return !std::isdigit(c); }) == std::end(s);
+}
+
+/**
+ * `tunnel_route` may contain matching groups ie: `$1` which needs to be 
replaced by the corresponding
+ * captured group from the `fqdn`, this function will replace them using 
proper group string. Matching
+ * groups could be at any order.
+ */
+std::string
+TunnelDestination::replace_match_groups(std::string_view dst, const 
ActionItem::Context::CapturedGroupViewVec &groups,
+                                        bool &port_is_dynamic)
+{
+  port_is_dynamic = false;
+  if (dst.empty() || groups.empty()) {
+    return std::string{dst};
+  }
+  std::string real_dst;
+  std::string::size_type pos{0};
+
+  const auto end = std::end(dst);
+  // We need to split the tunnel string and place each corresponding match on 
the
+  // configured one, so we need to first, get the match, then get the match 
number
+  // making sure that it does exist in the captured group.
+  bool is_writing_port = false;
+  for (auto c = std::begin(dst); c != end; c++, pos++) {
+    if (*c == ':') {
+      is_writing_port = true;
+    }
+    if (*c == '$') {
+      // find the next '.' so we can get the group number.
+      const auto dot            = dst.find('.', pos);
+      std::string::size_type to = std::string::npos;
+      if (dot != std::string::npos) {
+        to = dot - (pos + 1);
+      } else {
+        // It may not have a dot, which could be because it's the last part. 
In that case
+        // we should check for the port separator.
+        if (const auto port = dst.find(':', pos); port != std::string::npos) {
+          to = (port - pos) - 1;
+        }
+      }
+      std::string_view number_str{dst.substr(pos + 1, to)};
+      if (!is_number(number_str)) {
+        // it may be some issue on the configured string, place the char and 
keep going.
+        real_dst += *c;
+        continue;
+      }
+      const std::size_t group_index = swoc::svtoi(number_str);
+      if ((group_index - 1) < groups.size()) {
+        // place the captured group.
+        real_dst += groups[group_index - 1];
+        if (is_writing_port) {
+          port_is_dynamic = true;
+        }
+        // if it was the last match, then ...
+        if (dot == std::string::npos && to == std::string::npos) {
+          // that's it.
+          break;
+        }
+        pos += number_str.size() + 1;
+        std::advance(c, number_str.size() + 1);
+      }
+      // If there is no match for a specific group, then we keep the `$#` as 
defined in the string.
+    }
+    real_dst += *c;
+  }
+
+  return real_dst;
+}
+
+int
+VerifyClient::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  auto snis   = TLSSNISupport::getInstance(&ssl);
+  auto ssl_vc = SSLNetVCAccess(&ssl);
+
+  if (snis == nullptr || ssl_vc == nullptr) {
+    return SSL_TLSEXT_ERR_OK;
+  }
+
+  const char *servername = snis->get_sni_server_name();
+  Dbg(dbg_ctl_ssl_sni, "action verify param %d, fqdn [%s]", this->mode, 
servername);
+  setClientCertLevel(ssl_vc->ssl, this->mode);
+  ssl_vc->set_ca_cert_file(ca_file, ca_dir);
+  setClientCertCACerts(ssl_vc->ssl, ssl_vc->get_ca_cert_file(), 
ssl_vc->get_ca_cert_dir());
+
+  return SSL_TLSEXT_ERR_OK;
+}
+
+bool
+VerifyClient::TestClientSNIAction(const char *servername, const IpEndpoint 
&ep, int &policy) const
+{
+  // This action is triggered by a SNI if it was set
+  return true;
+}
+
+int
+HostSniPolicy::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  // On action this doesn't do anything
+  return SSL_TLSEXT_ERR_OK;
+}
+
+bool
+HostSniPolicy::TestClientSNIAction(const char *servername, const IpEndpoint 
&ep, int &in_policy) const
+{
+  // Update the policy when testing
+  in_policy = this->policy;
+  // But this action didn't really trigger during the action phase
+  return false;
+}
+
+int
+TLSValidProtocols::SNIAction(SSL &ssl, const Context & /* ctx */) const
+{
+  auto snis = TLSSNISupport::getInstance(&ssl);
+  auto tbs  = TLSBasicSupport::getInstance(&ssl);
+
+  if (snis == nullptr || tbs == nullptr) {
+    return SSL_TLSEXT_ERR_OK;
+  }
+
+  if (this->min_ver >= 0 || this->max_ver >= 0) {
+    const char *servername = snis->get_sni_server_name();
+    Dbg(dbg_ctl_ssl_sni, "TLSValidProtocol min=%d, max=%d, fqdn [%s]", 
this->min_ver, this->max_ver, servername);
+    tbs->set_valid_tls_version_min(this->min_ver);
+    tbs->set_valid_tls_version_max(this->max_ver);
+  } else {
+    if (!unset) {
+      const char *servername = snis->get_sni_server_name();
+      Dbg(dbg_ctl_ssl_sni, "TLSValidProtocol param 0%x, fqdn [%s]", 
static_cast<unsigned int>(this->protocol_mask), servername);
+      tbs->set_valid_tls_protocols(protocol_mask, TLSValidProtocols::max_mask);
+      Warning("valid_tls_versions_in is deprecated. Use 
valid_tls_version_min_in and ivalid_tls_version_max_in instead.");
+    }
+  }
+
+  return SSL_TLSEXT_ERR_OK;
+}
+
 SNI_IpAllow::SNI_IpAllow(std::string &ip_allow_list, std::string const 
&servername)
 {
   swoc::TextView content{ip_allow_list};
@@ -122,3 +410,34 @@ SNI_IpAllow::TestClientSNIAction(char const *servrername, 
IpEndpoint const &ep,
 {
   return ip_addrs.contains(swoc::IPAddr(ep));
 }
+
+int
+OutboundSNIPolicy::SNIAction(SSL &ssl, const Context &ctx) const
+{
+  if (!policy.empty()) {
+    if (auto snis = TLSSNISupport::getInstance(&ssl)) {
+      snis->hints_from_sni.outbound_sni_policy = policy;
+    }
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+int
+ServerMaxEarlyData::SNIAction(SSL &ssl, const Context &ctx) const
+{
+#if TS_HAS_TLS_EARLY_DATA
+  auto snis = TLSSNISupport::getInstance(&ssl);
+  auto eds  = TLSEarlyDataSupport::getInstance(&ssl);
+
+  if (snis == nullptr || eds == nullptr) {
+    return SSL_TLSEXT_ERR_OK;
+  }
+
+  snis->hints_from_sni.server_max_early_data = server_max_early_data;
+  const uint32_t EARLY_DATA_DEFAULT_SIZE     = 16384;
+  const uint32_t server_recv_max_early_data =
+    server_max_early_data > 0 ? std::max(server_max_early_data, 
EARLY_DATA_DEFAULT_SIZE) : 0;
+  eds->update_early_data_config(&ssl, server_max_early_data, 
server_recv_max_early_data);
+#endif
+  return SSL_TLSEXT_ERR_OK;
+}
diff --git a/src/iocore/net/SNIActionPerformer.h 
b/src/iocore/net/SNIActionPerformer.h
new file mode 100644
index 0000000000..46fa1e8737
--- /dev/null
+++ b/src/iocore/net/SNIActionPerformer.h
@@ -0,0 +1,304 @@
+/** @file
+
+  SNI based Configuration in ATS
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#pragma once
+
+#include "swoc/TextView.h"
+#include "swoc/swoc_ip.h"
+
+#include "iocore/eventsystem/EventSystem.h"
+#include "iocore/net/SNIActionItem.h"
+#include "iocore/net/SSLTypes.h"
+#include "iocore/net/YamlSNIConfig.h"
+
+#include "tscore/ink_inet.h"
+
+#include <vector>
+
+class SSLNetVConnection;
+
+class ControlQUIC : public ActionItem
+{
+public:
+#if TS_USE_QUIC == 1
+  ControlQUIC(bool turn_on) : enable_quic(turn_on) {}
+#else
+  ControlQUIC(bool turn_on) {}
+#endif
+  ~ControlQUIC() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+#if TS_USE_QUIC == 1
+  bool enable_quic = false;
+#endif
+};
+
+class ControlH2 : public ActionItem
+{
+public:
+  ControlH2(bool turn_on) : enable_h2(turn_on) {}
+  ~ControlH2() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  bool enable_h2 = false;
+};
+
+class HTTP2BufferWaterMark : public ActionItem
+{
+public:
+  HTTP2BufferWaterMark(int value) : value(value) {}
+  ~HTTP2BufferWaterMark() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  int value = -1;
+};
+
+class HTTP2InitialWindowSizeIn : public ActionItem
+{
+public:
+  HTTP2InitialWindowSizeIn(int value) : value(value) {}
+  ~HTTP2InitialWindowSizeIn() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  int value = -1;
+};
+
+class HTTP2MaxSettingsFramesPerMinute : public ActionItem
+{
+public:
+  HTTP2MaxSettingsFramesPerMinute(int value) : value(value) {}
+  ~HTTP2MaxSettingsFramesPerMinute() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  int value = -1;
+};
+
+class HTTP2MaxPingFramesPerMinute : public ActionItem
+{
+public:
+  HTTP2MaxPingFramesPerMinute(int value) : value(value) {}
+  ~HTTP2MaxPingFramesPerMinute() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  int value = -1;
+};
+
+class HTTP2MaxPriorityFramesPerMinute : public ActionItem
+{
+public:
+  HTTP2MaxPriorityFramesPerMinute(int value) : value(value) {}
+  ~HTTP2MaxPriorityFramesPerMinute() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  int value = -1;
+};
+
+class HTTP2MaxRstStreamFramesPerMinute : public ActionItem
+{
+public:
+  HTTP2MaxRstStreamFramesPerMinute(int value) : value(value) {}
+  ~HTTP2MaxRstStreamFramesPerMinute() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  int value = -1;
+};
+
+class TunnelDestination : public ActionItem
+{
+  // ID of the configured variable. This will be used to know which function
+  // should be called when processing the tunnel destination.
+  enum OpId : int32_t {
+    MATCH_GROUPS,                 // Deal with configured groups.
+    MAP_WITH_RECV_PORT,           // Use port from inbound local
+    MAP_WITH_PROXY_PROTOCOL_PORT, // Use port from the proxy protocol
+    MAX                           // Always at the end and do not change the 
value of the above items.
+  };
+  static constexpr std::string_view MAP_WITH_RECV_PORT_STR           = 
"{inbound_local_port}";
+  static constexpr std::string_view MAP_WITH_PROXY_PROTOCOL_PORT_STR = 
"{proxy_protocol_port}";
+
+public:
+  TunnelDestination(const std::string_view &dest, SNIRoutingType type, 
YamlSNIConfig::TunnelPreWarm prewarm,
+                    const std::vector<int> &alpn);
+  ~TunnelDestination() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  static bool is_number(std::string_view s);
+
+  /**
+   * `tunnel_route` may contain matching groups ie: `$1` which needs to be 
replaced by the corresponding
+   * captured group from the `fqdn`, this function will replace them using 
proper group string. Matching
+   * groups could be at any order.
+   */
+  static std::string replace_match_groups(std::string_view dst, const 
ActionItem::Context::CapturedGroupViewVec &groups,
+                                          bool &port_is_dynamic);
+
+  std::string destination;
+
+  /// The start position of a tunnel destination variable, such as 
'{proxy_protocol_port}'.
+  size_t var_start_pos{0};
+  SNIRoutingType type                         = SNIRoutingType::NONE;
+  YamlSNIConfig::TunnelPreWarm tunnel_prewarm = 
YamlSNIConfig::TunnelPreWarm::UNSET;
+  const std::vector<int> &alpn_ids;
+
+  /** The indexes of the mapping functions that need to be called. On
+  creation, we decide which functions need to be called, add the coressponding
+  indexes and then we call those functions with the relevant data.
+  */
+  std::vector<OpId> fnArrIndexes;
+
+  /// tunnel_route destination callback array.
+  static std::array<std::function<std::string(std::string_view,    // 
destination view
+                                              size_t,              // The 
start position for any relevant tunnel_route variable.
+                                              const Context &,     // Context
+                                              SSLNetVConnection *, // Net vc 
to get the port.
+                                              bool &               // Whether 
the port is derived from information on the wire.
+                                              )>,
+                    OpId::MAX>
+    fix_destination;
+};
+
+class VerifyClient : public ActionItem
+{
+  uint8_t mode;
+  std::string ca_file;
+  std::string ca_dir;
+
+public:
+  VerifyClient(uint8_t param, std::string_view file, std::string_view dir) : 
mode(param), ca_file(file), ca_dir(dir) {}
+  VerifyClient(const char *param, std::string_view file, std::string_view dir) 
: VerifyClient(atoi(param), file, dir) {}
+  ~VerifyClient() override;
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+  bool TestClientSNIAction(const char *servername, const IpEndpoint &ep, int 
&policy) const override;
+
+  // No copying or moving.
+  VerifyClient(VerifyClient const &)            = delete;
+  VerifyClient &operator=(VerifyClient const &) = delete;
+};
+
+class HostSniPolicy : public ActionItem
+{
+  uint8_t policy;
+
+public:
+  HostSniPolicy(const char *param) : policy(atoi(param)) {}
+  HostSniPolicy(uint8_t param) : policy(param) {}
+  ~HostSniPolicy() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+  bool TestClientSNIAction(const char *servername, const IpEndpoint &ep, int 
&in_policy) const override;
+};
+
+class TLSValidProtocols : public ActionItem
+{
+  bool unset = true;
+  unsigned long protocol_mask;
+  int min_ver = -1;
+  int max_ver = -1;
+
+public:
+#ifdef SSL_OP_NO_TLSv1_3
+  static const unsigned long max_mask = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | 
SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3;
+#else
+  static const unsigned long max_mask = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | 
SSL_OP_NO_TLSv1_2;
+#endif
+  TLSValidProtocols() : protocol_mask(max_mask) {}
+  TLSValidProtocols(unsigned long protocols) : unset(false), 
protocol_mask(protocols) {}
+  TLSValidProtocols(int min_ver, int max_ver) : unset(false), 
protocol_mask(0), min_ver(min_ver), max_ver(max_ver) {}
+
+  int SNIAction(SSL &ssl, const Context & /* ctx */) const override;
+};
+
+class SNI_IpAllow : public ActionItem
+{
+  swoc::IPRangeSet ip_addrs;
+
+public:
+  SNI_IpAllow(std::string &ip_allow_list, const std::string &servername);
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+  bool TestClientSNIAction(const char *servrername, const IpEndpoint &ep, int 
&policy) const override;
+
+protected:
+  /** Load the map from @a text.
+   *
+   * @param content A list of IP addresses in text form, separated by commas 
or newlines.
+   * @param server_name Server named, used only for debugging messages.
+   */
+  void load(swoc::TextView content, swoc::TextView server_name);
+};
+
+/**
+   Override proxy.config.ssl.client.sni_policy by client_sni_policy in sni.yaml
+ */
+class OutboundSNIPolicy : public ActionItem
+{
+public:
+  OutboundSNIPolicy(const std::string_view &p) : policy(p) {}
+  ~OutboundSNIPolicy() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+  std::string_view policy{};
+};
+
+class ServerMaxEarlyData : public ActionItem
+{
+public:
+  ServerMaxEarlyData(uint32_t value)
+#if TS_HAS_TLS_EARLY_DATA
+    : server_max_early_data(value)
+#endif
+  {
+  }
+  ~ServerMaxEarlyData() override {}
+
+  int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+#if TS_HAS_TLS_EARLY_DATA
+private:
+  uint32_t server_max_early_data = 0;
+#endif
+};
diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc
index d17b241527..961dc8487b 100644
--- a/src/iocore/net/SSLSNIConfig.cc
+++ b/src/iocore/net/SSLSNIConfig.cc
@@ -30,7 +30,10 @@
  ****************************************************************************/
 
 #include "iocore/net/SSLSNIConfig.h"
-#include "P_SNIActionPerformer.h"
+#include "iocore/net/SNIActionItem.h"
+
+#include "P_SSLUtils.h"
+#include "P_SSLConfig.h"
 
 #include "tscore/Diags.h"
 #include "tscore/SimpleTokenizer.h"
diff --git a/src/iocore/net/YamlSNIConfig.cc b/src/iocore/net/YamlSNIConfig.cc
index 844e6a0562..05dcd5ee57 100644
--- a/src/iocore/net/YamlSNIConfig.cc
+++ b/src/iocore/net/YamlSNIConfig.cc
@@ -38,7 +38,9 @@
 #include "swoc/TextView.h"
 #include "swoc/bwf_base.h"
 
-#include "P_SNIActionPerformer.h"
+#include "SNIActionPerformer.h"
+#include "P_SSLConfig.h"
+#include "P_SSLNetVConnection.h"
 
 #include "tscpp/util/ts_ip.h"
 
diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc
index 24325f600a..e987911eaf 100644
--- a/src/proxy/http/HttpSM.cc
+++ b/src/proxy/http/HttpSM.cc
@@ -50,6 +50,7 @@
 #include "iocore/net/SSLSNIConfig.h"
 #include "iocore/net/TLSALPNSupport.h"
 #include "iocore/net/TLSBasicSupport.h"
+#include "iocore/net/TLSSNISupport.h"
 #include "iocore/net/TLSSessionResumptionSupport.h"
 #include "iocore/net/TLSTunnelSupport.h"
 #include "proxy/http/HttpPages.h"
diff --git a/src/proxy/http3/Http3SessionAccept.cc 
b/src/proxy/http3/Http3SessionAccept.cc
index 188959845f..0d3f9aed73 100644
--- a/src/proxy/http3/Http3SessionAccept.cc
+++ b/src/proxy/http3/Http3SessionAccept.cc
@@ -26,6 +26,7 @@
 #include "../../iocore/net/P_Net.h"
 #include "iocore/utils/Machine.h"
 #include "proxy/IPAllow.h"
+#include "iocore/net/TLSSNISupport.h"
 #include "iocore/net/QUICSupport.h"
 
 #include "proxy/http3/Http09App.h"


Reply via email to