diff --git a/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst index 1a604afdc33..cfbee11b924 100644 --- a/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst +++ b/doc/developer-guide/api/functions/TSHttpTxnOutgoingAddrGet.en.rst @@ -14,11 +14,13 @@ implied. See the License for the specific language governing permissions and limitations under the License. +.. include:: ../../../common.defs +.. default-domain:: c -TSHttpTxnOutgoingAddrGet +Local outbound address ======================== -Get the outgoing address used in origin connection. +Get or set the local IP address for outbound connections. Synopsis @@ -27,13 +29,26 @@ Synopsis `#include ` .. c:function:: sockaddr const* TSHttpTxnOutgoingAddrGet(TSHttpTxn txnp) +.. c:function:: TSReturnCode TSHttpTxnOutgoingAddrSet(TSHttpTxn txnp, sockaddr const* addr) Description ----------- -.. note:: +These functions concern the local IP address and port, that is the address and port on the |TS| side +of outbound connections (network connections *from* |TS| *to* another socket). - The pointer is valid only for the current callback. Clients that - need to keep the value across callbacks must maintain their own - storage. +The address and optional the port can be set with :func:`TSHttpTxnOutgoingAddrSet`. This must be +done before the outbound connection is made, that is in the :macro:`TS_HTTP_SEND_REQUEST_HDR_HOOK` or earlier. +The :arg:`addr` must be populated with the IP address and port to be used. If the port is not +relevant it can be set to zero, which means use any available local port. This function returns +:macro:`TS_SUCCESS` on success and :macro:`TS_ERROR` on failure. + +Even on a successful call to :func:`TSHttpTxnOutgoingAddrSet`, the local IP address may not match +what was passing :arg:`addr` if :ts:cv:`session sharing ` is enabled. + +Conversely :func:`TSHttpTxnOutgoingAddrGet` retrieves the local address and must be called after +:macro:`TS_HTTP_SEND_REQUEST_HDR_HOOK`, after the outbound connection has been established. It returns a +pointer to a :code:`sockaddr` which contains the local IP address and port. If there is no valid +outbound connection, :arg:`addr` will be :code:`NULL`. The returned pointer is a transient pointer +and must not be referenced after the callback in which :func:`TSHttpTxnOutgoingAddrGet` was called. diff --git a/proxy/ProxyClientSession.h b/proxy/ProxyClientSession.h index c797e9d3f97..ec636bda558 100644 --- a/proxy/ProxyClientSession.h +++ b/proxy/ProxyClientSession.h @@ -161,6 +161,24 @@ class ProxyClientSession : public VConnection // Indicate we are done with a transaction. virtual void release(ProxyClientTransaction *trans) = 0; + virtual in_port_t + get_outbound_port() const + { + return outbound_port; + } + + virtual IpAddr + get_outbound_ip4() const + { + return outbound_ip4; + } + + virtual IpAddr + get_outbound_ip6() const + { + return outbound_ip6; + } + int64_t connection_id() const { @@ -240,6 +258,13 @@ class ProxyClientSession : public VConnection /// acl record - cache IpAllow::match() call const AclRecord *acl_record = nullptr; + /// Local address for outbound connection. + IpAddr outbound_ip4; + /// Local address for outbound connection. + IpAddr outbound_ip6; + /// Local port for outbound connection. + in_port_t outbound_port{0}; + /// DNS resolution preferences. HostResStyle host_res_style = HOST_RES_IPV4; diff --git a/proxy/ProxyClientTransaction.h b/proxy/ProxyClientTransaction.h index 224df0511a8..0ada783458b 100644 --- a/proxy/ProxyClientTransaction.h +++ b/proxy/ProxyClientTransaction.h @@ -154,28 +154,37 @@ class ProxyClientTransaction : public VConnection virtual void release(IOBufferReader *r); // outbound values Set via the server port definition. Really only used for Http1 at the moment - virtual uint16_t + virtual in_port_t get_outbound_port() const { - return 0; + return outbound_port; } virtual IpAddr get_outbound_ip4() const { - return IpAddr(); + return outbound_ip4; } virtual IpAddr get_outbound_ip6() const { - return IpAddr(); + return outbound_ip6; } virtual void - set_outbound_port(uint16_t new_port) + set_outbound_port(in_port_t port) { + outbound_port = port; } virtual void set_outbound_ip(const IpAddr &new_addr) { + if (new_addr.isIp4()) { + outbound_ip4 = new_addr; + } else if (new_addr.isIp6()) { + outbound_ip6 = new_addr; + } else { + outbound_ip4.invalidate(); + outbound_ip6.invalidate(); + } } virtual bool is_outbound_transparent() const @@ -269,6 +278,10 @@ class ProxyClientTransaction : public VConnection /// DNS resolution preferences. HostResStyle host_res_style; + /// Local outbound address control. + in_port_t outbound_port{0}; + IpAddr outbound_ip4; + IpAddr outbound_ip6; bool restart_immediate; diff --git a/proxy/http/Http1ClientSession.cc b/proxy/http/Http1ClientSession.cc index 5ead86832c8..4fae601b216 100644 --- a/proxy/http/Http1ClientSession.cc +++ b/proxy/http/Http1ClientSession.cc @@ -76,7 +76,6 @@ Http1ClientSession::Http1ClientSession() slave_ka_vio(nullptr), bound_ss(nullptr), released_transactions(0), - outbound_port(0), f_outbound_transparent(false), f_transparent_passthrough(false) { @@ -134,7 +133,7 @@ Http1ClientSession::free() this->do_io_write(nullptr, 0, nullptr); // Free the transaction resources - this->trans.super::destroy(); + this->trans.super_type::destroy(); super::free(); THREAD_FREE(this, http1ClientSessionAllocator, this_thread()); diff --git a/proxy/http/Http1ClientSession.h b/proxy/http/Http1ClientSession.h index 779c3ec2578..7bd5b19c0c3 100644 --- a/proxy/http/Http1ClientSession.h +++ b/proxy/http/Http1ClientSession.h @@ -128,24 +128,6 @@ class Http1ClientSession : public ProxyClientSession // Indicate we are done with a transaction void release(ProxyClientTransaction *trans) override; - virtual uint16_t - get_outbound_port() const - { - return outbound_port; - } - - virtual IpAddr - get_outbound_ip4() const - { - return outbound_ip4; - } - - virtual IpAddr - get_outbound_ip6() const - { - return outbound_ip6; - } - void attach_server_session(HttpServerSession *ssession, bool transaction_done = true) override; HttpServerSession * @@ -228,12 +210,6 @@ class Http1ClientSession : public ProxyClientSession // Link debug_link; LINK(Http1ClientSession, debug_link); - /// Local address for outbound connection. - IpAddr outbound_ip4; - /// Local address for outbound connection. - IpAddr outbound_ip6; - /// Local port for outbound connection. - uint16_t outbound_port; /// Set outbound connection to transparent. bool f_outbound_transparent; /// Transparently pass-through non-HTTP traffic. diff --git a/proxy/http/Http1ClientTransaction.cc b/proxy/http/Http1ClientTransaction.cc index 9c662c63ac6..54d5fc21b19 100644 --- a/proxy/http/Http1ClientTransaction.cc +++ b/proxy/http/Http1ClientTransaction.cc @@ -42,7 +42,7 @@ Http1ClientTransaction::release(IOBufferReader *r) if (r != sm_reader) { this->do_io_close(); } else { - super::release(r); + super_type::release(r); } } @@ -57,7 +57,7 @@ Http1ClientTransaction::set_parent(ProxyClientSession *new_parent) outbound_ip6 = http1_parent->outbound_ip6; outbound_transparent = http1_parent->f_outbound_transparent; } - super::set_parent(new_parent); + super_type::set_parent(new_parent); } void diff --git a/proxy/http/Http1ClientTransaction.h b/proxy/http/Http1ClientTransaction.h index fb23bc7a5b2..e53372d15e0 100644 --- a/proxy/http/Http1ClientTransaction.h +++ b/proxy/http/Http1ClientTransaction.h @@ -31,9 +31,9 @@ class Continuation; class Http1ClientTransaction : public ProxyClientTransaction { public: - typedef ProxyClientTransaction super; + using super_type = ProxyClientTransaction; - Http1ClientTransaction() : super(), outbound_port(0), outbound_transparent(false) {} + Http1ClientTransaction() {} // Implement VConnection interface. VIO * do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = 0) override @@ -96,47 +96,6 @@ class Http1ClientTransaction : public ProxyClientTransaction void set_parent(ProxyClientSession *new_parent) override; - uint16_t - get_outbound_port() const override - { - return outbound_port; - } - - IpAddr - get_outbound_ip4() const override - { - return outbound_ip4; - } - - IpAddr - get_outbound_ip6() const override - { - return outbound_ip6; - } - - void - set_outbound_port(uint16_t new_port) override - { - outbound_port = new_port; - } - - void - set_outbound_ip(const IpAddr &new_addr) override - { - if (new_addr.isIp4()) { - outbound_ip4 = new_addr; - } else if (new_addr.isIp6()) { - outbound_ip6 = new_addr; - } else { - clear_outbound_ip(); - } - } - void - clear_outbound_ip() - { - outbound_ip4.invalidate(); - outbound_ip6.invalidate(); - } bool is_outbound_transparent() const override { @@ -180,10 +139,7 @@ class Http1ClientTransaction : public ProxyClientTransaction } protected: - uint16_t outbound_port; - IpAddr outbound_ip4; - IpAddr outbound_ip6; - bool outbound_transparent; + bool outbound_transparent{false}; }; #endif diff --git a/proxy/http2/Http2SessionAccept.cc b/proxy/http2/Http2SessionAccept.cc index 5081d042bf1..1c53b94c99d 100644 --- a/proxy/http2/Http2SessionAccept.cc +++ b/proxy/http2/Http2SessionAccept.cc @@ -57,6 +57,10 @@ Http2SessionAccept::accept(NetVConnection *netvc, MIOBuffer *iobuf, IOBufferRead Http2ClientSession *new_session = THREAD_ALLOC_INIT(http2ClientSessionAllocator, this_ethread()); new_session->acl_record = session_acl_record; + new_session->host_res_style = ats_host_res_from(client_ip->sa_family, options.host_res_preference); + new_session->outbound_ip4 = options.outbound_ip4; + new_session->outbound_ip6 = options.outbound_ip6; + new_session->outbound_port = options.outbound_port; new_session->new_connection(netvc, iobuf, reader, false /* backdoor */); return true;