diff --git a/doc/configuration.txt b/doc/configuration.txt index 2e0836727..b3ac72be6 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -17753,6 +17753,67 @@ dst_port : integer a same server, or to pass the destination port information to a server using an HTTP header. +fc_conn_err : integer + Returns the ID of the error that might have occurred on the current + connection. Any strictly positive value of this fetch indicates that the + connection did not succeed and would result in an error log being output (as + decribed in section 8.2.5). See the "fc_conn_err_str" fetch for a full list of + error codes and their corresponding error message. + +fc_conn_err_str : string + Returns an error message decribing what problem happened on the current + connection, resulting in a connection failure. This string corresponds to the + "message" part of the error log format (see section 8.2.5). See below for a + full list of error codes and their corresponding error messages : + + +----+---------------------------------------------------------------------------+ + | ID | message | + +----+---------------------------------------------------------------------------+ + | 0 | "Success" | + | 1 | "Reached configured maxconn value" | + | 2 | "Too many sockets on the process" | + | 3 | "Too many sockets on the system" | + | 4 | "Out of system buffers" | + | 5 | "Protocol or address family not supported" | + | 6 | "General socket error" | + | 7 | "Source port range exhausted" | + | 8 | "Can't bind to source address" | + | 9 | "Out of local source ports on the system" | + | 10 | "Local source address already in use" | + | 11 | "Connection closed while waiting for PROXY protocol header" | + | 12 | "Connection error while waiting for PROXY protocol header" | + | 13 | "Timeout while waiting for PROXY protocol header" | + | 14 | "Truncated PROXY protocol header received" | + | 15 | "Received something which does not look like a PROXY protocol header" | + | 16 | "Received an invalid PROXY protocol header" | + | 17 | "Received an unhandled protocol in the PROXY protocol header" | + | 18 | "Connection closed while waiting for NetScaler Client IP header" | + | 19 | "Connection error while waiting for NetScaler Client IP header" | + | 20 | "Timeout while waiting for a NetScaler Client IP header" | + | 21 | "Truncated NetScaler Client IP header received" | + | 22 | "Received an invalid NetScaler Client IP magic number" | + | 23 | "Received an unhandled protocol in the NetScaler Client IP header" | + | 24 | "Connection closed during SSL handshake" | + | 25 | "Connection error during SSL handshake" | + | 26 | "Timeout during SSL handshake" | + | 27 | "Too many SSL connections" | + | 28 | "Out of memory when initializing an SSL connection" | + | 29 | "Rejected a client-initiated SSL renegotiation attempt" | + | 30 | "SSL client CA chain cannot be verified" | + | 31 | "SSL client certificate not trusted" | + | 32 | "Server presented an SSL certificate different from the configured one" | + | 33 | "Server presented an SSL certificate different from the expected one" | + | 34 | "SSL handshake failure" | + | 35 | "SSL handshake failure after heartbeat" | + | 36 | "Stopped a TLSv1 heartbeat attack (CVE-2014-0160)" | + | 37 | "Attempt to use SSL on an unknown target (internal error)" | + | 38 | "Server refused early data" | + | 39 | "SOCKS4 Proxy write error during handshake" | + | 40 | "SOCKS4 Proxy read error during handshake" | + | 41 | "SOCKS4 Proxy deny the request" | + | 42 | "SOCKS4 Proxy handshake aborted by server" | + +----+---------------------------------------------------------------------------+ + fc_http_major : integer Reports the front connection's HTTP major version encoding, which may be 1 for HTTP/0.9 to HTTP/1.1 or 2 for HTTP/2. Note, this is based on the on-wire diff --git a/include/haproxy/connection-t.h b/include/haproxy/connection-t.h index 9451585ae..ff8927dba 100644 --- a/include/haproxy/connection-t.h +++ b/include/haproxy/connection-t.h @@ -194,7 +194,11 @@ enum { CO_FL_SOCKS4 = CO_FL_SOCKS4_SEND | CO_FL_SOCKS4_RECV, }; -/* possible connection error codes */ +/* Possible connection error codes. + * Warning: Do not reorder the codes, they are fetchable through the + * "fc_conn_err" sample fetch. If a new code is added, please add an error label + * in conn_err_code_str and in the "fc_conn_err_str" sample fetch documentation. + */ enum { CO_ER_NONE, /* no error */ diff --git a/src/connection.c b/src/connection.c index 0ba29ed66..09c91a542 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1498,6 +1498,55 @@ int smp_fetch_fc_pp_unique_id(const struct arg *args, struct sample *smp, const return 1; } +/* fetch the error code of a connection */ +int smp_fetch_fc_conn_err(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct connection *conn; + + conn = objt_conn(smp->sess->origin); + if (!conn) + return 0; + + if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) { + smp->flags |= SMP_F_MAY_CHANGE; + return 0; + } + + smp->flags = 0; + smp->data.type = SMP_T_SINT; + smp->data.u.sint = (unsigned long long int)conn->err_code; + + return 1; +} + +/* fetch a string representation of the error code of a connection */ +int smp_fetch_fc_conn_err_str(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct connection *conn; + const char *err_code_str; + + conn = objt_conn(smp->sess->origin); + if (!conn) + return 0; + + if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) { + smp->flags |= SMP_F_MAY_CHANGE; + return 0; + } + + err_code_str = conn_err_code_str(conn); + + if (!err_code_str) + return 0; + + smp->flags = 0; + smp->data.type = SMP_T_STR; + smp->data.u.str.area = (char*)err_code_str; + smp->data.u.str.data = strlen(err_code_str); + + return 1; +} + /* Note: must not be declared as its list will be overwritten. * Note: fetches that may return multiple types must be declared as the lowest * common denominator, the type that can be casted into all other ones. For @@ -1509,6 +1558,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "fc_rcvd_proxy", smp_fetch_fc_rcvd_proxy, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI }, { "fc_pp_authority", smp_fetch_fc_pp_authority, 0, NULL, SMP_T_STR, SMP_USE_L4CLI }, { "fc_pp_unique_id", smp_fetch_fc_pp_unique_id, 0, NULL, SMP_T_STR, SMP_USE_L4CLI }, + { "fc_conn_err", smp_fetch_fc_conn_err, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI }, + { "fc_conn_err_str", smp_fetch_fc_conn_err_str, 0, NULL, SMP_T_STR, SMP_USE_L4CLI }, { /* END */ }, }};