diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h index a1dc46564..67b04e2d7 100644 --- a/include/haproxy/stream-t.h +++ b/include/haproxy/stream-t.h @@ -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 */ diff --git a/include/haproxy/stream_interface-t.h b/include/haproxy/stream_interface-t.h index e95c72d5a..f271557d0 100644 --- a/include/haproxy/stream_interface-t.h +++ b/include/haproxy/stream_interface-t.h @@ -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 */ diff --git a/include/haproxy/stream_interface.h b/include/haproxy/stream_interface.h index a1f67c2dc..d799216ed 100644 --- a/include/haproxy/stream_interface.h +++ b/include/haproxy/stream_interface.h @@ -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 */ /* diff --git a/src/stream.c b/src/stream.c index 081c5bbb7..7aaa0a050 100644 --- a/src/stream.c +++ b/src/stream.c @@ -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 */