}
}
+ if (check->state & CHK_ST_PORT_MISS) {
+ /* NOTE: this is reported after <fall> tries */
+ chunk_printf(chk, "No port available for the TCP connection");
+ set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
+ }
+
if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L4_CONN)) == CO_FL_WAIT_L4_CONN) {
/* L4 not established (yet) */
if (conn->flags & CO_FL_ERROR)
* - SF_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
* - SF_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
* - SF_ERR_INTERNAL for any other purely internal errors
+ * - SF_ERR_CHK_PORT if no port could be found to run a health check on an AF_INET* socket
* Additionnally, in the case of SF_ERR_RESOURCE, an emergency log will be emitted.
* Note that we try to prevent the network stack from sending the ACK during the
* connect() when a pure TCP check is used (without PROXY protocol).
conn->addr.to = s->addr;
}
- if (check->port) {
- set_host_port(&conn->addr.to, check->port);
+ if ((conn->addr.to.ss_family == AF_INET) || (conn->addr.to.ss_family == AF_INET6)) {
+ int i = 0;
+
+ i = srv_check_healthcheck_port(check);
+ if (i == 0) {
+ conn->owner = check;
+ return SF_ERR_CHK_PORT;
+ }
+
+ set_host_port(&conn->addr.to, i);
}
proto = protocol_by_family(conn->addr.to.ss_family);
conn->flags |= CO_FL_ERROR;
chk_report_conn_err(conn, errno, 0);
break;
+ /* should share same code than cases below */
+ case SF_ERR_CHK_PORT:
+ check->state |= CHK_ST_PORT_MISS;
case SF_ERR_PRXCOND:
case SF_ERR_RESOURCE:
case SF_ERR_INTERNAL:
enqueue_email_alert(p, buf);
}
+/*
+ * Return value:
+ * the port to be used for the health check
+ * 0 in case no port could be found for the check
+ */
+int srv_check_healthcheck_port(struct check *chk)
+{
+ int i = 0;
+ struct server *srv = NULL;
+
+ srv = chk->server;
+
+ /* If neither a port nor an addr was specified and no check transport
+ * layer is forced, then the transport layer used by the checks is the
+ * same as for the production traffic. Otherwise we use raw_sock by
+ * default, unless one is specified.
+ */
+ if (!chk->port && !is_addr(&chk->addr)) {
+#ifdef USE_OPENSSL
+ chk->use_ssl |= (srv->use_ssl || (srv->proxy->options & PR_O_TCPCHK_SSL));
+#endif
+ chk->send_proxy |= (srv->pp_opts);
+ }
+
+ /* by default, we use the health check port ocnfigured */
+ if (chk->port > 0)
+ return chk->port;
+
+ /* try to get the port from check_core.addr if check.port not set */
+ i = get_host_port(&chk->addr);
+ if (i > 0)
+ return i;
+
+ /* try to get the port from server address */
+ /* prevent MAPPORTS from working at this point, since checks could
+ * not be performed in such case (MAPPORTS impose a relative ports
+ * based on live traffic)
+ */
+ if (srv->flags & SRV_F_MAPPORTS)
+ return 0;
+ i = get_host_port(&srv->addr); /* by default */
+ if (i > 0)
+ return i;
+
+ return 0;
+}
+
/*
* Local variables:
if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
int cur_arg;
- short realport = 0;
int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
if (!defsrv && curproxy == defproxy) {
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- else {
- /* used by checks */
- realport = port1;
- }
/* save hostname and create associated name resolution */
newsrv->hostname = fqdn;
goto out;
}
- /* If neither a port nor an addr was specified and no check transport
- * layer is forced, then the transport layer used by the checks is the
- * same as for the production traffic. Otherwise we use raw_sock by
- * default, unless one is specified.
- */
- if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
-#ifdef USE_OPENSSL
- newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
-#endif
- newsrv->check.send_proxy |= (newsrv->pp_opts);
- }
- /* try to get the port from check_core.addr if check.port not set */
- if (!newsrv->check.port)
- newsrv->check.port = get_host_port(&newsrv->check.addr);
-
- if (!newsrv->check.port)
- newsrv->check.port = realport; /* by default */
-
/*
* We need at least a service port, a check port or the first tcp-check rule must
* be a 'connect' one when checking an IPv4/IPv6 server.
*/
- if (!newsrv->check.port &&
+ if ((srv_check_healthcheck_port(&newsrv->check) == 0) &&
(is_inet_addr(&newsrv->check.addr) ||
(!is_addr(&newsrv->check.addr) && is_inet_addr(&newsrv->addr)))) {
struct tcpcheck_rule *r = NULL;