This can be useful in order to extend ACL and log format with upstream
proxy information when accept-proxy or accept-netscaler-cip is being
used
---
 include/proto/connection.h | 32 ++++++++++++++++++++++++++++++++
 include/types/connection.h |  9 ++++++++-
 src/connection.c           | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/session.c              |  4 ++--
 4 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/include/proto/connection.h b/include/proto/connection.h
index ef078add2f20..86087950b421 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -524,6 +524,22 @@ static inline void conn_get_from_addr(struct connection 
*conn)
        conn->flags |= CO_FL_ADDR_FROM_SET;
 }
 
+/* Retrieves the connection's proxy source address */
+static inline void conn_get_from_proxy_addr(struct connection *conn)
+{
+       if (conn->flags & CO_FL_PROXY_ADDR_FROM_SET)
+               return;
+
+       if (!conn_ctrl_ready(conn) || !conn->ctrl->get_src)
+               return;
+
+       if (conn->ctrl->get_src(conn->t.sock.fd, (struct sockaddr 
*)&conn->proxy_addr.from,
+                               sizeof(conn->proxy_addr.from),
+                               obj_type(conn->target) != OBJ_TYPE_LISTENER) == 
-1)
+               return;
+       conn->flags |= CO_FL_PROXY_ADDR_FROM_SET;
+}
+
 /* Retrieves the connection's original destination address */
 static inline void conn_get_to_addr(struct connection *conn)
 {
@@ -540,6 +556,22 @@ static inline void conn_get_to_addr(struct connection 
*conn)
        conn->flags |= CO_FL_ADDR_TO_SET;
 }
 
+/* Retrieves the connection's proxy destination address */
+static inline void conn_get_to_proxy_addr(struct connection *conn)
+{
+       if (conn->flags & CO_FL_PROXY_ADDR_TO_SET)
+               return;
+
+       if (!conn_ctrl_ready(conn) || !conn->ctrl->get_dst)
+               return;
+
+       if (conn->ctrl->get_dst(conn->t.sock.fd, (struct sockaddr 
*)&conn->proxy_addr.to,
+                               sizeof(conn->proxy_addr.to),
+                               obj_type(conn->target) != OBJ_TYPE_LISTENER) == 
-1)
+               return;
+       conn->flags |= CO_FL_PROXY_ADDR_TO_SET;
+}
+
 /* Attaches a connection to an owner and assigns a data layer */
 static inline void conn_attach(struct connection *conn, void *owner, const 
struct data_cb *data)
 {
diff --git a/include/types/connection.h b/include/types/connection.h
index beb9b898e2cd..0576778f62b1 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -126,7 +126,10 @@ enum {
        /* This connection may not be shared between clients */
        CO_FL_PRIVATE       = 0x10000000,
 
-       /* unused : 0x20000000, 0x40000000 */
+       /* These flags are used to report whether the from/to proxy
+        * addresses are set or not */
+       CO_FL_PROXY_ADDR_FROM_SET = 0x20000000, /* proxy_addr.from is set */
+       CO_FL_PROXY_ADDR_TO_SET   = 0x40000000, /* proxy_addr.to is set */
 
        /* This last flag indicates that the transport layer is used (for 
instance
         * by logs) and must not be cleared yet. The last call to 
conn_xprt_close()
@@ -286,6 +289,10 @@ struct connection {
                struct sockaddr_storage from;   /* client address, or address 
to spoof when connecting to the server */
                struct sockaddr_storage to;     /* address reached by the 
client, or address to connect to */
        } addr; /* addresses of the remote side, client for producer and server 
for consumer */
+       struct {
+               struct sockaddr_storage from;   /* upstream proxy address */
+               struct sockaddr_storage to;     /* address reached by upstream 
proxy */
+       } proxy_addr; /* Addresses of the upstream proxy if accept-proxy or 
accept-netscaler-cip is used */
 };
 
 /* proxy protocol v2 definitions */
diff --git a/src/connection.c b/src/connection.c
index 7a9f3913ca74..380dca1b5370 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -420,6 +420,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
                if (*line++ != '\n')
                        goto bad_header;
 
+               /* update the session's proxy addresses and mark them set */
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct 
sockaddr_in *)&conn->addr.from,
+                       sizeof(struct sockaddr_in));
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct 
sockaddr_in *)&conn->addr.to,
+                       sizeof(struct sockaddr_in));
+               conn->flags |= CO_FL_PROXY_ADDR_TO_SET | 
CO_FL_PROXY_ADDR_TO_SET;
+
                /* update the session's addresses and mark them set */
                ((struct sockaddr_in *)&conn->addr.from)->sin_family      = 
AF_INET;
                ((struct sockaddr_in *)&conn->addr.from)->sin_addr.s_addr = 
htonl(src3);
@@ -481,6 +488,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
                if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
                        goto bad_header;
 
+               /* update the session's proxy addresses and mark them set */
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct 
sockaddr_in *)&conn->addr.from,
+                       sizeof(struct sockaddr_in));
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct 
sockaddr_in *)&conn->addr.to,
+                       sizeof(struct sockaddr_in));
+               conn->flags |= CO_FL_PROXY_ADDR_TO_SET | 
CO_FL_PROXY_ADDR_TO_SET;
+
                /* update the session's addresses and mark them set */
                ((struct sockaddr_in6 *)&conn->addr.from)->sin6_family      = 
AF_INET6;
                memcpy(&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr, 
&src3, sizeof(struct in6_addr));
@@ -527,6 +541,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
                        if (ntohs(hdr_v2->len) < PP2_ADDR_LEN_INET)
                                goto bad_header;
 
+                       /* update the session's proxy addresses and mark them 
set */
+                       memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, 
(struct sockaddr_in *)&conn->addr.from,
+                               sizeof(struct sockaddr_in));
+                       memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, 
(struct sockaddr_in *)&conn->addr.to,
+                               sizeof(struct sockaddr_in));
+                       conn->flags |= CO_FL_PROXY_ADDR_TO_SET | 
CO_FL_PROXY_ADDR_TO_SET;
+
                        ((struct sockaddr_in *)&conn->addr.from)->sin_family = 
AF_INET;
                        ((struct sockaddr_in 
*)&conn->addr.from)->sin_addr.s_addr = hdr_v2->addr.ip4.src_addr;
                        ((struct sockaddr_in *)&conn->addr.from)->sin_port = 
hdr_v2->addr.ip4.src_port;
@@ -541,6 +562,13 @@ int conn_recv_proxy(struct connection *conn, int flag)
                        if (ntohs(hdr_v2->len) < PP2_ADDR_LEN_INET6)
                                goto bad_header;
 
+                       /* update the session's proxy addresses and mark them 
set */
+                       memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, 
(struct sockaddr_in *)&conn->addr.from,
+                               sizeof(struct sockaddr_in));
+                       memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, 
(struct sockaddr_in *)&conn->addr.to,
+                               sizeof(struct sockaddr_in));
+                       conn->flags |= CO_FL_PROXY_ADDR_TO_SET | 
CO_FL_PROXY_ADDR_TO_SET;
+
                        ((struct sockaddr_in6 *)&conn->addr.from)->sin6_family 
= AF_INET6;
                        memcpy(&((struct sockaddr_in6 
*)&conn->addr.from)->sin6_addr, hdr_v2->addr.ip6.src_addr, 16);
                        ((struct sockaddr_in6 *)&conn->addr.from)->sin6_port = 
hdr_v2->addr.ip6.src_port;
@@ -733,6 +761,13 @@ int conn_recv_netscaler_cip(struct connection *conn, int 
flag)
 
                hdr_tcp = (struct my_tcphdr *)(line + (hdr_ip4->ip_hl * 4));
 
+               /* update the session's proxy addresses and mark them set */
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct 
sockaddr_in *)&conn->addr.from,
+                       sizeof(struct sockaddr_in));
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct 
sockaddr_in *)&conn->addr.to,
+                       sizeof(struct sockaddr_in));
+               conn->flags |= CO_FL_PROXY_ADDR_TO_SET | 
CO_FL_PROXY_ADDR_TO_SET;
+
                /* update the session's addresses and mark them set */
                ((struct sockaddr_in *)&conn->addr.from)->sin_family = AF_INET;
                ((struct sockaddr_in *)&conn->addr.from)->sin_addr.s_addr = 
hdr_ip4->ip_src.s_addr;
@@ -766,6 +801,13 @@ int conn_recv_netscaler_cip(struct connection *conn, int 
flag)
 
                hdr_tcp = (struct my_tcphdr *)(line + sizeof(struct ip6_hdr));
 
+               /* update the session's proxy addresses and mark them set */
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.from, (struct 
sockaddr_in *)&conn->addr.from,
+                       sizeof(struct sockaddr_in));
+               memcpy ((struct sockaddr_in *)&conn->proxy_addr.to, (struct 
sockaddr_in *)&conn->addr.to,
+                       sizeof(struct sockaddr_in));
+               conn->flags |= CO_FL_PROXY_ADDR_TO_SET | 
CO_FL_PROXY_ADDR_TO_SET;
+
                /* update the session's addresses and mark them set */
                ((struct sockaddr_in6 *)&conn->addr.from)->sin6_family = 
AF_INET6;
                ((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr = 
hdr_ip6->ip6_src;
diff --git a/src/session.c b/src/session.c
index cdf57e388a26..90a465c1fb31 100644
--- a/src/session.c
+++ b/src/session.c
@@ -138,13 +138,13 @@ int session_accept_fd(struct listener *l, int cfd, struct 
sockaddr_storage *addr
 
        /* wait for a PROXY protocol header */
        if (l->options & LI_O_ACC_PROXY) {
-               cli_conn->flags |= CO_FL_ACCEPT_PROXY;
+               cli_conn->flags |= CO_FL_PROXY_ADDR_FROM_SET | 
CO_FL_ACCEPT_PROXY;
                conn_sock_want_recv(cli_conn);
        }
 
        /* wait for a NetScaler client IP insertion protocol header */
        if (l->options & LI_O_ACC_CIP) {
-               cli_conn->flags |= CO_FL_ACCEPT_CIP;
+               cli_conn->flags |= CO_FL_PROXY_ADDR_FROM_SET | CO_FL_ACCEPT_CIP;
                conn_sock_want_recv(cli_conn);
        }
 

Reply via email to