]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: add the fc_pp_authority fetch -- authority TLV, from PROXYv2
authorGeoff Simmons <geoff@uplex.de>
Tue, 27 Aug 2019 16:31:16 +0000 (18:31 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 28 Aug 2019 15:16:20 +0000 (17:16 +0200)
Save the authority TLV in a PROXYv2 header from the client connection,
if present, and make it available as fc_pp_authority.

The fetch can be used, for example, to set the SNI for a backend TLS
connection.

doc/configuration.txt
include/proto/connection.h
include/types/connection.h
src/connection.c

index 20c39c7735384ecbeced67af10b805043044a8cf..d4b7bcdef6922e70137c92fe59ad6dbd5bc9fc29 100644 (file)
@@ -14467,6 +14467,10 @@ fc_http_major : integer
   for HTTP/0.9 to HTTP/1.1 or 2 for HTTP/2. Note, this is based on the on-wire
   encoding and not on the version present in the request header.
 
+fc_pp_authority : string
+  Returns the authority TLV sent by the client in the PROXY protocol header,
+  if any.
+
 fc_rcvd_proxy : boolean
   Returns true if the client initiated the connection with a PROXY protocol
   header.
index bbb9759acd33830914b9f7eaf601982a639cf480..059d5d85af4110ab66d666de85e1185872ca3dba 100644 (file)
@@ -35,6 +35,7 @@
 extern struct pool_head *pool_head_connection;
 extern struct pool_head *pool_head_connstream;
 extern struct pool_head *pool_head_sockaddr;
+extern struct pool_head *pool_head_authority;
 extern struct xprt_ops *registered_xprt[XPRT_ENTRIES];
 extern struct mux_proto_list mux_proto_list;
 
@@ -471,6 +472,7 @@ static inline void conn_init(struct connection *conn)
        conn->idle_time = 0;
        conn->src = NULL;
        conn->dst = NULL;
+       conn->proxy_authority = NULL;
 }
 
 /* sets <owner> as the connection's owner */
@@ -617,6 +619,11 @@ static inline void conn_free(struct connection *conn)
        sockaddr_free(&conn->src);
        sockaddr_free(&conn->dst);
 
+       if (conn->proxy_authority != NULL) {
+               pool_free(pool_head_authority, conn->proxy_authority);
+               conn->proxy_authority = NULL;
+       }
+
        /* By convention we always place a NULL where the ctx points to if the
         * mux is null. It may have been used to store the connection as a
         * stream_interface's end point for example.
index f8e4c07f93281f425283991f88b7b28c2c189a7b..f6a7d1b7e516408b1bc313d57935b32ee73f60e3 100644 (file)
@@ -461,7 +461,9 @@ struct connection {
        void (*destroy_cb)(struct connection *conn);  /* callback to notify of imminent death of the connection */
        struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */
        struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */
+       char *proxy_authority;        /* Value of authority TLV received via PROXYv2 */
        unsigned int idle_time;                 /* Time the connection was added to the idle list, or 0 if not in the idle list */
+       uint8_t proxy_authority_len;  /* Length of authority TLV received via PROXYv2 */
 };
 
 /* PROTO token registration */
@@ -578,6 +580,8 @@ struct tlv_ssl {
 #define PP2_CLIENT_CERT_CONN     0x02
 #define PP2_CLIENT_CERT_SESS     0x04
 
+/* Max length of the authority TLV */
+#define PP2_AUTHORITY_MAX 255
 
 /*
  * Linux seems to be able to send 253 fds per sendmsg(), not sure
index 602fc79ec48ff88de39c5d48c7724c2ff5849471..7bdd6f0ddf4c50a608f842f5998ec22c091c1b83 100644 (file)
@@ -32,6 +32,7 @@
 DECLARE_POOL(pool_head_connection, "connection",  sizeof(struct connection));
 DECLARE_POOL(pool_head_connstream, "conn_stream", sizeof(struct conn_stream));
 DECLARE_POOL(pool_head_sockaddr,   "sockaddr",    sizeof(struct sockaddr_storage));
+DECLARE_POOL(pool_head_authority,  "authority",   PP2_AUTHORITY_MAX);
 
 struct xprt_ops *registered_xprt[XPRT_ENTRIES] = { NULL, };
 
@@ -631,6 +632,16 @@ int conn_recv_proxy(struct connection *conn, int flag)
                                        break;
                                }
 #endif
+                               case PP2_TYPE_AUTHORITY: {
+                                       if (tlv_len > PP2_AUTHORITY_MAX)
+                                               goto bad_header;
+                                       conn->proxy_authority = pool_alloc(pool_head_authority);
+                                       if (conn->proxy_authority == NULL)
+                                               goto fail;
+                                       memcpy(conn->proxy_authority, (const char *)tlv_packet->value, tlv_len);
+                                       conn->proxy_authority_len = tlv_len;
+                                       break;
+                               }
                                default:
                                        break;
                                }
@@ -1415,6 +1426,31 @@ int smp_fetch_fc_rcvd_proxy(const struct arg *args, struct sample *smp, const ch
        return 1;
 }
 
+/* fetch the authority TLV from a PROXY protocol header */
+int smp_fetch_fc_pp_authority(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       struct connection *conn;
+
+       conn = objt_conn(smp->sess->origin);
+       if (!conn)
+               return 0;
+
+       if (!(conn->flags & CO_FL_CONNECTED)) {
+               smp->flags |= SMP_F_MAY_CHANGE;
+               return 0;
+       }
+
+       if (conn->proxy_authority == NULL)
+               return 0;
+
+       smp->flags = 0;
+       smp->data.type = SMP_T_STR;
+       smp->data.u.str.area = conn->proxy_authority;
+       smp->data.u.str.data = conn->proxy_authority_len;
+
+       return 1;
+}
+
 /* Note: must not be declared <const> as its list will be overwritten.
  * Note: fetches that may return multiple types must be declared as the lowest
  * common denominator, the type that can be casted into all other ones. For
@@ -1424,6 +1460,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "fc_http_major", smp_fetch_fc_http_major, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
        { "bc_http_major", smp_fetch_fc_http_major, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
        { "fc_rcvd_proxy", smp_fetch_fc_rcvd_proxy, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
+       { "fc_pp_authority", smp_fetch_fc_pp_authority, 0, NULL, SMP_T_STR, SMP_USE_L4CLI },
        { /* END */ },
 }};