diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 98a010e03..cf4ec5a95 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -546,7 +546,8 @@ struct connection { /* Members used if connection must be reversed. */ struct { - enum obj_type *target; /* Server for passive reverse. */ + enum obj_type *target; /* Listener for active reverse, server for passive. */ + struct buffer name; /* Only used for passive reverse. Used as SNI when connection added to server idle pool. */ } reverse; }; diff --git a/src/connection.c b/src/connection.c index f6ac7dbf5..6363ff7fd 100644 --- a/src/connection.c +++ b/src/connection.c @@ -436,6 +436,7 @@ void conn_init(struct connection *conn, void *target) conn->hash_node = NULL; conn->xprt = NULL; conn->reverse.target = NULL; + conn->reverse.name = BUF_NULL; } /* Initialize members used for backend connections. @@ -531,6 +532,8 @@ void conn_free(struct connection *conn) pool_free(pool_head_uniqueid, istptr(conn->proxy_unique_id)); conn->proxy_unique_id = IST_NULL; + ha_free(&conn->reverse.name.area); + conn_force_unsubscribe(conn); pool_free(pool_head_connection, conn); } @@ -2461,6 +2464,15 @@ int conn_reverse(struct connection *conn) memset(&hash_params, 0, sizeof(hash_params)); hash_params.target = srv; + if (b_data(&conn->reverse.name)) { + /* data cannot wrap else prehash usage is incorrect */ + BUG_ON(b_data(&conn->reverse.name) != b_contig_data(&conn->reverse.name, 0)); + + hash_params.sni_prehash = + conn_hash_prehash(b_head(&conn->reverse.name), + b_data(&conn->reverse.name)); + } + hash = conn_calculate_hash(&hash_params); conn->hash_node->node.key = hash; @@ -2481,6 +2493,9 @@ int conn_reverse(struct connection *conn) SWAP(conn->src, conn->dst); conn->reverse.target = NULL; + ha_free(&conn->reverse.name.area); + conn->reverse.name = BUF_NULL; + return 0; } diff --git a/src/tcp_act.c b/src/tcp_act.c index ab0649937..291f70488 100644 --- a/src/tcp_act.c +++ b/src/tcp_act.c @@ -44,11 +44,30 @@ static enum act_return tcp_action_attach_srv(struct act_rule *rule, struct proxy struct session *sess, struct stream *s, int flags) { struct server *srv = rule->arg.attach_srv.srv; + struct sample *name_smp; struct connection *conn = objt_conn(sess->origin); if (!conn) return ACT_RET_ABRT; conn_set_reverse(conn, &srv->obj_type); + + if (rule->arg.attach_srv.name) { + name_smp = sample_fetch_as_type(sess->fe, sess, s, + SMP_OPT_DIR_REQ | SMP_OPT_FINAL, + rule->arg.attach_srv.name, SMP_T_STR); + /* TODO strdup du buffer du sample */ + if (name_smp) { + struct buffer *buf = &name_smp->data.u.str; + char *area = malloc(b_data(buf)); + + if (!area) + return ACT_RET_ERR; + + conn->reverse.name = b_make(area, b_data(buf), 0, 0); + b_ncat(&conn->reverse.name, buf, b_data(buf)); + } + } + return ACT_RET_CONT; }