]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream-int: Add src and dst addresses to the stream-interface
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 22 Oct 2021 15:25:58 +0000 (17:25 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 27 Oct 2021 09:34:21 +0000 (11:34 +0200)
For now, these addresses are never set. But the idea is to be able to set, at
least first, the client source and destination addresses at the stream level
without updating the session or connection ones.

Of course, because these addresses are carried by the strream-interface, it
would be possible to set server source and destination addresses at this level
too.

Functions to fill these addresses have been added: si_get_src() and
si_get_dst(). If not already set, these functions relies on underlying
layers to fill stream-interface addresses. On the frontend side, the session
addresses are used if set, otherwise the client connection ones are used. On
the backend side, the server connection addresses are used.

And just like for sessions and conncetions, si_src() and si_dst() may be used to
get source and destination addresses or the stream-interface. And, if not set,
same mechanism as above is used.

include/haproxy/stream-t.h
include/haproxy/stream_interface-t.h
include/haproxy/stream_interface.h
src/stream.c

index a1dc46564fb6f8616fb5ea9f041bde04fba8802d..67b04e2d7201761536badf98396d8ba994abb489 100644 (file)
@@ -81,7 +81,6 @@
 #define SF_SRV_REUSED   0x00100000     /* the server-side connection was reused */
 #define SF_SRV_REUSED_ANTICIPATED  0x00200000  /* the connection was reused but the mux is not ready yet */
 
-
 /* flags for the proxy of the master CLI */
 /* 0x1.. to 0x3 are reserved for ACCESS_LVL_MASK */
 
index e95c72d5aa3e593688376380853f21efd3543514..f271557d0bf73c90cc0b83c218e47853c9d3922c 100644 (file)
@@ -105,6 +105,9 @@ enum {
        SI_FL_RX_WAIT_EP = 0x00200000,  /* stream-int waits for more data from the end point */
        SI_FL_L7_RETRY   = 0x01000000,  /* The stream interface may attempt L7 retries */
        SI_FL_D_L7_RETRY = 0x02000000,  /* Disable L7 retries on this stream interface, even if configured to do it */
+
+       SI_FL_ADDR_FROM_SET = 0x04000000, /* source address is set */
+       SI_FL_ADDR_TO_SET   = 0x08000000  /* destination address is set */
 };
 
 /* A stream interface has 3 parts :
@@ -126,11 +129,14 @@ struct stream_interface {
        unsigned int flags;     /* SI_FL_* */
        enum obj_type *end;     /* points to the end point (connection or appctx) */
        struct si_ops *ops;     /* general operations at the stream interface layer */
+       struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */
+       struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */
        unsigned int exp;       /* wake up time for connect, queue, turn-around, ... */
 
        /* struct members below are the "remote" part, as seen from the buffer side */
        unsigned int err_type;  /* first error detected, one of SI_ET_* */
        int conn_retries;       /* number of connect retries left */
+
        unsigned int hcto;      /* half-closed timeout (0 = unset) */
        struct wait_event wait_event; /* We're in a wait list */
        struct buffer l7_buffer; /* To store the data, in case we have to retry */
index a1f67c2dcb8e205efb59e4f06b97c46c47e17406..d799216edd30633febe40779e007dec2b1d264b8 100644 (file)
@@ -112,6 +112,8 @@ static inline struct stream_interface *si_opposite(struct stream_interface *si)
  */
 static inline int si_reset(struct stream_interface *si)
 {
+       si->src            = NULL;
+       si->dst            = NULL;
        si->err_type       = SI_ET_NONE;
        si->conn_retries   = 0;  /* used for logging too */
        si->exp            = TICK_ETERNITY;
@@ -562,6 +564,108 @@ static inline const char *si_state_str(int state)
        }
 }
 
+
+/* Returns the source address of the stream-int and, if not set, fallbacks on
+ * the session for frontend SI and the server connection for the backend SI. It
+ * returns a const address on succes or NULL on failure.
+ */
+static inline const struct sockaddr_storage *si_src(struct stream_interface *si)
+{
+       if (si->flags & SI_FL_ADDR_FROM_SET)
+               return si->src;
+       if (!(si->flags & SI_FL_ISBACK))
+               return sess_src(strm_sess(si_strm(si)));
+       else {
+               struct conn_stream *cs = objt_cs(si->end);
+
+               if (cs && cs->conn)
+                       return conn_src(cs->conn);
+       }
+       return NULL;
+}
+
+
+/* Returns the destination address of the stream-int and, if not set, fallbacks
+ * on the session for frontend SI and the server connection for the backend
+ * SI. It returns a const address on succes or NULL on failure.
+ */
+static inline const struct sockaddr_storage *si_dst(struct stream_interface *si)
+{
+       if (si->flags & SI_FL_ADDR_TO_SET)
+               return si->dst;
+       if (!(si->flags & SI_FL_ISBACK))
+               return sess_dst(strm_sess(si_strm(si)));
+       else {
+               struct conn_stream *cs = objt_cs(si->end);
+
+               if (cs && cs->conn)
+                       return conn_dst(cs->conn);
+       }
+       return NULL;
+}
+
+/* Retrieves the source address of the stream-int. Returns non-zero on success
+ * or zero on failure. The operation is only performed once and the address is
+ * stored in the stream-int for future use. On the first call, the stream-int
+ * source address is copied from the session one for frontend SI and the server
+ * connection for the backend SI.
+ */
+static inline int si_get_src(struct stream_interface *si)
+{
+       const struct sockaddr_storage *src = NULL;
+
+       if (si->flags & SI_FL_ADDR_FROM_SET)
+               return 1;
+
+       if (!(si->flags & SI_FL_ISBACK))
+               src = sess_src(strm_sess(si_strm(si)));
+       else {
+               struct conn_stream *cs = objt_cs(si->end);
+
+               if (cs && cs->conn)
+                       src = conn_src(cs->conn);
+       }
+       if (!src)
+               return 0;
+
+       if (!sockaddr_alloc(&si->src, src, sizeof(*src)))
+               return 0;
+
+       si->flags |= SI_FL_ADDR_FROM_SET;
+       return 1;
+}
+
+/* Retrieves the destination address of the stream-int. Returns non-zero on
+ * success or zero on failure. The operation is only performed once and the
+ * address is stored in the stream-int for future use. On the first call, the
+ * stream-int destination address is copied from the session one for frontend SI
+ * and the server connection for the backend SI.
+ */
+static inline int si_get_dst(struct stream_interface *si)
+{
+       const struct sockaddr_storage *dst = NULL;
+
+       if (si->flags & SI_FL_ADDR_TO_SET)
+               return 1;
+
+       if (!(si->flags & SI_FL_ISBACK))
+               dst = sess_dst(strm_sess(si_strm(si)));
+       else {
+               struct conn_stream *cs = objt_cs(si->end);
+
+               if (cs && cs->conn)
+                       dst = conn_dst(cs->conn);
+       }
+       if (!dst)
+               return 0;
+
+       if (!sockaddr_alloc(&si->dst, dst, sizeof(*dst)))
+               return 0;
+
+       si->flags |= SI_FL_ADDR_TO_SET;
+       return 1;
+}
+
 #endif /* _HAPROXY_STREAM_INTERFACE_H */
 
 /*
index 081c5bbb715ba72d986db0d7c61831f558f5196b..7aaa0a0500366f4587cb744566e75e9506ce7b45 100644 (file)
@@ -744,6 +744,10 @@ static void stream_free(struct stream *s)
        }
 
        sockaddr_free(&s->target_addr);
+       sockaddr_free(&s->si[0].src);
+       sockaddr_free(&s->si[0].dst);
+       sockaddr_free(&s->si[1].src);
+       sockaddr_free(&s->si[1].dst);
        pool_free(pool_head_stream, s);
 
        /* We may want to free the maximum amount of pools if the proxy is stopping */