]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: stream-int: stop using si->conn and use si->end instead
authorWilly Tarreau <w@1wt.eu>
Tue, 1 Oct 2013 08:45:07 +0000 (10:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 9 Dec 2013 14:40:22 +0000 (15:40 +0100)
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.

12 files changed:
include/proto/stream_interface.h
include/types/stream_interface.h
src/backend.c
src/dumpstats.c
src/frontend.c
src/log.c
src/peers.c
src/proto_http.c
src/proto_tcp.c
src/session.c
src/ssl_sock.c
src/stream_interface.c

index 42b1ebb2d7a51b3c4d6dbc283a19f4fd73cd1352..d1c2b36bd86da0b799bdb88673f9ab772170ae01 100644 (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;
index 0862c900936c3271b77a54130e067f842555e0f9..bb3eb180ac3060daba1cca3f38e25e6f300e0a69 100644 (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 */
index 63bd368c2d7dbb0012dbc1cdd49d2973b0d6abb9..65cbcb6500fb68d588d437599ee14f6b265f912e 100644 (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);
index 629bf96b708984a3f8a469aa178c76dfe6d8253d..6703b9be960026b8eb5ef8367bbccae4067b70cd 100644 (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)) : "");
index 1048052140e79232d65f5dc844651174b3a23ac2..8a01a4ab999c0d9e46b8d20ca67b2de65e3bc551 100644 (file)
 /* 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 */
index 69e495b083f94ade95c4d4791de7be0b8a52fe3f..ef89dd3b4c88a46251bcabd46e74bc077e62591d 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -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;
index d265f483c840474db04c9da23c3d784c698c0690..40936e45d197ee96f036097f3e206948520e275f 100644 (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;
index 94cf352bef591a06ee27c0ba2ffe3e0363bbd64f..af96f4119dfdb77c42ef9189941273eeff810081 100644 (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:
index a1c69a278d4bf4ff77cd2373ff604143eda68f5b..de1e4ae9346c99163817a0e0ac7cace04d491348 100644 (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;
index 2184766507bca0e759da178baf6a553dbd4d6457..a6dd5193e82b13a5eaec7f607cffc5f4ebb8b032 100644 (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;
 
index 9396cbd524bf5814f2b2729359ce9b04115a5d08..5b8fdb95cf902ca52458449bd78a8a26532a05e8 100644 (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;
+
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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)
+               return 0;
 
-       if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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;
+
+       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(l4->si[0].conn->xprt_ctx);
+       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;
+
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
+       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;
+
+       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(l4->si[0].conn->xprt_ctx, NULL);
+       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;
+
+       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(l4->si[0].conn->xprt_ctx);
+       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;
+
+       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(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
+       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;
+
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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;
+
+       conn = objt_conn(l4->si[0].end);
+       if (!conn || conn->xprt != &ssl_sock)
                return 0;
 
-       if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+       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;
index d66d301fd624d0ec5223e28a524b3787890fa0b6..6932e1597348ca8775dafb6cfd4b1b2e7fe79a8a 100644 (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;