#include <haproxy/listener-t.h>
#include <haproxy/sock-t.h>
-int sock_create_server_socket(struct connection *conn, struct proxy *be);
+int sock_create_server_socket(struct connection *conn, struct proxy *be, int *stream_err);
void sock_enable(struct receiver *rx);
void sock_disable(struct receiver *rx);
void sock_unbind(struct receiver *rx);
int quic_connect_server(struct connection *conn, int flags)
{
- int fd;
+ int fd, stream_err;
struct server *srv;
struct proxy *be;
struct conn_src *src;
}
/* perform common checks on obtained socket FD, return appropriate Stream Error Flag in case of failure */
- fd = conn->handle.fd = sock_create_server_socket(conn, be);
- if (fd & SF_ERR_MASK)
- return fd;
+ fd = conn->handle.fd = sock_create_server_socket(conn, be, &stream_err);
+ if (fd == -1) {
+ return stream_err;
+ }
/* FD is ok, perform protocol specific settings */
/* allow specific binding :
int tcp_connect_server(struct connection *conn, int flags)
{
- int fd;
+ int fd, stream_err;
struct server *srv;
struct proxy *be;
struct conn_src *src;
/* perform common checks on obtained socket FD, return appropriate Stream Error Flag in case of failure */
- fd = conn->handle.fd = sock_create_server_socket(conn, be);
- if ((fd & SF_ERR_MASK) == fd)
- return fd;
+ fd = conn->handle.fd = sock_create_server_socket(conn, be, &stream_err);
+ if (fd == -1) {
+ return stream_err;
+ }
/* FD is OK, continue with protocol specific settings */
if (be->options & PR_O_TCP_SRV_KA) {
*/
static int uxst_connect_server(struct connection *conn, int flags)
{
- int fd;
+ int fd, stream_err;
struct server *srv;
struct proxy *be;
}
/* perform common checks on obtained socket FD, return appropriate Stream Error Flag in case of failure */
- fd = conn->handle.fd = sock_create_server_socket(conn, be);
- if (fd & SF_ERR_MASK)
- return fd;
+ fd = conn->handle.fd = sock_create_server_socket(conn, be, &stream_err);
+ if (fd == -1) {
+ return stream_err;
+ }
/* FD is ok, continue with protocol specific settings */
if (global.tune.server_sndbuf)
* using the configured namespace if needed, or the one passed by the proxy
* protocol if required to do so. It then calls socket() or socketat(). On
* success, checks if mark or tos sockopts need to be set on the file handle.
- * Returns the FD or error code.
+ * Returns backend connection socket FD on success, stream_err flag needed by
+ * upper level is set as SF_ERR_NONE; -1 on failure, stream_err is set to
+ * appropriate value.
*/
-int sock_create_server_socket(struct connection *conn, struct proxy *be)
+int sock_create_server_socket(struct connection *conn, struct proxy *be, int *stream_err)
{
const struct netns_entry *ns = NULL;
int sock_fd;
/* at first, handle common to all proto families system limits and permission related errors */
if (sock_fd == -1) {
- return sock_handle_system_err(conn, be);
+ *stream_err = sock_handle_system_err(conn, be);
+
+ return -1;
}
/* now perform some runtime condition checks */
close(sock_fd);
conn->err_code = CO_ER_CONF_FDLIM;
conn->flags |= CO_FL_ERROR;
+ *stream_err = SF_ERR_PRXCOND; /* it is a configuration limit */
- return SF_ERR_PRXCOND; /* it is a configuration limit */
+ return -1;
}
if (fd_set_nonblock(sock_fd) == -1 ||
close(sock_fd);
conn->err_code = CO_ER_SOCK_ERR;
conn->flags |= CO_FL_ERROR;
+ *stream_err = SF_ERR_INTERNAL;
- return SF_ERR_INTERNAL;
+ return -1;
}
if (master == 1 && fd_set_cloexec(sock_fd) == -1) {
close(sock_fd);
conn->err_code = CO_ER_SOCK_ERR;
conn->flags |= CO_FL_ERROR;
+ *stream_err = SF_ERR_INTERNAL;
- return SF_ERR_INTERNAL;
+ return -1;
}
if (conn->flags & CO_FL_OPT_MARK)
if (conn->flags & CO_FL_OPT_TOS)
sock_set_tos(sock_fd, conn->dst, conn->tos);
+ stream_err = SF_ERR_NONE;
return sock_fd;
}