]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tcp-sample: Rely on addresses at the appropriate level in tcp samples
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 25 Oct 2021 06:01:20 +0000 (08:01 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 27 Oct 2021 09:34:21 +0000 (11:34 +0200)
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

index 0ea7d79faa373abb37fde049e5a138a2e719a177..d167bde86b33eda58987fa2d10a5b24dd346dc61 100644 (file)
 #include <haproxy/namespace.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/sample.h>
-#include <haproxy/session-t.h>
+#include <haproxy/session.h>
+#include <haproxy/stream_interface.h>
 #include <haproxy/tools.h>
 
-
 /* 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;
-
-       if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+       const struct sockaddr_storage *src = 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;
 
-       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;
-
-       if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+       const struct sockaddr_storage *src = 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;
-
-       if (!conn)
-               return 0;
+               src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
-       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;
-
-       if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+       const struct sockaddr_storage *dst = 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;
 
-       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;
-
-       if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+       const struct sockaddr_storage *dst = 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;
-
-       if (!conn)
-               return 0;
+               dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
-       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;