From c03be1a1297107ec2f8b8e253f4750823c0f3328 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 25 Oct 2021 08:01:20 +0200 Subject: [PATCH] MEDIUM: tcp-sample: Rely on addresses at the appropriate level in tcp samples In src, src-port, dst and dst-port sample fetches, the client source and destination addresses are retrieved from the appropriate level. It means that, if the stream exits, we use the frontend stream-interface to get the client source and destination addresses. Otherwise, the session is used. For now, stream-interface or session addresses are never set. So, thanks to the fallback mechanism, no changes are expected with this patch. But its purpose is to rely on addresses at the appropriate level when set instead of those at the connection level. --- src/tcp_sample.c | 114 +++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/src/tcp_sample.c b/src/tcp_sample.c index 0ea7d79fa..d167bde86 100644 --- a/src/tcp_sample.c +++ b/src/tcp_sample.c @@ -39,37 +39,38 @@ #include #include #include -#include +#include +#include #include - /* Fetch the connection's source IPv4/IPv6 address. Depending on the keyword, it * may be the frontend or the backend connection. */ static int smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn; + const struct sockaddr_storage *src = NULL; - if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) - conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL; + if (kw[0] == 'b') { + struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + ? cs_conn(__objt_check(smp->sess->origin)->cs) + : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); + if (conn && conn_get_src(conn)) + src = conn_src(conn); + } else - conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) : - smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; + src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess)); - if (!conn) + if (!src) return 0; - if (!conn_get_src(conn)) - return 0; - - switch (conn->src->ss_family) { + switch (src->ss_family) { case AF_INET: - smp->data.u.ipv4 = ((struct sockaddr_in *)conn->src)->sin_addr; + smp->data.u.ipv4 = ((struct sockaddr_in *)src)->sin_addr; smp->data.type = SMP_T_IPV4; break; case AF_INET6: - smp->data.u.ipv6 = ((struct sockaddr_in6 *)conn->src)->sin6_addr; + smp->data.u.ipv6 = ((struct sockaddr_in6 *)src)->sin6_addr; smp->data.type = SMP_T_IPV6; break; default: @@ -86,22 +87,23 @@ smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void * static int smp_fetch_sport(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn; + const struct sockaddr_storage *src = NULL; - if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) - conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL; + if (kw[0] == 'b') { + struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + ? cs_conn(__objt_check(smp->sess->origin)->cs) + : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); + if (conn && conn_get_src(conn)) + src = conn_src(conn); + } else - conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) : - smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; + src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess)); - if (!conn) - return 0; - - if (!conn_get_src(conn)) + if (!src) return 0; smp->data.type = SMP_T_SINT; - if (!(smp->data.u.sint = get_host_port(conn->src))) + if (!(smp->data.u.sint = get_host_port(src))) return 0; smp->flags = 0; @@ -114,27 +116,28 @@ smp_fetch_sport(const struct arg *args, struct sample *smp, const char *kw, void static int smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn; + const struct sockaddr_storage *dst = NULL; - if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) - conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL; + if (kw[0] == 'b') { + struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + ? cs_conn(__objt_check(smp->sess->origin)->cs) + : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); + if (conn && conn_get_dst(conn)) + dst = conn_dst(conn); + } else - conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) : - smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; + dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess)); - if (!conn) + if (!dst) return 0; - if (!conn_get_dst(conn)) - return 0; - - switch (conn->dst->ss_family) { + switch (dst->ss_family) { case AF_INET: - smp->data.u.ipv4 = ((struct sockaddr_in *)conn->dst)->sin_addr; + smp->data.u.ipv4 = ((struct sockaddr_in *)dst)->sin_addr; smp->data.type = SMP_T_IPV4; break; case AF_INET6: - smp->data.u.ipv6 = ((struct sockaddr_in6 *)conn->dst)->sin6_addr; + smp->data.u.ipv6 = ((struct sockaddr_in6 *)dst)->sin6_addr; smp->data.type = SMP_T_IPV6; break; default: @@ -150,18 +153,15 @@ smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void * */ int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn = objt_conn(smp->sess->origin); struct listener *li = smp->sess->listener; + const struct sockaddr_storage *dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess)); - if (!conn) - return 0; - - if (!conn_get_dst(conn)) + if (!dst) return 0; smp->data.type = SMP_T_BOOL; smp->flags = 0; - smp->data.u.sint = addr_is_local(li->rx.settings->netns, conn->dst); + smp->data.u.sint = addr_is_local(li->rx.settings->netns, dst); return smp->data.u.sint >= 0; } @@ -170,18 +170,15 @@ int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const cha */ int smp_fetch_src_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn = objt_conn(smp->sess->origin); struct listener *li = smp->sess->listener; + const struct sockaddr_storage *src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess)); - if (!conn) - return 0; - - if (!conn_get_src(conn)) + if (!src) return 0; smp->data.type = SMP_T_BOOL; smp->flags = 0; - smp->data.u.sint = addr_is_local(li->rx.settings->netns, conn->src); + smp->data.u.sint = addr_is_local(li->rx.settings->netns, src); return smp->data.u.sint >= 0; } @@ -191,22 +188,23 @@ int smp_fetch_src_is_local(const struct arg *args, struct sample *smp, const cha static int smp_fetch_dport(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn; + const struct sockaddr_storage *dst = NULL; - if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) - conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL; + if (kw[0] == 'b') { + struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + ? cs_conn(__objt_check(smp->sess->origin)->cs) + : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL)); + if (conn && conn_get_dst(conn)) + dst = conn_dst(conn); + } else - conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) : - smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL; + dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess)); - if (!conn) - return 0; - - if (!conn_get_dst(conn)) + if (!dst) return 0; smp->data.type = SMP_T_SINT; - if (!(smp->data.u.sint = get_host_port(conn->dst))) + if (!(smp->data.u.sint = get_host_port(dst))) return 0; smp->flags = 0;