MEDIUM: server: support track keyword for dynamic servers
Allow the usage of the 'track' keyword for dynamic servers. On server
deletion, the server is properly removed from the tracking chain to
prevents NULL pointer dereferencing.
diff --git a/doc/management.txt b/doc/management.txt
index 7abfc85..4b01ddc 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -1470,6 +1470,11 @@
init-addr method. This means that no resolution will be undertaken if a FQDN
is specified as an address, even if the server creation will be validated.
+ A dynamic server may use the "track" keyword to follow the check status of
+ another server from the configuration. However, it is not possible to track
+ another dynamic server. This is to ensure that the tracking chain is kept
+ consistent even in the case of dynamic servers deletion.
+
Here is the list of the currently supported keywords :
- allow-0rtt
@@ -1507,6 +1512,7 @@
- ssl-min-ver
- tfo
- tls-tickets
+ - track
- usesrc
- verify
- verifyhost
diff --git a/src/server.c b/src/server.c
index 664e2f4..5fa3946 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1678,7 +1678,7 @@
{ "source", srv_parse_source, -1, 1, 1 }, /* Set the source address to be used to connect to the server */
{ "stick", srv_parse_stick, 0, 1, 0 }, /* Enable stick-table persistence */
{ "tfo", srv_parse_tfo, 0, 1, 1 }, /* enable TCP Fast Open of server */
- { "track", srv_parse_track, 1, 1, 0 }, /* Set the current state of the server, tracking another one */
+ { "track", srv_parse_track, 1, 1, 1 }, /* Set the current state of the server, tracking another one */
{ "socks4", srv_parse_socks4, 1, 1, 0 }, /* Set the socks4 proxy of the server*/
{ "usesrc", srv_parse_usesrc, 0, 1, 1 }, /* safe-guard against usesrc without preceding <source> keyword */
{ "weight", srv_parse_weight, 1, 1, 1 }, /* Set the load-balancing weight */
@@ -2228,6 +2228,31 @@
srv = NULL;
}
+/* Remove a server <srv> from a tracking list if <srv> is tracking another
+ * server. No special care is taken if <srv> is tracked itself by another one :
+ * this situation should be avoided by the caller.
+ *
+ * Not thread-safe.
+ */
+static void release_server_track(struct server *srv)
+{
+ struct server *strack = srv->track;
+ struct server **base;
+
+ if (!strack)
+ return;
+
+ for (base = &strack->trackers; *base; base = &((*base)->tracknext)) {
+ if (*base == srv) {
+ *base = srv->tracknext;
+ return;
+ }
+ }
+
+ /* srv not found on the tracking list, this should never happen */
+ BUG_ON(!*base);
+}
+
/*
* Parse as much as possible such a range string argument: low[-high]
* Set <nb_low> and <nb_high> values so that they may be reused by this loop
@@ -4503,6 +4528,11 @@
}
}
+ if (srv->trackit) {
+ if (srv_apply_track(srv, be))
+ goto out;
+ }
+
/* Attach the server to the end of the proxy linked list. Note that this
* operation is not thread-safe so this is executed under thread
* isolation.
@@ -4564,8 +4594,11 @@
if (!usermsgs_empty())
cli_err(appctx, usermsgs_str());
- if (srv)
+ if (srv) {
+ release_server_track(srv);
free_server(srv);
+ }
+
return 1;
}
@@ -4650,6 +4683,10 @@
goto out;
}
+ /* remove srv from tracking list */
+ if (srv->track)
+ release_server_track(srv);
+
/* TODO remove server for check list once 'check' will be implemented for
* dynamic servers
*/