MAJOR: stream-int: stop using si->conn and use si->end instead

The connection will only remain there as a pre-allocated entity whose
goal is to be placed in ->end when establishing an outgoing connection.
All connection initialization can be made on this connection, but all
information retrieved should be applied to the end point only.

This change is huge because there were many users of si->conn. Now the
only users are those who initialize the new connection. The difficulty
appears in a few places such as backend.c, proto_http.c, peers.c where
si->conn is used to hold the connection's target address before assigning
the connection to the stream interface. This is why we have to keep
si->conn for now. A future improvement might consist in dynamically
allocating the connection when it is needed.
This commit is contained in:
Willy Tarreau 2013-10-01 10:45:07 +02:00
parent 691b1f429e
commit b363a1f469
12 changed files with 687 additions and 357 deletions

View File

@ -53,18 +53,30 @@ static inline void si_prepare_none(struct stream_interface *si)
si->appctx.applet = NULL;
}
/* Assign the stream interface's pre-allocated connection to the end point,
* and initialize the connection's context. This is used for outgoing
* connections.
*/
static inline void si_prepare_conn(struct stream_interface *si, const struct protocol *ctrl, const struct xprt_ops *xprt)
{
struct connection *conn = si->conn;
si->ops = &si_conn_ops;
si->end = &si->conn->obj_type;
conn_prepare(si->conn, &si_conn_cb, ctrl, xprt, si);
si->end = &conn->obj_type;
conn_prepare(conn, &si_conn_cb, ctrl, xprt, si);
}
/* Assign the stream interface's pre-allocated connection to the end point,
* and leave the connection's context untouched. This is used for incoming
* connections.
*/
static inline void si_takeover_conn(struct stream_interface *si, const struct protocol *ctrl, const struct xprt_ops *xprt)
{
struct connection *conn = si->conn;
si->ops = &si_conn_ops;
si->end = &si->conn->obj_type;
conn_assign(si->conn, &si_conn_cb, ctrl, xprt, si);
si->end = &conn->obj_type;
conn_assign(conn, &si_conn_cb, ctrl, xprt, si);
}
static inline void si_prepare_applet(struct stream_interface *si, struct si_applet *applet)
@ -141,25 +153,26 @@ static inline void si_chk_snd(struct stream_interface *si)
/* Calls chk_snd on the connection using the ctrl layer */
static inline int si_connect(struct stream_interface *si)
{
struct connection *conn = objt_conn(si->end);
int ret;
if (unlikely(!si->conn->ctrl || !si->conn->ctrl->connect))
if (unlikely(!conn || !conn->ctrl || !conn->ctrl->connect))
return SN_ERR_INTERNAL;
ret = si->conn->ctrl->connect(si->conn, !channel_is_empty(si->ob), !!si->send_proxy_ofs);
ret = conn->ctrl->connect(conn, !channel_is_empty(si->ob), !!si->send_proxy_ofs);
if (ret != SN_ERR_NONE)
return ret;
/* needs src ip/port for logging */
if (si->flags & SI_FL_SRC_ADDR)
conn_get_from_addr(si->conn);
conn_get_from_addr(conn);
/* Prepare to send a few handshakes related to the on-wire protocol. */
if (si->send_proxy_ofs)
si->conn->flags |= CO_FL_SI_SEND_PROXY;
conn->flags |= CO_FL_SI_SEND_PROXY;
/* we need to be notified about connection establishment */
si->conn->flags |= CO_FL_WAKE_DATA;
conn->flags |= CO_FL_WAKE_DATA;
/* we're in the process of establishing a connection */
si->state = SI_ST_CON;

View File

@ -164,7 +164,7 @@ struct stream_interface {
unsigned int err_type; /* first error detected, one of SI_ET_* */
enum obj_type *end; /* points to the end point (connection or appctx) */
struct connection *conn; /* descriptor for a connection */
struct connection *conn; /* pre-allocated connection */
struct si_ops *ops; /* general operations at the stream interface layer */
/* struct members below are the "remote" part, as seen from the buffer side */

View File

@ -505,7 +505,7 @@ struct server *get_server_rch(struct session *s)
int assign_server(struct session *s)
{
struct connection *conn;
struct server *conn_slot;
struct server *srv, *prev_srv;
int err;
@ -574,14 +574,15 @@ int assign_server(struct session *s)
switch (s->be->lbprm.algo & BE_LB_PARM) {
case BE_LB_HASH_SRC:
if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
conn = objt_conn(s->req->prod->end);
if (conn && conn->addr.from.ss_family == AF_INET) {
srv = get_server_sh(s->be,
(void *)&((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr,
(void *)&((struct sockaddr_in *)&conn->addr.from)->sin_addr,
4);
}
else if (s->req->prod->conn->addr.from.ss_family == AF_INET6) {
else if (conn && conn->addr.from.ss_family == AF_INET6) {
srv = get_server_sh(s->be,
(void *)&((struct sockaddr_in6 *)&s->req->prod->conn->addr.from)->sin6_addr,
(void *)&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr,
16);
}
else {
@ -664,7 +665,8 @@ int assign_server(struct session *s)
s->target = &s->be->obj_type;
}
else if ((s->be->options & PR_O_HTTP_PROXY) &&
is_addr(&s->req->cons->conn->addr.to)) {
(conn = objt_conn(s->req->cons->end)) &&
is_addr(&conn->addr.to)) {
/* in proxy mode, we need a valid destination address */
s->target = &s->be->obj_type;
}
@ -706,9 +708,15 @@ int assign_server(struct session *s)
* Upon successful return, the session flag SN_ADDR_SET is set. This flag is
* not cleared, so it's to the caller to clear it if required.
*
* The address is set on si->conn only. This connection is expected to be
* already allocated and initialized.
*
*/
int assign_server_address(struct session *s)
{
struct connection *cli_conn = objt_conn(s->req->prod->end);
struct connection *srv_conn = s->req->cons->conn;
#ifdef DEBUG_FULL
fprintf(stderr,"assign_server_address : s=%p\n",s);
#endif
@ -718,51 +726,47 @@ int assign_server_address(struct session *s)
if (!(s->flags & SN_ASSIGNED))
return SRV_STATUS_INTERNAL;
s->req->cons->conn->addr.to = objt_server(s->target)->addr;
srv_conn->addr.to = objt_server(s->target)->addr;
if (!is_addr(&s->req->cons->conn->addr.to)) {
if (!is_addr(&srv_conn->addr.to) && cli_conn) {
/* if the server has no address, we use the same address
* the client asked, which is handy for remapping ports
* locally on multiple addresses at once.
*/
conn_get_to_addr(s->req->prod->conn);
conn_get_to_addr(cli_conn);
if (s->req->prod->conn->addr.to.ss_family == AF_INET) {
((struct sockaddr_in *)&s->req->cons->conn->addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr;
} else if (s->req->prod->conn->addr.to.ss_family == AF_INET6) {
((struct sockaddr_in6 *)&s->req->cons->conn->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&s->req->prod->conn->addr.to)->sin6_addr;
if (cli_conn->addr.to.ss_family == AF_INET) {
((struct sockaddr_in *)&srv_conn->addr.to)->sin_addr = ((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr;
} else if (cli_conn->addr.to.ss_family == AF_INET6) {
((struct sockaddr_in6 *)&srv_conn->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&cli_conn->addr.to)->sin6_addr;
}
}
/* if this server remaps proxied ports, we'll use
* the port the client connected to with an offset. */
if (objt_server(s->target)->state & SRV_MAPPORTS) {
if ((objt_server(s->target)->state & SRV_MAPPORTS) && cli_conn) {
int base_port;
conn_get_to_addr(s->req->prod->conn);
conn_get_to_addr(cli_conn);
/* First, retrieve the port from the incoming connection */
base_port = get_host_port(&s->req->prod->conn->addr.to);
base_port = get_host_port(&cli_conn->addr.to);
/* Second, assign the outgoing connection's port */
base_port += get_host_port(&s->req->cons->conn->addr.to);
set_host_port(&s->req->cons->conn->addr.to, base_port);
base_port += get_host_port(&srv_conn->addr.to);
set_host_port(&srv_conn->addr.to, base_port);
}
}
else if (s->be->options & PR_O_DISPATCH) {
/* connect to the defined dispatch addr */
s->req->cons->conn->addr.to = s->be->dispatch_addr;
srv_conn->addr.to = s->be->dispatch_addr;
}
else if (s->be->options & PR_O_TRANSP) {
else if ((s->be->options & PR_O_TRANSP) && cli_conn) {
/* in transparent mode, use the original dest addr if no dispatch specified */
conn_get_to_addr(s->req->prod->conn);
conn_get_to_addr(cli_conn);
if (s->req->prod->conn->addr.to.ss_family == AF_INET || s->req->prod->conn->addr.to.ss_family == AF_INET6) {
memcpy(&s->req->cons->conn->addr.to, &s->req->prod->conn->addr.to, MIN(sizeof(s->req->cons->conn->addr.to), sizeof(s->req->prod->conn->addr.to)));
}
/* when we support IPv6 on the backend, we may add other tests */
//qfprintf(stderr, "Cannot get original server address.\n");
//return SRV_STATUS_INTERNAL;
if (cli_conn->addr.to.ss_family == AF_INET || cli_conn->addr.to.ss_family == AF_INET6)
srv_conn->addr.to = cli_conn->addr.to;
}
else if (s->be->options & PR_O_HTTP_PROXY) {
/* If HTTP PROXY option is set, then server is already assigned
@ -902,13 +906,16 @@ int assign_server_and_queue(struct session *s)
/* If an explicit source binding is specified on the server and/or backend, and
* this source makes use of the transparent proxy, then it is extracted now and
* assigned to the session's req->cons->addr.from entry.
* assigned to the session's pending connection. This function assumes that an
* outgoing connection has already been allocated into s->req->cons->conn.
*/
static void assign_tproxy_address(struct session *s)
{
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
struct server *srv = objt_server(s->target);
struct conn_src *src;
struct connection *cli_conn;
struct connection *srv_conn = s->req->cons->conn;
if (srv && srv->conn_src.opts & CO_SRC_BIND)
src = &srv->conn_src;
@ -919,12 +926,16 @@ static void assign_tproxy_address(struct session *s)
switch (src->opts & CO_SRC_TPROXY_MASK) {
case CO_SRC_TPROXY_ADDR:
s->req->cons->conn->addr.from = src->tproxy_addr;
srv_conn->addr.from = src->tproxy_addr;
break;
case CO_SRC_TPROXY_CLI:
case CO_SRC_TPROXY_CIP:
/* FIXME: what can we do if the client connects in IPv6 or unix socket ? */
s->req->cons->conn->addr.from = s->req->prod->conn->addr.from;
cli_conn = objt_conn(s->req->prod->end);
if (cli_conn)
srv_conn->addr.from = cli_conn->addr.from;
else
memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from));
break;
case CO_SRC_TPROXY_DYN:
if (src->bind_hdr_occ) {
@ -933,21 +944,21 @@ static void assign_tproxy_address(struct session *s)
int rewind;
/* bind to the IP in a header */
((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_family = AF_INET;
((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_port = 0;
((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr = 0;
((struct sockaddr_in *)&srv_conn->addr.from)->sin_family = AF_INET;
((struct sockaddr_in *)&srv_conn->addr.from)->sin_port = 0;
((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr = 0;
b_rew(s->req->buf, rewind = s->req->buf->o);
if (http_get_hdr(&s->txn.req, src->bind_hdr_name, src->bind_hdr_len,
&s->txn.hdr_idx, src->bind_hdr_occ, NULL, &vptr, &vlen)) {
((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr =
((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr =
htonl(inetaddr_host_lim(vptr, vptr + vlen));
}
b_adv(s->req->buf, rewind);
}
break;
default:
memset(&s->req->cons->conn->addr.from, 0, sizeof(s->req->cons->conn->addr.from));
memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from));
}
#endif
}
@ -965,9 +976,13 @@ static void assign_tproxy_address(struct session *s)
* - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
* - SN_ERR_INTERNAL for any other purely internal errors
* Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
* The server-facing stream interface is expected to hold a pre-allocated connection
* in s->req->cons->conn.
*/
int connect_server(struct session *s)
{
struct connection *cli_conn;
struct connection *srv_conn = s->req->cons->conn;
struct server *srv;
int err;
@ -978,7 +993,7 @@ int connect_server(struct session *s)
}
/* the target was only on the session, assign it to the SI now */
s->req->cons->conn->target = s->target;
srv_conn->target = s->target;
/* set the correct protocol on the output stream interface */
if (objt_server(s->target)) {
@ -986,8 +1001,8 @@ int connect_server(struct session *s)
}
else if (obj_type(s->target) == OBJ_TYPE_PROXY) {
/* proxies exclusively run on raw_sock right now */
si_prepare_conn(s->req->cons, protocol_by_family(s->req->cons->conn->addr.to.ss_family), &raw_sock);
if (!s->req->cons->conn->ctrl)
si_prepare_conn(s->req->cons, protocol_by_family(srv_conn->addr.to.ss_family), &raw_sock);
if (!objt_conn(s->req->cons->end) || !objt_conn(s->req->cons->end)->ctrl)
return SN_ERR_INTERNAL;
}
else
@ -997,7 +1012,9 @@ int connect_server(struct session *s)
s->req->cons->send_proxy_ofs = 0;
if (objt_server(s->target) && (objt_server(s->target)->state & SRV_SEND_PROXY)) {
s->req->cons->send_proxy_ofs = 1; /* must compute size */
conn_get_to_addr(s->req->prod->conn);
cli_conn = objt_conn(s->req->prod->end);
if (cli_conn)
conn_get_to_addr(cli_conn);
}
assign_tproxy_address(s);

View File

@ -151,7 +151,7 @@ enum {
extern const char *stat_status_codes[];
/* This function is called from the session-level accept() in order to instanciate
* a new stats socket. It returns a positive value upon success, 0 if the connection
* a new stats socket. It returns a positive value upon success, 0 if the session
* needs to be closed and ignored, or a negative value upon critical failure.
*/
static int stats_accept(struct session *s)
@ -3881,6 +3881,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
struct tm tm;
extern const char *monthname[12];
char pn[INET6_ADDRSTRLEN];
struct connection *conn;
chunk_reset(&trash);
@ -3910,12 +3911,12 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
sess->uniq_id,
sess->listener && sess->listener->proto->name ? sess->listener->proto->name : "?");
switch ((obj_type(sess->si[0].end) == OBJ_TYPE_CONN) ?
addr_to_str(&sess->si[0].conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
conn = objt_conn(sess->si[0].end);
switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " source=%s:%d\n",
pn, get_host_port(&sess->si[0].conn->addr.from));
pn, get_host_port(&conn->addr.from));
break;
case AF_UNIX:
chunk_appendf(&trash, " source=unix:%d\n", sess->listener->luid);
@ -3936,15 +3937,14 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
sess->listener ? sess->listener->luid : 0);
if (obj_type(sess->si[0].end) == OBJ_TYPE_CONN)
conn_get_to_addr(sess->si[0].conn);
if (conn)
conn_get_to_addr(conn);
switch ((obj_type(sess->si[0].end) == OBJ_TYPE_CONN) ?
addr_to_str(&sess->si[0].conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
switch (conn ? addr_to_str(&conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " addr=%s:%d\n",
pn, get_host_port(&sess->si[0].conn->addr.to));
pn, get_host_port(&conn->addr.to));
break;
case AF_UNIX:
chunk_appendf(&trash, " addr=unix:%d\n", sess->listener->luid);
@ -3963,15 +3963,15 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
else
chunk_appendf(&trash, " backend=<NONE> (id=-1 mode=-)");
if (obj_type(sess->si[1].end) == OBJ_TYPE_CONN)
conn_get_from_addr(sess->si[1].conn);
conn = objt_conn(sess->si[1].end);
if (conn)
conn_get_from_addr(conn);
switch ((obj_type(sess->si[1].end) == OBJ_TYPE_CONN) ?
addr_to_str(&sess->si[1].conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " addr=%s:%d\n",
pn, get_host_port(&sess->si[1].conn->addr.from));
pn, get_host_port(&conn->addr.from));
break;
case AF_UNIX:
chunk_appendf(&trash, " addr=unix\n");
@ -3990,15 +3990,14 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
else
chunk_appendf(&trash, " server=<NONE> (id=-1)");
if (obj_type(sess->si[1].end) == OBJ_TYPE_CONN)
conn_get_to_addr(sess->si[1].conn);
if (conn)
conn_get_to_addr(conn);
switch ((obj_type(sess->si[1].end) == OBJ_TYPE_CONN) ?
addr_to_str(&sess->si[1].conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
switch (conn ? addr_to_str(&conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " addr=%s:%d\n",
pn, get_host_port(&sess->si[1].conn->addr.to));
pn, get_host_port(&conn->addr.to));
break;
case AF_UNIX:
chunk_appendf(&trash, " addr=unix\n");
@ -4057,42 +4056,44 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
TICKS_TO_MS(1000)) : "<NEVER>",
sess->si[1].err_type);
if (obj_type(sess->si[0].end) == OBJ_TYPE_CONN) {
conn = objt_conn(sess->si[0].end);
if (conn) {
chunk_appendf(&trash,
" co0=%p ctrl=%s xprt=%s data=%s target=%s:%p\n",
sess->si[0].conn,
get_conn_ctrl_name(sess->si[0].conn),
get_conn_xprt_name(sess->si[0].conn),
get_conn_data_name(sess->si[0].conn),
obj_type_name(sess->si[0].conn->target),
obj_base_ptr(sess->si[0].conn->target));
conn,
get_conn_ctrl_name(conn),
get_conn_xprt_name(conn),
get_conn_data_name(conn),
obj_type_name(conn->target),
obj_base_ptr(conn->target));
chunk_appendf(&trash,
" flags=0x%08x fd=%d fd_spec_e=%02x fd_spec_p=%d updt=%d\n",
sess->si[0].conn->flags,
sess->si[0].conn->t.sock.fd,
sess->si[0].conn->t.sock.fd >= 0 ? fdtab[sess->si[0].conn->t.sock.fd].spec_e : 0,
sess->si[0].conn->t.sock.fd >= 0 ? fdtab[sess->si[0].conn->t.sock.fd].spec_p : 0,
sess->si[0].conn->t.sock.fd >= 0 ? fdtab[sess->si[0].conn->t.sock.fd].updated : 0);
conn->flags,
conn->t.sock.fd,
conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_e : 0,
conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_p : 0,
conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].updated : 0);
}
if (obj_type(sess->si[1].end) == OBJ_TYPE_CONN) {
conn = objt_conn(sess->si[1].end);
if (conn) {
chunk_appendf(&trash,
" co1=%p ctrl=%s xprt=%s data=%s target=%s:%p\n",
sess->si[1].conn,
get_conn_ctrl_name(sess->si[1].conn),
get_conn_xprt_name(sess->si[1].conn),
get_conn_data_name(sess->si[1].conn),
obj_type_name(sess->si[1].conn->target),
obj_base_ptr(sess->si[1].conn->target));
conn,
get_conn_ctrl_name(conn),
get_conn_xprt_name(conn),
get_conn_data_name(conn),
obj_type_name(conn->target),
obj_base_ptr(conn->target));
chunk_appendf(&trash,
" flags=0x%08x fd=%d fd_spec_e=%02x fd_spec_p=%d updt=%d\n",
sess->si[1].conn->flags,
sess->si[1].conn->t.sock.fd,
sess->si[1].conn->t.sock.fd >= 0 ? fdtab[sess->si[1].conn->t.sock.fd].spec_e : 0,
sess->si[1].conn->t.sock.fd >= 0 ? fdtab[sess->si[1].conn->t.sock.fd].spec_p : 0,
sess->si[1].conn->t.sock.fd >= 0 ? fdtab[sess->si[1].conn->t.sock.fd].updated : 0);
conn->flags,
conn->t.sock.fd,
conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_e : 0,
conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_p : 0,
conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].updated : 0);
}
chunk_appendf(&trash,
@ -4171,6 +4172,8 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct se
*/
static int stats_dump_sess_to_buffer(struct stream_interface *si)
{
struct connection *conn;
if (unlikely(si->ib->flags & (CF_WRITE_ERROR|CF_SHUTW))) {
/* If we're forced to shut down, we might have to remove our
* reference to the last session being dumped.
@ -4240,14 +4243,14 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si)
curr_sess->listener->proto->name);
switch ((obj_type(curr_sess->si[0].end) == OBJ_TYPE_CONN) ?
addr_to_str(&curr_sess->si[0].conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
conn = objt_conn(curr_sess->si[0].end);
switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash,
" src=%s:%d fe=%s be=%s srv=%s",
pn,
get_host_port(&curr_sess->si[0].conn->addr.from),
get_host_port(&conn->addr.from),
curr_sess->fe->id,
(curr_sess->be->cap & PR_CAP_BE) ? curr_sess->be->id : "<NONE>",
objt_server(curr_sess->target) ? objt_server(curr_sess->target)->id : "<none>"
@ -4312,22 +4315,22 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si)
human_time(TICKS_TO_MS(curr_sess->rep->analyse_exp - now_ms),
TICKS_TO_MS(1000)) : "");
conn = objt_conn(curr_sess->si[0].end);
chunk_appendf(&trash,
" s0=[%d,%1xh,fd=%d,ex=%s]",
curr_sess->si[0].state,
curr_sess->si[0].flags,
(obj_type(curr_sess->si[0].end) == OBJ_TYPE_CONN) ?
curr_sess->si[0].conn->t.sock.fd : -1,
conn ? conn->t.sock.fd : -1,
curr_sess->si[0].exp ?
human_time(TICKS_TO_MS(curr_sess->si[0].exp - now_ms),
TICKS_TO_MS(1000)) : "");
conn = objt_conn(curr_sess->si[1].end);
chunk_appendf(&trash,
" s1=[%d,%1xh,fd=%d,ex=%s]",
curr_sess->si[1].state,
curr_sess->si[1].flags,
(obj_type(curr_sess->si[1].end) == OBJ_TYPE_CONN) ?
curr_sess->si[1].conn->t.sock.fd : -1,
conn ? conn->t.sock.fd : -1,
curr_sess->si[1].exp ?
human_time(TICKS_TO_MS(curr_sess->si[1].exp - now_ms),
TICKS_TO_MS(1000)) : "");

View File

@ -49,11 +49,13 @@
/* Finish a session accept() for a proxy (TCP or HTTP). It returns a negative
* value in case of a critical failure which must cause the listener to be
* disabled, a positive value in case of success, or zero if it is a success
* but the session must be closed ASAP (eg: monitoring).
* but the session must be closed ASAP (eg: monitoring). It only supports
* sessions with a connection in si[0].
*/
int frontend_accept(struct session *s)
{
int cfd = s->si[0].conn->t.sock.fd;
struct connection *conn = __objt_conn(s->si[0].end);
int cfd = conn->t.sock.fd;
tv_zero(&s->logs.tv_request);
s->logs.t_queue = -1;
@ -140,16 +142,16 @@ int frontend_accept(struct session *s)
else {
char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
conn_get_from_addr(s->req->prod->conn);
conn_get_to_addr(s->req->prod->conn);
conn_get_from_addr(conn);
conn_get_to_addr(conn);
switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) {
switch (addr_to_str(&conn->addr.from, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
addr_to_str(&s->req->prod->conn->addr.to, sn, sizeof(sn));
addr_to_str(&conn->addr.to, sn, sizeof(sn));
send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
pn, get_host_port(&s->req->prod->conn->addr.from),
sn, get_host_port(&s->req->prod->conn->addr.to),
pn, get_host_port(&conn->addr.from),
sn, get_host_port(&conn->addr.to),
s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
break;
case AF_UNIX:
@ -165,14 +167,14 @@ int frontend_accept(struct session *s)
if (unlikely((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
char pn[INET6_ADDRSTRLEN];
conn_get_from_addr(s->req->prod->conn);
conn_get_from_addr(conn);
switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) {
switch (addr_to_str(&conn->addr.from, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n",
s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
pn, get_host_port(&s->req->prod->conn->addr.from));
pn, get_host_port(&conn->addr.from));
break;
case AF_UNIX:
/* UNIX socket, only the destination is known */

View File

@ -935,6 +935,7 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
return 0;
list_for_each_entry(tmp, list_format, list) {
struct connection *conn;
const char *src = NULL;
struct sample *key;
@ -969,8 +970,11 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_CLIENTIP: // %ci
ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.from,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->prod->end);
if (conn)
ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -978,12 +982,18 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_CLIENTPORT: // %cp
if (s->req->prod->conn->addr.from.ss_family == AF_UNIX) {
ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
} else {
ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.from,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->prod->end);
if (conn) {
if (conn->addr.from.ss_family == AF_UNIX) {
ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
} else {
ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.from,
dst + maxsize - tmplog, tmp);
}
}
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -991,9 +1001,14 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_FRONTENDIP: // %fi
conn_get_to_addr(s->req->prod->conn);
ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.to,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->prod->end);
if (conn) {
conn_get_to_addr(conn);
ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
}
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -1001,14 +1016,17 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_FRONTENDPORT: // %fp
conn_get_to_addr(s->req->prod->conn);
if (s->req->prod->conn->addr.to.ss_family == AF_UNIX) {
ret = ltoa_o(s->listener->luid,
tmplog, dst + maxsize - tmplog);
} else {
ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.to,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->prod->end);
if (conn) {
conn_get_to_addr(conn);
if (conn->addr.to.ss_family == AF_UNIX)
ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
else
ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
}
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -1016,8 +1034,12 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_BACKENDIP: // %bi
ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.from,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->cons->end);
if (conn)
ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -1025,8 +1047,12 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_BACKENDPORT: // %bp
ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.from,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->cons->end);
if (conn)
ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -1034,8 +1060,12 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_SERVERIP: // %si
ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.to,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->cons->end);
if (conn)
ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -1043,8 +1073,12 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
break;
case LOG_FMT_SERVERPORT: // %sp
ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.to,
dst + maxsize - tmplog, tmp);
conn = objt_conn(s->req->cons->end);
if (conn)
ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
else
ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
@ -1143,8 +1177,11 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
#ifdef USE_OPENSSL
case LOG_FMT_SSL_CIPHER: // %sslc
src = NULL;
if (s->listener->xprt == &ssl_sock)
src = ssl_sock_get_cipher_name(s->si[0].conn);
conn = objt_conn(s->si[0].end);
if (conn) {
if (s->listener->xprt == &ssl_sock)
src = ssl_sock_get_cipher_name(conn);
}
ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
@ -1154,8 +1191,11 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
case LOG_FMT_SSL_VERSION: // %sslv
src = NULL;
if (s->listener->xprt == &ssl_sock)
src = ssl_sock_get_proto_version(s->si[0].conn);
conn = objt_conn(s->si[0].end);
if (conn) {
if (s->listener->xprt == &ssl_sock)
src = ssl_sock_get_proto_version(conn);
}
ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;

View File

@ -1076,11 +1076,10 @@ static void peer_session_forceshutdown(struct session * session)
task_wakeup(session->task, TASK_WOKEN_MSG);
}
/*
* this function is called on a read event from a listen socket, corresponding
* to an accept. It tries to accept as many connections as possible.
* It returns a positive value upon success, 0 if the connection needs to be
* closed and ignored, or a negative value upon critical failure.
/* Finish a session accept() for a peer. It returns a negative value in case of
* a critical failure which must cause the listener to be disabled, a positive
* value in case of success, or zero if it is a success but the session must be
* closed ASAP and ignored.
*/
int peer_accept(struct session *s)
{
@ -1162,15 +1161,17 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
s->req = s->rep = NULL; /* will be allocated later */
/* si[0] is the applet, we should not need s->si[0].conn anymore soon */
s->si[0].conn->obj_type = OBJ_TYPE_CONN;
s->si[0].conn->t.sock.fd = -1;
s->si[0].conn->flags = CO_FL_NONE;
s->si[0].conn->err_code = CO_ER_NONE;
s->si[0].conn->target = &l->obj_type;
s->si[0].owner = t;
s->si[0].state = s->si[0].prev_state = SI_ST_EST;
s->si[0].err_type = SI_ET_NONE;
s->si[0].send_proxy_ofs = 0;
s->si[0].conn->target = &l->obj_type;
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
if (s->fe->options2 & PR_O2_INDEPSTR)
@ -1184,18 +1185,23 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
s->si[1].conn->t.sock.fd = -1; /* just to help with debugging */
s->si[1].conn->flags = CO_FL_NONE;
s->si[1].conn->err_code = CO_ER_NONE;
s->si[1].conn->target = &s->be->obj_type;
s->si[1].owner = t;
s->si[1].state = s->si[1].prev_state = SI_ST_ASS;
s->si[1].conn_retries = p->conn_retries;
s->si[1].err_type = SI_ET_NONE;
s->si[1].send_proxy_ofs = 0;
s->si[1].conn->target = &s->be->obj_type;
si_prepare_conn(&s->si[1], peer->proto, peer->xprt);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
if (s->be->options2 & PR_O2_INDEPSTR)
s->si[1].flags |= SI_FL_INDEP_STR;
/* will automatically prepare the stream interface to connect to the
* pre-initialized connection in si->conn.
*/
si_prepare_conn(&s->si[1], peer->proto, peer->xprt);
session_init_srv_conn(s);
s->target = &s->be->obj_type;
s->pend_pos = NULL;

View File

@ -2488,12 +2488,12 @@ int http_wait_for_request(struct session *s, struct channel *req, int an_bit)
req->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
s->rep->flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
#ifdef TCP_QUICKACK
if (s->listener->options & LI_O_NOQUICKACK && req->buf->i) {
if (s->listener->options & LI_O_NOQUICKACK && req->buf->i && objt_conn(s->req->prod->end)) {
/* We need more data, we have to re-enable quick-ack in case we
* previously disabled it, otherwise we might cause the client
* to delay next data.
*/
setsockopt(s->si[0].conn->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
setsockopt(__objt_conn(s->req->prod->end)->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
}
#endif
@ -2969,6 +2969,7 @@ static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos)
static struct http_req_rule *
http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session *s, struct http_txn *txn)
{
struct connection *cli_conn;
struct http_req_rule *rule;
struct hdr_ctx ctx;
@ -3014,12 +3015,14 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
break;
case HTTP_REQ_ACT_SET_TOS:
inet_set_tos(s->req->prod->conn->t.sock.fd, s->req->prod->conn->addr.from, rule->arg.tos);
if ((cli_conn = objt_conn(s->req->prod->end)))
inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
break;
case HTTP_REQ_ACT_SET_MARK:
#ifdef SO_MARK
setsockopt(s->req->prod->conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
if ((cli_conn = objt_conn(s->req->prod->end)))
setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
#endif
break;
@ -3062,6 +3065,7 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
static struct http_res_rule *
http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session *s, struct http_txn *txn)
{
struct connection *cli_conn;
struct http_res_rule *rule;
struct hdr_ctx ctx;
@ -3097,12 +3101,14 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session
break;
case HTTP_RES_ACT_SET_TOS:
inet_set_tos(s->req->prod->conn->t.sock.fd, s->req->prod->conn->addr.from, rule->arg.tos);
if ((cli_conn = objt_conn(s->req->prod->end)))
inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
break;
case HTTP_RES_ACT_SET_MARK:
#ifdef SO_MARK
setsockopt(s->req->prod->conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
if ((cli_conn = objt_conn(s->req->prod->end)))
setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
#endif
break;
@ -3684,6 +3690,7 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
{
struct http_txn *txn = &s->txn;
struct http_msg *msg = &txn->req;
struct connection *cli_conn = objt_conn(req->prod->end);
if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
/* we need more data */
@ -3711,8 +3718,9 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
*/
/*
* If HTTP PROXY is set we simply get remote server address
* parsing incoming request.
* If HTTP PROXY is set we simply get remote server address parsing
* incoming request. Note that this requires that a connection is
* allocated on the server side.
*/
if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
url2sa(req->buf->p + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->conn->addr.to);
@ -3769,19 +3777,19 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
* and we found it, so don't do anything.
*/
}
else if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
else if (cli_conn && cli_conn->addr.from.ss_family == AF_INET) {
/* Add an X-Forwarded-For header unless the source IP is
* in the 'except' network range.
*/
if ((!s->fe->except_mask.s_addr ||
(((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
(((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
!= s->fe->except_net.s_addr) &&
(!s->be->except_mask.s_addr ||
(((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
(((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
!= s->be->except_net.s_addr)) {
int len;
unsigned char *pn;
pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr;
pn = (unsigned char *)&((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
* x-forwarded-for, because the header is really meant for the backends.
@ -3801,14 +3809,14 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
goto return_bad_req;
}
}
else if (s->req->prod->conn->addr.from.ss_family == AF_INET6) {
else if (cli_conn && cli_conn->addr.from.ss_family == AF_INET6) {
/* FIXME: for the sake of completeness, we should also support
* 'except' here, although it is mostly useless in this case.
*/
int len;
char pn[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6,
(const void *)&((struct sockaddr_in6 *)(&s->req->prod->conn->addr.from))->sin6_addr,
(const void *)&((struct sockaddr_in6 *)(&cli_conn->addr.from))->sin6_addr,
pn, sizeof(pn));
/* Note: we rely on the backend to get the header name to be used for
@ -3837,22 +3845,22 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
if ((s->fe->options | s->be->options) & PR_O_ORGTO) {
/* FIXME: don't know if IPv6 can handle that case too. */
if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
if (cli_conn && cli_conn->addr.from.ss_family == AF_INET) {
/* Add an X-Original-To header unless the destination IP is
* in the 'except' network range.
*/
conn_get_to_addr(s->req->prod->conn);
conn_get_to_addr(cli_conn);
if (s->req->prod->conn->addr.to.ss_family == AF_INET &&
if (cli_conn->addr.to.ss_family == AF_INET &&
((!s->fe->except_mask_to.s_addr ||
(((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
(((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
!= s->fe->except_to.s_addr) &&
(!s->be->except_mask_to.s_addr ||
(((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
(((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
!= s->be->except_to.s_addr))) {
int len;
unsigned char *pn;
pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr;
pn = (unsigned char *)&((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
* x-original-to, because the header is really meant for the backends.
@ -3922,9 +3930,10 @@ int http_process_request(struct session *s, struct channel *req, int an_bit)
* the client to delay further data.
*/
if ((s->listener->options & LI_O_NOQUICKACK) &&
cli_conn &&
((msg->flags & HTTP_MSGF_TE_CHNK) ||
(msg->body_len > req->buf->i - txn->req.eoh - 2)))
setsockopt(s->si[0].conn->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
setsockopt(cli_conn->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif
}
@ -4282,7 +4291,9 @@ void http_end_txn_clean_session(struct session *s)
s->target = NULL;
/* reinitialize the connection to the server */
s->req->cons->state = s->req->cons->prev_state = SI_ST_INI;
s->req->cons->end = NULL;
s->req->cons->conn->obj_type = OBJ_TYPE_CONN;
s->req->cons->conn->t.sock.fd = -1; /* just to help with debugging */
s->req->cons->conn->flags = CO_FL_NONE;
@ -7786,7 +7797,11 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s,
es->sid = s->uniq_id;
es->srv = objt_server(s->target);
es->oe = other_end;
es->src = s->req->prod->conn->addr.from;
if (objt_conn(s->req->prod->end))
es->src = __objt_conn(s->req->prod->end)->addr.from;
else
memset(&es->src, 0, sizeof(es->src));
es->state = state;
es->ev_id = error_snapshot_id++;
es->b_flags = chn->flags;
@ -7939,8 +7954,9 @@ void debug_hdr(const char *dir, struct session *t, const char *start, const char
{
int max;
chunk_printf(&trash, "%08x:%s.%s[%04x:%04x]: ", t->uniq_id, t->be->id,
dir, (unsigned short)t->req->prod->conn->t.sock.fd,
(unsigned short)t->req->cons->conn->t.sock.fd);
dir,
objt_conn(t->req->prod->end) ? (unsigned short)objt_conn(t->req->prod->end)->t.sock.fd : -1,
objt_conn(t->req->cons->end) ? (unsigned short)objt_conn(t->req->cons->end)->t.sock.fd : -1);
for (max = 0; start + max < end; max++)
if (start[max] == '\r' || start[max] == '\n')
@ -9264,6 +9280,10 @@ smp_fetch_base32_src(struct proxy *px, struct session *l4, void *l7, unsigned in
const struct arg *args, struct sample *smp, const char *kw)
{
struct chunk *temp;
struct connection *cli_conn = objt_conn(l4->si[0].end);
if (!cli_conn)
return 0;
if (!smp_fetch_base32(px, l4, l7, opt, args, smp, kw))
return 0;
@ -9272,13 +9292,13 @@ smp_fetch_base32_src(struct proxy *px, struct session *l4, void *l7, unsigned in
memcpy(temp->str + temp->len, &smp->data.uint, sizeof(smp->data.uint));
temp->len += sizeof(smp->data.uint);
switch (l4->si[0].conn->addr.from.ss_family) {
switch (cli_conn->addr.from.ss_family) {
case AF_INET:
memcpy(temp->str + temp->len, &((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr, 4);
memcpy(temp->str + temp->len, &((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr, 4);
temp->len += 4;
break;
case AF_INET6:
memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr, 16);
memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr, 16);
temp->len += 16;
break;
default:
@ -9848,6 +9868,7 @@ smp_fetch_url32_src(struct proxy *px, struct session *l4, void *l7, unsigned int
const struct arg *args, struct sample *smp, const char *kw)
{
struct chunk *temp;
struct connection *cli_conn = objt_conn(l4->si[0].end);
if (!smp_fetch_url32(px, l4, l7, opt, args, smp, kw))
return 0;
@ -9856,13 +9877,13 @@ smp_fetch_url32_src(struct proxy *px, struct session *l4, void *l7, unsigned int
memcpy(temp->str + temp->len, &smp->data.uint, sizeof(smp->data.uint));
temp->len += sizeof(smp->data.uint);
switch (l4->si[0].conn->addr.from.ss_family) {
switch (cli_conn->addr.from.ss_family) {
case AF_INET:
memcpy(temp->str + temp->len, &((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr, 4);
memcpy(temp->str + temp->len, &((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr, 4);
temp->len += 4;
break;
case AF_INET6:
memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr, 16);
memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr, 16);
temp->len += 16;
break;
default:

View File

@ -1086,16 +1086,20 @@ int tcp_inspect_response(struct session *s, struct channel *rep, int an_bit)
/* This function performs the TCP layer4 analysis on the current request. It
* returns 0 if a reject rule matches, otherwise 1 if either an accept rule
* matches or if no more rule matches. It can only use rules which don't need
* any data.
* any data. This only works on connection-based client-facing stream interfaces.
*/
int tcp_exec_req_rules(struct session *s)
{
struct tcp_rule *rule;
struct stksess *ts;
struct stktable *t = NULL;
struct connection *conn = objt_conn(s->si[0].end);
int result = 1;
enum acl_test_res ret;
if (!conn)
return result;
list_for_each_entry(rule, &s->fe->tcp_req.l4_rules, list) {
ret = ACL_TEST_PASS;
@ -1136,8 +1140,8 @@ int tcp_exec_req_rules(struct session *s)
session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts);
}
else if (rule->action == TCP_ACT_EXPECT_PX) {
s->si[0].conn->flags |= CO_FL_ACCEPT_PROXY;
conn_sock_want_recv(s->si[0].conn);
conn->flags |= CO_FL_ACCEPT_PROXY;
conn_sock_want_recv(conn);
}
else {
/* otherwise it's an accept */
@ -1577,13 +1581,18 @@ static int
smp_fetch_src(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
switch (l4->si[0].conn->addr.from.ss_family) {
struct connection *cli_conn = objt_conn(l4->si[0].end);
if (!cli_conn)
return 0;
switch (cli_conn->addr.from.ss_family) {
case AF_INET:
smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr;
smp->data.ipv4 = ((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr;
smp->type = SMP_T_IPV4;
break;
case AF_INET6:
smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr;
smp->data.ipv6 = ((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr;
smp->type = SMP_T_IPV6;
break;
default:
@ -1599,8 +1608,13 @@ static int
smp_fetch_sport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *cli_conn = objt_conn(l4->si[0].end);
if (!cli_conn)
return 0;
smp->type = SMP_T_UINT;
if (!(smp->data.uint = get_host_port(&l4->si[0].conn->addr.from)))
if (!(smp->data.uint = get_host_port(&cli_conn->addr.from)))
return 0;
smp->flags = 0;
@ -1612,15 +1626,20 @@ static int
smp_fetch_dst(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
conn_get_to_addr(l4->si[0].conn);
struct connection *cli_conn = objt_conn(l4->si[0].end);
switch (l4->si[0].conn->addr.to.ss_family) {
if (!cli_conn)
return 0;
conn_get_to_addr(cli_conn);
switch (cli_conn->addr.to.ss_family) {
case AF_INET:
smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn->addr.to)->sin_addr;
smp->data.ipv4 = ((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr;
smp->type = SMP_T_IPV4;
break;
case AF_INET6:
smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn->addr.to))->sin6_addr;
smp->data.ipv6 = ((struct sockaddr_in6 *)&cli_conn->addr.to)->sin6_addr;
smp->type = SMP_T_IPV6;
break;
default:
@ -1636,10 +1655,15 @@ static int
smp_fetch_dport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
conn_get_to_addr(l4->si[0].conn);
struct connection *cli_conn = objt_conn(l4->si[0].end);
if (!cli_conn)
return 0;
conn_get_to_addr(cli_conn);
smp->type = SMP_T_UINT;
if (!(smp->data.uint = get_host_port(&l4->si[0].conn->addr.to)))
if (!(smp->data.uint = get_host_port(&cli_conn->addr.to)))
return 0;
smp->flags = 0;

View File

@ -72,6 +72,7 @@ struct data_cb sess_conn_cb = {
*/
int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
{
struct connection *cli_conn;
struct proxy *p = l->frontend;
struct session *s;
struct task *t;
@ -83,7 +84,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
goto out_close;
if (unlikely((s->si[0].conn = pool_alloc2(pool2_connection)) == NULL))
if (unlikely((cli_conn = s->si[0].conn = pool_alloc2(pool2_connection)) == NULL))
goto out_fail_conn0;
if (unlikely((s->si[1].conn = pool_alloc2(pool2_connection)) == NULL))
@ -104,19 +105,21 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
s->listener = l;
s->fe = p;
/* OK, we're keeping the session, so let's properly initialize the session */
s->si[0].conn->obj_type = OBJ_TYPE_CONN;
s->si[0].conn->t.sock.fd = cfd;
s->si[0].conn->ctrl = l->proto;
s->si[0].conn->flags = CO_FL_NONE | CO_FL_ADDR_FROM_SET;
s->si[0].conn->err_code = CO_ER_NONE;
s->si[0].conn->addr.from = *addr;
s->si[0].conn->target = &l->obj_type;
/* FIXME: this should be replaced with OBJ_TYPE_NONE once all users check the
* object type before dereferencing the connection pointer.
/* OK, we're keeping the session, so let's properly initialize the session.
* We first have to initialize the client-side connection.
*/
s->si[1].conn->obj_type = OBJ_TYPE_CONN;
cli_conn->obj_type = OBJ_TYPE_CONN;
cli_conn->t.sock.fd = cfd;
cli_conn->ctrl = l->proto;
cli_conn->flags = CO_FL_NONE | CO_FL_ADDR_FROM_SET;
cli_conn->err_code = CO_ER_NONE;
cli_conn->addr.from = *addr;
cli_conn->target = &l->obj_type;
/* The server side is not used yet, but just initialize it to avoid
* confusing some debugging or "show sess" for example.
*/
s->si[1].conn->obj_type = OBJ_TYPE_NONE;
s->logs.accept_date = date; /* user-visible date for logging */
s->logs.tv_accept = now; /* corrected date for internal use */
@ -178,8 +181,8 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
/* wait for a PROXY protocol header */
if (l->options & LI_O_ACC_PROXY) {
s->si[0].conn->flags |= CO_FL_ACCEPT_PROXY;
conn_sock_want_recv(s->si[0].conn);
cli_conn->flags |= CO_FL_ACCEPT_PROXY;
conn_sock_want_recv(cli_conn);
}
if (unlikely((t = task_new()) == NULL))
@ -193,14 +196,14 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
* but not initialized. Also note we need to be careful as the stream
* int is not initialized yet.
*/
conn_prepare(s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
conn_prepare(cli_conn, &sess_conn_cb, l->proto, l->xprt, s);
/* finish initialization of the accepted file descriptor */
fd_insert(cfd);
fdtab[cfd].owner = s->si[0].conn;
fdtab[cfd].owner = cli_conn;
fdtab[cfd].iocb = conn_fd_handler;
conn_data_want_recv(s->si[0].conn);
if (conn_xprt_init(s->si[0].conn) < 0)
conn_data_want_recv(cli_conn);
if (conn_xprt_init(cli_conn) < 0)
goto out_free_task;
/* OK, now either we have a pending handshake to execute with and
@ -209,16 +212,16 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
* set the I/O timeout to the frontend's client timeout.
*/
if (s->si[0].conn->flags & CO_FL_HANDSHAKE) {
if (cli_conn->flags & CO_FL_HANDSHAKE) {
t->process = expire_mini_session;
t->expire = tick_add_ifset(now_ms, p->timeout.client);
task_queue(t);
s->si[0].conn->flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
cli_conn->flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
return 1;
}
/* OK let's complete session initialization since there is no handshake */
s->si[0].conn->flags |= CO_FL_CONNECTED;
cli_conn->flags |= CO_FL_CONNECTED;
ret = session_complete(s);
if (ret > 0)
return ret;
@ -252,21 +255,24 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
}
/* prepare the trash with a log prefix for session <s> */
/* prepare the trash with a log prefix for session <s>. It only works with
* embryonic sessions based on a real connection.
*/
static void prepare_mini_sess_log_prefix(struct session *s)
{
struct tm tm;
char pn[INET6_ADDRSTRLEN];
int ret;
char *end;
struct connection *cli_conn = s->si[0].conn;
ret = addr_to_str(&s->si[0].conn->addr.from, pn, sizeof(pn));
ret = addr_to_str(&cli_conn->addr.from, pn, sizeof(pn));
if (ret <= 0)
chunk_printf(&trash, "unknown [");
else if (ret == AF_UNIX)
chunk_printf(&trash, "%s:%d [", pn, s->listener->luid);
else
chunk_printf(&trash, "%s:%d [", pn, get_host_port(&s->si[0].conn->addr.from));
chunk_printf(&trash, "%s:%d [", pn, get_host_port(&cli_conn->addr.from));
get_localtime(s->logs.accept_date.tv_sec, &tm);
end = date2str_log(trash.str + trash.len, &tm, &(s->logs.accept_date), trash.size - trash.len);
@ -317,7 +323,7 @@ static void kill_mini_session(struct session *s)
}
/* kill the connection now */
conn_full_close(s->si[0].conn);
conn_full_close(conn);
s->fe->feconn--;
session_store_counters(s);
@ -393,6 +399,7 @@ static struct task *expire_mini_session(struct task *t)
* be called with an embryonic session. It returns a positive value upon
* success, 0 if the connection can be ignored, or a negative value upon
* critical failure. The accepted file descriptor is closed if we return <= 0.
* The client-side end point is assumed to be a connection.
*/
int session_complete(struct session *s)
{
@ -462,15 +469,17 @@ int session_complete(struct session *s)
s->si[1].conn->t.sock.fd = -1; /* just to help with debugging */
s->si[1].conn->flags = CO_FL_NONE;
s->si[1].conn->err_code = CO_ER_NONE;
s->si[1].conn->target = NULL;
s->si[1].owner = t;
s->si[1].state = s->si[1].prev_state = SI_ST_INI;
s->si[1].err_type = SI_ET_NONE;
s->si[1].conn_retries = 0; /* used for logging too */
s->si[1].send_proxy_ofs = 0;
si_prepare_none(&s->si[1]);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
si_prepare_none(&s->si[1]);
if (likely(s->fe->options2 & PR_O2_INDEPSTR))
s->si[1].flags |= SI_FL_INDEP_STR;
@ -549,7 +558,7 @@ int session_complete(struct session *s)
txn->rsp.chn = s->rep;
/* finish initialization of the accepted file descriptor */
conn_data_want_recv(s->si[0].conn);
conn_data_want_recv(__objt_conn(s->si[0].end));
if (p->accept && (ret = p->accept(s)) <= 0) {
/* Either we had an unrecoverable error (<0) or work is
@ -561,10 +570,10 @@ int session_complete(struct session *s)
/* if logs require transport layer information, note it on the connection */
if (s->logs.logwait & LW_XPRT)
s->si[0].conn->flags |= CO_FL_XPRT_TRACKED;
__objt_conn(s->si[0].end)->flags |= CO_FL_XPRT_TRACKED;
/* we want the connection handler to notify the stream interface about updates. */
s->si[0].conn->flags |= CO_FL_WAKE_DATA;
__objt_conn(s->si[0].end)->flags |= CO_FL_WAKE_DATA;
/* it is important not to call the wakeup function directly but to
* pass through task_wakeup(), because this one knows how to apply
@ -594,6 +603,7 @@ static void session_free(struct session *s)
struct http_txn *txn = &s->txn;
struct proxy *fe = s->fe;
struct bref *bref, *back;
struct connection *cli_conn = objt_conn(s->si[0].end);
int i;
if (s->pend_pos)
@ -636,8 +646,10 @@ static void session_free(struct session *s)
http_end_txn(s);
/* ensure the client-side transport layer is destroyed */
s->si[0].conn->flags &= ~CO_FL_XPRT_TRACKED;
conn_full_close(s->si[0].conn);
if (cli_conn) {
cli_conn->flags &= ~CO_FL_XPRT_TRACKED;
conn_full_close(cli_conn);
}
for (i = 0; i < s->store_count; i++) {
if (!s->store[i].ts)
@ -771,12 +783,13 @@ void session_process_counters(struct session *s)
* We must check for establishment, error and abort. Possible output states
* are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
* SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
* otherwise 1.
* otherwise 1. This only works with connection-based sessions.
*/
static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
{
struct channel *req = si->ob;
struct channel *rep = si->ib;
struct connection *srv_conn = __objt_conn(si->end);
/* If we got an error, or if nothing happened and the connection timed
* out, we must give up. The CER state handler will take care of retry
@ -798,8 +811,8 @@ static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si
si->exp = TICK_ETERNITY;
si->state = SI_ST_CER;
si->conn->flags &= ~CO_FL_XPRT_TRACKED;
conn_full_close(si->conn);
srv_conn->flags &= ~CO_FL_XPRT_TRACKED;
conn_full_close(srv_conn);
if (si->err_type)
return 0;
@ -954,7 +967,7 @@ static void sess_establish(struct session *s, struct stream_interface *si)
rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
if (si->conn->ctrl) {
if (objt_conn(si->end)) {
/* real connections have timeouts */
req->wto = s->be->timeout.server;
rep->rto = s->be->timeout.server;
@ -2130,8 +2143,8 @@ struct task *process_session(struct task *t)
if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
s->req->to_forward &&
(global.tune.options & GTUNE_USE_SPLICE) &&
(s->si[0].conn->xprt && s->si[0].conn->xprt->rcv_pipe && s->si[0].conn->xprt->snd_pipe) &&
(s->si[1].conn->xprt && s->si[1].conn->xprt->rcv_pipe && s->si[1].conn->xprt->snd_pipe) &&
(objt_conn(s->si[0].end) && __objt_conn(s->si[0].end)->xprt && __objt_conn(s->si[0].end)->xprt->rcv_pipe) &&
(objt_conn(s->si[1].end) && __objt_conn(s->si[1].end)->xprt && __objt_conn(s->si[1].end)->xprt->snd_pipe) &&
(pipes_used < global.maxpipes) &&
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
@ -2278,8 +2291,8 @@ struct task *process_session(struct task *t)
if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
s->rep->to_forward &&
(global.tune.options & GTUNE_USE_SPLICE) &&
(s->si[0].conn->xprt && s->si[0].conn->xprt->rcv_pipe && s->si[0].conn->xprt->snd_pipe) &&
(s->si[1].conn->xprt && s->si[1].conn->xprt->rcv_pipe && s->si[1].conn->xprt->snd_pipe) &&
(objt_conn(s->si[0].end) && __objt_conn(s->si[0].end)->xprt && __objt_conn(s->si[0].end)->xprt->snd_pipe) &&
(objt_conn(s->si[1].end) && __objt_conn(s->si[1].end)->xprt && __objt_conn(s->si[1].end)->xprt->rcv_pipe) &&
(pipes_used < global.maxpipes) &&
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
@ -2345,8 +2358,8 @@ struct task *process_session(struct task *t)
s->si[1].prev_state == SI_ST_EST) {
chunk_printf(&trash, "%08x:%s.srvcls[%04x:%04x]\n",
s->uniq_id, s->be->id,
(unsigned short)s->si[0].conn->t.sock.fd,
(unsigned short)s->si[1].conn->t.sock.fd);
objt_conn(s->si[0].end) ? (unsigned short)objt_conn(s->si[0].end)->t.sock.fd : -1,
objt_conn(s->si[1].end) ? (unsigned short)objt_conn(s->si[1].end)->t.sock.fd : -1);
if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */;
}
@ -2354,8 +2367,8 @@ struct task *process_session(struct task *t)
s->si[0].prev_state == SI_ST_EST) {
chunk_printf(&trash, "%08x:%s.clicls[%04x:%04x]\n",
s->uniq_id, s->be->id,
(unsigned short)s->si[0].conn->t.sock.fd,
(unsigned short)s->si[1].conn->t.sock.fd);
objt_conn(s->si[0].end) ? (unsigned short)objt_conn(s->si[0].end)->t.sock.fd : -1,
objt_conn(s->si[1].end) ? (unsigned short)objt_conn(s->si[1].end)->t.sock.fd : -1);
if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */;
}
}
@ -2459,8 +2472,8 @@ struct task *process_session(struct task *t)
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
chunk_printf(&trash, "%08x:%s.closed[%04x:%04x]\n",
s->uniq_id, s->be->id,
(unsigned short)s->req->prod->conn->t.sock.fd,
(unsigned short)s->req->cons->conn->t.sock.fd);
objt_conn(s->si[0].end) ? (unsigned short)objt_conn(s->si[0].end)->t.sock.fd : -1,
objt_conn(s->si[1].end) ? (unsigned short)objt_conn(s->si[1].end)->t.sock.fd : -1);
if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */;
}
@ -2619,10 +2632,16 @@ smp_fetch_sc_stkctr(struct session *l4, const struct arg *args, const char *kw)
return NULL;
}
else if (num > 9) { /* src_* variant, args[0] = table */
struct stktable_key *key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
struct stktable_key *key;
struct connection *conn = objt_conn(l4->si[0].end);
if (!conn)
return NULL;
key = addr_to_stktable_key(&conn->addr.from);
if (!key)
return NULL;
stkctr.table = &args->data.prx->table;
stkctr.entry = stktable_lookup_key(stkctr.table, key);
return &stkctr;
@ -2831,11 +2850,15 @@ static int
smp_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn = objt_conn(l4->si[0].end);
struct stksess *ts;
struct stktable_key *key;
void *ptr;
key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
if (!conn)
return 0;
key = addr_to_stktable_key(&conn->addr.from);
if (!key)
return 0;

View File

@ -1704,17 +1704,23 @@ static int
smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
struct connection *conn;
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
smp->flags = 0;
smp->type = SMP_T_BOOL;
smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
return 1;
}
@ -1727,17 +1733,22 @@ smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -1763,17 +1774,22 @@ smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned in
const EVP_MD *digest;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -1798,17 +1814,22 @@ smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigne
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -1834,17 +1855,22 @@ smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned in
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -1884,17 +1910,22 @@ smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsign
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -1920,17 +1951,22 @@ smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned in
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -1968,17 +2004,22 @@ smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned in
const struct arg *args, struct sample *smp, const char *kw)
{
X509 *crt;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (crt) {
X509_free(crt);
}
@ -1994,17 +2035,22 @@ smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned
const struct arg *args, struct sample *smp, const char *kw)
{
X509 *crt;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
return 0;
@ -2022,17 +2068,22 @@ smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned
{
X509 *crt;
int nid;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
return 0;
@ -2058,17 +2109,22 @@ smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned
{
X509 *crt;
int nid;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
return 0;
@ -2092,8 +2148,10 @@ static int
smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn = objt_conn(l4->si[0].end);
smp->type = SMP_T_BOOL;
smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
smp->data.uint = (conn && conn->xprt == &ssl_sock);
return 1;
}
@ -2103,10 +2161,12 @@ smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigne
const struct arg *args, struct sample *smp, const char *kw)
{
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
struct connection *conn = objt_conn(l4->si[0].end);
smp->type = SMP_T_BOOL;
smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
l4->si[0].conn->xprt_ctx &&
SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
conn->xprt_ctx &&
SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
return 1;
#else
return 0;
@ -2121,16 +2181,21 @@ smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -2152,16 +2217,21 @@ smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigne
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -2184,16 +2254,21 @@ smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsign
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -2214,17 +2289,22 @@ smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned
const struct arg *args, struct sample *smp, const char *kw)
{
X509 *crt;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
return 0;
@ -2241,16 +2321,21 @@ smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned
{
X509 *crt;
int nid;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
return 0;
@ -2273,16 +2358,21 @@ smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned
{
X509 *crt;
int nid;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
return 0;
@ -2307,16 +2397,21 @@ smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned in
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -2355,16 +2450,21 @@ smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned in
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
struct connection *conn;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
@ -2398,12 +2498,18 @@ static int
smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn;
smp->flags = 0;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
if (!smp->data.str.str)
return 0;
@ -2417,12 +2523,18 @@ static int
smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn;
smp->flags = 0;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
return 0;
smp->type = SMP_T_UINT;
@ -2434,12 +2546,18 @@ static int
smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn;
smp->flags = 0;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
if (!smp->data.uint)
return 0;
@ -2453,14 +2571,20 @@ static int
smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn;
smp->flags = 0;
smp->type = SMP_T_CSTR;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = NULL;
SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
SSL_get0_next_proto_negotiated(conn->xprt_ctx,
(const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
if (!smp->data.str.str)
@ -2475,14 +2599,20 @@ static int
smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn;
smp->flags = 0;
smp->type = SMP_T_CSTR;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = NULL;
SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
SSL_get0_alpn_negotiated(conn->xprt_ctx,
(const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
if (!smp->data.str.str)
@ -2496,12 +2626,18 @@ static int
smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
struct connection *conn;
smp->flags = 0;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
if (!smp->data.str.str)
return 0;
@ -2517,14 +2653,19 @@ smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsi
{
#if OPENSSL_VERSION_NUMBER > 0x0090800fL
SSL_SESSION *sess;
struct connection *conn;
smp->flags = 0;
smp->type = SMP_T_CBIN;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
sess = SSL_get_session(conn->xprt_ctx);
if (!sess)
return 0;
@ -2543,13 +2684,19 @@ smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned in
const struct arg *args, struct sample *smp, const char *kw)
{
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
struct connection *conn;
smp->flags = 0;
smp->type = SMP_T_CSTR;
if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
if (!l4)
return 0;
smp->data.str.str = (char *)SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
if (!smp->data.str.str)
return 0;
@ -2565,16 +2712,22 @@ static int
smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
struct connection *conn;
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
smp->type = SMP_T_UINT;
smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
smp->flags = 0;
return 1;
@ -2585,16 +2738,22 @@ static int
smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
struct connection *conn;
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
smp->type = SMP_T_UINT;
smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
smp->flags = 0;
return 1;
@ -2605,16 +2764,22 @@ static int
smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
struct connection *conn;
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
smp->type = SMP_T_UINT;
smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
smp->flags = 0;
return 1;
@ -2625,19 +2790,25 @@ static int
smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
struct connection *conn;
if (!l4)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
conn = objt_conn(l4->si[0].end);
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
if (!l4->si[0].conn->xprt_ctx)
if (!conn->xprt_ctx)
return 0;
smp->type = SMP_T_UINT;
smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
smp->flags = 0;
return 1;

View File

@ -395,7 +395,12 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag)
* (which is recomputed every time since it's constant). If
* it is positive, it means we have to send from the start.
*/
ret = make_proxy_line(trash.str, trash.size, &si->ob->prod->conn->addr.from, &si->ob->prod->conn->addr.to);
struct connection *remote = objt_conn(si->ob->prod->end);
if (remote)
ret = make_proxy_line(trash.str, trash.size, &remote->addr.from, &remote->addr.to);
else
ret = make_proxy_line(trash.str, trash.size, NULL, NULL);
if (!ret)
goto out_error;
@ -638,6 +643,7 @@ void stream_int_update_conn(struct stream_interface *si)
{
struct channel *ib = si->ib;
struct channel *ob = si->ob;
struct connection *conn = __objt_conn(si->end);
/* Check if we need to close the read side */
if (!(ib->flags & CF_SHUTR)) {
@ -647,7 +653,7 @@ void stream_int_update_conn(struct stream_interface *si)
if (!(si->flags & SI_FL_WAIT_ROOM)) {
if (!(ib->flags & CF_DONT_READ)) /* full */
si->flags |= SI_FL_WAIT_ROOM;
conn_data_stop_recv(si->conn);
conn_data_stop_recv(conn);
ib->rex = TICK_ETERNITY;
}
}
@ -658,7 +664,7 @@ void stream_int_update_conn(struct stream_interface *si)
* have updated it if there has been a completed I/O.
*/
si->flags &= ~SI_FL_WAIT_ROOM;
conn_data_want_recv(si->conn);
conn_data_want_recv(conn);
if (!(ib->flags & (CF_READ_NOEXP|CF_DONT_READ)) && !tick_isset(ib->rex))
ib->rex = tick_add_ifset(now_ms, ib->rto);
}
@ -672,7 +678,7 @@ void stream_int_update_conn(struct stream_interface *si)
if (!(si->flags & SI_FL_WAIT_DATA)) {
if ((ob->flags & CF_SHUTW_NOW) == 0)
si->flags |= SI_FL_WAIT_DATA;
conn_data_stop_send(si->conn);
conn_data_stop_send(conn);
ob->wex = TICK_ETERNITY;
}
}
@ -683,7 +689,7 @@ void stream_int_update_conn(struct stream_interface *si)
* have updated it if there has been a completed I/O.
*/
si->flags &= ~SI_FL_WAIT_DATA;
conn_data_want_send(si->conn);
conn_data_want_send(conn);
if (!tick_isset(ob->wex)) {
ob->wex = tick_add_ifset(now_ms, ob->wto);
if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
@ -712,7 +718,7 @@ void stream_int_update_conn(struct stream_interface *si)
*/
static void stream_int_shutr_conn(struct stream_interface *si)
{
struct connection *conn = si->conn;
struct connection *conn = __objt_conn(si->end);
si->ib->flags &= ~CF_SHUTR_NOW;
if (si->ib->flags & CF_SHUTR)
@ -754,7 +760,7 @@ static void stream_int_shutr_conn(struct stream_interface *si)
*/
static void stream_int_shutw_conn(struct stream_interface *si)
{
struct connection *conn = si->conn;
struct connection *conn = __objt_conn(si->end);
si->ob->flags &= ~CF_SHUTW_NOW;
if (si->ob->flags & CF_SHUTW)
@ -840,24 +846,25 @@ static void stream_int_shutw_conn(struct stream_interface *si)
static void stream_int_chk_rcv_conn(struct stream_interface *si)
{
struct channel *ib = si->ib;
struct connection *conn = __objt_conn(si->end);
if (unlikely(si->state > SI_ST_EST || (ib->flags & CF_SHUTR)))
return;
conn_refresh_polling_flags(si->conn);
conn_refresh_polling_flags(conn);
if ((ib->flags & CF_DONT_READ) || channel_full(ib)) {
/* stop reading */
if (!(ib->flags & CF_DONT_READ)) /* full */
si->flags |= SI_FL_WAIT_ROOM;
__conn_data_stop_recv(si->conn);
__conn_data_stop_recv(conn);
}
else {
/* (re)start reading */
si->flags &= ~SI_FL_WAIT_ROOM;
__conn_data_want_recv(si->conn);
__conn_data_want_recv(conn);
}
conn_cond_update_data_polling(si->conn);
conn_cond_update_data_polling(conn);
}
@ -869,6 +876,7 @@ static void stream_int_chk_rcv_conn(struct stream_interface *si)
static void stream_int_chk_snd_conn(struct stream_interface *si)
{
struct channel *ob = si->ob;
struct connection *conn = __objt_conn(si->end);
if (unlikely(si->state > SI_ST_EST || (ob->flags & CF_SHUTW)))
return;
@ -880,7 +888,7 @@ static void stream_int_chk_snd_conn(struct stream_interface *si)
!(si->flags & SI_FL_WAIT_DATA)) /* not waiting for data */
return;
if (si->conn->flags & (CO_FL_DATA_WR_ENA|CO_FL_CURR_WR_ENA)) {
if (conn->flags & (CO_FL_DATA_WR_ENA|CO_FL_CURR_WR_ENA)) {
/* already subscribed to write notifications, will be called
* anyway, so let's avoid calling it especially if the reader
* is not ready.
@ -888,20 +896,20 @@ static void stream_int_chk_snd_conn(struct stream_interface *si)
return;
}
if (!(si->conn->flags & (CO_FL_HANDSHAKE|CO_FL_WAIT_L4_CONN|CO_FL_WAIT_L6_CONN))) {
if (!(conn->flags & (CO_FL_HANDSHAKE|CO_FL_WAIT_L4_CONN|CO_FL_WAIT_L6_CONN))) {
/* Before calling the data-level operations, we have to prepare
* the polling flags to ensure we properly detect changes.
*/
if (si->conn->ctrl)
fd_want_send(si->conn->t.sock.fd);
if (conn->ctrl)
fd_want_send(conn->t.sock.fd);
conn_refresh_polling_flags(si->conn);
conn_refresh_polling_flags(conn);
si_conn_send(si->conn);
if (si->conn->flags & CO_FL_ERROR) {
si_conn_send(conn);
if (conn->flags & CO_FL_ERROR) {
/* Write error on the file descriptor */
fd_stop_both(si->conn->t.sock.fd);
__conn_data_stop_both(si->conn);
fd_stop_both(conn->t.sock.fd);
__conn_data_stop_both(conn);
si->flags |= SI_FL_ERR;
goto out_wakeup;
}
@ -916,7 +924,7 @@ static void stream_int_chk_snd_conn(struct stream_interface *si)
* ->o limit was reached. Maybe we just wrote the last
* chunk and need to close.
*/
__conn_data_stop_send(si->conn);
__conn_data_stop_send(conn);
if (((ob->flags & (CF_SHUTW|CF_AUTO_CLOSE|CF_SHUTW_NOW)) ==
(CF_AUTO_CLOSE|CF_SHUTW_NOW)) &&
(si->state == SI_ST_EST)) {
@ -932,7 +940,7 @@ static void stream_int_chk_snd_conn(struct stream_interface *si)
/* Otherwise there are remaining data to be sent in the buffer,
* which means we have to poll before doing so.
*/
__conn_data_want_send(si->conn);
__conn_data_want_send(conn);
si->flags &= ~SI_FL_WAIT_DATA;
if (!tick_isset(ob->wex))
ob->wex = tick_add_ifset(now_ms, ob->wto);
@ -969,7 +977,7 @@ static void stream_int_chk_snd_conn(struct stream_interface *si)
}
/* commit possible polling changes */
conn_cond_update_polling(si->conn);
conn_cond_update_polling(conn);
}
/*
@ -1205,7 +1213,7 @@ static void si_conn_send_cb(struct connection *conn)
if (conn->flags & CO_FL_ERROR)
return;
if (si->conn->flags & CO_FL_HANDSHAKE)
if (conn->flags & CO_FL_HANDSHAKE)
/* a handshake was requested */
return;
@ -1229,6 +1237,8 @@ static void si_conn_send_cb(struct connection *conn)
*/
void stream_sock_read0(struct stream_interface *si)
{
struct connection *conn = __objt_conn(si->end);
si->ib->flags &= ~CF_SHUTR_NOW;
if (si->ib->flags & CF_SHUTR)
return;
@ -1246,22 +1256,22 @@ void stream_sock_read0(struct stream_interface *si)
/* we want to immediately forward this close to the write side */
if (si->flags & SI_FL_NOLINGER) {
si->flags &= ~SI_FL_NOLINGER;
setsockopt(si->conn->t.sock.fd, SOL_SOCKET, SO_LINGER,
setsockopt(conn->t.sock.fd, SOL_SOCKET, SO_LINGER,
(struct linger *) &nolinger, sizeof(struct linger));
}
/* force flag on ssl to keep session in cache */
if (si->conn->xprt->shutw)
si->conn->xprt->shutw(si->conn, 0);
if (conn->xprt->shutw)
conn->xprt->shutw(conn, 0);
goto do_close;
}
/* otherwise that's just a normal read shutdown */
__conn_data_stop_recv(si->conn);
__conn_data_stop_recv(conn);
return;
do_close:
/* OK we completely close the socket here just as if we went through si_shut[rw]() */
conn_full_close(si->conn);
conn_full_close(conn);
si->ib->flags &= ~CF_SHUTR_NOW;
si->ib->flags |= CF_SHUTR;