From: Amaury Denoyelle Date: Tue, 13 Jul 2021 08:36:03 +0000 (+0200) Subject: MEDIUM: server: support track keyword for dynamic servers X-Git-Tag: v2.5-dev2~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=56eb8ed37db7cada6297f5b771b3d51eb4a63986;p=thirdparty%2Fhaproxy.git 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 7abfc85fb2..4b01ddcb42 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1470,6 +1470,11 @@ add server / [args]* 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 @@ add server / [args]* - ssl-min-ver - tfo - tls-tickets + - track - usesrc - verify - verifyhost diff --git a/src/server.c b/src/server.c index 664e2f4ec5..5fa3946662 100644 --- a/src/server.c +++ b/src/server.c @@ -1678,7 +1678,7 @@ static struct srv_kw_list srv_kws = { "ALL", { }, { { "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 keyword */ { "weight", srv_parse_weight, 1, 1, 1 }, /* Set the load-balancing weight */ @@ -2228,6 +2228,31 @@ void free_server(struct server *srv) srv = NULL; } +/* Remove a server from a tracking list if is tracking another + * server. No special care is taken if 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 and values so that they may be reused by this loop @@ -4503,6 +4528,11 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct } } + 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 @@ out: 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 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap 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 */